1: #include <stdio.h> 2: #include <sys/types.h> 3: #include <sys/stat.h> 4: #include <ar.h> 5: #include <signal.h> 6: struct stat stbuf; 7: struct ar_hdr arbuf; 8: 9: #define SKIP 1 10: #define IODD 2 11: #define OODD 4 12: #define HEAD 8 13: 14: char *man = { "mrxtdpq" }; 15: char *opt = { "uvnbail" }; 16: 17: int signum[] = {SIGHUP, SIGINT, SIGQUIT, 0}; 18: int sigdone(); 19: long lseek(); 20: int rcmd(); 21: int dcmd(); 22: int xcmd(); 23: int tcmd(); 24: int pcmd(); 25: int mcmd(); 26: int qcmd(); 27: int (*comfun)(); 28: char flg[26]; 29: char **namv; 30: int namc; 31: char *arnam; 32: char *ponam; 33: char *tmpnam = { "/tmp/vXXXXX" }; 34: char *tmp1nam = { "/tmp/v1XXXXX" }; 35: char *tmp2nam = { "/tmp/v2XXXXX" }; 36: char *tfnam; 37: char *tf1nam; 38: char *tf2nam; 39: char *file; 40: char name[16]; 41: int af; 42: int tf; 43: int tf1; 44: int tf2; 45: int qf; 46: int bastate; 47: char buf[512]; 48: 49: char *trim(); 50: char *mktemp(); 51: char *ctime(); 52: 53: main(argc, argv) 54: char *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: 139: setcom(fun) 140: int (*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: 150: rcmd() 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: 182: dcmd() 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: 200: xcmd() 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: 226: pcmd() 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: 244: mcmd() 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: 270: tcmd() 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: 285: qcmd() 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: 314: init() 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: 329: getaf() 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: 343: getqf() 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: 366: usage() 367: { 368: printf("usage: ar [%s][%s] archive files ...\n", opt, man); 369: done(1); 370: } 371: 372: noar() 373: { 374: 375: fprintf(stderr, "ar: %s does not exist\n", arnam); 376: done(1); 377: } 378: 379: sigdone() 380: { 381: done(100); 382: } 383: 384: done(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: 396: notfound() 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: 409: morefil() 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: 420: cleanup() 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: 440: install() 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: */ 479: movefil(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: 497: stats() 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: */ 515: copyfil(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: 546: getdir() 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: 565: match() 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: 581: bamatch() 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: 608: phserr() 609: { 610: 611: fprintf(stderr, "ar: phase error on %s\n", file); 612: } 613: 614: mesg(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: 622: char * 623: trim(s) 624: char *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: 658: longt() 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: 669: int m1[] = { 1, ROWN, 'r', '-' }; 670: int m2[] = { 1, WOWN, 'w', '-' }; 671: int m3[] = { 2, SUID, 's', XOWN, 'x', '-' }; 672: int m4[] = { 1, RGRP, 'r', '-' }; 673: int m5[] = { 1, WGRP, 'w', '-' }; 674: int m6[] = { 2, SGID, 's', XGRP, 'x', '-' }; 675: int m7[] = { 1, ROTH, 'r', '-' }; 676: int m8[] = { 1, WOTH, 'w', '-' }; 677: int m9[] = { 2, STXT, 't', XOTH, 'x', '-' }; 678: 679: int *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9}; 680: 681: pmode() 682: { 683: register int **mp; 684: 685: for (mp = &m[0]; mp < &m[9];) 686: select(*mp++); 687: } 688: 689: select(pairp) 690: int *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: 701: wrerr() 702: { 703: perror("ar write error"); 704: done(1); 705: }