1 #include <sys/param.h> /* for MAXPATHLEN */ 2 #undef MAX 3 # include "../hdr/defines.h" 4 # include "../hdr/had.h" 5 # include <sys/dir.h> 6 7 static char Sccsid[] = "@(#)get.c 4.9 02/02/88"; 8 9 int Debug = 0; 10 struct packet gpkt; 11 struct sid sid; 12 unsigned Ser; 13 int num_files; 14 char had[26]; 15 char *ilist, *elist, *lfile; 16 long cutoff = 0X7FFFFFFFL; /* max positive long */ 17 int verbosity; 18 char Gfile[MAXNAMLEN + 3]; 19 char Mod[MAXNAMLEN + 3]; /* should be as large as Gfile? */ 20 char *Type; 21 int Did_id; 22 23 main(argc,argv) 24 int argc; 25 register char *argv[]; 26 { 27 register int i; 28 register char *p; 29 char c; 30 int testmore; 31 extern int Fcnt; 32 extern get(); 33 34 Fflags = FTLEXIT | FTLMSG | FTLCLN; 35 for(i=1; i<argc; i++) 36 if(argv[i][0] == '-' && (c=argv[i][1])) { 37 p = &argv[i][2]; 38 testmore = 0; 39 switch (c) { 40 41 case 'a': 42 if (!p[0]) { 43 argv[i] = 0; 44 continue; 45 } 46 Ser = patoi(p); 47 break; 48 case 'r': 49 if (!p[0]) { 50 argv[i] = 0; 51 continue; 52 } 53 chksid(sid_ab(p,&sid),&sid); 54 break; 55 case 'c': 56 if (!p[0]) { 57 argv[i] = 0; 58 continue; 59 } 60 if (date_ab(p,&cutoff)) 61 fatal("bad date/time (cm5)"); 62 break; 63 case 'l': 64 lfile = p; 65 break; 66 case 'i': 67 if (!p[0]) { 68 argv[i] = 0; 69 continue; 70 } 71 ilist = p; 72 break; 73 case 'x': 74 if (!p[0]) { 75 argv[i] = 0; 76 continue; 77 } 78 elist = p; 79 break; 80 case 'b': 81 case 'g': 82 case 'e': 83 case 'p': 84 case 'k': 85 case 'm': 86 case 'n': 87 case 's': 88 case 't': 89 testmore++; 90 break; 91 default: 92 fatal("unknown key letter (cm1)"); 93 } 94 95 if (testmore) { 96 testmore = 0; 97 if (*p) { 98 sprintf(Error,"value after %c arg (cm8)",c); 99 fatal(Error); 100 } 101 } 102 if (had[c - 'a']++) 103 fatal("key letter twice (cm2)"); 104 argv[i] = 0; 105 } 106 else num_files++; 107 108 if(num_files == 0) 109 fatal("missing file arg (cm3)"); 110 if (HADE && HADM) 111 fatal("e not allowed with m (ge3)"); 112 if (HADE || HADI || HADX) 113 HADK = 1; 114 if (!HADS) 115 verbosity = -1; 116 setsig(); 117 Fflags &= ~FTLEXIT; 118 Fflags |= FTLJMP; 119 for (i=1; i<argc; i++) 120 if (p=argv[i]) 121 do_file(p,get); 122 exit(Fcnt ? 1 : 0); 123 } 124 125 126 get(file) 127 { 128 register char *p; 129 register unsigned ser; 130 extern char had_dir, had_standinp; 131 extern char *Sflags[]; 132 struct stats stats; 133 char str[32]; 134 135 if (setjmp(Fjmp)) 136 return; 137 sinit(&gpkt,file,1); 138 gpkt.p_ixuser = (HADI | HADX); 139 gpkt.p_reqsid.s_rel = sid.s_rel; 140 gpkt.p_reqsid.s_lev = sid.s_lev; 141 gpkt.p_reqsid.s_br = sid.s_br; 142 gpkt.p_reqsid.s_seq = sid.s_seq; 143 gpkt.p_verbose = verbosity; 144 gpkt.p_stdout = (HADP ? stderr : stdout); 145 gpkt.p_cutoff = cutoff; 146 gpkt.p_lfile = lfile; 147 copy(auxf(gpkt.p_file,'g'),Gfile); 148 149 if (gpkt.p_verbose && (num_files > 1 || had_dir || had_standinp)) 150 fprintf(gpkt.p_stdout,"\n%s:\n",gpkt.p_file); 151 if (dodelt(&gpkt,&stats,0,0) == 0) 152 fmterr(&gpkt); 153 finduser(&gpkt); 154 doflags(&gpkt); 155 if (!HADA) 156 ser = getser(&gpkt); 157 else { 158 if ((ser = Ser) > maxser(&gpkt)) 159 fatal("serial number too large (ge19)"); 160 bcopy(&gpkt.p_idel[ser].i_sid, &gpkt.p_gotsid, sizeof(sid)); 161 if (HADR && sid.s_rel != gpkt.p_gotsid.s_rel) { 162 bzero(&gpkt.p_reqsid, sizeof(gpkt.p_reqsid)); 163 gpkt.p_reqsid.s_rel = sid.s_rel; 164 } 165 else 166 bcopy(&gpkt.p_gotsid, &gpkt.p_reqsid, sizeof(sid)); 167 } 168 doie(&gpkt,ilist,elist,0); 169 setup(&gpkt,ser); 170 if (!(Type = Sflags[TYPEFLAG - 'a'])) 171 Type = Null; 172 if (!(HADP || HADG) && writable(Gfile)) { 173 sprintf(Error,"writable `%s' exists (ge4)",Gfile); 174 fatal(Error); 175 } 176 if (gpkt.p_verbose) { 177 sid_ba(&gpkt.p_gotsid,str); 178 fprintf(gpkt.p_stdout,"%s\n",str); 179 } 180 if (HADE) { 181 if (!HADR) 182 bcopy(&gpkt.p_gotsid,&gpkt.p_reqsid, 183 sizeof(gpkt.p_reqsid)); 184 newsid(&gpkt,Sflags[BRCHFLAG - 'a'] && HADB); 185 permiss(&gpkt); 186 wrtpfile(&gpkt,ilist,elist); 187 } 188 setuid(getuid()); 189 if (HADL) 190 gen_lfile(&gpkt); 191 if (HADG) { 192 fclose(gpkt.p_iop); 193 xfreeall(); 194 return; 195 } 196 flushto(&gpkt,EUSERTXT,1); 197 idsetup(&gpkt); 198 gpkt.p_chkeof = 1; 199 Did_id = 0; 200 while(readmod(&gpkt)) { 201 if (gpkt.p_gout == 0) { 202 if (HADP) 203 gpkt.p_gout = stdout; 204 else 205 gpkt.p_gout = xfcreat(Gfile,HADK ? 0666 : 0444); 206 } 207 if (HADN) 208 fprintf(gpkt.p_gout,"%s\t",Mod); 209 if (HADM) { 210 sid_ba(&gpkt.p_inssid,str); 211 fprintf(gpkt.p_gout,"%s\t",str); 212 } 213 p = gpkt.p_line; 214 if (!HADK && any('%',p)) 215 p = idsubst(&gpkt,p); 216 fputs(p,gpkt.p_gout); 217 } 218 fflush(gpkt.p_gout); 219 if (gpkt.p_gout && gpkt.p_gout != stdout) 220 fclose(gpkt.p_gout); 221 if (gpkt.p_verbose) 222 fprintf(gpkt.p_stdout,"%u lines\n",gpkt.p_glnno); 223 if (!Did_id && !HADK) 224 if (Sflags[IDFLAG - 'a']) 225 fatal("no id keywords (cm6)"); 226 else if (gpkt.p_verbose) 227 fprintf(stderr,"No id keywords (cm7)\n"); 228 xfreeall(); 229 } 230 231 writable(fn) 232 char *fn; 233 { 234 struct stat s; 235 236 return (stat(fn, &s) >= 0 && (s.st_mode & 0222) != 0); 237 } 238 239 240 newsid(pkt,branch) 241 register struct packet *pkt; 242 int branch; 243 { 244 int chkbr; 245 246 chkbr = 0; 247 if (pkt->p_reqsid.s_br == 0) { 248 pkt->p_reqsid.s_lev += 1; 249 if (sidtoser(&pkt->p_reqsid,pkt) || 250 pkt->p_maxr > pkt->p_reqsid.s_rel || branch) { 251 pkt->p_reqsid.s_rel = pkt->p_gotsid.s_rel; 252 pkt->p_reqsid.s_lev = pkt->p_gotsid.s_lev; 253 pkt->p_reqsid.s_br = pkt->p_gotsid.s_br + 1; 254 pkt->p_reqsid.s_seq = 1; 255 chkbr++; 256 } 257 } 258 else if (pkt->p_reqsid.s_seq == 0 && !branch) 259 pkt->p_reqsid.s_seq = pkt->p_gotsid.s_seq + 1; 260 else { 261 pkt->p_reqsid.s_seq += 1; 262 if (branch || sidtoser(&pkt->p_reqsid,pkt)) { 263 pkt->p_reqsid.s_br += 1; 264 pkt->p_reqsid.s_seq = 1; 265 chkbr++; 266 } 267 } 268 if (chkbr) 269 while (sidtoser(&pkt->p_reqsid,pkt)) 270 pkt->p_reqsid.s_br += 1; 271 if (sidtoser(&pkt->p_reqsid,pkt)) 272 fatal("internal error in newsid()"); 273 } 274 275 276 enter(pkt,ch,n,sidp) 277 struct packet *pkt; 278 char ch; 279 int n; 280 struct sid *sidp; 281 { 282 char str[32]; 283 register struct apply *ap; 284 285 sid_ba(sidp,str); 286 if (pkt->p_verbose) 287 fprintf(pkt->p_stdout,"%s\n",str); 288 ap = &pkt->p_apply[n]; 289 switch(ap->a_code) { 290 291 case EMPTY: 292 if (ch == INCLUDE) 293 condset(ap,APPLY,INCLUSER); 294 else 295 condset(ap,NOAPPLY,EXCLUSER); 296 break; 297 case APPLY: 298 sid_ba(sidp,str); 299 sprintf(Error,"%s already included (ge9)",str); 300 fatal(Error); 301 break; 302 case NOAPPLY: 303 sid_ba(sidp,str); 304 sprintf(Error,"%s already excluded (ge10)",str); 305 fatal(Error); 306 break; 307 default: 308 fatal("internal error in get/enter() (ge11)"); 309 break; 310 } 311 } 312 313 314 gen_lfile(pkt) 315 register struct packet *pkt; 316 { 317 int n; 318 int reason; 319 char str[32]; 320 char line[BUFSIZ]; 321 struct deltab dt; 322 FILE *in; 323 FILE *out; 324 325 in = xfopen(pkt->p_file,0); 326 if (*pkt->p_lfile) 327 out = stdout; 328 else 329 out = xfcreat(auxf(pkt->p_file,'l'),0444); 330 fgets(line,sizeof(line),in); 331 while (fgets(line,sizeof(line),in) != NULL && line[0] == CTLCHAR && line[1] == STATS) { 332 fgets(line,sizeof(line),in); 333 del_ab(line,&dt); 334 if (dt.d_type == 'D') { 335 reason = pkt->p_apply[dt.d_serial].a_reason; 336 if (pkt->p_apply[dt.d_serial].a_code == APPLY) { 337 putc(' ',out); 338 putc(' ',out); 339 } 340 else { 341 putc('*',out); 342 if (reason & IGNR) 343 putc(' ',out); 344 else 345 putc('*',out); 346 } 347 switch (reason & (INCL | EXCL | CUTOFF)) { 348 349 case INCL: 350 putc('I',out); 351 break; 352 case EXCL: 353 putc('X',out); 354 break; 355 case CUTOFF: 356 putc('C',out); 357 break; 358 default: 359 putc(' ',out); 360 break; 361 } 362 putc(' ',out); 363 sid_ba(&dt.d_sid,str); 364 fprintf(out,"%s\t",str); 365 date_ba(&dt.d_datetime,str); 366 fprintf(out,"%s %s\n",str,dt.d_pgmr); 367 } 368 while ((n = fgets(line,sizeof(line),in)) != NULL) 369 if (line[0] != CTLCHAR) 370 break; 371 else { 372 switch (line[1]) { 373 374 case EDELTAB: 375 break; 376 default: 377 continue; 378 case MRNUM: 379 case COMMENTS: 380 if (dt.d_type == 'D') 381 fprintf(out,"\t%s",&line[3]); 382 continue; 383 } 384 break; 385 } 386 if (n == NULL || line[0] != CTLCHAR) 387 break; 388 putc('\n',out); 389 } 390 fclose(in); 391 if (out != stdout) 392 fclose(out); 393 } 394 395 char Curdate[18]; 396 char *Curtime; 397 char Gdate[9]; 398 char Chgdate[18]; 399 char *Chgtime; 400 char Gchgdate[9]; 401 char Qchgdate[30]; 402 char Sid[32]; 403 char Olddir[MAXPATHLEN+1]; 404 char Pname[MAXPATHLEN+1]; 405 char Dir[MAXPATHLEN+1]; 406 407 idsetup(pkt) 408 register struct packet *pkt; 409 { 410 extern long Timenow; 411 register int n; 412 register char *p; 413 414 date_ba(&Timenow,Curdate); 415 Curtime = &Curdate[9]; 416 Curdate[8] = 0; 417 copy(pkt->p_file,Dir); 418 dname(Dir); 419 if(getwd(Olddir) == 0) 420 fatal("getwd failed (ge20)"); 421 if(chdir(Dir) != 0) 422 fatal("cannot change directory (ge22)"); 423 if(getwd(Pname) == 0) 424 fatal("getwd failed (ge21)"); 425 if(chdir(Olddir) != 0) 426 fatal("cannot change directory (ge23)"); 427 makgdate(Curdate,Gdate); 428 for (n = maxser(pkt); n; n--) 429 if (pkt->p_apply[n].a_code == APPLY) 430 break; 431 if (n) 432 date_ba(&pkt->p_idel[n].i_datetime,Chgdate); 433 Chgtime = &Chgdate[9]; 434 Chgdate[8] = 0; 435 makgdate(Chgdate,Gchgdate); 436 makqdate(Gchgdate,Qchgdate); 437 sid_ba(&pkt->p_gotsid,Sid); 438 if (p = Sflags[MODFLAG - 'a']) 439 copy(p,Mod); 440 else 441 copy(Gfile,Mod); 442 } 443 444 445 makgdate(old,new) 446 register char *old, *new; 447 { 448 if ((*new = old[3]) != '0') 449 new++; 450 *new++ = old[4]; 451 *new++ = '/'; 452 if ((*new = old[6]) != '0') 453 new++; 454 *new++ = old[7]; 455 *new++ = '/'; 456 *new++ = old[0]; 457 *new++ = old[1]; 458 *new = 0; 459 } 460 461 makqdate(old,new) 462 register char *old, *new; 463 { 464 static char *months[12] = 465 { "January", "February", "March", "April", "May", "June", "July", 466 "August", "September", "October", "November", "December" }; 467 468 strcpy(new, months[atoi(old)-1]); 469 while (*new != '\0') 470 new++; 471 while (*old++ != '/') 472 ; 473 *new++ = ' '; 474 *new++ = *old++; 475 if (*old != '/') 476 *new++ = *old++; 477 *new++ = ','; 478 *new++ = ' '; 479 *new++ = '1'; *new++ = '9'; /* works for this century at least */ 480 *new++ = *++old; 481 *new++ = *++old; 482 *new = '\0'; 483 } 484 485 static char Zkeywd[5] = "@(#)"; 486 487 488 idsubst(pkt,line) 489 register struct packet *pkt; 490 char line[]; 491 { 492 static char tline[BUFSIZ]; 493 static char str[32]; 494 register char *lp, *tp; 495 extern char *Type; 496 extern char *Sflags[]; 497 498 tp = tline; 499 for(lp=line; *lp != 0; lp++) { 500 if(lp[0] == '%' && lp[1] != 0 && lp[2] == '%') { 501 switch(*++lp) { 502 503 case 'M': 504 tp = trans(tp,Mod); 505 break; 506 case 'R': 507 sprintf(str,"%u",pkt->p_gotsid.s_rel); 508 tp = trans(tp,str); 509 break; 510 case 'L': 511 sprintf(str,"%u",pkt->p_gotsid.s_lev); 512 tp = trans(tp,str); 513 break; 514 case 'B': 515 sprintf(str,"%u",pkt->p_gotsid.s_br); 516 tp = trans(tp,str); 517 break; 518 case 'S': 519 sprintf(str,"%u",pkt->p_gotsid.s_seq); 520 tp = trans(tp,str); 521 break; 522 case 'D': 523 tp = trans(tp,Curdate); 524 break; 525 case 'H': 526 tp = trans(tp,Gdate); 527 break; 528 case 'T': 529 tp = trans(tp,Curtime); 530 break; 531 case 'E': 532 tp = trans(tp,Chgdate); 533 break; 534 case 'G': 535 tp = trans(tp,Gchgdate); 536 break; 537 case 'Q': 538 tp = trans(tp,Qchgdate); 539 break; 540 case 'U': 541 tp = trans(tp,Chgtime); 542 break; 543 case 'Z': 544 tp = trans(tp,Zkeywd); 545 break; 546 case 'Y': 547 tp = trans(tp,Type); 548 break; 549 case 'W': 550 tp = trans(tp,Zkeywd); 551 tp = trans(tp,Mod); 552 *tp++ = '\t'; 553 case 'I': 554 tp = trans(tp,Sid); 555 break; 556 case 'P': 557 tp = trans(tp,Pname); 558 *tp++ = '/'; 559 tp = trans(tp,(sname(pkt->p_file))); 560 break; 561 case 'F': 562 tp = trans(tp,pkt->p_file); 563 break; 564 case 'C': 565 sprintf(str,"%u",pkt->p_glnno); 566 tp = trans(tp,str); 567 break; 568 case 'A': 569 tp = trans(tp,Zkeywd); 570 tp = trans(tp,Type); 571 *tp++ = ' '; 572 tp = trans(tp,Mod); 573 *tp++ = ' '; 574 tp = trans(tp,Sid); 575 tp = trans(tp,Zkeywd); 576 break; 577 default: 578 *tp++ = '%'; 579 *tp++ = *lp; 580 continue; 581 } 582 lp++; 583 } 584 else 585 *tp++ = *lp; 586 } 587 588 *tp = 0; 589 return(tline); 590 } 591 592 593 trans(tp,str) 594 register char *tp, *str; 595 { 596 Did_id = 1; 597 while(*tp++ = *str++) 598 ; 599 return(tp-1); 600 } 601 602 603 clean_up(n) 604 { 605 if (gpkt.p_file[0]) 606 unlockit(auxf(gpkt.p_file,'z'),getpid()); 607 if (gpkt.p_iop) 608 fclose(gpkt.p_iop); 609 xfreeall(); 610 } 611 612 613 wrtpfile(pkt,inc,exc) 614 register struct packet *pkt; 615 char *inc, *exc; 616 { 617 char line[64], str1[32], str2[32]; 618 char *user; 619 FILE *in, *out; 620 struct pfile pf; 621 register char *p; 622 int fd; 623 int i; 624 extern long Timenow; 625 626 user = logname(); 627 if (lockit(auxf(pkt->p_file,'z'),2,getpid())) 628 fatal("cannot create lock file (cm4)"); 629 if (exists(p = auxf(pkt->p_file,'p'))) { 630 fd = xopen(p,2); 631 in = fdopen(fd,"r"); 632 while (fgets(line,sizeof(line),in) != NULL) { 633 p = line; 634 p[length(p) - 1] = 0; 635 pf_ab(p,&pf,0); 636 if ((pf.pf_gsid.s_rel == pkt->p_gotsid.s_rel && 637 pf.pf_gsid.s_lev == pkt->p_gotsid.s_lev && 638 pf.pf_gsid.s_br == pkt->p_gotsid.s_br && 639 pf.pf_gsid.s_seq == pkt->p_gotsid.s_seq) || 640 (pf.pf_nsid.s_rel == pkt->p_reqsid.s_rel && 641 pf.pf_nsid.s_lev == pkt->p_reqsid.s_lev && 642 pf.pf_nsid.s_br == pkt->p_reqsid.s_br && 643 pf.pf_nsid.s_seq == pkt->p_reqsid.s_seq)) { 644 fclose(in); 645 sprintf(Error,"being edited: `%s' (ge17)",line); 646 fatal(Error); 647 } 648 if (!equal(pf.pf_user,user)) 649 fprintf(stderr,"WARNING: being edited: `%s' (ge18)\n",line); 650 } 651 out = fdopen(dup(fd),"w"); 652 fclose(in); 653 } 654 else 655 out = xfcreat(p,0666); 656 fseek(out,0L,2); 657 sid_ba(&pkt->p_gotsid,str1); 658 sid_ba(&pkt->p_reqsid,str2); 659 date_ba(&Timenow,line); 660 fprintf(out,"%s %s %s %s",str1,str2,user,line); 661 if (inc) 662 fprintf(out," -i%s",inc); 663 if (exc) 664 fprintf(out," -x%s",exc); 665 fprintf(out,"\n"); 666 fclose(out); 667 if (pkt->p_verbose) 668 fprintf(pkt->p_stdout,"new delta %s\n",str2); 669 unlockit(auxf(pkt->p_file,'z'),getpid()); 670 } 671 672 673 getser(pkt) 674 register struct packet *pkt; 675 { 676 register struct idel *rdp; 677 int n, ser, def; 678 char *p; 679 extern char *Sflags[]; 680 681 def = 0; 682 if (pkt->p_reqsid.s_rel == 0) { 683 if (p = Sflags[DEFTFLAG - 'a']) 684 chksid(sid_ab(p, &pkt->p_reqsid), &pkt->p_reqsid); 685 else { 686 pkt->p_reqsid.s_rel = MAX; 687 def = 1; 688 } 689 } 690 ser = 0; 691 if (pkt->p_reqsid.s_lev == 0) { 692 for (n = maxser(pkt); n; n--) { 693 rdp = &pkt->p_idel[n]; 694 if ((rdp->i_sid.s_br == 0 || HADT) && 695 pkt->p_reqsid.s_rel >= rdp->i_sid.s_rel && 696 rdp->i_sid.s_rel > pkt->p_gotsid.s_rel) { 697 ser = n; 698 pkt->p_gotsid.s_rel = rdp->i_sid.s_rel; 699 } 700 } 701 } 702 else if (pkt->p_reqsid.s_br && pkt->p_reqsid.s_seq == 0) { 703 for (n = maxser(pkt); n; n--) { 704 rdp = &pkt->p_idel[n]; 705 if (rdp->i_sid.s_rel == pkt->p_reqsid.s_rel && 706 rdp->i_sid.s_lev == pkt->p_reqsid.s_lev && 707 rdp->i_sid.s_br == pkt->p_reqsid.s_br) 708 break; 709 } 710 ser = n; 711 } 712 else { 713 ser = sidtoser(&pkt->p_reqsid,pkt); 714 } 715 if (ser == 0) 716 fatal("nonexistent sid (ge5)"); 717 rdp = &pkt->p_idel[ser]; 718 bcopy(&rdp->i_sid, &pkt->p_gotsid, sizeof(pkt->p_gotsid)); 719 if (def || (pkt->p_reqsid.s_lev == 0 && pkt->p_reqsid.s_rel == pkt->p_gotsid.s_rel)) 720 bcopy(&pkt->p_gotsid, &pkt->p_reqsid, sizeof(pkt->p_gotsid)); 721 return(ser); 722 } 723 724 725 /* Null routine to satisfy external reference from dodelt() */ 726 727 escdodelt() 728 { 729 } 730