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