1: static char *sccsid = "@(#)ar11.c 4.3 (Berkeley) 12/6/82"; 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 ((short)0177545) 9: struct ar_hdr { 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]; 16: }; 17: long ar_date; 18: long 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) 31: struct ar_hdr swaphdr(); 32: #endif 33: 34: struct stat stbuf; 35: struct ar_hdr arbuf; 36: 37: #define SKIP 1 38: #define IODD 2 39: #define OODD 4 40: #define HEAD 8 41: 42: char *man = { "mrxtdp" }; 43: char *opt = { "uvnbai" }; 44: 45: int signum[] = {SIGHUP, SIGINT, SIGQUIT, 0}; 46: int sigdone(); 47: int rcmd(); 48: int dcmd(); 49: int xcmd(); 50: int tcmd(); 51: int pcmd(); 52: int mcmd(); 53: int (*comfun)(); 54: char flg[26]; 55: char **namv; 56: int namc; 57: char *arnam; 58: char *ponam; 59: char *tfnam; 60: char *tf1nam; 61: char *tf2nam; 62: char *file; 63: char name[16]; 64: int af; 65: int tf; 66: int tf1; 67: int tf2; 68: int bastate; 69: char buf[512]; 70: 71: char *trim(); 72: char *mktemp(); 73: char *ctime(); 74: 75: main(argc, argv) 76: char *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: 151: setcom(fun) 152: int (*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: 162: rcmd() 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: 197: dcmd() 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: 215: xcmd() 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: 239: pcmd() 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: 257: mcmd() 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: 283: tcmd() 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: 298: init() 299: { 300: static short mbuf = fixshort(ARMAG); 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: 313: getaf() 314: { 315: short mbuf; 316: 317: af = open(arnam, 0); 318: if(af < 0) 319: return(1); 320: if (read(af, (char *)&mbuf, sizeof(short)) != sizeof(short) || 321: mbuf != fixshort(ARMAG)) { 322: fprintf(stderr, "ar11: %s not in PDP-11 archive format\n", arnam); 323: done(1); 324: } 325: return(0); 326: } 327: 328: usage() 329: { 330: printf("usage: ar11 [%s][%s] archive files ...\n", opt, man); 331: done(1); 332: } 333: 334: noar() 335: { 336: 337: fprintf(stderr, "ar11: %s does not exist\n", arnam); 338: done(1); 339: } 340: 341: sigdone() 342: { 343: done(100); 344: } 345: 346: done(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: 358: notfound() 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: 371: cleanup() 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: 391: install() 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: */ 425: movefil(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++; 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); 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: 445: stats() 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: */ 463: copyfil(fi, fo, flag) 464: { 465: register i, o; 466: int pe; 467: 468: if(flag & HEAD) { 469: struct ar_hdr tmpbuf; 470: 471: tmpbuf = fixhdr(arbuf); 472: if (write(fo, (char *)&tmpbuf, sizeof arbuf) != sizeof arbuf) 473: wrerr(); 474: } 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: 498: getdir() 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: } 511: arbuf = fixhdr(arbuf); 512: for(i=0; i<14; i++) 513: name[i] = arbuf.ar_name[i]; 514: file = name; 515: ar_date = mklong(arbuf.ar_sdate); 516: ar_size = mklong(arbuf.ar_ssize); 517: return(0); 518: } 519: 520: match() 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: 536: bamatch() 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: 563: phserr() 564: { 565: 566: fprintf(stderr, "ar11: phase error on %s\n", file); 567: } 568: 569: mesg(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: 577: char * 578: trim(s) 579: char *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: 613: longt() 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: 624: int m1[] = { 1, ROWN, 'r', '-' }; 625: int m2[] = { 1, WOWN, 'w', '-' }; 626: int m3[] = { 2, SUID, 's', XOWN, 'x', '-' }; 627: int m4[] = { 1, RGRP, 'r', '-' }; 628: int m5[] = { 1, WGRP, 'w', '-' }; 629: int m6[] = { 2, SGID, 's', XGRP, 'x', '-' }; 630: int m7[] = { 1, ROTH, 'r', '-' }; 631: int m8[] = { 1, WOTH, 'w', '-' }; 632: int m9[] = { 2, STXT, 't', XOTH, 'x', '-' }; 633: 634: int *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9}; 635: 636: pmode() 637: { 638: register int **mp; 639: 640: for (mp = &m[0]; mp < &m[9];) 641: select(*mp++); 642: } 643: 644: select(pairp) 645: int *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: 656: wrerr() 657: { 658: perror("ar write error"); 659: done(1); 660: } 661: 662: #ifdef mc68000 663: struct ar_hdr 664: swaphdr(hdr) 665: struct ar_hdr hdr; 666: { 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); 673: } 674: #endif