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
main(argc,argv)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
rcmd()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
dcmd()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
xcmd()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
pcmd()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
mcmd()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
tcmd()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
init()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
getaf()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
usage()332 usage()
333 {
334 printf("usage: ar11 [%s][%s] archive files ...\n", opt, man);
335 done(1);
336 }
337
noar()338 noar()
339 {
340
341 fprintf(stderr, "ar11: %s does not exist\n", arnam);
342 done(1);
343 }
344
sigdone()345 sigdone()
346 {
347 done(100);
348 }
349
done(c)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
notfound()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
cleanup()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
install()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 */
movefil(f)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
stats()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 */
copyfil(fi,fo,flag)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
getdir()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
match()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
bamatch()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
phserr()568 phserr()
569 {
570
571 fprintf(stderr, "ar11: phase error on %s\n", file);
572 }
573
mesg(c)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 *
trim(s)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
longt()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
pmode()641 pmode()
642 {
643 register int **mp;
644
645 for (mp = &m[0]; mp < &m[9];)
646 select(*mp++);
647 }
648
select(pairp)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
wrerr()661 wrerr()
662 {
663 perror("ar write error");
664 done(1);
665 }
666
667 #if defined(mc68000) || defined(tahoe)
668 struct ar_hdr
swaphdr(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