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