1*9570Spugs static char *sccsid = "@(#)ar11.c 4.3 (Berkeley) 12/06/82"; 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> 8*9570Spugs #define ARMAG ((short)0177545) 9952Sbill struct ar_hdr { 10*9570Spugs char ar_name[14]; 11*9570Spugs short ar_sdate[2]; 12*9570Spugs char ar_uid; 13*9570Spugs char ar_gid; 14*9570Spugs short ar_mode; 15*9570Spugs short ar_ssize[2]; 16952Sbill }; 17*9570Spugs long ar_date; 18*9570Spugs long ar_size; 19*9570Spugs 20*9570Spugs #ifdef vax 21*9570Spugs #define fixshort(s) (s) 22*9570Spugs #define mklong(sp) (((sp)[0] << 16) + (sp)[1]) 23*9570Spugs #define unmklong(sp,l) { sp[0] = l >> 16; sp[1] = l & 0177777; } 24*9570Spugs #define fixhdr(hdr) (hdr) 25*9570Spugs #endif 26*9570Spugs #ifdef mc68000 27*9570Spugs #define fixshort(s) ((short)(((s>>8)&0377)+((s&0377)<<8))) 28*9570Spugs #define mklong(sp) (((sp)[0] << 16) + (sp)[1]) 29*9570Spugs #define unmklong(sp,l) { sp[0] = l >> 16; sp[1] = l & 0177777; } 30*9570Spugs #define fixhdr(hdr) swaphdr(hdr) 31*9570Spugs struct ar_hdr swaphdr(); 32*9570Spugs #endif 33*9570Spugs 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 { 259952Sbill 260952Sbill init(); 261952Sbill if(getaf()) 262952Sbill noar(); 263952Sbill tf2nam = mktemp("/tmp/v2XXXXX"); 264952Sbill close(creat(tf2nam, 0600)); 265952Sbill tf2 = open(tf2nam, 2); 266952Sbill if(tf2 < 0) { 267952Sbill fprintf(stderr, "ar11: cannot create third temp\n"); 268952Sbill done(1); 269952Sbill } 270952Sbill while(!getdir()) { 271952Sbill bamatch(); 272952Sbill if(match()) { 273952Sbill mesg('m'); 274952Sbill copyfil(af, tf2, IODD+OODD+HEAD); 275952Sbill continue; 276952Sbill } 277952Sbill mesg('c'); 278952Sbill copyfil(af, tf, IODD+OODD+HEAD); 279952Sbill } 280952Sbill install(); 281952Sbill } 282952Sbill 283952Sbill tcmd() 284952Sbill { 285952Sbill 286952Sbill if(getaf()) 287952Sbill noar(); 288952Sbill while(!getdir()) { 289952Sbill if(namc == 0 || match()) { 290952Sbill if(flg['v'-'a']) 291952Sbill longt(); 292952Sbill printf("%s\n", trim(file)); 293952Sbill } 294952Sbill copyfil(af, -1, IODD+SKIP); 295952Sbill } 296952Sbill } 297952Sbill 298952Sbill init() 299952Sbill { 300*9570Spugs static short mbuf = fixshort(ARMAG); 301952Sbill 302952Sbill tfnam = mktemp("/tmp/vXXXXX"); 303952Sbill close(creat(tfnam, 0600)); 304952Sbill tf = open(tfnam, 2); 305952Sbill if(tf < 0) { 306952Sbill fprintf(stderr, "ar11: cannot create temp file\n"); 307952Sbill done(1); 308952Sbill } 309952Sbill if (write(tf, (char *)&mbuf, sizeof(short)) != sizeof(short)) 310952Sbill wrerr(); 311952Sbill } 312952Sbill 313952Sbill getaf() 314952Sbill { 315952Sbill short mbuf; 316952Sbill 317952Sbill af = open(arnam, 0); 318952Sbill if(af < 0) 319952Sbill return(1); 320*9570Spugs if (read(af, (char *)&mbuf, sizeof(short)) != sizeof(short) || 321*9570Spugs mbuf != fixshort(ARMAG)) { 322952Sbill fprintf(stderr, "ar11: %s not in PDP-11 archive format\n", arnam); 323952Sbill done(1); 324952Sbill } 325952Sbill return(0); 326952Sbill } 327952Sbill 328952Sbill usage() 329952Sbill { 330952Sbill printf("usage: ar11 [%s][%s] archive files ...\n", opt, man); 331952Sbill done(1); 332952Sbill } 333952Sbill 334952Sbill noar() 335952Sbill { 336952Sbill 337952Sbill fprintf(stderr, "ar11: %s does not exist\n", arnam); 338952Sbill done(1); 339952Sbill } 340952Sbill 341952Sbill sigdone() 342952Sbill { 343952Sbill done(100); 344952Sbill } 345952Sbill 346952Sbill done(c) 347952Sbill { 348952Sbill 349952Sbill if(tfnam) 350952Sbill unlink(tfnam); 351952Sbill if(tf1nam) 352952Sbill unlink(tf1nam); 353952Sbill if(tf2nam) 354952Sbill unlink(tf2nam); 355952Sbill exit(c); 356952Sbill } 357952Sbill 358952Sbill notfound() 359952Sbill { 360952Sbill register i, n; 361952Sbill 362952Sbill n = 0; 363952Sbill for(i=0; i<namc; i++) 364952Sbill if(namv[i]) { 365952Sbill fprintf(stderr, "ar11: %s not found\n", namv[i]); 366952Sbill n++; 367952Sbill } 368952Sbill return(n); 369952Sbill } 370952Sbill 371952Sbill cleanup() 372952Sbill { 373952Sbill register i, f; 374952Sbill 375952Sbill for(i=0; i<namc; i++) { 376952Sbill file = namv[i]; 377952Sbill if(file == 0) 378952Sbill continue; 379952Sbill namv[i] = 0; 380952Sbill mesg('a'); 381952Sbill f = stats(); 382952Sbill if(f < 0) { 383952Sbill fprintf(stderr, "ar11: %s cannot open\n", file); 384952Sbill continue; 385952Sbill } 386952Sbill movefil(f); 387952Sbill } 388952Sbill install(); 389952Sbill } 390952Sbill 391952Sbill install() 392952Sbill { 393952Sbill register i; 394952Sbill 395952Sbill for(i=0; signum[i]; i++) 396952Sbill signal(signum[i], (int (*)())1); 397952Sbill close(af); 398952Sbill af = creat(arnam, 0666); 399952Sbill if(af < 0) { 400952Sbill fprintf(stderr, "ar11: cannot create %s\n", arnam); 401952Sbill done(1); 402952Sbill } 403952Sbill lseek(tf, 0l, 0); 404952Sbill while((i = read(tf, buf, 512)) > 0) 405952Sbill if (write(af, buf, i) != i) 406952Sbill wrerr(); 407952Sbill if(tf2nam) { 408952Sbill lseek(tf2, 0l, 0); 409952Sbill while((i = read(tf2, buf, 512)) > 0) 410952Sbill if (write(af, buf, i) != i) 411952Sbill wrerr(); 412952Sbill } 413952Sbill if(tf1nam) { 414952Sbill lseek(tf1, 0l, 0); 415952Sbill while((i = read(tf1, buf, 512)) > 0) 416952Sbill if (write(af, buf, i) != i) 417952Sbill wrerr(); 418952Sbill } 419952Sbill } 420952Sbill 421952Sbill /* 422952Sbill * insert the file 'file' 423952Sbill * into the temporary file 424952Sbill */ 425952Sbill movefil(f) 426952Sbill { 427952Sbill register char *cp; 428952Sbill register i; 429952Sbill 430952Sbill cp = trim(file); 431952Sbill for(i=0; i<14; i++) 432952Sbill if(arbuf.ar_name[i] = *cp) 433952Sbill cp++; 434*9570Spugs ar_size = stbuf.st_size; 435*9570Spugs ar_date = stbuf.st_mtime; 436*9570Spugs unmklong(arbuf.ar_ssize, ar_size); 437*9570Spugs unmklong(arbuf.ar_sdate, ar_date); 438952Sbill arbuf.ar_uid = stbuf.st_uid; 439952Sbill arbuf.ar_gid = stbuf.st_gid; 440952Sbill arbuf.ar_mode = stbuf.st_mode; 441952Sbill copyfil(f, tf, OODD+HEAD); 442952Sbill close(f); 443952Sbill } 444952Sbill 445952Sbill stats() 446952Sbill { 447952Sbill register f; 448952Sbill 449952Sbill f = open(file, 0); 450952Sbill if(f < 0) 451952Sbill return(f); 452952Sbill if(fstat(f, &stbuf) < 0) { 453952Sbill close(f); 454952Sbill return(-1); 455952Sbill } 456952Sbill return(f); 457952Sbill } 458952Sbill 459952Sbill /* 460952Sbill * copy next file 461952Sbill * size given in arbuf 462952Sbill */ 463952Sbill copyfil(fi, fo, flag) 464952Sbill { 465952Sbill register i, o; 466952Sbill int pe; 467952Sbill 468*9570Spugs if(flag & HEAD) { 469*9570Spugs struct ar_hdr tmpbuf; 470*9570Spugs 471*9570Spugs tmpbuf = fixhdr(arbuf); 472*9570Spugs if (write(fo, (char *)&tmpbuf, sizeof arbuf) != sizeof arbuf) 473952Sbill wrerr(); 474*9570Spugs } 475952Sbill pe = 0; 476952Sbill while(ar_size > 0) { 477952Sbill i = o = 512; 478952Sbill if(ar_size < i) { 479952Sbill i = o = ar_size; 480952Sbill if(i&1) { 481952Sbill if(flag & IODD) 482952Sbill i++; 483952Sbill if(flag & OODD) 484952Sbill o++; 485952Sbill } 486952Sbill } 487952Sbill if(read(fi, buf, i) != i) 488952Sbill pe++; 489952Sbill if((flag & SKIP) == 0) 490952Sbill if (write(fo, buf, o) != o) 491952Sbill wrerr(); 492952Sbill ar_size -= 512; 493952Sbill } 494952Sbill if(pe) 495952Sbill phserr(); 496952Sbill } 497952Sbill 498952Sbill getdir() 499952Sbill { 500952Sbill register i; 501952Sbill 502952Sbill i = read(af, (char *)&arbuf, sizeof arbuf); 503952Sbill if(i != sizeof arbuf) { 504952Sbill if(tf1nam) { 505952Sbill i = tf; 506952Sbill tf = tf1; 507952Sbill tf1 = i; 508952Sbill } 509952Sbill return(1); 510952Sbill } 511*9570Spugs arbuf = fixhdr(arbuf); 512952Sbill for(i=0; i<14; i++) 513952Sbill name[i] = arbuf.ar_name[i]; 514952Sbill file = name; 515*9570Spugs ar_date = mklong(arbuf.ar_sdate); 516*9570Spugs ar_size = mklong(arbuf.ar_ssize); 517952Sbill return(0); 518952Sbill } 519952Sbill 520952Sbill match() 521952Sbill { 522952Sbill register i; 523952Sbill 524952Sbill for(i=0; i<namc; i++) { 525952Sbill if(namv[i] == 0) 526952Sbill continue; 527952Sbill if(strcmp(trim(namv[i]), file) == 0) { 528952Sbill file = namv[i]; 529952Sbill namv[i] = 0; 530952Sbill return(1); 531952Sbill } 532952Sbill } 533952Sbill return(0); 534952Sbill } 535952Sbill 536952Sbill bamatch() 537952Sbill { 538952Sbill register f; 539952Sbill 540952Sbill switch(bastate) { 541952Sbill 542952Sbill case 1: 543952Sbill if(strcmp(file, ponam) != 0) 544952Sbill return; 545952Sbill bastate = 2; 546952Sbill if(flg['a'-'a']) 547952Sbill return; 548952Sbill 549952Sbill case 2: 550952Sbill bastate = 0; 551952Sbill tf1nam = mktemp("/tmp/v1XXXXX"); 552952Sbill close(creat(tf1nam, 0600)); 553952Sbill f = open(tf1nam, 2); 554952Sbill if(f < 0) { 555952Sbill fprintf(stderr, "ar11: cannot create second temp\n"); 556952Sbill return; 557952Sbill } 558952Sbill tf1 = tf; 559952Sbill tf = f; 560952Sbill } 561952Sbill } 562952Sbill 563952Sbill phserr() 564952Sbill { 565952Sbill 566952Sbill fprintf(stderr, "ar11: phase error on %s\n", file); 567952Sbill } 568952Sbill 569952Sbill mesg(c) 570952Sbill { 571952Sbill 572952Sbill if(flg['v'-'a']) 573952Sbill if(c != 'c' || flg['v'-'a'] > 1) 574952Sbill printf("%c - %s\n", c, file); 575952Sbill } 576952Sbill 577952Sbill char * 578952Sbill trim(s) 579952Sbill char *s; 580952Sbill { 581952Sbill register char *p1, *p2; 582952Sbill 583952Sbill for(p1 = s; *p1; p1++) 584952Sbill ; 585952Sbill while(p1 > s) { 586952Sbill if(*--p1 != '/') 587952Sbill break; 588952Sbill *p1 = 0; 589952Sbill } 590952Sbill p2 = s; 591952Sbill for(p1 = s; *p1; p1++) 592952Sbill if(*p1 == '/') 593952Sbill p2 = p1+1; 594952Sbill return(p2); 595952Sbill } 596952Sbill 597952Sbill #define IFMT 060000 598952Sbill #define ISARG 01000 599952Sbill #define LARGE 010000 600952Sbill #define SUID 04000 601952Sbill #define SGID 02000 602952Sbill #define ROWN 0400 603952Sbill #define WOWN 0200 604952Sbill #define XOWN 0100 605952Sbill #define RGRP 040 606952Sbill #define WGRP 020 607952Sbill #define XGRP 010 608952Sbill #define ROTH 04 609952Sbill #define WOTH 02 610952Sbill #define XOTH 01 611952Sbill #define STXT 01000 612952Sbill 613952Sbill longt() 614952Sbill { 615952Sbill register char *cp; 616952Sbill 617952Sbill pmode(); 618952Sbill printf("%3d/%1d", arbuf.ar_uid, arbuf.ar_gid); 619952Sbill printf("%7D", ar_size); 620952Sbill cp = ctime(&ar_date); 621952Sbill printf(" %-12.12s %-4.4s ", cp+4, cp+20); 622952Sbill } 623952Sbill 624952Sbill int m1[] = { 1, ROWN, 'r', '-' }; 625952Sbill int m2[] = { 1, WOWN, 'w', '-' }; 626952Sbill int m3[] = { 2, SUID, 's', XOWN, 'x', '-' }; 627952Sbill int m4[] = { 1, RGRP, 'r', '-' }; 628952Sbill int m5[] = { 1, WGRP, 'w', '-' }; 629952Sbill int m6[] = { 2, SGID, 's', XGRP, 'x', '-' }; 630952Sbill int m7[] = { 1, ROTH, 'r', '-' }; 631952Sbill int m8[] = { 1, WOTH, 'w', '-' }; 632952Sbill int m9[] = { 2, STXT, 't', XOTH, 'x', '-' }; 633952Sbill 634952Sbill int *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9}; 635952Sbill 636952Sbill pmode() 637952Sbill { 638952Sbill register int **mp; 639952Sbill 640952Sbill for (mp = &m[0]; mp < &m[9];) 641952Sbill select(*mp++); 642952Sbill } 643952Sbill 644952Sbill select(pairp) 645952Sbill int *pairp; 646952Sbill { 647952Sbill register int n, *ap; 648952Sbill 649952Sbill ap = pairp; 650952Sbill n = *ap++; 651952Sbill while (--n>=0 && (arbuf.ar_mode&*ap++)==0) 652952Sbill ap++; 653952Sbill putchar(*ap); 654952Sbill } 655952Sbill 656952Sbill wrerr() 657952Sbill { 658952Sbill perror("ar write error"); 659952Sbill done(1); 660952Sbill } 661952Sbill 662*9570Spugs #ifdef mc68000 663*9570Spugs struct ar_hdr 664*9570Spugs swaphdr(hdr) 665*9570Spugs struct ar_hdr hdr; 666952Sbill { 667*9570Spugs hdr.ar_sdate[0] = fixshort(hdr.ar_sdate[0]); 668*9570Spugs hdr.ar_sdate[1] = fixshort(hdr.ar_sdate[1]); 669*9570Spugs hdr.ar_ssize[0] = fixshort(hdr.ar_ssize[0]); 670*9570Spugs hdr.ar_ssize[1] = fixshort(hdr.ar_ssize[1]); 671*9570Spugs hdr.ar_mode = fixshort(hdr.ar_mode); 672*9570Spugs return (hdr); 673952Sbill } 674*9570Spugs #endif 675