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