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