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