1 /*
2  * $Header: /cvsroot/arc/arc/marc.c,v 1.6 2010/08/07 13:06:11 k_reimer Exp $
3  */
4 
5 /*  MARC - Archive merge utility
6 
7     Version 5.21, created on 04/22/87 at 15:05:10
8 
9 (C) COPYRIGHT 1985-87 by System Enhancement Associates; ALL RIGHTS RESERVED
10 
11     By:	 Thom Henderson
12 
13     Description:
14 	 This program is used to "merge" archives.  That is, to move
15 	 files from one archive to another with no data conversion.
16 	 Please refer to the ARC source for a description of archives
17 	 and archive formats.
18 
19     Instructions:
20 	 Run this program with no arguments for complete instructions.
21 
22     Language:
23 	 Computer Innovations Optimizing C86
24 */
25 #include <stdio.h>
26 #include <string.h>
27 #include "arc.h"
28 
29 #if	UNIX
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <unistd.h>
33 #include <errno.h>
34 #endif
35 
36 #include "proto.h"
37 
38 #ifndef	__STDC__
39 char *calloc(), *malloc(), *realloc(); /* memory managers */
40 #endif
41 int gethdr(), match(), readhdr();
42 VOID	arcdie(), filecopy(), setstamp(), writehdr();
43 static VOID copyfile(), expandlst(), merge();
44 
45 FILE *src;			       /* source archive */
46 char srcname[STRLEN];		       /* source archive name */
47 char *pinbuf;				/* block input buffer */
48 
49 static char **lst;		       /* files list */
50 static int lnum;		       /* length of files list */
51 
52 int
main(nargs,arg)53 main(nargs,arg)			       /* system entry point */
54 int nargs;			       /* number of arguments */
55 char *arg[];			       /* pointers to arguments */
56 {
57     char *makefnam();
58     char *envfind();
59 #if	!_MTS
60     char *arctemp2;		       /* temp file stuff */
61 #endif
62 #if	GEMDOS
63     VOID exitpause();
64 #endif
65     int n;			       /* index */
66 #if	UNIX
67     struct	stat	sbuf;
68 #endif
69 
70 
71     if(nargs<3)
72     {	 printf("MARC - Archive merger, Version 5.21p, created on 08/07/2010\n");
73 /*	 printf("(C) COPYRIGHT 1985,86,87 by System Enhancement Associates;");
74 	 printf(" ALL RIGHTS RESERVED\n\n");
75 	 printf("Please refer all inquiries to:\n\n");
76 	 printf("	System Enhancement Associates\n");
77 	 printf("	21 New Street, Wayne NJ 07470\n\n");
78 	 printf("You may copy and distribute this program freely,");
79 	 printf(" provided that:\n");
80 	 printf("    1)	  No fee is charged for such copying and");
81 	 printf(" distribution, and\n");
82 	 printf("    2)	  It is distributed ONLY in its original,");
83 	 printf(" unmodified state.\n\n");
84 	 printf("If you like this program, and find it of use, then your");
85 	 printf(" contribution will\n");
86 	 printf("be appreciated.  You may not use this product in a");
87 	 printf(" commercial environment\n");
88 	 printf("or a governmental organization without paying a license");
89 	 printf(" fee of $35.  Site\n");
90 	 printf("licenses and commercial distribution licenses are");
91 	 printf(" available.  A program\n");
92 	 printf("disk and printed documentation are available for $50.\n");
93 	 printf("\nIf you fail to abide by the terms of this license, ");
94 	 printf(" then your conscience\n");
95 	 printf("will haunt you for the rest of your life.\n\n");
96 */
97 	 printf("Usage: MARC <tgtarc> <srcarc> [<filename> . . .]\n");
98 	 printf("Where: <tgtarc> is the archive to add files to,\n");
99 	 printf("	<srcarc> is the archive to get files from, and\n");
100 	 printf("	<filename> is zero or more file names to get.\n");
101 	 printf("\nAdapted from MSDOS by Howard Chu\n");
102 #if	GEMDOS
103 	 exitpause();
104 #endif
105 	 return 1;
106     }
107 
108 	/* see where temp files go */
109 #if	!_MTS
110 	arctemp = calloc(1, STRLEN);
111 	if (!(arctemp2 = envfind("ARCTEMP")))
112 		arctemp2 = envfind("TMPDIR");
113 	if (arctemp2) {
114 		strncpy(arctemp, arctemp2, STRLEN - 16);
115 		arctemp[STRLEN - 17] = '\0';
116 		n = strlen(arctemp);
117 		if (arctemp[n - 1] != CUTOFF)
118 			arctemp[n] = CUTOFF;
119 	}
120 #if	UNIX
121 	else	strcpy(arctemp, "/tmp/");
122 #endif
123 #if	!MSDOS
124 	{
125 		strcat(arctemp, "AXXXXXX");
126 		int fd = mkstemp(arctemp);
127 		if (fd == -1)
128 		{
129 			fprintf(stderr, "Unable to create temporary files: %s\n", strerror(errno));
130 			exit(235);
131 		}
132 		close(fd);
133 		unlink(arctemp);
134 	}
135 #else
136 	strcat(arctemp, "$ARCTEMP");
137 #endif
138 #else
139 	guinfo("SHFSEP	", gotinf);
140 	sepchr[0] = gotinf[0];
141 	guinfo("SCRFCHAR", gotinf);
142 	tmpchr[0] = gotinf[0];
143 	arctemp = "-$$$";
144 	arctemp[0] = tmpchr[0];
145 #endif
146 
147 	for (n = 1; n < nargs; n++)
148 	  if (strlen(arg[n]) > (STRLEN - 16))
149 	  {
150 	    fprintf(stderr, "Too long argument: %s\n", arg[n]);
151 	    exit(235);
152 	  }
153 
154 #if	UNIX
155 	if (!stat(arg[1],&sbuf))
156 		strcpy(arcname,arg[1]);
157 	else
158 		makefnam(arg[1],".arc",arcname);
159 	if (!stat(arg[2],&sbuf))
160 		strcpy(srcname,arg[2]);
161 	else
162 		makefnam(arg[2],".arc",srcname);
163 #else
164     makefnam(arg[1],".ARC",arcname);   /* fix up archive names */
165     makefnam(arg[2],".ARC",srcname);
166 /*	makefnam(".$$$",arcname,newname);*/
167 #endif
168 	sprintf(newname,"%s.arc",arctemp);
169 
170     arc = fopen(arcname,OPEN_R);	       /* open the archives */
171     if(!(src=fopen(srcname,OPEN_R)))
172 	 arcdie("Cannot read source archive %s",srcname);
173     if(!(new=tmpopen(newname)))
174 	 arcdie("Cannot create new archive %s",newname);
175 
176     if(!arc)
177 	 printf("Creating new archive %s\n",arcname);
178 
179     /* get the files list set up */
180 
181     lnum = nargs-3;		       /* initial length of list */
182     if(lnum<1)			       /* phoney for default case */
183     {	 lnum = 1;
184 	 lst = (char **) calloc(1,sizeof(char *));
185 	 lst[0] = "*.*";
186     }
187     else			       /* else use filenames given */
188     {	 lst = (char **) calloc(lnum,sizeof(char *));
189 	 for(n=3; n<nargs; n++)
190 	      lst[n-3] = arg[n];
191 
192 	 for(n=0; n<lnum; )	       /* expand indirect references */
193 	 {    if(*lst[n] == '@')
194 		   expandlst(n);
195 	      else n++;
196 	 }
197     }
198     if (!(pinbuf = malloc(MYBUF)))
199 	arcdie("Not enough memory for input buffer.");
200 
201     merge(lnum,lst);		       /* merge desired files */
202 
203     if(arc) fclose(arc);	       /* close the archives */
204     fclose(src);
205     fclose(new);
206 
207     if(arc)			       /* make the switch */
208 	 if(unlink(arcname))
209 	      arcdie("Unable to delete old copy of %s",arcname);
210     if(move(newname,arcname))
211 	 arcdie("Unable to rename %s to %s",newname,arcname);
212 
213     setstamp(arcname,arcdate,arctime);     /* new arc matches newest file */
214 
215 #if	GEMDOS
216     exitpause();
217 #endif
218     return nerrs;
219 }
220 
221 static	VOID
merge(nargs,arg)222 merge(nargs,arg)		       /* merge two archives */
223 int nargs;			       /* number of filename templates */
224 char *arg[];			       /* pointers to names */
225 {
226     struct heads srch;		       /* source archive header */
227     struct heads arch;		       /* target archive header */
228     int gotsrc, gotarc;		       /* archive entry versions (0=end) */
229     int copy;			       /* true to copy file from source */
230     int n;			       /* index */
231 
232     gotsrc = gethdr(src,&srch);	       /* get first source file */
233     gotarc = gethdr(arc,&arch);	       /* get first target file */
234 
235     while(gotsrc || gotarc)	       /* while more to merge */
236     {	 if(strcmp(srch.name,arch.name)>0)
237 	 {    copyfile(arc,&arch,gotarc);
238 	      gotarc = gethdr(arc,&arch);
239 	 }
240 
241 	 else if(strcmp(srch.name,arch.name)<0)
242 	 {    copy = 0;
243 	      for(n=0; n<nargs; n++)
244 	      {	   if(match(srch.name,arg[n]))
245 		   {	copy = 1;
246 			break;
247 		   }
248 	      }
249 	      if(copy)		       /* select source or target */
250 	      {	   printf("Adding file:	  %s\n",srch.name);
251 		   copyfile(src,&srch,gotsrc);
252 	      }
253 	      else fseek(src,srch.size,1);
254 	      gotsrc = gethdr(src,&srch);
255 	 }
256 
257 	 else			       /* duplicate names */
258 	 {    copy = 0;
259 	      {	   if((srch.date>arch.date)
260 		   || (srch.date==arch.date && srch.time>arch.time))
261 		   {	for(n=0; n<nargs; n++)
262 			{    if(match(srch.name,arg[n]))
263 			     {	  copy = 1;
264 				  break;
265 			     }
266 			}
267 		   }
268 	      }
269 	      if(copy)		       /* select source or target */
270 	      {	   printf("Updating file: %s\n",srch.name);
271 		   copyfile(src,&srch,gotsrc);
272 		   gotsrc = gethdr(src,&srch);
273 		   if(gotarc)
274 		   {	fseek(arc,arch.size,1);
275 			gotarc = gethdr(arc,&arch);
276 		   }
277 	      }
278 	      else
279 	      {	   copyfile(arc,&arch,gotarc);
280 		   gotarc = gethdr(arc,&arch);
281 		   if(gotsrc)
282 		   {	fseek(src,srch.size,1);
283 			gotsrc = gethdr(src,&srch);
284 		   }
285 	      }
286 	 }
287     }
288 
289     hdrver = 0;			       /* end of archive marker */
290     writehdr(&arch,new);	       /* mark the end of the archive */
291 }
292 
gethdr(f,hdr)293 int gethdr(f,hdr)		       /* special read header for merge */
294 FILE *f;			       /* file to read from */
295 struct heads *hdr;		       /* storage for header */
296 {
297     char *i = hdr->name;	       /* string index */
298     int n;			       /* index */
299 
300     for(n=0; n<FNLEN; n++)	       /* fill name field */
301 	 *i++ = 0176;		       /* impossible high value */
302     *--i = '\0';		       /* properly end the name */
303 
304     hdrver = 0;			       /* reset header version */
305     if(readhdr(hdr,f))		       /* use normal reading logic */
306 	 return hdrver;		       /* return the version */
307     else return 0;		       /* or fake end of archive */
308 }
309 
310 static VOID
copyfile(f,hdr,ver)311 copyfile(f,hdr,ver)		       /* copy a file from an archive */
312 FILE *f;			       /* archive to copy from */
313 struct heads *hdr;		       /* header data for file */
314 int ver;			       /* header version */
315 {
316     hdrver = ver;		       /* set header version */
317     writehdr(hdr,new);		       /* write out the header */
318     filecopy(f,new,hdr->size);	       /* copy over the data */
319 }
320 
321 static VOID
expandlst(n)322 expandlst(n)			       /* expand an indirect reference */
323 int n;				       /* number of entry to expand */
324 {
325     FILE *lf, *fopen();		       /* list file, opener */
326     char buf[100];		       /* input buffer */
327     int x;			       /* index */
328     char *p = lst[n]+1;		       /* filename pointer */
329     char *makefnam();
330 
331     if(*p)			       /* use name if one was given */
332     {	 makefnam(p,".CMD",buf);
333 	 upper(buf);
334 	 if(!(lf=fopen(buf,"r")))
335 	      arcdie("Cannot read list of files in %s",buf);
336     }
337     else lf = stdin;		       /* else use standard input */
338 
339     for(x=n+1; x<lnum; x++)	       /* drop reference from the list */
340 	 lst[x-1] = lst[x];
341     lnum--;
342 
343     while(fscanf(lf,"%99s",buf)>0)     /* read in the list */
344     {	 if(!(lst=(char **) realloc(lst,(lnum+1)*sizeof(char *))))
345 	      arcdie("too many file references");
346 
347 	 lst[lnum] = malloc(strlen(buf)+1);
348 	 strcpy(lst[lnum],buf);	       /* save the name */
349 	 lnum++;
350     }
351 
352     if(lf!=stdin)		       /* avoid closing standard input */
353 	 fclose(lf);
354 }
355