1*37944Sbostic static char *sccsid = "@(#)ar11.c 4.6 (Berkeley) 05/11/89";
2952Sbill /* ar11 - archiver for PDP-11 formatted archives */
3952Sbill
4952Sbill #include <sys/types.h>
5*37944Sbostic #include <sys/signal.h>
6952Sbill #include <sys/stat.h>
7*37944Sbostic #include <stdio.h>
8*37944Sbostic #include "pathnames.h"
9*37944Sbostic
109570Spugs #define ARMAG ((short)0177545)
11952Sbill struct ar_hdr {
129570Spugs char ar_name[14];
139570Spugs short ar_sdate[2];
149570Spugs char ar_uid;
159570Spugs char ar_gid;
169570Spugs short ar_mode;
179570Spugs short ar_ssize[2];
18952Sbill };
199570Spugs long ar_date;
209570Spugs long ar_size;
219570Spugs
229570Spugs #ifdef vax
239570Spugs #define fixshort(s) (s)
249570Spugs #define mklong(sp) (((sp)[0] << 16) + (sp)[1])
259570Spugs #define unmklong(sp,l) { sp[0] = l >> 16; sp[1] = l & 0177777; }
269570Spugs #define fixhdr(hdr) (hdr)
279570Spugs #endif
2830068Ssam #if defined(mc68000) || defined(tahoe)
299570Spugs #define fixshort(s) ((short)(((s>>8)&0377)+((s&0377)<<8)))
309570Spugs #define mklong(sp) (((sp)[0] << 16) + (sp)[1])
319570Spugs #define unmklong(sp,l) { sp[0] = l >> 16; sp[1] = l & 0177777; }
329570Spugs #define fixhdr(hdr) swaphdr(hdr)
339570Spugs struct ar_hdr swaphdr();
349570Spugs #endif
359570Spugs
36952Sbill struct stat stbuf;
37952Sbill struct ar_hdr arbuf;
38952Sbill
39952Sbill #define SKIP 1
40952Sbill #define IODD 2
41952Sbill #define OODD 4
42952Sbill #define HEAD 8
43952Sbill
44952Sbill char *man = { "mrxtdp" };
45952Sbill char *opt = { "uvnbai" };
46952Sbill
47952Sbill int signum[] = {SIGHUP, SIGINT, SIGQUIT, 0};
48952Sbill int sigdone();
49952Sbill int rcmd();
50952Sbill int dcmd();
51952Sbill int xcmd();
52952Sbill int tcmd();
53952Sbill int pcmd();
54952Sbill int mcmd();
55952Sbill int (*comfun)();
56952Sbill char flg[26];
57952Sbill char **namv;
58952Sbill int namc;
59952Sbill char *arnam;
60952Sbill char *ponam;
61952Sbill char *tfnam;
62952Sbill char *tf1nam;
63952Sbill char *tf2nam;
64952Sbill char *file;
65952Sbill char name[16];
66952Sbill int af;
67952Sbill int tf;
68952Sbill int tf1;
69952Sbill int tf2;
70952Sbill int bastate;
71952Sbill char buf[512];
72952Sbill
73952Sbill char *trim();
74952Sbill char *mktemp();
75952Sbill char *ctime();
76952Sbill
main(argc,argv)77952Sbill main(argc, argv)
78952Sbill char *argv[];
79952Sbill {
80952Sbill register i;
81952Sbill register char *cp;
82952Sbill
83952Sbill for(i=0; signum[i]; i++)
84952Sbill if(signal(signum[i], SIG_IGN) != SIG_IGN)
85952Sbill signal(signum[i], sigdone);
86952Sbill if(argc < 3)
87952Sbill usage();
88952Sbill cp = argv[1];
89952Sbill for(cp = argv[1]; *cp; cp++)
90952Sbill switch(*cp) {
91952Sbill case 'c':
92952Sbill case 'v':
93952Sbill case 'u':
94952Sbill case 'n':
95952Sbill case 'a':
96952Sbill case 'b':
97952Sbill case 'i':
98952Sbill flg[*cp - 'a']++;
99952Sbill continue;
100952Sbill
101952Sbill case 'r':
102952Sbill setcom(rcmd);
103952Sbill continue;
104952Sbill
105952Sbill case 'd':
106952Sbill setcom(dcmd);
107952Sbill continue;
108952Sbill
109952Sbill case 'x':
110952Sbill setcom(xcmd);
111952Sbill continue;
112952Sbill
113952Sbill case 't':
114952Sbill setcom(tcmd);
115952Sbill continue;
116952Sbill
117952Sbill case 'p':
118952Sbill setcom(pcmd);
119952Sbill continue;
120952Sbill
121952Sbill case 'm':
122952Sbill setcom(mcmd);
123952Sbill continue;
124952Sbill
125952Sbill default:
126952Sbill fprintf(stderr, "ar11: bad option `%c'\n", *cp);
127952Sbill done(1);
128952Sbill }
129952Sbill if(flg['i'-'a'])
130952Sbill flg['b'-'a']++;
131952Sbill if(flg['a'-'a'] || flg['b'-'a']) {
132952Sbill bastate = 1;
133952Sbill ponam = trim(argv[2]);
134952Sbill argv++;
135952Sbill argc--;
136952Sbill if(argc < 3)
137952Sbill usage();
138952Sbill }
139952Sbill arnam = argv[2];
140952Sbill namv = argv+3;
141952Sbill namc = argc-3;
142952Sbill if(comfun == 0) {
143952Sbill if(flg['u'-'a'] == 0) {
144952Sbill fprintf(stderr, "ar11: one of [%s] must be specified\n", man);
145952Sbill done(1);
146952Sbill }
147952Sbill setcom(rcmd);
148952Sbill }
149952Sbill (*comfun)();
150952Sbill done(notfound());
151952Sbill }
152952Sbill
153952Sbill setcom(fun)
154952Sbill int (*fun)();
155952Sbill {
156952Sbill
157952Sbill if(comfun != 0) {
158952Sbill fprintf(stderr, "ar11: only one of [%s] allowed\n", man);
159952Sbill done(1);
160952Sbill }
161952Sbill comfun = fun;
162952Sbill }
163952Sbill
rcmd()164952Sbill rcmd()
165952Sbill {
166952Sbill register f;
167952Sbill
168952Sbill init();
169952Sbill if(getaf() && flg['c'-'a']==0) {
170952Sbill fprintf(stderr, "ar11: %s does not exist\n", arnam);
171952Sbill done(1);
172952Sbill }
173952Sbill while(!getdir()) {
174952Sbill bamatch();
175952Sbill if(namc == 0 || match()) {
176952Sbill f = stats();
177952Sbill if(f < 0) {
178952Sbill if(namc)
179952Sbill fprintf(stderr, "ar11: cannot open %s\n", file);
180952Sbill goto cp;
181952Sbill }
182952Sbill if(flg['u'-'a'])
183952Sbill if(stbuf.st_mtime <= ar_date) {
184952Sbill close(f);
185952Sbill goto cp;
186952Sbill }
187952Sbill mesg('r');
188952Sbill copyfil(af, -1, IODD+SKIP);
189952Sbill movefil(f);
190952Sbill continue;
191952Sbill }
192952Sbill cp:
193952Sbill mesg('c');
194952Sbill copyfil(af, tf, IODD+OODD+HEAD);
195952Sbill }
196952Sbill cleanup();
197952Sbill }
198952Sbill
dcmd()199952Sbill dcmd()
200952Sbill {
201952Sbill
202952Sbill init();
203952Sbill if(getaf())
204952Sbill noar();
205952Sbill while(!getdir()) {
206952Sbill if(match()) {
207952Sbill mesg('d');
208952Sbill copyfil(af, -1, IODD+SKIP);
209952Sbill continue;
210952Sbill }
211952Sbill mesg('c');
212952Sbill copyfil(af, tf, IODD+OODD+HEAD);
213952Sbill }
214952Sbill install();
215952Sbill }
216952Sbill
xcmd()217952Sbill xcmd()
218952Sbill {
219952Sbill register f;
220952Sbill
221952Sbill if(getaf())
222952Sbill noar();
223952Sbill while(!getdir()) {
224952Sbill if(namc == 0 || match()) {
225952Sbill f = creat(file, arbuf.ar_mode & 0777);
226952Sbill if(f < 0) {
227952Sbill fprintf(stderr, "ar11: %s cannot create\n", file);
228952Sbill goto sk;
229952Sbill }
230952Sbill mesg('x');
231952Sbill copyfil(af, f, IODD);
232952Sbill close(f);
233952Sbill continue;
234952Sbill }
235952Sbill sk:
236952Sbill mesg('c');
237952Sbill copyfil(af, -1, IODD+SKIP);
238952Sbill }
239952Sbill }
240952Sbill
pcmd()241952Sbill pcmd()
242952Sbill {
243952Sbill
244952Sbill if(getaf())
245952Sbill noar();
246952Sbill while(!getdir()) {
247952Sbill if(namc == 0 || match()) {
248952Sbill if(flg['v'-'a']) {
249952Sbill printf("\n<%s>\n\n", file);
250952Sbill fflush(stdout);
251952Sbill }
252952Sbill copyfil(af, 1, IODD);
253952Sbill continue;
254952Sbill }
255952Sbill copyfil(af, -1, IODD+SKIP);
256952Sbill }
257952Sbill }
258952Sbill
mcmd()259952Sbill mcmd()
260952Sbill {
261*37944Sbostic static char name2[] = _PATH_TMP2;
262952Sbill
263952Sbill init();
264952Sbill if(getaf())
265952Sbill noar();
26635259Sbostic tf2nam = mktemp(name2);
267952Sbill close(creat(tf2nam, 0600));
268952Sbill tf2 = open(tf2nam, 2);
269952Sbill if(tf2 < 0) {
270952Sbill fprintf(stderr, "ar11: cannot create third temp\n");
271952Sbill done(1);
272952Sbill }
273952Sbill while(!getdir()) {
274952Sbill bamatch();
275952Sbill if(match()) {
276952Sbill mesg('m');
277952Sbill copyfil(af, tf2, IODD+OODD+HEAD);
278952Sbill continue;
279952Sbill }
280952Sbill mesg('c');
281952Sbill copyfil(af, tf, IODD+OODD+HEAD);
282952Sbill }
283952Sbill install();
284952Sbill }
285952Sbill
tcmd()286952Sbill tcmd()
287952Sbill {
288952Sbill
289952Sbill if(getaf())
290952Sbill noar();
291952Sbill while(!getdir()) {
292952Sbill if(namc == 0 || match()) {
293952Sbill if(flg['v'-'a'])
294952Sbill longt();
295952Sbill printf("%s\n", trim(file));
296952Sbill }
297952Sbill copyfil(af, -1, IODD+SKIP);
298952Sbill }
299952Sbill }
300952Sbill
init()301952Sbill init()
302952Sbill {
303*37944Sbostic static char name0[] = _PATH_TMP0;
3049570Spugs static short mbuf = fixshort(ARMAG);
305952Sbill
30635259Sbostic tfnam = mktemp(name0);
307952Sbill close(creat(tfnam, 0600));
308952Sbill tf = open(tfnam, 2);
309952Sbill if(tf < 0) {
310952Sbill fprintf(stderr, "ar11: cannot create temp file\n");
311952Sbill done(1);
312952Sbill }
313952Sbill if (write(tf, (char *)&mbuf, sizeof(short)) != sizeof(short))
314952Sbill wrerr();
315952Sbill }
316952Sbill
getaf()317952Sbill getaf()
318952Sbill {
319952Sbill short mbuf;
320952Sbill
321952Sbill af = open(arnam, 0);
322952Sbill if(af < 0)
323952Sbill return(1);
3249570Spugs if (read(af, (char *)&mbuf, sizeof(short)) != sizeof(short) ||
3259570Spugs mbuf != fixshort(ARMAG)) {
326952Sbill fprintf(stderr, "ar11: %s not in PDP-11 archive format\n", arnam);
327952Sbill done(1);
328952Sbill }
329952Sbill return(0);
330952Sbill }
331952Sbill
usage()332952Sbill usage()
333952Sbill {
334952Sbill printf("usage: ar11 [%s][%s] archive files ...\n", opt, man);
335952Sbill done(1);
336952Sbill }
337952Sbill
noar()338952Sbill noar()
339952Sbill {
340952Sbill
341952Sbill fprintf(stderr, "ar11: %s does not exist\n", arnam);
342952Sbill done(1);
343952Sbill }
344952Sbill
sigdone()345952Sbill sigdone()
346952Sbill {
347952Sbill done(100);
348952Sbill }
349952Sbill
done(c)350952Sbill done(c)
351952Sbill {
352952Sbill
353952Sbill if(tfnam)
354952Sbill unlink(tfnam);
355952Sbill if(tf1nam)
356952Sbill unlink(tf1nam);
357952Sbill if(tf2nam)
358952Sbill unlink(tf2nam);
359952Sbill exit(c);
360952Sbill }
361952Sbill
notfound()362952Sbill notfound()
363952Sbill {
364952Sbill register i, n;
365952Sbill
366952Sbill n = 0;
367952Sbill for(i=0; i<namc; i++)
368952Sbill if(namv[i]) {
369952Sbill fprintf(stderr, "ar11: %s not found\n", namv[i]);
370952Sbill n++;
371952Sbill }
372952Sbill return(n);
373952Sbill }
374952Sbill
cleanup()375952Sbill cleanup()
376952Sbill {
377952Sbill register i, f;
378952Sbill
379952Sbill for(i=0; i<namc; i++) {
380952Sbill file = namv[i];
381952Sbill if(file == 0)
382952Sbill continue;
383952Sbill namv[i] = 0;
384952Sbill mesg('a');
385952Sbill f = stats();
386952Sbill if(f < 0) {
387952Sbill fprintf(stderr, "ar11: %s cannot open\n", file);
388952Sbill continue;
389952Sbill }
390952Sbill movefil(f);
391952Sbill }
392952Sbill install();
393952Sbill }
394952Sbill
install()395952Sbill install()
396952Sbill {
397952Sbill register i;
398952Sbill
399952Sbill for(i=0; signum[i]; i++)
400952Sbill signal(signum[i], (int (*)())1);
401952Sbill close(af);
402952Sbill af = creat(arnam, 0666);
403952Sbill if(af < 0) {
404952Sbill fprintf(stderr, "ar11: cannot create %s\n", arnam);
405952Sbill done(1);
406952Sbill }
407952Sbill lseek(tf, 0l, 0);
408952Sbill while((i = read(tf, buf, 512)) > 0)
409952Sbill if (write(af, buf, i) != i)
410952Sbill wrerr();
411952Sbill if(tf2nam) {
412952Sbill lseek(tf2, 0l, 0);
413952Sbill while((i = read(tf2, buf, 512)) > 0)
414952Sbill if (write(af, buf, i) != i)
415952Sbill wrerr();
416952Sbill }
417952Sbill if(tf1nam) {
418952Sbill lseek(tf1, 0l, 0);
419952Sbill while((i = read(tf1, buf, 512)) > 0)
420952Sbill if (write(af, buf, i) != i)
421952Sbill wrerr();
422952Sbill }
423952Sbill }
424952Sbill
425952Sbill /*
426952Sbill * insert the file 'file'
427952Sbill * into the temporary file
428952Sbill */
movefil(f)429952Sbill movefil(f)
430952Sbill {
431952Sbill register char *cp;
432952Sbill register i;
433952Sbill
434952Sbill cp = trim(file);
435952Sbill for(i=0; i<14; i++)
436952Sbill if(arbuf.ar_name[i] = *cp)
437952Sbill cp++;
4389570Spugs ar_size = stbuf.st_size;
4399570Spugs ar_date = stbuf.st_mtime;
4409570Spugs unmklong(arbuf.ar_ssize, ar_size);
4419570Spugs unmklong(arbuf.ar_sdate, ar_date);
442952Sbill arbuf.ar_uid = stbuf.st_uid;
443952Sbill arbuf.ar_gid = stbuf.st_gid;
444952Sbill arbuf.ar_mode = stbuf.st_mode;
445952Sbill copyfil(f, tf, OODD+HEAD);
446952Sbill close(f);
447952Sbill }
448952Sbill
stats()449952Sbill stats()
450952Sbill {
451952Sbill register f;
452952Sbill
453952Sbill f = open(file, 0);
454952Sbill if(f < 0)
455952Sbill return(f);
456952Sbill if(fstat(f, &stbuf) < 0) {
457952Sbill close(f);
458952Sbill return(-1);
459952Sbill }
460952Sbill return(f);
461952Sbill }
462952Sbill
463952Sbill /*
464952Sbill * copy next file
465952Sbill * size given in arbuf
466952Sbill */
copyfil(fi,fo,flag)467952Sbill copyfil(fi, fo, flag)
468952Sbill {
469952Sbill register i, o;
470952Sbill int pe;
471952Sbill
4729570Spugs if(flag & HEAD) {
4739570Spugs struct ar_hdr tmpbuf;
4749570Spugs
4759570Spugs tmpbuf = fixhdr(arbuf);
4769570Spugs if (write(fo, (char *)&tmpbuf, sizeof arbuf) != sizeof arbuf)
477952Sbill wrerr();
4789570Spugs }
479952Sbill pe = 0;
480952Sbill while(ar_size > 0) {
481952Sbill i = o = 512;
482952Sbill if(ar_size < i) {
483952Sbill i = o = ar_size;
484952Sbill if(i&1) {
485952Sbill if(flag & IODD)
486952Sbill i++;
487952Sbill if(flag & OODD)
488952Sbill o++;
489952Sbill }
490952Sbill }
491952Sbill if(read(fi, buf, i) != i)
492952Sbill pe++;
493952Sbill if((flag & SKIP) == 0)
494952Sbill if (write(fo, buf, o) != o)
495952Sbill wrerr();
496952Sbill ar_size -= 512;
497952Sbill }
498952Sbill if(pe)
499952Sbill phserr();
500952Sbill }
501952Sbill
getdir()502952Sbill getdir()
503952Sbill {
504952Sbill register i;
505952Sbill
506952Sbill i = read(af, (char *)&arbuf, sizeof arbuf);
507952Sbill if(i != sizeof arbuf) {
508952Sbill if(tf1nam) {
509952Sbill i = tf;
510952Sbill tf = tf1;
511952Sbill tf1 = i;
512952Sbill }
513952Sbill return(1);
514952Sbill }
5159570Spugs arbuf = fixhdr(arbuf);
516952Sbill for(i=0; i<14; i++)
517952Sbill name[i] = arbuf.ar_name[i];
518952Sbill file = name;
5199570Spugs ar_date = mklong(arbuf.ar_sdate);
5209570Spugs ar_size = mklong(arbuf.ar_ssize);
521952Sbill return(0);
522952Sbill }
523952Sbill
match()524952Sbill match()
525952Sbill {
526952Sbill register i;
527952Sbill
528952Sbill for(i=0; i<namc; i++) {
529952Sbill if(namv[i] == 0)
530952Sbill continue;
531952Sbill if(strcmp(trim(namv[i]), file) == 0) {
532952Sbill file = namv[i];
533952Sbill namv[i] = 0;
534952Sbill return(1);
535952Sbill }
536952Sbill }
537952Sbill return(0);
538952Sbill }
539952Sbill
bamatch()540952Sbill bamatch()
541952Sbill {
542*37944Sbostic static char name1[] = _PATH_TMP1;
543952Sbill register f;
544952Sbill
545952Sbill switch(bastate) {
546952Sbill
547952Sbill case 1:
548952Sbill if(strcmp(file, ponam) != 0)
549952Sbill return;
550952Sbill bastate = 2;
551952Sbill if(flg['a'-'a'])
552952Sbill return;
553952Sbill
554952Sbill case 2:
555952Sbill bastate = 0;
55635259Sbostic tf1nam = mktemp(name1);
557952Sbill close(creat(tf1nam, 0600));
558952Sbill f = open(tf1nam, 2);
559952Sbill if(f < 0) {
560952Sbill fprintf(stderr, "ar11: cannot create second temp\n");
561952Sbill return;
562952Sbill }
563952Sbill tf1 = tf;
564952Sbill tf = f;
565952Sbill }
566952Sbill }
567952Sbill
phserr()568952Sbill phserr()
569952Sbill {
570952Sbill
571952Sbill fprintf(stderr, "ar11: phase error on %s\n", file);
572952Sbill }
573952Sbill
mesg(c)574952Sbill mesg(c)
575952Sbill {
576952Sbill
577952Sbill if(flg['v'-'a'])
578952Sbill if(c != 'c' || flg['v'-'a'] > 1)
579952Sbill printf("%c - %s\n", c, file);
580952Sbill }
581952Sbill
582952Sbill char *
trim(s)583952Sbill trim(s)
584952Sbill char *s;
585952Sbill {
586952Sbill register char *p1, *p2;
587952Sbill
588952Sbill for(p1 = s; *p1; p1++)
589952Sbill ;
590952Sbill while(p1 > s) {
591952Sbill if(*--p1 != '/')
592952Sbill break;
593952Sbill *p1 = 0;
594952Sbill }
595952Sbill p2 = s;
596952Sbill for(p1 = s; *p1; p1++)
597952Sbill if(*p1 == '/')
598952Sbill p2 = p1+1;
599952Sbill return(p2);
600952Sbill }
601952Sbill
602952Sbill #define IFMT 060000
603952Sbill #define ISARG 01000
604952Sbill #define LARGE 010000
605952Sbill #define SUID 04000
606952Sbill #define SGID 02000
607952Sbill #define ROWN 0400
608952Sbill #define WOWN 0200
609952Sbill #define XOWN 0100
610952Sbill #define RGRP 040
611952Sbill #define WGRP 020
612952Sbill #define XGRP 010
613952Sbill #define ROTH 04
614952Sbill #define WOTH 02
615952Sbill #define XOTH 01
616952Sbill #define STXT 01000
617952Sbill
longt()618952Sbill longt()
619952Sbill {
620952Sbill register char *cp;
621952Sbill
622952Sbill pmode();
623952Sbill printf("%3d/%1d", arbuf.ar_uid, arbuf.ar_gid);
624952Sbill printf("%7D", ar_size);
625952Sbill cp = ctime(&ar_date);
626952Sbill printf(" %-12.12s %-4.4s ", cp+4, cp+20);
627952Sbill }
628952Sbill
629952Sbill int m1[] = { 1, ROWN, 'r', '-' };
630952Sbill int m2[] = { 1, WOWN, 'w', '-' };
631952Sbill int m3[] = { 2, SUID, 's', XOWN, 'x', '-' };
632952Sbill int m4[] = { 1, RGRP, 'r', '-' };
633952Sbill int m5[] = { 1, WGRP, 'w', '-' };
634952Sbill int m6[] = { 2, SGID, 's', XGRP, 'x', '-' };
635952Sbill int m7[] = { 1, ROTH, 'r', '-' };
636952Sbill int m8[] = { 1, WOTH, 'w', '-' };
637952Sbill int m9[] = { 2, STXT, 't', XOTH, 'x', '-' };
638952Sbill
639952Sbill int *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9};
640952Sbill
pmode()641952Sbill pmode()
642952Sbill {
643952Sbill register int **mp;
644952Sbill
645952Sbill for (mp = &m[0]; mp < &m[9];)
646952Sbill select(*mp++);
647952Sbill }
648952Sbill
select(pairp)649952Sbill select(pairp)
650952Sbill int *pairp;
651952Sbill {
652952Sbill register int n, *ap;
653952Sbill
654952Sbill ap = pairp;
655952Sbill n = *ap++;
656952Sbill while (--n>=0 && (arbuf.ar_mode&*ap++)==0)
657952Sbill ap++;
658952Sbill putchar(*ap);
659952Sbill }
660952Sbill
wrerr()661952Sbill wrerr()
662952Sbill {
663952Sbill perror("ar write error");
664952Sbill done(1);
665952Sbill }
666952Sbill
66730068Ssam #if defined(mc68000) || defined(tahoe)
6689570Spugs struct ar_hdr
swaphdr(hdr)6699570Spugs swaphdr(hdr)
6709570Spugs struct ar_hdr hdr;
671952Sbill {
6729570Spugs hdr.ar_sdate[0] = fixshort(hdr.ar_sdate[0]);
6739570Spugs hdr.ar_sdate[1] = fixshort(hdr.ar_sdate[1]);
6749570Spugs hdr.ar_ssize[0] = fixshort(hdr.ar_ssize[0]);
6759570Spugs hdr.ar_ssize[1] = fixshort(hdr.ar_ssize[1]);
6769570Spugs hdr.ar_mode = fixshort(hdr.ar_mode);
6779570Spugs return (hdr);
678952Sbill }
6799570Spugs #endif
680