12143Seric # include "../hdr/defines.h" 22143Seric # include "../hdr/had.h" 32143Seric 4*30503Slepreau static char Sccsid[] = "@(#)admin.c 4.2 02/15/87"; 52143Seric 62143Seric /* 72143Seric Program to create new SCCS files and change parameters 82143Seric of existing ones. Arguments to the program may appear in 92143Seric any order and consist of keyletters, which begin with '-', 102143Seric and named files. Named files which do not exist are created 112143Seric and their parameters are initialized according to the given 122143Seric keyletter arguments, or are given default values if the 132143Seric corresponding keyletters were not supplied. Named files which 142143Seric do exist have those parameters corresponding to given key-letter 152143Seric arguments changed and other parameters are left as is. 162143Seric 172143Seric If a directory is given as an argument, each SCCS file within 182143Seric the directory is processed as if it had been specifically named. 192143Seric If a name of '-' is given, the standard input is read for a list 202143Seric of names of SCCS files to be processed. 212143Seric Non-SCCS files are ignored. 222143Seric 232143Seric Files created are given mode 444. 242143Seric */ 252143Seric 262143Seric # define MINR 1 /* minimum release number */ 272143Seric # define MAXR 9999 /* maximum release number */ 282143Seric # define MAXNAMES 9 292143Seric # define COPY 0 302143Seric # define NOCOPY 1 312143Seric 322143Seric char *ifile, *tfile; 332143Seric char *z; /* for validation program name */ 342143Seric char had[26], had_flag[26], rm_flag[26]; 352143Seric char *Comments, *Mrs; 36*30503Slepreau char Valpgm[] = "/usr/local/val"; 372143Seric int irel, fexists, num_files; 38*30503Slepreau int VFLAG = 0; 392143Seric int Domrs; 402143Seric char *Sflags[]; 412143Seric char *anames[MAXNAMES], *enames[MAXNAMES]; 422143Seric char *flag_p[26]; 432143Seric int asub, esub; 442143Seric int check_id; 452143Seric int Did_id; 462143Seric 472143Seric main(argc,argv) 482143Seric int argc; 492143Seric char *argv[]; 502143Seric { 512143Seric register int j; 522143Seric register char *p; 532143Seric char c, f; 542143Seric int i, testklt; 552143Seric extern admin(); 562143Seric extern int Fcnt; 572143Seric struct sid sid; 582143Seric 592143Seric /* 602143Seric Set flags for 'fatal' to issue message, call clean-up 612143Seric routine and terminate processing. 622143Seric */ 632143Seric Fflags = FTLMSG | FTLCLN | FTLEXIT; 642143Seric 652143Seric testklt = 1; 662143Seric 672143Seric /* 682143Seric The following loop processes keyletters and arguments. 692143Seric Note that these are processed only once for each 702143Seric invocation of 'main'. 712143Seric */ 722143Seric for(j=1; j<argc; j++) 732143Seric if(argv[j][0] == '-' && (c = argv[j][1])) { 742143Seric p = &argv[j][2]; 752143Seric switch (c) { 762143Seric 772143Seric case 'i': /* name of file of body */ 782143Seric ifile = p; 792143Seric break; 802143Seric 812143Seric case 't': /* name of file of descriptive text */ 822143Seric tfile = p; 832143Seric break; 842143Seric case 'm': /* mr flag */ 852143Seric Mrs = p; 862143Seric break; 872143Seric case 'y': /* comments flag for entry */ 882143Seric Comments = p; 892143Seric break; 902143Seric 912143Seric case 'd': /* flags to be deleted */ 922143Seric testklt = 0; 932143Seric if (!(f = *p)) 942143Seric fatal("d has no argument (ad1)"); 952143Seric p = &argv[j][3]; 962143Seric 972143Seric switch (f) { 982143Seric 992143Seric case IDFLAG: /* see 'f' keyletter */ 1002143Seric case BRCHFLAG: /* for meanings of flags */ 1012143Seric case VALFLAG: 1022143Seric case TYPEFLAG: 1032143Seric case MODFLAG: 1042143Seric case NULLFLAG: 1052143Seric case FLORFLAG: 1062143Seric case CEILFLAG: 1072143Seric case DEFTFLAG: 1082143Seric if (*p) 1092143Seric fatal(sprintf(Error, 1102143Seric "value after %c flag (ad12)",f)); 1112143Seric break; 1122143Seric 1132143Seric default: 1142143Seric fatal("unknown flag (ad3)"); 1152143Seric } 1162143Seric 1172143Seric if (rm_flag[f - 'a']++) 1182143Seric fatal("flag twice (ad4)"); 1192143Seric break; 1202143Seric 1212143Seric case 'f': /* flags to be added */ 1222143Seric testklt = 0; 1232143Seric if (!(f = *p)) 1242143Seric fatal("f has no argument (ad5)"); 1252143Seric p = &argv[j][3]; 1262143Seric 1272143Seric switch (f) { 1282143Seric 1292143Seric case IDFLAG: /* id-kwd message (err/warn) */ 1302143Seric case BRCHFLAG: /* branch */ 1312143Seric case NULLFLAG: /* null deltas */ 1322143Seric if (*p) 1332143Seric fatal(sprintf(Error, 1342143Seric "value after %c flag (ad13)",f)); 1352143Seric break; 1362143Seric 1372143Seric case VALFLAG: /* mr validation */ 1382143Seric VFLAG++; 1392143Seric if (*p) 1402143Seric z = p; 1412143Seric break; 1422143Seric 1432143Seric case FLORFLAG: /* floor */ 1442143Seric if ((i = patoi(p)) == -1) 1452143Seric fatal("floor not numeric (ad22)"); 1462143Seric if ((size(p) > 5) || (i < MINR) || 1472143Seric (i > MAXR)) 1482143Seric fatal("floor out of range (ad23)"); 1492143Seric break; 1502143Seric 1512143Seric case CEILFLAG: /* ceiling */ 1522143Seric if ((i = patoi(p)) == -1) 1532143Seric fatal("ceiling not numeric (ad24)"); 1542143Seric if ((size(p) > 5) || (i < MINR) || 1552143Seric (i > MAXR)) 1562143Seric fatal("ceiling out of range (ad25)"); 1572143Seric break; 1582143Seric 1592143Seric case DEFTFLAG: /* default sid */ 1602143Seric if (!(*p)) 1612143Seric fatal("no default sid (ad14)"); 1622143Seric chksid(sid_ab(p,&sid),&sid); 1632143Seric break; 1642143Seric 1652143Seric case TYPEFLAG: /* type */ 1662143Seric case MODFLAG: /* module name */ 1672143Seric if (!(*p)) 1682143Seric fatal(sprintf(Error, 1692143Seric "flag %c has no value (ad2)",f)); 1702143Seric break; 1712143Seric 1722143Seric default: 1732143Seric fatal("unknown flag (ad3)"); 1742143Seric } 1752143Seric 1762143Seric if (had_flag[f - 'a']++) 1772143Seric fatal("flag twice (ad4)"); 1782143Seric flag_p[f - 'a'] = p; 1792143Seric break; 1802143Seric 1812143Seric case 'r': /* initial release number supplied */ 1822143Seric if ((irel = patoi(p)) == -1) 1832143Seric fatal("r arg not numeric (ad6)"); 1842143Seric if ((size(p) > 5) || (irel < MINR) || 1852143Seric (irel > MAXR)) 1862143Seric fatal("r out of range (ad7)"); 1872143Seric break; 1882143Seric 1892143Seric case 'n': /* creating new SCCS file */ 1902143Seric case 'h': /* only check hash of file */ 1912143Seric case 'z': /* zero the input hash */ 1922143Seric break; 1932143Seric 1942143Seric case 'a': /* user-name allowed to make deltas */ 1952143Seric testklt = 0; 1962143Seric if (!(*p)) 1972143Seric fatal("bad a argument (ad8)"); 1982143Seric if (asub > MAXNAMES) 1992143Seric fatal("too many 'a' keyletters (ad9)"); 2002143Seric anames[asub++] = p; 2012143Seric break; 2022143Seric 2032143Seric case 'e': /* user-name to be removed */ 2042143Seric testklt = 0; 2052143Seric if (!(*p)) 2062143Seric fatal("bad e argument (ad10)"); 2072143Seric if (esub > MAXNAMES) 2082143Seric fatal("too many 'e' keyletters (ad11)"); 2092143Seric enames[esub++] = p; 2102143Seric break; 2112143Seric 2122143Seric default: 2132143Seric fatal("unknown key letter (cm1)"); 2142143Seric } 2152143Seric 2162143Seric if (had[c - 'a']++ && testklt++) 2172143Seric fatal("key letter twice (cm2)"); 2182143Seric argv[j] = 0; 2192143Seric } 2202143Seric else 2212143Seric num_files++; 2222143Seric 2232143Seric if (num_files == 0) 2242143Seric fatal("missing file arg (cm3)"); 2252143Seric 2262143Seric if (HADI && num_files > 1) /* only one file allowed with `i' */ 2272143Seric fatal("more than one file (ad15)"); 2282143Seric 2292143Seric setsig(); 2302143Seric 2312143Seric /* 2322143Seric Change flags for 'fatal' so that it will return to this 2332143Seric routine (main) instead of terminating processing. 2342143Seric */ 235*30503Slepreau Fflags &= ~FTLEXIT; 236*30503Slepreau Fflags |= FTLJMP; 2372143Seric 2382143Seric /* 2392143Seric Call 'admin' routine for each file argument. 2402143Seric */ 2412143Seric for (j=1; j<argc; j++) 2422143Seric if (p = argv[j]) 2432143Seric do_file(p,admin); 2442143Seric 2452143Seric exit(Fcnt ? 1 : 0); 2462143Seric } 2472143Seric 2482143Seric 2492143Seric /* 2502143Seric Routine that actually does admin's work on SCCS files. 2512143Seric Existing s-files are copied, with changes being made, to a 2522143Seric temporary file (x-file). The name of the x-file is the same as the 2532143Seric name of the s-file, with the 's.' replaced by 'x.'. 2542143Seric s-files which are to be created are processed in a similar 2552143Seric manner, except that a dummy s-file is first created with 2562143Seric mode 444. 2572143Seric At end of processing, the x-file is renamed with the name of s-file 2582143Seric and the old s-file is removed. 2592143Seric */ 2602143Seric 2612143Seric struct packet gpkt; /* see file defines.h */ 2622143Seric char Zhold[BUFSIZ]; /* temporary z-file name */ 2632143Seric 2642143Seric USXALLOC(); /* defines alloc() and free() */ 2652143Seric 2662143Seric admin(afile) 2672143Seric char *afile; 2682143Seric { 2692143Seric struct deltab dt; /* see file defines.h */ 2702143Seric struct stats stats; /* see file defines.h */ 2712143Seric FILE *iptr; 2722143Seric register int k; 2732143Seric register char *cp, *q; 2742143Seric char command[80]; 2752143Seric char line[512]; 2762143Seric int i; /* used in forking procedure */ 2772143Seric int status; 2782143Seric extern nfiles; 2792143Seric extern had_dir; 2802143Seric 2812143Seric if (setjmp(Fjmp)) /* set up to return here from 'fatal' */ 2822143Seric return; /* and return to caller of admin */ 2832143Seric 2842143Seric if (HADI && had_dir) /* directory not allowed with `i' keyletter */ 2852143Seric fatal("directory named with `i' keyletter (ad26)"); 2862143Seric 2872143Seric fexists = exists(afile); 2882143Seric 2892143Seric if (HADI) 2902143Seric HADN = 1; 2912143Seric if (HADI || HADN) { 2922143Seric if (HADM && !VFLAG) 2932143Seric fatal("MRs not allowed (de8)"); 2942143Seric 2952143Seric if (VFLAG && !HADM) 2962143Seric fatal("MRs required (de10)"); 2972143Seric 2982143Seric } 2992143Seric 3002143Seric if (!HADI && HADR) 3012143Seric fatal("r only allowed with i (ad16)"); 3022143Seric 3032143Seric if (HADN && HADT && !(*tfile)) 3042143Seric fatal("t has no argument (ad17)"); 3052143Seric 3062143Seric if (HADN && HADD) 3072143Seric fatal("d not allowed with n (ad18)"); 3082143Seric 3092143Seric if (HADN && fexists) 3102143Seric fatal(sprintf(Error,"file %s exists (ad19)",afile)); 3112143Seric 3122143Seric if (!HADN && !fexists) 3132143Seric fatal(sprintf(Error,"file %s does not exist (ad20)",afile)); 3142143Seric /* 3152143Seric Check for '-h' flag. If set, create child process and 3162143Seric invoke 'get' to examine format of SCCS file. 3172143Seric */ 3182143Seric 3192143Seric if (HADH) { 3202143Seric /* 3212143Seric fork here so 'admin' can execute 'val' to 3222143Seric check for a corrupted file. 3232143Seric */ 3242143Seric if ((i = fork()) < 0) 3252143Seric fatal("cannot fork, try again"); 3262143Seric if (i == 0) { /* child */ 3272143Seric /* 3282143Seric perform 'val' with appropriate keyletters 3292143Seric */ 3302143Seric execl("/bin/sh","/bin/sh","-c", 3312143Seric sprintf(command, 3322143Seric "/usr/local/val -s %s", 3332143Seric afile),0); 3342143Seric fatal(sprintf(Error,"cannot execute '%s'",Valpgm)); 3352143Seric } 3362143Seric else { 3372143Seric wait(&status); /* wait on status from 'execl' */ 3382143Seric if (status) 3392143Seric fatal("corrupted file (co6)"); 3402143Seric return; /* return to caller of 'admin' */ 3412143Seric } 3422143Seric } 3432143Seric 3442143Seric /* 3452143Seric Lock out any other user who may be trying to process 3462143Seric the same file. 3472143Seric */ 3482143Seric if (!HADH && lockit(copy(auxf(afile,'z'),Zhold),2,getpid())) 3492143Seric fatal("cannot create lock file (cm4)"); 3502143Seric 3512143Seric if (fexists) 3522143Seric sinit(&gpkt,afile,1); /* init pkt & open s-file */ 3532143Seric else { 3542143Seric xfcreat(afile,0444); /* create dummy s-file */ 3552143Seric sinit(&gpkt,afile,0); /* and init pkt */ 3562143Seric } 3572143Seric 3582143Seric if (!HADH) 3592143Seric /* 3602143Seric set the flag for 'putline' routine to open 3612143Seric the 'x-file' and allow writing on it. 3622143Seric */ 3632143Seric gpkt.p_upd = 1; 3642143Seric 3652143Seric if (HADZ) { 3662143Seric gpkt.do_chksum = 0; /* ignore checksum processing */ 3672143Seric gpkt.p_ihash = 0; 3682143Seric } 3692143Seric 3702143Seric /* 3712143Seric Get statistics of latest delta in old file. 3722143Seric */ 3732143Seric if (!HADN) { 3742143Seric stats_ab(&gpkt,&stats); 3752143Seric gpkt.p_wrttn++; 3762143Seric newstats(&gpkt,line,"0"); 3772143Seric } 3782143Seric 3792143Seric if (HADN) { /* N E W F I L E */ 3802143Seric 3812143Seric /* 3822143Seric Beginning of SCCS file. 3832143Seric */ 3842143Seric putline(&gpkt,sprintf(line,"%c%c%s\n",CTLCHAR,HEAD,"00000")); 3852143Seric 3862143Seric /* 3872143Seric Statistics. 3882143Seric */ 3892143Seric newstats(&gpkt,line,"0"); 3902143Seric 3912143Seric dt.d_type = 'D'; /* type of delta */ 3922143Seric 3932143Seric /* 3942143Seric Set initial release, level, branch and 3952143Seric sequence values. 3962143Seric */ 3972143Seric if (HADR) 3982143Seric dt.d_sid.s_rel = irel; 3992143Seric else 4002143Seric dt.d_sid.s_rel = 1; 4012143Seric dt.d_sid.s_lev = 1; 4022143Seric dt.d_sid.s_br = dt.d_sid.s_seq = 0; 4032143Seric 4042143Seric time(&dt.d_datetime); /* get time and date */ 4052143Seric 4062143Seric copy(logname(),dt.d_pgmr); /* get user's name */ 4072143Seric 4082143Seric dt.d_serial = 1; 4092143Seric dt.d_pred = 0; 4102143Seric 4112143Seric del_ba(&dt,line); /* form and write */ 4122143Seric putline(&gpkt,line); /* delta-table entry */ 4132143Seric 4142143Seric /* 4152143Seric If -m flag, enter MR numbers 4162143Seric */ 4172143Seric 4182143Seric if (Mrs) { 4192143Seric mrfixup(); 4202143Seric if (z && valmrs(&gpkt,z)) 4212143Seric fatal("invalid MRs (de9)"); 4222143Seric putmrs(&gpkt); 4232143Seric } 4242143Seric 4252143Seric /* 4262143Seric Enter comment line for `chghist' 4272143Seric */ 4282143Seric 4292143Seric if (HADY) { 4302143Seric putline(&gpkt,sprintf(line,"%c%c ",CTLCHAR,COMMENTS)); 4312143Seric putline(&gpkt,Comments); 4322143Seric putline(&gpkt,"\n"); 4332143Seric } 4342143Seric else { 4352143Seric /* 4362143Seric insert date/time and pgmr into comment line 4372143Seric */ 4382143Seric cmt_ba(&dt,line); 4392143Seric putline(&gpkt,line); 4402143Seric } 4412143Seric /* 4422143Seric End of delta-table. 4432143Seric */ 4442143Seric putline(&gpkt,sprintf(line,CTLSTR,CTLCHAR,EDELTAB)); 4452143Seric 4462143Seric /* 4472143Seric Beginning of user-name section. 4482143Seric */ 4492143Seric putline(&gpkt,sprintf(line,CTLSTR,CTLCHAR,BUSERNAM)); 4502143Seric } 4512143Seric else 4522143Seric /* 4532143Seric For old file, copy to x-file until user-name section 4542143Seric is found. 4552143Seric */ 4562143Seric flushto(&gpkt,BUSERNAM,COPY); 4572143Seric 4582143Seric /* 4592143Seric Write user-names to be added to list of those 4602143Seric allowed to make deltas. 4612143Seric */ 4622143Seric if (HADA) 4632143Seric for (k = 0; k < asub; k++) 4642143Seric putline(&gpkt,sprintf(line,"%s\n",anames[k])); 4652143Seric 4662143Seric /* 4672143Seric Do not copy those user-names which are to be erased. 4682143Seric */ 4692143Seric if (HADE && !HADN) 4702143Seric while ((cp = getline(&gpkt)) && 4712143Seric !(*cp++ == CTLCHAR && *cp == EUSERNAM)) { 4722143Seric for (k = 0; k < esub; k++) { 4732143Seric cp = &gpkt.p_line; 4742143Seric while (*cp) /* find and */ 4752143Seric cp++; /* zero newline */ 4762143Seric *--cp = '\0'; /* character */ 4772143Seric 4782143Seric if (equal(enames[k],&gpkt.p_line)) { 4792143Seric /* 4802143Seric Tell getline not to output 4812143Seric previously read line. 4822143Seric */ 4832143Seric gpkt.p_wrttn = 1; 4842143Seric break; 4852143Seric } 4862143Seric else 4872143Seric *cp = '\n'; /* restore newline */ 4882143Seric } 4892143Seric } 4902143Seric 4912143Seric if (HADN) { /* N E W F I L E */ 4922143Seric 4932143Seric /* 4942143Seric End of user-name section. 4952143Seric */ 4962143Seric putline(&gpkt,sprintf(line,CTLSTR,CTLCHAR,EUSERNAM)); 4972143Seric } 4982143Seric else 4992143Seric /* 5002143Seric For old file, copy to x-file until end of 5012143Seric user-names section is found. 5022143Seric */ 5032143Seric if (!HADE) 5042143Seric flushto(&gpkt,EUSERNAM,COPY); 5052143Seric 5062143Seric /* 5072143Seric For old file, read flags and their values (if any), and 5082143Seric store them. Check to see if the flag read is one that 5092143Seric should be deleted. 5102143Seric */ 5112143Seric if (!HADN) 5122143Seric while ((cp = getline(&gpkt)) && 5132143Seric (*cp++ == CTLCHAR && *cp == FLAG)) { 5142143Seric 5152143Seric gpkt.p_wrttn = 1; /* don't write previous line */ 5162143Seric 517*30503Slepreau cp += 2; /* point to flag character */ 5182143Seric k = *cp - 'a'; 5192143Seric 5202143Seric if (!had_flag[k] && !rm_flag[k]) { 5212143Seric had_flag[k] = 2; /* indicate flag is */ 5222143Seric /* from file, not */ 5232143Seric /* from arg list */ 5242143Seric 5252143Seric if (*++cp != '\n') { /* get flag value */ 5262143Seric q = alloc(size(gpkt.p_line)-5); 5272143Seric copy(++cp,q); 5282143Seric flag_p[k] = q; 5292143Seric while (*q) /* find and */ 5302143Seric q++; /* zero newline */ 5312143Seric *--q = '\0'; /* character */ 5322143Seric } 5332143Seric } 5342143Seric else 5352143Seric if (rm_flag[k]) 5362143Seric had_flag[k] = 0; 5372143Seric } 5382143Seric 5392143Seric 5402143Seric /* 5412143Seric Write out flags. 5422143Seric */ 5432143Seric for (k = 0; k < 26; k++) 5442143Seric if (had_flag[k]) { 5452143Seric if (flag_p[k]) 5462143Seric sprintf(line,"%c%c %c %s\n", 5472143Seric CTLCHAR,FLAG,'a'+k,flag_p[k]); 5482143Seric else 5492143Seric sprintf(line,"%c%c %c\n", 5502143Seric CTLCHAR,FLAG,'a'+k); 5512143Seric 5522143Seric putline(&gpkt,line); 5532143Seric 5542143Seric if (had_flag[k] == 2) { /* flag was taken from file */ 5552143Seric had_flag[k] = 0; 5562143Seric if (flag_p[k]) { 5572143Seric free(flag_p[k]); 5582143Seric flag_p[k] = 0; 5592143Seric } 5602143Seric } 5612143Seric } 5622143Seric 5632143Seric if (HADN) 5642143Seric /* 5652143Seric Beginning of descriptive (user) text. 5662143Seric */ 5672143Seric putline(&gpkt,sprintf(line,CTLSTR,CTLCHAR,BUSERTXT)); 5682143Seric else 5692143Seric /* 5702143Seric Write out BUSERTXT record which was read in 5712143Seric above loop that processes flags. 5722143Seric */ 5732143Seric gpkt.p_wrttn = 0; 5742143Seric putline(&gpkt,0); 5752143Seric 5762143Seric /* 5772143Seric Get user description, copy to x-file. 5782143Seric */ 5792143Seric if (HADT) { 5802143Seric if (*tfile) { 5812143Seric iptr = xfopen(tfile,0); 5822143Seric fgetchk(line,512,iptr,tfile,&gpkt); 5832143Seric fclose(iptr); 5842143Seric } 5852143Seric 5862143Seric /* 5872143Seric If old file, ignore any previously supplied 5882143Seric commentary. (i.e., don't copy it to x-file.) 5892143Seric */ 5902143Seric if (!HADN) 5912143Seric flushto(&gpkt,EUSERTXT,NOCOPY); 5922143Seric } 5932143Seric 5942143Seric if (HADN) { /* N E W F I L E */ 5952143Seric 5962143Seric /* 5972143Seric End of user description. 5982143Seric */ 5992143Seric putline(&gpkt,sprintf(line,CTLSTR,CTLCHAR,EUSERTXT)); 6002143Seric 6012143Seric /* 6022143Seric Beginning of body (text) of first delta. 6032143Seric */ 6042143Seric putline(&gpkt,sprintf(line,"%c%c %u\n",CTLCHAR,INS,1)); 6052143Seric 6062143Seric if (HADI) { /* get body */ 6072143Seric 6082143Seric /* 6092143Seric Set indicator to check lines of body of file for 6102143Seric keyword definitions. 6112143Seric If no keywords are found, a warning 6122143Seric will be produced. 6132143Seric */ 6142143Seric check_id = 1; 6152143Seric /* 6162143Seric Set indicator that tells whether there 6172143Seric were any keywords to 'no'. 6182143Seric */ 6192143Seric Did_id = 0; 6202143Seric if (*ifile) 6212143Seric iptr = xfopen(ifile,0); /* from a file */ 6222143Seric else 6232143Seric iptr = stdin; /* from standard input */ 6242143Seric 6252143Seric /* 6262143Seric Read and copy to x-file, while checking 6272143Seric first character of each line to see that it 6282143Seric is not the control character (octal 1). 6292143Seric Also, count lines read, and set statistics' 6302143Seric structure appropriately. 6312143Seric The 'fgetchk' routine will check for keywords. 6322143Seric */ 6332143Seric stats.s_ins = fgetchk(line,512,iptr,ifile,&gpkt); 6342143Seric stats.s_del = stats.s_unc = 0; 6352143Seric 6362143Seric /* 6372143Seric If no keywords were found, issue warning. 6382143Seric */ 6392143Seric if (!Did_id) { 6402143Seric if (had_flag[IDFLAG - 'a']) 6412143Seric fatal("no id keywords (cm6)"); 6422143Seric else 6432143Seric fprintf(stderr,"%s\n","No id keywords (cm7)"); 6442143Seric } 6452143Seric 6462143Seric check_id = 0; 6472143Seric Did_id = 0; 6482143Seric } 6492143Seric 6502143Seric /* 6512143Seric End of body of first delta. 6522143Seric */ 6532143Seric putline(&gpkt,sprintf(line,"%c%c %u\n",CTLCHAR,END,1)); 6542143Seric } 6552143Seric else { 6562143Seric /* 6572143Seric Indicate that EOF at this point is ok, and 6582143Seric flush rest of (old) s-file to x-file. 6592143Seric */ 6602143Seric gpkt.p_chkeof = 1; 6612143Seric while (getline(&gpkt)) ; 6622143Seric } 6632143Seric 6642143Seric /* 6652143Seric Flush the buffer, take care of rewinding to insert 6662143Seric checksum and statistics in file, and close. 6672143Seric */ 6682143Seric flushline(&gpkt,&stats); 6692143Seric 6702143Seric /* 6712143Seric Change x-file name to s-file, and delete old file. 6722143Seric Unlock file before returning. 6732143Seric */ 6742143Seric if (!HADH) { 6752143Seric rename(auxf(&gpkt,'x'),&gpkt); 6762143Seric xrm(&gpkt); 6772143Seric unlockit(auxf(afile,'z'),getpid()); 6782143Seric } 6792143Seric } 6802143Seric 6812143Seric 6822143Seric fgetchk(strp,len,inptr,file,pkt) 6832143Seric register char *strp; 6842143Seric register int len; 6852143Seric FILE *inptr; 6862143Seric register char *file; 6872143Seric register struct packet *pkt; 6882143Seric { 6892143Seric register int k; 6902143Seric 6912143Seric for (k = 1; fgets(strp,len,inptr); k++) { 6922143Seric if (*strp == CTLCHAR) fatal( 6932143Seric sprintf(Error,"%s illegal data on line %d (ad21)", 6942143Seric file,k)); 6952143Seric 6962143Seric if (check_id) 6972143Seric chkid(strp); 6982143Seric 6992143Seric putline(pkt,strp); 7002143Seric } 7012143Seric return(k - 1); 7022143Seric } 7032143Seric 7042143Seric 7052143Seric clean_up() 7062143Seric { 7072143Seric xrm(&gpkt); 7082143Seric if (!HADH) 7092143Seric unlockit(Zhold,getpid()); 7102143Seric if (HADN) 7112143Seric unlink(&gpkt); 7122143Seric } 7132143Seric 7142143Seric 7152143Seric cmt_ba(dt,str) 7162143Seric register struct deltab *dt; 7172143Seric char *str; 7182143Seric { 7192143Seric register char *p; 7202143Seric 7212143Seric p = str; 7222143Seric *p++ = CTLCHAR; 7232143Seric *p++ = COMMENTS; 7242143Seric *p++ = ' '; 7252143Seric copy("date and time created",p); 7262143Seric while (*p++) 7272143Seric ; 7282143Seric --p; 7292143Seric *p++ = ' '; 7302143Seric date_ba(&dt->d_datetime,p); 7312143Seric while (*p++) 7322143Seric ; 7332143Seric --p; 7342143Seric *p++ = ' '; 7352143Seric copy("by",p); 7362143Seric while (*p++) 7372143Seric ; 7382143Seric --p; 7392143Seric *p++ = ' '; 7402143Seric copy(dt->d_pgmr,p); 7412143Seric while (*p++) 7422143Seric ; 7432143Seric --p; 7442143Seric *p++ = '\n'; 7452143Seric *p = 0; 7462143Seric return(str); 7472143Seric } 7482143Seric 7492143Seric 7502143Seric putmrs(pkt) 7512143Seric struct packet *pkt; 7522143Seric { 7532143Seric register char **argv; 7542143Seric char str[64]; 7552143Seric extern char *Varg[]; 7562143Seric 7572143Seric for (argv = &Varg[VSTART]; *argv; argv++) 7582143Seric putline(pkt,sprintf(str,"%c%c %s\n",CTLCHAR,MRNUM,*argv)); 7592143Seric } 760