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