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