xref: /original-bsd/old/ar11/ar11.c (revision 8431ec24)
1 static char *sccsid = "@(#)ar11.c	4.6 (Berkeley) 05/11/89";
2 /* ar11 - archiver for PDP-11 formatted archives */
3 
4 #include <sys/types.h>
5 #include <sys/signal.h>
6 #include <sys/stat.h>
7 #include <stdio.h>
8 #include "pathnames.h"
9 
10 #define	ARMAG ((short)0177545)
11 struct ar_hdr {
12 	char	ar_name[14];
13 	short	ar_sdate[2];
14 	char	ar_uid;
15 	char	ar_gid;
16 	short	ar_mode;
17 	short	ar_ssize[2];
18 };
19 long	ar_date;
20 long	ar_size;
21 
22 #ifdef vax
23 #define	fixshort(s)	(s)
24 #define	mklong(sp)	(((sp)[0] << 16) + (sp)[1])
25 #define unmklong(sp,l)	{ sp[0] = l >> 16; sp[1] = l & 0177777; }
26 #define fixhdr(hdr)	(hdr)
27 #endif
28 #if defined(mc68000) || defined(tahoe)
29 #define	fixshort(s)	((short)(((s>>8)&0377)+((s&0377)<<8)))
30 #define	mklong(sp)	(((sp)[0] << 16) + (sp)[1])
31 #define unmklong(sp,l)	{ sp[0] = l >> 16; sp[1] = l & 0177777; }
32 #define fixhdr(hdr)	swaphdr(hdr)
33 struct	ar_hdr swaphdr();
34 #endif
35 
36 struct	stat	stbuf;
37 struct	ar_hdr	arbuf;
38 
39 #define	SKIP	1
40 #define	IODD	2
41 #define	OODD	4
42 #define	HEAD	8
43 
44 char	*man	= { "mrxtdp" };
45 char	*opt	= { "uvnbai" };
46 
47 int	signum[] = {SIGHUP, SIGINT, SIGQUIT, 0};
48 int	sigdone();
49 int	rcmd();
50 int	dcmd();
51 int	xcmd();
52 int	tcmd();
53 int	pcmd();
54 int	mcmd();
55 int	(*comfun)();
56 char	flg[26];
57 char	**namv;
58 int	namc;
59 char	*arnam;
60 char	*ponam;
61 char	*tfnam;
62 char	*tf1nam;
63 char	*tf2nam;
64 char	*file;
65 char	name[16];
66 int	af;
67 int	tf;
68 int	tf1;
69 int	tf2;
70 int	bastate;
71 char	buf[512];
72 
73 char	*trim();
74 char	*mktemp();
75 char	*ctime();
76 
77 main(argc, argv)
78 char *argv[];
79 {
80 	register i;
81 	register char *cp;
82 
83 	for(i=0; signum[i]; i++)
84 		if(signal(signum[i], SIG_IGN) != SIG_IGN)
85 			signal(signum[i], sigdone);
86 	if(argc < 3)
87 		usage();
88 	cp = argv[1];
89 	for(cp = argv[1]; *cp; cp++)
90 	switch(*cp) {
91 	case 'c':
92 	case 'v':
93 	case 'u':
94 	case 'n':
95 	case 'a':
96 	case 'b':
97 	case 'i':
98 		flg[*cp - 'a']++;
99 		continue;
100 
101 	case 'r':
102 		setcom(rcmd);
103 		continue;
104 
105 	case 'd':
106 		setcom(dcmd);
107 		continue;
108 
109 	case 'x':
110 		setcom(xcmd);
111 		continue;
112 
113 	case 't':
114 		setcom(tcmd);
115 		continue;
116 
117 	case 'p':
118 		setcom(pcmd);
119 		continue;
120 
121 	case 'm':
122 		setcom(mcmd);
123 		continue;
124 
125 	default:
126 		fprintf(stderr, "ar11: bad option `%c'\n", *cp);
127 		done(1);
128 	}
129 	if(flg['i'-'a'])
130 		flg['b'-'a']++;
131 	if(flg['a'-'a'] || flg['b'-'a']) {
132 		bastate = 1;
133 		ponam = trim(argv[2]);
134 		argv++;
135 		argc--;
136 		if(argc < 3)
137 			usage();
138 	}
139 	arnam = argv[2];
140 	namv = argv+3;
141 	namc = argc-3;
142 	if(comfun == 0) {
143 		if(flg['u'-'a'] == 0) {
144 			fprintf(stderr, "ar11: one of [%s] must be specified\n", man);
145 			done(1);
146 		}
147 		setcom(rcmd);
148 	}
149 	(*comfun)();
150 	done(notfound());
151 }
152 
153 setcom(fun)
154 int (*fun)();
155 {
156 
157 	if(comfun != 0) {
158 		fprintf(stderr, "ar11: only one of [%s] allowed\n", man);
159 		done(1);
160 	}
161 	comfun = fun;
162 }
163 
164 rcmd()
165 {
166 	register f;
167 
168 	init();
169 	if(getaf() && flg['c'-'a']==0) {
170 		fprintf(stderr, "ar11: %s does not exist\n", arnam);
171 		done(1);
172 	}
173 	while(!getdir()) {
174 		bamatch();
175 		if(namc == 0 || match()) {
176 			f = stats();
177 			if(f < 0) {
178 				if(namc)
179 					fprintf(stderr, "ar11: cannot open %s\n", file);
180 				goto cp;
181 			}
182 			if(flg['u'-'a'])
183 				if(stbuf.st_mtime <= ar_date) {
184 					close(f);
185 					goto cp;
186 				}
187 			mesg('r');
188 			copyfil(af, -1, IODD+SKIP);
189 			movefil(f);
190 			continue;
191 		}
192 	cp:
193 		mesg('c');
194 		copyfil(af, tf, IODD+OODD+HEAD);
195 	}
196 	cleanup();
197 }
198 
199 dcmd()
200 {
201 
202 	init();
203 	if(getaf())
204 		noar();
205 	while(!getdir()) {
206 		if(match()) {
207 			mesg('d');
208 			copyfil(af, -1, IODD+SKIP);
209 			continue;
210 		}
211 		mesg('c');
212 		copyfil(af, tf, IODD+OODD+HEAD);
213 	}
214 	install();
215 }
216 
217 xcmd()
218 {
219 	register f;
220 
221 	if(getaf())
222 		noar();
223 	while(!getdir()) {
224 		if(namc == 0 || match()) {
225 			f = creat(file, arbuf.ar_mode & 0777);
226 			if(f < 0) {
227 				fprintf(stderr, "ar11: %s cannot create\n", file);
228 				goto sk;
229 			}
230 			mesg('x');
231 			copyfil(af, f, IODD);
232 			close(f);
233 			continue;
234 		}
235 	sk:
236 		mesg('c');
237 		copyfil(af, -1, IODD+SKIP);
238 	}
239 }
240 
241 pcmd()
242 {
243 
244 	if(getaf())
245 		noar();
246 	while(!getdir()) {
247 		if(namc == 0 || match()) {
248 			if(flg['v'-'a']) {
249 				printf("\n<%s>\n\n", file);
250 				fflush(stdout);
251 			}
252 			copyfil(af, 1, IODD);
253 			continue;
254 		}
255 		copyfil(af, -1, IODD+SKIP);
256 	}
257 }
258 
259 mcmd()
260 {
261 	static char name2[] = _PATH_TMP2;
262 
263 	init();
264 	if(getaf())
265 		noar();
266 	tf2nam = mktemp(name2);
267 	close(creat(tf2nam, 0600));
268 	tf2 = open(tf2nam, 2);
269 	if(tf2 < 0) {
270 		fprintf(stderr, "ar11: cannot create third temp\n");
271 		done(1);
272 	}
273 	while(!getdir()) {
274 		bamatch();
275 		if(match()) {
276 			mesg('m');
277 			copyfil(af, tf2, IODD+OODD+HEAD);
278 			continue;
279 		}
280 		mesg('c');
281 		copyfil(af, tf, IODD+OODD+HEAD);
282 	}
283 	install();
284 }
285 
286 tcmd()
287 {
288 
289 	if(getaf())
290 		noar();
291 	while(!getdir()) {
292 		if(namc == 0 || match()) {
293 			if(flg['v'-'a'])
294 				longt();
295 			printf("%s\n", trim(file));
296 		}
297 		copyfil(af, -1, IODD+SKIP);
298 	}
299 }
300 
301 init()
302 {
303 	static char name0[] = _PATH_TMP0;
304 	static short mbuf = fixshort(ARMAG);
305 
306 	tfnam = mktemp(name0);
307 	close(creat(tfnam, 0600));
308 	tf = open(tfnam, 2);
309 	if(tf < 0) {
310 		fprintf(stderr, "ar11: cannot create temp file\n");
311 		done(1);
312 	}
313 	if (write(tf, (char *)&mbuf, sizeof(short)) != sizeof(short))
314 		wrerr();
315 }
316 
317 getaf()
318 {
319 	short mbuf;
320 
321 	af = open(arnam, 0);
322 	if(af < 0)
323 		return(1);
324 	if (read(af, (char *)&mbuf, sizeof(short)) != sizeof(short) ||
325 	    mbuf != fixshort(ARMAG)) {
326 		fprintf(stderr, "ar11: %s not in PDP-11 archive format\n", arnam);
327 		done(1);
328 	}
329 	return(0);
330 }
331 
332 usage()
333 {
334 	printf("usage: ar11 [%s][%s] archive files ...\n", opt, man);
335 	done(1);
336 }
337 
338 noar()
339 {
340 
341 	fprintf(stderr, "ar11: %s does not exist\n", arnam);
342 	done(1);
343 }
344 
345 sigdone()
346 {
347 	done(100);
348 }
349 
350 done(c)
351 {
352 
353 	if(tfnam)
354 		unlink(tfnam);
355 	if(tf1nam)
356 		unlink(tf1nam);
357 	if(tf2nam)
358 		unlink(tf2nam);
359 	exit(c);
360 }
361 
362 notfound()
363 {
364 	register i, n;
365 
366 	n = 0;
367 	for(i=0; i<namc; i++)
368 		if(namv[i]) {
369 			fprintf(stderr, "ar11: %s not found\n", namv[i]);
370 			n++;
371 		}
372 	return(n);
373 }
374 
375 cleanup()
376 {
377 	register i, f;
378 
379 	for(i=0; i<namc; i++) {
380 		file = namv[i];
381 		if(file == 0)
382 			continue;
383 		namv[i] = 0;
384 		mesg('a');
385 		f = stats();
386 		if(f < 0) {
387 			fprintf(stderr, "ar11: %s cannot open\n", file);
388 			continue;
389 		}
390 		movefil(f);
391 	}
392 	install();
393 }
394 
395 install()
396 {
397 	register i;
398 
399 	for(i=0; signum[i]; i++)
400 		signal(signum[i], (int (*)())1);
401 	close(af);
402 	af = creat(arnam, 0666);
403 	if(af < 0) {
404 		fprintf(stderr, "ar11: cannot create %s\n", arnam);
405 		done(1);
406 	}
407 	lseek(tf, 0l, 0);
408 	while((i = read(tf, buf, 512)) > 0)
409 		if (write(af, buf, i) != i)
410 			wrerr();
411 	if(tf2nam) {
412 		lseek(tf2, 0l, 0);
413 		while((i = read(tf2, buf, 512)) > 0)
414 			if (write(af, buf, i) != i)
415 				wrerr();
416 	}
417 	if(tf1nam) {
418 		lseek(tf1, 0l, 0);
419 		while((i = read(tf1, buf, 512)) > 0)
420 			if (write(af, buf, i) != i)
421 				wrerr();
422 	}
423 }
424 
425 /*
426  * insert the file 'file'
427  * into the temporary file
428  */
429 movefil(f)
430 {
431 	register char *cp;
432 	register i;
433 
434 	cp = trim(file);
435 	for(i=0; i<14; i++)
436 		if(arbuf.ar_name[i] = *cp)
437 			cp++;
438 	ar_size =  stbuf.st_size;
439 	ar_date = stbuf.st_mtime;
440 	unmklong(arbuf.ar_ssize, ar_size);
441 	unmklong(arbuf.ar_sdate, ar_date);
442 	arbuf.ar_uid = stbuf.st_uid;
443 	arbuf.ar_gid = stbuf.st_gid;
444 	arbuf.ar_mode = stbuf.st_mode;
445 	copyfil(f, tf, OODD+HEAD);
446 	close(f);
447 }
448 
449 stats()
450 {
451 	register f;
452 
453 	f = open(file, 0);
454 	if(f < 0)
455 		return(f);
456 	if(fstat(f, &stbuf) < 0) {
457 		close(f);
458 		return(-1);
459 	}
460 	return(f);
461 }
462 
463 /*
464  * copy next file
465  * size given in arbuf
466  */
467 copyfil(fi, fo, flag)
468 {
469 	register i, o;
470 	int pe;
471 
472 	if(flag & HEAD) {
473 		struct ar_hdr tmpbuf;
474 
475 		tmpbuf = fixhdr(arbuf);
476 		if (write(fo, (char *)&tmpbuf, sizeof arbuf) != sizeof arbuf)
477 			wrerr();
478 	}
479 	pe = 0;
480 	while(ar_size > 0) {
481 		i = o = 512;
482 		if(ar_size < i) {
483 			i = o = ar_size;
484 			if(i&1) {
485 				if(flag & IODD)
486 					i++;
487 				if(flag & OODD)
488 					o++;
489 			}
490 		}
491 		if(read(fi, buf, i) != i)
492 			pe++;
493 		if((flag & SKIP) == 0)
494 			if (write(fo, buf, o) != o)
495 				wrerr();
496 		ar_size -= 512;
497 	}
498 	if(pe)
499 		phserr();
500 }
501 
502 getdir()
503 {
504 	register i;
505 
506 	i = read(af, (char *)&arbuf, sizeof arbuf);
507 	if(i != sizeof arbuf) {
508 		if(tf1nam) {
509 			i = tf;
510 			tf = tf1;
511 			tf1 = i;
512 		}
513 		return(1);
514 	}
515 	arbuf = fixhdr(arbuf);
516 	for(i=0; i<14; i++)
517 		name[i] = arbuf.ar_name[i];
518 	file = name;
519 	ar_date = mklong(arbuf.ar_sdate);
520 	ar_size = mklong(arbuf.ar_ssize);
521 	return(0);
522 }
523 
524 match()
525 {
526 	register i;
527 
528 	for(i=0; i<namc; i++) {
529 		if(namv[i] == 0)
530 			continue;
531 		if(strcmp(trim(namv[i]), file) == 0) {
532 			file = namv[i];
533 			namv[i] = 0;
534 			return(1);
535 		}
536 	}
537 	return(0);
538 }
539 
540 bamatch()
541 {
542 	static char name1[] = _PATH_TMP1;
543 	register f;
544 
545 	switch(bastate) {
546 
547 	case 1:
548 		if(strcmp(file, ponam) != 0)
549 			return;
550 		bastate = 2;
551 		if(flg['a'-'a'])
552 			return;
553 
554 	case 2:
555 		bastate = 0;
556 		tf1nam = mktemp(name1);
557 		close(creat(tf1nam, 0600));
558 		f = open(tf1nam, 2);
559 		if(f < 0) {
560 			fprintf(stderr, "ar11: cannot create second temp\n");
561 			return;
562 		}
563 		tf1 = tf;
564 		tf = f;
565 	}
566 }
567 
568 phserr()
569 {
570 
571 	fprintf(stderr, "ar11: phase error on %s\n", file);
572 }
573 
574 mesg(c)
575 {
576 
577 	if(flg['v'-'a'])
578 		if(c != 'c' || flg['v'-'a'] > 1)
579 			printf("%c - %s\n", c, file);
580 }
581 
582 char *
583 trim(s)
584 char *s;
585 {
586 	register char *p1, *p2;
587 
588 	for(p1 = s; *p1; p1++)
589 		;
590 	while(p1 > s) {
591 		if(*--p1 != '/')
592 			break;
593 		*p1 = 0;
594 	}
595 	p2 = s;
596 	for(p1 = s; *p1; p1++)
597 		if(*p1 == '/')
598 			p2 = p1+1;
599 	return(p2);
600 }
601 
602 #define	IFMT	060000
603 #define	ISARG	01000
604 #define	LARGE	010000
605 #define	SUID	04000
606 #define	SGID	02000
607 #define	ROWN	0400
608 #define	WOWN	0200
609 #define	XOWN	0100
610 #define	RGRP	040
611 #define	WGRP	020
612 #define	XGRP	010
613 #define	ROTH	04
614 #define	WOTH	02
615 #define	XOTH	01
616 #define	STXT	01000
617 
618 longt()
619 {
620 	register char *cp;
621 
622 	pmode();
623 	printf("%3d/%1d", arbuf.ar_uid, arbuf.ar_gid);
624 	printf("%7D", ar_size);
625 	cp = ctime(&ar_date);
626 	printf(" %-12.12s %-4.4s ", cp+4, cp+20);
627 }
628 
629 int	m1[] = { 1, ROWN, 'r', '-' };
630 int	m2[] = { 1, WOWN, 'w', '-' };
631 int	m3[] = { 2, SUID, 's', XOWN, 'x', '-' };
632 int	m4[] = { 1, RGRP, 'r', '-' };
633 int	m5[] = { 1, WGRP, 'w', '-' };
634 int	m6[] = { 2, SGID, 's', XGRP, 'x', '-' };
635 int	m7[] = { 1, ROTH, 'r', '-' };
636 int	m8[] = { 1, WOTH, 'w', '-' };
637 int	m9[] = { 2, STXT, 't', XOTH, 'x', '-' };
638 
639 int	*m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9};
640 
641 pmode()
642 {
643 	register int **mp;
644 
645 	for (mp = &m[0]; mp < &m[9];)
646 		select(*mp++);
647 }
648 
649 select(pairp)
650 int *pairp;
651 {
652 	register int n, *ap;
653 
654 	ap = pairp;
655 	n = *ap++;
656 	while (--n>=0 && (arbuf.ar_mode&*ap++)==0)
657 		ap++;
658 	putchar(*ap);
659 }
660 
661 wrerr()
662 {
663 	perror("ar write error");
664 	done(1);
665 }
666 
667 #if defined(mc68000) || defined(tahoe)
668 struct ar_hdr
669 swaphdr(hdr)
670 	struct ar_hdr hdr;
671 {
672 	hdr.ar_sdate[0] = fixshort(hdr.ar_sdate[0]);
673 	hdr.ar_sdate[1] = fixshort(hdr.ar_sdate[1]);
674 	hdr.ar_ssize[0] = fixshort(hdr.ar_ssize[0]);
675 	hdr.ar_ssize[1] = fixshort(hdr.ar_ssize[1]);
676 	hdr.ar_mode = fixshort(hdr.ar_mode);
677 	return (hdr);
678 }
679 #endif
680