1 static char *sccsid = "@(#)ar11.c 4.5 (Berkeley) 07/22/88"; 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 #if defined(mc68000) || defined(tahoe) 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 static char name2[] = "/tmp/v2XXXXX"; 260 261 init(); 262 if(getaf()) 263 noar(); 264 tf2nam = mktemp(name2); 265 close(creat(tf2nam, 0600)); 266 tf2 = open(tf2nam, 2); 267 if(tf2 < 0) { 268 fprintf(stderr, "ar11: cannot create third temp\n"); 269 done(1); 270 } 271 while(!getdir()) { 272 bamatch(); 273 if(match()) { 274 mesg('m'); 275 copyfil(af, tf2, IODD+OODD+HEAD); 276 continue; 277 } 278 mesg('c'); 279 copyfil(af, tf, IODD+OODD+HEAD); 280 } 281 install(); 282 } 283 284 tcmd() 285 { 286 287 if(getaf()) 288 noar(); 289 while(!getdir()) { 290 if(namc == 0 || match()) { 291 if(flg['v'-'a']) 292 longt(); 293 printf("%s\n", trim(file)); 294 } 295 copyfil(af, -1, IODD+SKIP); 296 } 297 } 298 299 init() 300 { 301 static char name0[] = "/tmp/vXXXXX"; 302 static short mbuf = fixshort(ARMAG); 303 304 tfnam = mktemp(name0); 305 close(creat(tfnam, 0600)); 306 tf = open(tfnam, 2); 307 if(tf < 0) { 308 fprintf(stderr, "ar11: cannot create temp file\n"); 309 done(1); 310 } 311 if (write(tf, (char *)&mbuf, sizeof(short)) != sizeof(short)) 312 wrerr(); 313 } 314 315 getaf() 316 { 317 short mbuf; 318 319 af = open(arnam, 0); 320 if(af < 0) 321 return(1); 322 if (read(af, (char *)&mbuf, sizeof(short)) != sizeof(short) || 323 mbuf != fixshort(ARMAG)) { 324 fprintf(stderr, "ar11: %s not in PDP-11 archive format\n", arnam); 325 done(1); 326 } 327 return(0); 328 } 329 330 usage() 331 { 332 printf("usage: ar11 [%s][%s] archive files ...\n", opt, man); 333 done(1); 334 } 335 336 noar() 337 { 338 339 fprintf(stderr, "ar11: %s does not exist\n", arnam); 340 done(1); 341 } 342 343 sigdone() 344 { 345 done(100); 346 } 347 348 done(c) 349 { 350 351 if(tfnam) 352 unlink(tfnam); 353 if(tf1nam) 354 unlink(tf1nam); 355 if(tf2nam) 356 unlink(tf2nam); 357 exit(c); 358 } 359 360 notfound() 361 { 362 register i, n; 363 364 n = 0; 365 for(i=0; i<namc; i++) 366 if(namv[i]) { 367 fprintf(stderr, "ar11: %s not found\n", namv[i]); 368 n++; 369 } 370 return(n); 371 } 372 373 cleanup() 374 { 375 register i, f; 376 377 for(i=0; i<namc; i++) { 378 file = namv[i]; 379 if(file == 0) 380 continue; 381 namv[i] = 0; 382 mesg('a'); 383 f = stats(); 384 if(f < 0) { 385 fprintf(stderr, "ar11: %s cannot open\n", file); 386 continue; 387 } 388 movefil(f); 389 } 390 install(); 391 } 392 393 install() 394 { 395 register i; 396 397 for(i=0; signum[i]; i++) 398 signal(signum[i], (int (*)())1); 399 close(af); 400 af = creat(arnam, 0666); 401 if(af < 0) { 402 fprintf(stderr, "ar11: cannot create %s\n", arnam); 403 done(1); 404 } 405 lseek(tf, 0l, 0); 406 while((i = read(tf, buf, 512)) > 0) 407 if (write(af, buf, i) != i) 408 wrerr(); 409 if(tf2nam) { 410 lseek(tf2, 0l, 0); 411 while((i = read(tf2, buf, 512)) > 0) 412 if (write(af, buf, i) != i) 413 wrerr(); 414 } 415 if(tf1nam) { 416 lseek(tf1, 0l, 0); 417 while((i = read(tf1, buf, 512)) > 0) 418 if (write(af, buf, i) != i) 419 wrerr(); 420 } 421 } 422 423 /* 424 * insert the file 'file' 425 * into the temporary file 426 */ 427 movefil(f) 428 { 429 register char *cp; 430 register i; 431 432 cp = trim(file); 433 for(i=0; i<14; i++) 434 if(arbuf.ar_name[i] = *cp) 435 cp++; 436 ar_size = stbuf.st_size; 437 ar_date = stbuf.st_mtime; 438 unmklong(arbuf.ar_ssize, ar_size); 439 unmklong(arbuf.ar_sdate, ar_date); 440 arbuf.ar_uid = stbuf.st_uid; 441 arbuf.ar_gid = stbuf.st_gid; 442 arbuf.ar_mode = stbuf.st_mode; 443 copyfil(f, tf, OODD+HEAD); 444 close(f); 445 } 446 447 stats() 448 { 449 register f; 450 451 f = open(file, 0); 452 if(f < 0) 453 return(f); 454 if(fstat(f, &stbuf) < 0) { 455 close(f); 456 return(-1); 457 } 458 return(f); 459 } 460 461 /* 462 * copy next file 463 * size given in arbuf 464 */ 465 copyfil(fi, fo, flag) 466 { 467 register i, o; 468 int pe; 469 470 if(flag & HEAD) { 471 struct ar_hdr tmpbuf; 472 473 tmpbuf = fixhdr(arbuf); 474 if (write(fo, (char *)&tmpbuf, sizeof arbuf) != sizeof arbuf) 475 wrerr(); 476 } 477 pe = 0; 478 while(ar_size > 0) { 479 i = o = 512; 480 if(ar_size < i) { 481 i = o = ar_size; 482 if(i&1) { 483 if(flag & IODD) 484 i++; 485 if(flag & OODD) 486 o++; 487 } 488 } 489 if(read(fi, buf, i) != i) 490 pe++; 491 if((flag & SKIP) == 0) 492 if (write(fo, buf, o) != o) 493 wrerr(); 494 ar_size -= 512; 495 } 496 if(pe) 497 phserr(); 498 } 499 500 getdir() 501 { 502 register i; 503 504 i = read(af, (char *)&arbuf, sizeof arbuf); 505 if(i != sizeof arbuf) { 506 if(tf1nam) { 507 i = tf; 508 tf = tf1; 509 tf1 = i; 510 } 511 return(1); 512 } 513 arbuf = fixhdr(arbuf); 514 for(i=0; i<14; i++) 515 name[i] = arbuf.ar_name[i]; 516 file = name; 517 ar_date = mklong(arbuf.ar_sdate); 518 ar_size = mklong(arbuf.ar_ssize); 519 return(0); 520 } 521 522 match() 523 { 524 register i; 525 526 for(i=0; i<namc; i++) { 527 if(namv[i] == 0) 528 continue; 529 if(strcmp(trim(namv[i]), file) == 0) { 530 file = namv[i]; 531 namv[i] = 0; 532 return(1); 533 } 534 } 535 return(0); 536 } 537 538 bamatch() 539 { 540 static char name1[] = "/tmp/v1XXXXX"; 541 register f; 542 543 switch(bastate) { 544 545 case 1: 546 if(strcmp(file, ponam) != 0) 547 return; 548 bastate = 2; 549 if(flg['a'-'a']) 550 return; 551 552 case 2: 553 bastate = 0; 554 tf1nam = mktemp(name1); 555 close(creat(tf1nam, 0600)); 556 f = open(tf1nam, 2); 557 if(f < 0) { 558 fprintf(stderr, "ar11: cannot create second temp\n"); 559 return; 560 } 561 tf1 = tf; 562 tf = f; 563 } 564 } 565 566 phserr() 567 { 568 569 fprintf(stderr, "ar11: phase error on %s\n", file); 570 } 571 572 mesg(c) 573 { 574 575 if(flg['v'-'a']) 576 if(c != 'c' || flg['v'-'a'] > 1) 577 printf("%c - %s\n", c, file); 578 } 579 580 char * 581 trim(s) 582 char *s; 583 { 584 register char *p1, *p2; 585 586 for(p1 = s; *p1; p1++) 587 ; 588 while(p1 > s) { 589 if(*--p1 != '/') 590 break; 591 *p1 = 0; 592 } 593 p2 = s; 594 for(p1 = s; *p1; p1++) 595 if(*p1 == '/') 596 p2 = p1+1; 597 return(p2); 598 } 599 600 #define IFMT 060000 601 #define ISARG 01000 602 #define LARGE 010000 603 #define SUID 04000 604 #define SGID 02000 605 #define ROWN 0400 606 #define WOWN 0200 607 #define XOWN 0100 608 #define RGRP 040 609 #define WGRP 020 610 #define XGRP 010 611 #define ROTH 04 612 #define WOTH 02 613 #define XOTH 01 614 #define STXT 01000 615 616 longt() 617 { 618 register char *cp; 619 620 pmode(); 621 printf("%3d/%1d", arbuf.ar_uid, arbuf.ar_gid); 622 printf("%7D", ar_size); 623 cp = ctime(&ar_date); 624 printf(" %-12.12s %-4.4s ", cp+4, cp+20); 625 } 626 627 int m1[] = { 1, ROWN, 'r', '-' }; 628 int m2[] = { 1, WOWN, 'w', '-' }; 629 int m3[] = { 2, SUID, 's', XOWN, 'x', '-' }; 630 int m4[] = { 1, RGRP, 'r', '-' }; 631 int m5[] = { 1, WGRP, 'w', '-' }; 632 int m6[] = { 2, SGID, 's', XGRP, 'x', '-' }; 633 int m7[] = { 1, ROTH, 'r', '-' }; 634 int m8[] = { 1, WOTH, 'w', '-' }; 635 int m9[] = { 2, STXT, 't', XOTH, 'x', '-' }; 636 637 int *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9}; 638 639 pmode() 640 { 641 register int **mp; 642 643 for (mp = &m[0]; mp < &m[9];) 644 select(*mp++); 645 } 646 647 select(pairp) 648 int *pairp; 649 { 650 register int n, *ap; 651 652 ap = pairp; 653 n = *ap++; 654 while (--n>=0 && (arbuf.ar_mode&*ap++)==0) 655 ap++; 656 putchar(*ap); 657 } 658 659 wrerr() 660 { 661 perror("ar write error"); 662 done(1); 663 } 664 665 #if defined(mc68000) || defined(tahoe) 666 struct ar_hdr 667 swaphdr(hdr) 668 struct ar_hdr hdr; 669 { 670 hdr.ar_sdate[0] = fixshort(hdr.ar_sdate[0]); 671 hdr.ar_sdate[1] = fixshort(hdr.ar_sdate[1]); 672 hdr.ar_ssize[0] = fixshort(hdr.ar_ssize[0]); 673 hdr.ar_ssize[1] = fixshort(hdr.ar_ssize[1]); 674 hdr.ar_mode = fixshort(hdr.ar_mode); 675 return (hdr); 676 } 677 #endif 678