1*2143Seric # include "../hdr/defines.h" 2*2143Seric # include "../hdr/had.h" 3*2143Seric 4*2143Seric SCCSID(@(#)admin.c 4.1); 5*2143Seric 6*2143Seric /* 7*2143Seric Program to create new SCCS files and change parameters 8*2143Seric of existing ones. Arguments to the program may appear in 9*2143Seric any order and consist of keyletters, which begin with '-', 10*2143Seric and named files. Named files which do not exist are created 11*2143Seric and their parameters are initialized according to the given 12*2143Seric keyletter arguments, or are given default values if the 13*2143Seric corresponding keyletters were not supplied. Named files which 14*2143Seric do exist have those parameters corresponding to given key-letter 15*2143Seric arguments changed and other parameters are left as is. 16*2143Seric 17*2143Seric If a directory is given as an argument, each SCCS file within 18*2143Seric the directory is processed as if it had been specifically named. 19*2143Seric If a name of '-' is given, the standard input is read for a list 20*2143Seric of names of SCCS files to be processed. 21*2143Seric Non-SCCS files are ignored. 22*2143Seric 23*2143Seric Files created are given mode 444. 24*2143Seric */ 25*2143Seric 26*2143Seric # define MINR 1 /* minimum release number */ 27*2143Seric # define MAXR 9999 /* maximum release number */ 28*2143Seric # define MAXNAMES 9 29*2143Seric # define COPY 0 30*2143Seric # define NOCOPY 1 31*2143Seric 32*2143Seric char *ifile, *tfile; 33*2143Seric char *z; /* for validation program name */ 34*2143Seric char had[26], had_flag[26], rm_flag[26]; 35*2143Seric char *Comments, *Mrs; 36*2143Seric char Valpgm[] "/usr/local/val"; 37*2143Seric int irel, fexists, num_files; 38*2143Seric int VFLAG 0; 39*2143Seric int Domrs; 40*2143Seric char *Sflags[]; 41*2143Seric char *anames[MAXNAMES], *enames[MAXNAMES]; 42*2143Seric char *flag_p[26]; 43*2143Seric int asub, esub; 44*2143Seric int check_id; 45*2143Seric int Did_id; 46*2143Seric 47*2143Seric main(argc,argv) 48*2143Seric int argc; 49*2143Seric char *argv[]; 50*2143Seric { 51*2143Seric register int j; 52*2143Seric register char *p; 53*2143Seric char c, f; 54*2143Seric int i, testklt; 55*2143Seric extern admin(); 56*2143Seric extern int Fcnt; 57*2143Seric struct sid sid; 58*2143Seric 59*2143Seric /* 60*2143Seric Set flags for 'fatal' to issue message, call clean-up 61*2143Seric routine and terminate processing. 62*2143Seric */ 63*2143Seric Fflags = FTLMSG | FTLCLN | FTLEXIT; 64*2143Seric 65*2143Seric testklt = 1; 66*2143Seric 67*2143Seric /* 68*2143Seric The following loop processes keyletters and arguments. 69*2143Seric Note that these are processed only once for each 70*2143Seric invocation of 'main'. 71*2143Seric */ 72*2143Seric for(j=1; j<argc; j++) 73*2143Seric if(argv[j][0] == '-' && (c = argv[j][1])) { 74*2143Seric p = &argv[j][2]; 75*2143Seric switch (c) { 76*2143Seric 77*2143Seric case 'i': /* name of file of body */ 78*2143Seric ifile = p; 79*2143Seric break; 80*2143Seric 81*2143Seric case 't': /* name of file of descriptive text */ 82*2143Seric tfile = p; 83*2143Seric break; 84*2143Seric case 'm': /* mr flag */ 85*2143Seric Mrs = p; 86*2143Seric break; 87*2143Seric case 'y': /* comments flag for entry */ 88*2143Seric Comments = p; 89*2143Seric break; 90*2143Seric 91*2143Seric case 'd': /* flags to be deleted */ 92*2143Seric testklt = 0; 93*2143Seric if (!(f = *p)) 94*2143Seric fatal("d has no argument (ad1)"); 95*2143Seric p = &argv[j][3]; 96*2143Seric 97*2143Seric switch (f) { 98*2143Seric 99*2143Seric case IDFLAG: /* see 'f' keyletter */ 100*2143Seric case BRCHFLAG: /* for meanings of flags */ 101*2143Seric case VALFLAG: 102*2143Seric case TYPEFLAG: 103*2143Seric case MODFLAG: 104*2143Seric case NULLFLAG: 105*2143Seric case FLORFLAG: 106*2143Seric case CEILFLAG: 107*2143Seric case DEFTFLAG: 108*2143Seric if (*p) 109*2143Seric fatal(sprintf(Error, 110*2143Seric "value after %c flag (ad12)",f)); 111*2143Seric break; 112*2143Seric 113*2143Seric default: 114*2143Seric fatal("unknown flag (ad3)"); 115*2143Seric } 116*2143Seric 117*2143Seric if (rm_flag[f - 'a']++) 118*2143Seric fatal("flag twice (ad4)"); 119*2143Seric break; 120*2143Seric 121*2143Seric case 'f': /* flags to be added */ 122*2143Seric testklt = 0; 123*2143Seric if (!(f = *p)) 124*2143Seric fatal("f has no argument (ad5)"); 125*2143Seric p = &argv[j][3]; 126*2143Seric 127*2143Seric switch (f) { 128*2143Seric 129*2143Seric case IDFLAG: /* id-kwd message (err/warn) */ 130*2143Seric case BRCHFLAG: /* branch */ 131*2143Seric case NULLFLAG: /* null deltas */ 132*2143Seric if (*p) 133*2143Seric fatal(sprintf(Error, 134*2143Seric "value after %c flag (ad13)",f)); 135*2143Seric break; 136*2143Seric 137*2143Seric case VALFLAG: /* mr validation */ 138*2143Seric VFLAG++; 139*2143Seric if (*p) 140*2143Seric z = p; 141*2143Seric break; 142*2143Seric 143*2143Seric case FLORFLAG: /* floor */ 144*2143Seric if ((i = patoi(p)) == -1) 145*2143Seric fatal("floor not numeric (ad22)"); 146*2143Seric if ((size(p) > 5) || (i < MINR) || 147*2143Seric (i > MAXR)) 148*2143Seric fatal("floor out of range (ad23)"); 149*2143Seric break; 150*2143Seric 151*2143Seric case CEILFLAG: /* ceiling */ 152*2143Seric if ((i = patoi(p)) == -1) 153*2143Seric fatal("ceiling not numeric (ad24)"); 154*2143Seric if ((size(p) > 5) || (i < MINR) || 155*2143Seric (i > MAXR)) 156*2143Seric fatal("ceiling out of range (ad25)"); 157*2143Seric break; 158*2143Seric 159*2143Seric case DEFTFLAG: /* default sid */ 160*2143Seric if (!(*p)) 161*2143Seric fatal("no default sid (ad14)"); 162*2143Seric chksid(sid_ab(p,&sid),&sid); 163*2143Seric break; 164*2143Seric 165*2143Seric case TYPEFLAG: /* type */ 166*2143Seric case MODFLAG: /* module name */ 167*2143Seric if (!(*p)) 168*2143Seric fatal(sprintf(Error, 169*2143Seric "flag %c has no value (ad2)",f)); 170*2143Seric break; 171*2143Seric 172*2143Seric default: 173*2143Seric fatal("unknown flag (ad3)"); 174*2143Seric } 175*2143Seric 176*2143Seric if (had_flag[f - 'a']++) 177*2143Seric fatal("flag twice (ad4)"); 178*2143Seric flag_p[f - 'a'] = p; 179*2143Seric break; 180*2143Seric 181*2143Seric case 'r': /* initial release number supplied */ 182*2143Seric if ((irel = patoi(p)) == -1) 183*2143Seric fatal("r arg not numeric (ad6)"); 184*2143Seric if ((size(p) > 5) || (irel < MINR) || 185*2143Seric (irel > MAXR)) 186*2143Seric fatal("r out of range (ad7)"); 187*2143Seric break; 188*2143Seric 189*2143Seric case 'n': /* creating new SCCS file */ 190*2143Seric case 'h': /* only check hash of file */ 191*2143Seric case 'z': /* zero the input hash */ 192*2143Seric break; 193*2143Seric 194*2143Seric case 'a': /* user-name allowed to make deltas */ 195*2143Seric testklt = 0; 196*2143Seric if (!(*p)) 197*2143Seric fatal("bad a argument (ad8)"); 198*2143Seric if (asub > MAXNAMES) 199*2143Seric fatal("too many 'a' keyletters (ad9)"); 200*2143Seric anames[asub++] = p; 201*2143Seric break; 202*2143Seric 203*2143Seric case 'e': /* user-name to be removed */ 204*2143Seric testklt = 0; 205*2143Seric if (!(*p)) 206*2143Seric fatal("bad e argument (ad10)"); 207*2143Seric if (esub > MAXNAMES) 208*2143Seric fatal("too many 'e' keyletters (ad11)"); 209*2143Seric enames[esub++] = p; 210*2143Seric break; 211*2143Seric 212*2143Seric default: 213*2143Seric fatal("unknown key letter (cm1)"); 214*2143Seric } 215*2143Seric 216*2143Seric if (had[c - 'a']++ && testklt++) 217*2143Seric fatal("key letter twice (cm2)"); 218*2143Seric argv[j] = 0; 219*2143Seric } 220*2143Seric else 221*2143Seric num_files++; 222*2143Seric 223*2143Seric if (num_files == 0) 224*2143Seric fatal("missing file arg (cm3)"); 225*2143Seric 226*2143Seric if (HADI && num_files > 1) /* only one file allowed with `i' */ 227*2143Seric fatal("more than one file (ad15)"); 228*2143Seric 229*2143Seric setsig(); 230*2143Seric 231*2143Seric /* 232*2143Seric Change flags for 'fatal' so that it will return to this 233*2143Seric routine (main) instead of terminating processing. 234*2143Seric */ 235*2143Seric Fflags =& ~FTLEXIT; 236*2143Seric Fflags =| FTLJMP; 237*2143Seric 238*2143Seric /* 239*2143Seric Call 'admin' routine for each file argument. 240*2143Seric */ 241*2143Seric for (j=1; j<argc; j++) 242*2143Seric if (p = argv[j]) 243*2143Seric do_file(p,admin); 244*2143Seric 245*2143Seric exit(Fcnt ? 1 : 0); 246*2143Seric } 247*2143Seric 248*2143Seric 249*2143Seric /* 250*2143Seric Routine that actually does admin's work on SCCS files. 251*2143Seric Existing s-files are copied, with changes being made, to a 252*2143Seric temporary file (x-file). The name of the x-file is the same as the 253*2143Seric name of the s-file, with the 's.' replaced by 'x.'. 254*2143Seric s-files which are to be created are processed in a similar 255*2143Seric manner, except that a dummy s-file is first created with 256*2143Seric mode 444. 257*2143Seric At end of processing, the x-file is renamed with the name of s-file 258*2143Seric and the old s-file is removed. 259*2143Seric */ 260*2143Seric 261*2143Seric struct packet gpkt; /* see file defines.h */ 262*2143Seric char Zhold[BUFSIZ]; /* temporary z-file name */ 263*2143Seric 264*2143Seric USXALLOC(); /* defines alloc() and free() */ 265*2143Seric 266*2143Seric admin(afile) 267*2143Seric char *afile; 268*2143Seric { 269*2143Seric struct deltab dt; /* see file defines.h */ 270*2143Seric struct stats stats; /* see file defines.h */ 271*2143Seric FILE *iptr; 272*2143Seric register int k; 273*2143Seric register char *cp, *q; 274*2143Seric char command[80]; 275*2143Seric char line[512]; 276*2143Seric int i; /* used in forking procedure */ 277*2143Seric int status; 278*2143Seric extern nfiles; 279*2143Seric extern had_dir; 280*2143Seric 281*2143Seric if (setjmp(Fjmp)) /* set up to return here from 'fatal' */ 282*2143Seric return; /* and return to caller of admin */ 283*2143Seric 284*2143Seric if (HADI && had_dir) /* directory not allowed with `i' keyletter */ 285*2143Seric fatal("directory named with `i' keyletter (ad26)"); 286*2143Seric 287*2143Seric fexists = exists(afile); 288*2143Seric 289*2143Seric if (HADI) 290*2143Seric HADN = 1; 291*2143Seric if (HADI || HADN) { 292*2143Seric if (HADM && !VFLAG) 293*2143Seric fatal("MRs not allowed (de8)"); 294*2143Seric 295*2143Seric if (VFLAG && !HADM) 296*2143Seric fatal("MRs required (de10)"); 297*2143Seric 298*2143Seric } 299*2143Seric 300*2143Seric if (!HADI && HADR) 301*2143Seric fatal("r only allowed with i (ad16)"); 302*2143Seric 303*2143Seric if (HADN && HADT && !(*tfile)) 304*2143Seric fatal("t has no argument (ad17)"); 305*2143Seric 306*2143Seric if (HADN && HADD) 307*2143Seric fatal("d not allowed with n (ad18)"); 308*2143Seric 309*2143Seric if (HADN && fexists) 310*2143Seric fatal(sprintf(Error,"file %s exists (ad19)",afile)); 311*2143Seric 312*2143Seric if (!HADN && !fexists) 313*2143Seric fatal(sprintf(Error,"file %s does not exist (ad20)",afile)); 314*2143Seric /* 315*2143Seric Check for '-h' flag. If set, create child process and 316*2143Seric invoke 'get' to examine format of SCCS file. 317*2143Seric */ 318*2143Seric 319*2143Seric if (HADH) { 320*2143Seric /* 321*2143Seric fork here so 'admin' can execute 'val' to 322*2143Seric check for a corrupted file. 323*2143Seric */ 324*2143Seric if ((i = fork()) < 0) 325*2143Seric fatal("cannot fork, try again"); 326*2143Seric if (i == 0) { /* child */ 327*2143Seric /* 328*2143Seric perform 'val' with appropriate keyletters 329*2143Seric */ 330*2143Seric execl("/bin/sh","/bin/sh","-c", 331*2143Seric sprintf(command, 332*2143Seric "/usr/local/val -s %s", 333*2143Seric afile),0); 334*2143Seric fatal(sprintf(Error,"cannot execute '%s'",Valpgm)); 335*2143Seric } 336*2143Seric else { 337*2143Seric wait(&status); /* wait on status from 'execl' */ 338*2143Seric if (status) 339*2143Seric fatal("corrupted file (co6)"); 340*2143Seric return; /* return to caller of 'admin' */ 341*2143Seric } 342*2143Seric } 343*2143Seric 344*2143Seric /* 345*2143Seric Lock out any other user who may be trying to process 346*2143Seric the same file. 347*2143Seric */ 348*2143Seric if (!HADH && lockit(copy(auxf(afile,'z'),Zhold),2,getpid())) 349*2143Seric fatal("cannot create lock file (cm4)"); 350*2143Seric 351*2143Seric if (fexists) 352*2143Seric sinit(&gpkt,afile,1); /* init pkt & open s-file */ 353*2143Seric else { 354*2143Seric xfcreat(afile,0444); /* create dummy s-file */ 355*2143Seric sinit(&gpkt,afile,0); /* and init pkt */ 356*2143Seric } 357*2143Seric 358*2143Seric if (!HADH) 359*2143Seric /* 360*2143Seric set the flag for 'putline' routine to open 361*2143Seric the 'x-file' and allow writing on it. 362*2143Seric */ 363*2143Seric gpkt.p_upd = 1; 364*2143Seric 365*2143Seric if (HADZ) { 366*2143Seric gpkt.do_chksum = 0; /* ignore checksum processing */ 367*2143Seric gpkt.p_ihash = 0; 368*2143Seric } 369*2143Seric 370*2143Seric /* 371*2143Seric Get statistics of latest delta in old file. 372*2143Seric */ 373*2143Seric if (!HADN) { 374*2143Seric stats_ab(&gpkt,&stats); 375*2143Seric gpkt.p_wrttn++; 376*2143Seric newstats(&gpkt,line,"0"); 377*2143Seric } 378*2143Seric 379*2143Seric if (HADN) { /* N E W F I L E */ 380*2143Seric 381*2143Seric /* 382*2143Seric Beginning of SCCS file. 383*2143Seric */ 384*2143Seric putline(&gpkt,sprintf(line,"%c%c%s\n",CTLCHAR,HEAD,"00000")); 385*2143Seric 386*2143Seric /* 387*2143Seric Statistics. 388*2143Seric */ 389*2143Seric newstats(&gpkt,line,"0"); 390*2143Seric 391*2143Seric dt.d_type = 'D'; /* type of delta */ 392*2143Seric 393*2143Seric /* 394*2143Seric Set initial release, level, branch and 395*2143Seric sequence values. 396*2143Seric */ 397*2143Seric if (HADR) 398*2143Seric dt.d_sid.s_rel = irel; 399*2143Seric else 400*2143Seric dt.d_sid.s_rel = 1; 401*2143Seric dt.d_sid.s_lev = 1; 402*2143Seric dt.d_sid.s_br = dt.d_sid.s_seq = 0; 403*2143Seric 404*2143Seric time(&dt.d_datetime); /* get time and date */ 405*2143Seric 406*2143Seric copy(logname(),dt.d_pgmr); /* get user's name */ 407*2143Seric 408*2143Seric dt.d_serial = 1; 409*2143Seric dt.d_pred = 0; 410*2143Seric 411*2143Seric del_ba(&dt,line); /* form and write */ 412*2143Seric putline(&gpkt,line); /* delta-table entry */ 413*2143Seric 414*2143Seric /* 415*2143Seric If -m flag, enter MR numbers 416*2143Seric */ 417*2143Seric 418*2143Seric if (Mrs) { 419*2143Seric mrfixup(); 420*2143Seric if (z && valmrs(&gpkt,z)) 421*2143Seric fatal("invalid MRs (de9)"); 422*2143Seric putmrs(&gpkt); 423*2143Seric } 424*2143Seric 425*2143Seric /* 426*2143Seric Enter comment line for `chghist' 427*2143Seric */ 428*2143Seric 429*2143Seric if (HADY) { 430*2143Seric putline(&gpkt,sprintf(line,"%c%c ",CTLCHAR,COMMENTS)); 431*2143Seric putline(&gpkt,Comments); 432*2143Seric putline(&gpkt,"\n"); 433*2143Seric } 434*2143Seric else { 435*2143Seric /* 436*2143Seric insert date/time and pgmr into comment line 437*2143Seric */ 438*2143Seric cmt_ba(&dt,line); 439*2143Seric putline(&gpkt,line); 440*2143Seric } 441*2143Seric /* 442*2143Seric End of delta-table. 443*2143Seric */ 444*2143Seric putline(&gpkt,sprintf(line,CTLSTR,CTLCHAR,EDELTAB)); 445*2143Seric 446*2143Seric /* 447*2143Seric Beginning of user-name section. 448*2143Seric */ 449*2143Seric putline(&gpkt,sprintf(line,CTLSTR,CTLCHAR,BUSERNAM)); 450*2143Seric } 451*2143Seric else 452*2143Seric /* 453*2143Seric For old file, copy to x-file until user-name section 454*2143Seric is found. 455*2143Seric */ 456*2143Seric flushto(&gpkt,BUSERNAM,COPY); 457*2143Seric 458*2143Seric /* 459*2143Seric Write user-names to be added to list of those 460*2143Seric allowed to make deltas. 461*2143Seric */ 462*2143Seric if (HADA) 463*2143Seric for (k = 0; k < asub; k++) 464*2143Seric putline(&gpkt,sprintf(line,"%s\n",anames[k])); 465*2143Seric 466*2143Seric /* 467*2143Seric Do not copy those user-names which are to be erased. 468*2143Seric */ 469*2143Seric if (HADE && !HADN) 470*2143Seric while ((cp = getline(&gpkt)) && 471*2143Seric !(*cp++ == CTLCHAR && *cp == EUSERNAM)) { 472*2143Seric for (k = 0; k < esub; k++) { 473*2143Seric cp = &gpkt.p_line; 474*2143Seric while (*cp) /* find and */ 475*2143Seric cp++; /* zero newline */ 476*2143Seric *--cp = '\0'; /* character */ 477*2143Seric 478*2143Seric if (equal(enames[k],&gpkt.p_line)) { 479*2143Seric /* 480*2143Seric Tell getline not to output 481*2143Seric previously read line. 482*2143Seric */ 483*2143Seric gpkt.p_wrttn = 1; 484*2143Seric break; 485*2143Seric } 486*2143Seric else 487*2143Seric *cp = '\n'; /* restore newline */ 488*2143Seric } 489*2143Seric } 490*2143Seric 491*2143Seric if (HADN) { /* N E W F I L E */ 492*2143Seric 493*2143Seric /* 494*2143Seric End of user-name section. 495*2143Seric */ 496*2143Seric putline(&gpkt,sprintf(line,CTLSTR,CTLCHAR,EUSERNAM)); 497*2143Seric } 498*2143Seric else 499*2143Seric /* 500*2143Seric For old file, copy to x-file until end of 501*2143Seric user-names section is found. 502*2143Seric */ 503*2143Seric if (!HADE) 504*2143Seric flushto(&gpkt,EUSERNAM,COPY); 505*2143Seric 506*2143Seric /* 507*2143Seric For old file, read flags and their values (if any), and 508*2143Seric store them. Check to see if the flag read is one that 509*2143Seric should be deleted. 510*2143Seric */ 511*2143Seric if (!HADN) 512*2143Seric while ((cp = getline(&gpkt)) && 513*2143Seric (*cp++ == CTLCHAR && *cp == FLAG)) { 514*2143Seric 515*2143Seric gpkt.p_wrttn = 1; /* don't write previous line */ 516*2143Seric 517*2143Seric cp =+ 2; /* point to flag character */ 518*2143Seric k = *cp - 'a'; 519*2143Seric 520*2143Seric if (!had_flag[k] && !rm_flag[k]) { 521*2143Seric had_flag[k] = 2; /* indicate flag is */ 522*2143Seric /* from file, not */ 523*2143Seric /* from arg list */ 524*2143Seric 525*2143Seric if (*++cp != '\n') { /* get flag value */ 526*2143Seric q = alloc(size(gpkt.p_line)-5); 527*2143Seric copy(++cp,q); 528*2143Seric flag_p[k] = q; 529*2143Seric while (*q) /* find and */ 530*2143Seric q++; /* zero newline */ 531*2143Seric *--q = '\0'; /* character */ 532*2143Seric } 533*2143Seric } 534*2143Seric else 535*2143Seric if (rm_flag[k]) 536*2143Seric had_flag[k] = 0; 537*2143Seric } 538*2143Seric 539*2143Seric 540*2143Seric /* 541*2143Seric Write out flags. 542*2143Seric */ 543*2143Seric for (k = 0; k < 26; k++) 544*2143Seric if (had_flag[k]) { 545*2143Seric if (flag_p[k]) 546*2143Seric sprintf(line,"%c%c %c %s\n", 547*2143Seric CTLCHAR,FLAG,'a'+k,flag_p[k]); 548*2143Seric else 549*2143Seric sprintf(line,"%c%c %c\n", 550*2143Seric CTLCHAR,FLAG,'a'+k); 551*2143Seric 552*2143Seric putline(&gpkt,line); 553*2143Seric 554*2143Seric if (had_flag[k] == 2) { /* flag was taken from file */ 555*2143Seric had_flag[k] = 0; 556*2143Seric if (flag_p[k]) { 557*2143Seric free(flag_p[k]); 558*2143Seric flag_p[k] = 0; 559*2143Seric } 560*2143Seric } 561*2143Seric } 562*2143Seric 563*2143Seric if (HADN) 564*2143Seric /* 565*2143Seric Beginning of descriptive (user) text. 566*2143Seric */ 567*2143Seric putline(&gpkt,sprintf(line,CTLSTR,CTLCHAR,BUSERTXT)); 568*2143Seric else 569*2143Seric /* 570*2143Seric Write out BUSERTXT record which was read in 571*2143Seric above loop that processes flags. 572*2143Seric */ 573*2143Seric gpkt.p_wrttn = 0; 574*2143Seric putline(&gpkt,0); 575*2143Seric 576*2143Seric /* 577*2143Seric Get user description, copy to x-file. 578*2143Seric */ 579*2143Seric if (HADT) { 580*2143Seric if (*tfile) { 581*2143Seric iptr = xfopen(tfile,0); 582*2143Seric fgetchk(line,512,iptr,tfile,&gpkt); 583*2143Seric fclose(iptr); 584*2143Seric } 585*2143Seric 586*2143Seric /* 587*2143Seric If old file, ignore any previously supplied 588*2143Seric commentary. (i.e., don't copy it to x-file.) 589*2143Seric */ 590*2143Seric if (!HADN) 591*2143Seric flushto(&gpkt,EUSERTXT,NOCOPY); 592*2143Seric } 593*2143Seric 594*2143Seric if (HADN) { /* N E W F I L E */ 595*2143Seric 596*2143Seric /* 597*2143Seric End of user description. 598*2143Seric */ 599*2143Seric putline(&gpkt,sprintf(line,CTLSTR,CTLCHAR,EUSERTXT)); 600*2143Seric 601*2143Seric /* 602*2143Seric Beginning of body (text) of first delta. 603*2143Seric */ 604*2143Seric putline(&gpkt,sprintf(line,"%c%c %u\n",CTLCHAR,INS,1)); 605*2143Seric 606*2143Seric if (HADI) { /* get body */ 607*2143Seric 608*2143Seric /* 609*2143Seric Set indicator to check lines of body of file for 610*2143Seric keyword definitions. 611*2143Seric If no keywords are found, a warning 612*2143Seric will be produced. 613*2143Seric */ 614*2143Seric check_id = 1; 615*2143Seric /* 616*2143Seric Set indicator that tells whether there 617*2143Seric were any keywords to 'no'. 618*2143Seric */ 619*2143Seric Did_id = 0; 620*2143Seric if (*ifile) 621*2143Seric iptr = xfopen(ifile,0); /* from a file */ 622*2143Seric else 623*2143Seric iptr = stdin; /* from standard input */ 624*2143Seric 625*2143Seric /* 626*2143Seric Read and copy to x-file, while checking 627*2143Seric first character of each line to see that it 628*2143Seric is not the control character (octal 1). 629*2143Seric Also, count lines read, and set statistics' 630*2143Seric structure appropriately. 631*2143Seric The 'fgetchk' routine will check for keywords. 632*2143Seric */ 633*2143Seric stats.s_ins = fgetchk(line,512,iptr,ifile,&gpkt); 634*2143Seric stats.s_del = stats.s_unc = 0; 635*2143Seric 636*2143Seric /* 637*2143Seric If no keywords were found, issue warning. 638*2143Seric */ 639*2143Seric if (!Did_id) { 640*2143Seric if (had_flag[IDFLAG - 'a']) 641*2143Seric fatal("no id keywords (cm6)"); 642*2143Seric else 643*2143Seric fprintf(stderr,"%s\n","No id keywords (cm7)"); 644*2143Seric } 645*2143Seric 646*2143Seric check_id = 0; 647*2143Seric Did_id = 0; 648*2143Seric } 649*2143Seric 650*2143Seric /* 651*2143Seric End of body of first delta. 652*2143Seric */ 653*2143Seric putline(&gpkt,sprintf(line,"%c%c %u\n",CTLCHAR,END,1)); 654*2143Seric } 655*2143Seric else { 656*2143Seric /* 657*2143Seric Indicate that EOF at this point is ok, and 658*2143Seric flush rest of (old) s-file to x-file. 659*2143Seric */ 660*2143Seric gpkt.p_chkeof = 1; 661*2143Seric while (getline(&gpkt)) ; 662*2143Seric } 663*2143Seric 664*2143Seric /* 665*2143Seric Flush the buffer, take care of rewinding to insert 666*2143Seric checksum and statistics in file, and close. 667*2143Seric */ 668*2143Seric flushline(&gpkt,&stats); 669*2143Seric 670*2143Seric /* 671*2143Seric Change x-file name to s-file, and delete old file. 672*2143Seric Unlock file before returning. 673*2143Seric */ 674*2143Seric if (!HADH) { 675*2143Seric rename(auxf(&gpkt,'x'),&gpkt); 676*2143Seric xrm(&gpkt); 677*2143Seric unlockit(auxf(afile,'z'),getpid()); 678*2143Seric } 679*2143Seric } 680*2143Seric 681*2143Seric 682*2143Seric fgetchk(strp,len,inptr,file,pkt) 683*2143Seric register char *strp; 684*2143Seric register int len; 685*2143Seric FILE *inptr; 686*2143Seric register char *file; 687*2143Seric register struct packet *pkt; 688*2143Seric { 689*2143Seric register int k; 690*2143Seric 691*2143Seric for (k = 1; fgets(strp,len,inptr); k++) { 692*2143Seric if (*strp == CTLCHAR) fatal( 693*2143Seric sprintf(Error,"%s illegal data on line %d (ad21)", 694*2143Seric file,k)); 695*2143Seric 696*2143Seric if (check_id) 697*2143Seric chkid(strp); 698*2143Seric 699*2143Seric putline(pkt,strp); 700*2143Seric } 701*2143Seric return(k - 1); 702*2143Seric } 703*2143Seric 704*2143Seric 705*2143Seric clean_up() 706*2143Seric { 707*2143Seric xrm(&gpkt); 708*2143Seric if (!HADH) 709*2143Seric unlockit(Zhold,getpid()); 710*2143Seric if (HADN) 711*2143Seric unlink(&gpkt); 712*2143Seric } 713*2143Seric 714*2143Seric 715*2143Seric cmt_ba(dt,str) 716*2143Seric register struct deltab *dt; 717*2143Seric char *str; 718*2143Seric { 719*2143Seric register char *p; 720*2143Seric 721*2143Seric p = str; 722*2143Seric *p++ = CTLCHAR; 723*2143Seric *p++ = COMMENTS; 724*2143Seric *p++ = ' '; 725*2143Seric copy("date and time created",p); 726*2143Seric while (*p++) 727*2143Seric ; 728*2143Seric --p; 729*2143Seric *p++ = ' '; 730*2143Seric date_ba(&dt->d_datetime,p); 731*2143Seric while (*p++) 732*2143Seric ; 733*2143Seric --p; 734*2143Seric *p++ = ' '; 735*2143Seric copy("by",p); 736*2143Seric while (*p++) 737*2143Seric ; 738*2143Seric --p; 739*2143Seric *p++ = ' '; 740*2143Seric copy(dt->d_pgmr,p); 741*2143Seric while (*p++) 742*2143Seric ; 743*2143Seric --p; 744*2143Seric *p++ = '\n'; 745*2143Seric *p = 0; 746*2143Seric return(str); 747*2143Seric } 748*2143Seric 749*2143Seric 750*2143Seric putmrs(pkt) 751*2143Seric struct packet *pkt; 752*2143Seric { 753*2143Seric register char **argv; 754*2143Seric char str[64]; 755*2143Seric extern char *Varg[]; 756*2143Seric 757*2143Seric for (argv = &Varg[VSTART]; *argv; argv++) 758*2143Seric putline(pkt,sprintf(str,"%c%c %s\n",CTLCHAR,MRNUM,*argv)); 759*2143Seric } 760