12143Seric # include "../hdr/defines.h"
22143Seric # include "../hdr/had.h"
32143Seric
4*33423Sbostic static char Sccsid[] = "@(#)admin.c 4.3 02/02/88";
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;
3630503Slepreau char Valpgm[] = "/usr/local/val";
372143Seric int irel, fexists, num_files;
3830503Slepreau 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
main(argc,argv)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:
108*33423Sbostic if (*p) {
109*33423Sbostic sprintf(Error, "value after %c flag (ad12)",f);
110*33423Sbostic fatal(Error);
111*33423Sbostic }
1122143Seric break;
1132143Seric
1142143Seric default:
1152143Seric fatal("unknown flag (ad3)");
1162143Seric }
1172143Seric
1182143Seric if (rm_flag[f - 'a']++)
1192143Seric fatal("flag twice (ad4)");
1202143Seric break;
1212143Seric
1222143Seric case 'f': /* flags to be added */
1232143Seric testklt = 0;
1242143Seric if (!(f = *p))
1252143Seric fatal("f has no argument (ad5)");
1262143Seric p = &argv[j][3];
1272143Seric
1282143Seric switch (f) {
1292143Seric
1302143Seric case IDFLAG: /* id-kwd message (err/warn) */
1312143Seric case BRCHFLAG: /* branch */
1322143Seric case NULLFLAG: /* null deltas */
133*33423Sbostic if (*p) {
134*33423Sbostic sprintf(Error, "value after %c flag (ad13)",f);
135*33423Sbostic fatal(Error);
136*33423Sbostic }
1372143Seric break;
1382143Seric
1392143Seric case VALFLAG: /* mr validation */
1402143Seric VFLAG++;
1412143Seric if (*p)
1422143Seric z = p;
1432143Seric break;
1442143Seric
1452143Seric case FLORFLAG: /* floor */
1462143Seric if ((i = patoi(p)) == -1)
1472143Seric fatal("floor not numeric (ad22)");
1482143Seric if ((size(p) > 5) || (i < MINR) ||
1492143Seric (i > MAXR))
1502143Seric fatal("floor out of range (ad23)");
1512143Seric break;
1522143Seric
1532143Seric case CEILFLAG: /* ceiling */
1542143Seric if ((i = patoi(p)) == -1)
1552143Seric fatal("ceiling not numeric (ad24)");
1562143Seric if ((size(p) > 5) || (i < MINR) ||
1572143Seric (i > MAXR))
1582143Seric fatal("ceiling out of range (ad25)");
1592143Seric break;
1602143Seric
1612143Seric case DEFTFLAG: /* default sid */
1622143Seric if (!(*p))
1632143Seric fatal("no default sid (ad14)");
1642143Seric chksid(sid_ab(p,&sid),&sid);
1652143Seric break;
1662143Seric
1672143Seric case TYPEFLAG: /* type */
1682143Seric case MODFLAG: /* module name */
169*33423Sbostic if (!(*p)) {
170*33423Sbostic sprintf(Error, "flag %c has no value (ad2)",f);
171*33423Sbostic fatal(Error);
172*33423Sbostic }
1732143Seric break;
1742143Seric
1752143Seric default:
1762143Seric fatal("unknown flag (ad3)");
1772143Seric }
1782143Seric
1792143Seric if (had_flag[f - 'a']++)
1802143Seric fatal("flag twice (ad4)");
1812143Seric flag_p[f - 'a'] = p;
1822143Seric break;
1832143Seric
1842143Seric case 'r': /* initial release number supplied */
1852143Seric if ((irel = patoi(p)) == -1)
1862143Seric fatal("r arg not numeric (ad6)");
1872143Seric if ((size(p) > 5) || (irel < MINR) ||
1882143Seric (irel > MAXR))
1892143Seric fatal("r out of range (ad7)");
1902143Seric break;
1912143Seric
1922143Seric case 'n': /* creating new SCCS file */
1932143Seric case 'h': /* only check hash of file */
1942143Seric case 'z': /* zero the input hash */
1952143Seric break;
1962143Seric
1972143Seric case 'a': /* user-name allowed to make deltas */
1982143Seric testklt = 0;
1992143Seric if (!(*p))
2002143Seric fatal("bad a argument (ad8)");
2012143Seric if (asub > MAXNAMES)
2022143Seric fatal("too many 'a' keyletters (ad9)");
2032143Seric anames[asub++] = p;
2042143Seric break;
2052143Seric
2062143Seric case 'e': /* user-name to be removed */
2072143Seric testklt = 0;
2082143Seric if (!(*p))
2092143Seric fatal("bad e argument (ad10)");
2102143Seric if (esub > MAXNAMES)
2112143Seric fatal("too many 'e' keyletters (ad11)");
2122143Seric enames[esub++] = p;
2132143Seric break;
2142143Seric
2152143Seric default:
2162143Seric fatal("unknown key letter (cm1)");
2172143Seric }
2182143Seric
2192143Seric if (had[c - 'a']++ && testklt++)
2202143Seric fatal("key letter twice (cm2)");
2212143Seric argv[j] = 0;
2222143Seric }
2232143Seric else
2242143Seric num_files++;
2252143Seric
2262143Seric if (num_files == 0)
2272143Seric fatal("missing file arg (cm3)");
2282143Seric
2292143Seric if (HADI && num_files > 1) /* only one file allowed with `i' */
2302143Seric fatal("more than one file (ad15)");
2312143Seric
2322143Seric setsig();
2332143Seric
2342143Seric /*
2352143Seric Change flags for 'fatal' so that it will return to this
2362143Seric routine (main) instead of terminating processing.
2372143Seric */
23830503Slepreau Fflags &= ~FTLEXIT;
23930503Slepreau Fflags |= FTLJMP;
2402143Seric
2412143Seric /*
2422143Seric Call 'admin' routine for each file argument.
2432143Seric */
2442143Seric for (j=1; j<argc; j++)
2452143Seric if (p = argv[j])
2462143Seric do_file(p,admin);
2472143Seric
2482143Seric exit(Fcnt ? 1 : 0);
2492143Seric }
2502143Seric
2512143Seric
2522143Seric /*
2532143Seric Routine that actually does admin's work on SCCS files.
2542143Seric Existing s-files are copied, with changes being made, to a
2552143Seric temporary file (x-file). The name of the x-file is the same as the
2562143Seric name of the s-file, with the 's.' replaced by 'x.'.
2572143Seric s-files which are to be created are processed in a similar
2582143Seric manner, except that a dummy s-file is first created with
2592143Seric mode 444.
2602143Seric At end of processing, the x-file is renamed with the name of s-file
2612143Seric and the old s-file is removed.
2622143Seric */
2632143Seric
2642143Seric struct packet gpkt; /* see file defines.h */
2652143Seric char Zhold[BUFSIZ]; /* temporary z-file name */
2662143Seric
2672143Seric USXALLOC(); /* defines alloc() and free() */
2682143Seric
admin(afile)2692143Seric admin(afile)
2702143Seric char *afile;
2712143Seric {
2722143Seric struct deltab dt; /* see file defines.h */
2732143Seric struct stats stats; /* see file defines.h */
2742143Seric FILE *iptr;
2752143Seric register int k;
2762143Seric register char *cp, *q;
2772143Seric char command[80];
2782143Seric char line[512];
2792143Seric int i; /* used in forking procedure */
2802143Seric int status;
2812143Seric extern nfiles;
2822143Seric extern had_dir;
2832143Seric
2842143Seric if (setjmp(Fjmp)) /* set up to return here from 'fatal' */
2852143Seric return; /* and return to caller of admin */
2862143Seric
2872143Seric if (HADI && had_dir) /* directory not allowed with `i' keyletter */
2882143Seric fatal("directory named with `i' keyletter (ad26)");
2892143Seric
2902143Seric fexists = exists(afile);
2912143Seric
2922143Seric if (HADI)
2932143Seric HADN = 1;
2942143Seric if (HADI || HADN) {
2952143Seric if (HADM && !VFLAG)
2962143Seric fatal("MRs not allowed (de8)");
2972143Seric
2982143Seric if (VFLAG && !HADM)
2992143Seric fatal("MRs required (de10)");
3002143Seric
3012143Seric }
3022143Seric
3032143Seric if (!HADI && HADR)
3042143Seric fatal("r only allowed with i (ad16)");
3052143Seric
3062143Seric if (HADN && HADT && !(*tfile))
3072143Seric fatal("t has no argument (ad17)");
3082143Seric
3092143Seric if (HADN && HADD)
3102143Seric fatal("d not allowed with n (ad18)");
3112143Seric
312*33423Sbostic if (HADN && fexists) {
313*33423Sbostic sprintf(Error,"file %s exists (ad19)",afile);
314*33423Sbostic fatal(Error);
315*33423Sbostic }
3162143Seric
317*33423Sbostic if (!HADN && !fexists) {
318*33423Sbostic sprintf(Error,"file %s does not exist (ad20)",afile);
319*33423Sbostic fatal(Error);
320*33423Sbostic }
3212143Seric /*
3222143Seric Check for '-h' flag. If set, create child process and
3232143Seric invoke 'get' to examine format of SCCS file.
3242143Seric */
3252143Seric
3262143Seric if (HADH) {
3272143Seric /*
3282143Seric fork here so 'admin' can execute 'val' to
3292143Seric check for a corrupted file.
3302143Seric */
3312143Seric if ((i = fork()) < 0)
3322143Seric fatal("cannot fork, try again");
3332143Seric if (i == 0) { /* child */
3342143Seric /*
3352143Seric perform 'val' with appropriate keyletters
3362143Seric */
337*33423Sbostic sprintf(command, "/usr/local/val -s %s", afile);
338*33423Sbostic execl("/bin/sh","/bin/sh","-c", command, 0);
339*33423Sbostic sprintf(Error,"cannot execute '%s'",Valpgm);
340*33423Sbostic fatal(Error);
3412143Seric }
3422143Seric else {
3432143Seric wait(&status); /* wait on status from 'execl' */
3442143Seric if (status)
3452143Seric fatal("corrupted file (co6)");
3462143Seric return; /* return to caller of 'admin' */
3472143Seric }
3482143Seric }
3492143Seric
3502143Seric /*
3512143Seric Lock out any other user who may be trying to process
3522143Seric the same file.
3532143Seric */
3542143Seric if (!HADH && lockit(copy(auxf(afile,'z'),Zhold),2,getpid()))
3552143Seric fatal("cannot create lock file (cm4)");
3562143Seric
3572143Seric if (fexists)
3582143Seric sinit(&gpkt,afile,1); /* init pkt & open s-file */
3592143Seric else {
3602143Seric xfcreat(afile,0444); /* create dummy s-file */
3612143Seric sinit(&gpkt,afile,0); /* and init pkt */
3622143Seric }
3632143Seric
3642143Seric if (!HADH)
3652143Seric /*
3662143Seric set the flag for 'putline' routine to open
3672143Seric the 'x-file' and allow writing on it.
3682143Seric */
3692143Seric gpkt.p_upd = 1;
3702143Seric
3712143Seric if (HADZ) {
3722143Seric gpkt.do_chksum = 0; /* ignore checksum processing */
3732143Seric gpkt.p_ihash = 0;
3742143Seric }
3752143Seric
3762143Seric /*
3772143Seric Get statistics of latest delta in old file.
3782143Seric */
3792143Seric if (!HADN) {
3802143Seric stats_ab(&gpkt,&stats);
3812143Seric gpkt.p_wrttn++;
3822143Seric newstats(&gpkt,line,"0");
3832143Seric }
3842143Seric
3852143Seric if (HADN) { /* N E W F I L E */
3862143Seric
3872143Seric /*
3882143Seric Beginning of SCCS file.
3892143Seric */
390*33423Sbostic sprintf(line,"%c%c%s\n",CTLCHAR,HEAD,"00000");
391*33423Sbostic putline(&gpkt,line);
3922143Seric
3932143Seric /*
3942143Seric Statistics.
3952143Seric */
3962143Seric newstats(&gpkt,line,"0");
3972143Seric
3982143Seric dt.d_type = 'D'; /* type of delta */
3992143Seric
4002143Seric /*
4012143Seric Set initial release, level, branch and
4022143Seric sequence values.
4032143Seric */
4042143Seric if (HADR)
4052143Seric dt.d_sid.s_rel = irel;
4062143Seric else
4072143Seric dt.d_sid.s_rel = 1;
4082143Seric dt.d_sid.s_lev = 1;
4092143Seric dt.d_sid.s_br = dt.d_sid.s_seq = 0;
4102143Seric
4112143Seric time(&dt.d_datetime); /* get time and date */
4122143Seric
4132143Seric copy(logname(),dt.d_pgmr); /* get user's name */
4142143Seric
4152143Seric dt.d_serial = 1;
4162143Seric dt.d_pred = 0;
4172143Seric
4182143Seric del_ba(&dt,line); /* form and write */
4192143Seric putline(&gpkt,line); /* delta-table entry */
4202143Seric
4212143Seric /*
4222143Seric If -m flag, enter MR numbers
4232143Seric */
4242143Seric
4252143Seric if (Mrs) {
4262143Seric mrfixup();
4272143Seric if (z && valmrs(&gpkt,z))
4282143Seric fatal("invalid MRs (de9)");
4292143Seric putmrs(&gpkt);
4302143Seric }
4312143Seric
4322143Seric /*
4332143Seric Enter comment line for `chghist'
4342143Seric */
4352143Seric
4362143Seric if (HADY) {
437*33423Sbostic sprintf(line,"%c%c ",CTLCHAR,COMMENTS);
438*33423Sbostic putline(&gpkt,line);
4392143Seric putline(&gpkt,Comments);
4402143Seric putline(&gpkt,"\n");
4412143Seric }
4422143Seric else {
4432143Seric /*
4442143Seric insert date/time and pgmr into comment line
4452143Seric */
4462143Seric cmt_ba(&dt,line);
4472143Seric putline(&gpkt,line);
4482143Seric }
4492143Seric /*
4502143Seric End of delta-table.
4512143Seric */
452*33423Sbostic sprintf(line,CTLSTR,CTLCHAR,EDELTAB);
453*33423Sbostic putline(&gpkt,line);
4542143Seric
4552143Seric /*
4562143Seric Beginning of user-name section.
4572143Seric */
458*33423Sbostic sprintf(line,CTLSTR,CTLCHAR,BUSERNAM);
459*33423Sbostic putline(&gpkt,line);
4602143Seric }
4612143Seric else
4622143Seric /*
4632143Seric For old file, copy to x-file until user-name section
4642143Seric is found.
4652143Seric */
4662143Seric flushto(&gpkt,BUSERNAM,COPY);
4672143Seric
4682143Seric /*
4692143Seric Write user-names to be added to list of those
4702143Seric allowed to make deltas.
4712143Seric */
4722143Seric if (HADA)
473*33423Sbostic for (k = 0; k < asub; k++) {
474*33423Sbostic sprintf(line,"%s\n",anames[k]);
475*33423Sbostic putline(&gpkt,line);
476*33423Sbostic }
4772143Seric
4782143Seric /*
4792143Seric Do not copy those user-names which are to be erased.
4802143Seric */
4812143Seric if (HADE && !HADN)
4822143Seric while ((cp = getline(&gpkt)) &&
4832143Seric !(*cp++ == CTLCHAR && *cp == EUSERNAM)) {
4842143Seric for (k = 0; k < esub; k++) {
4852143Seric cp = &gpkt.p_line;
4862143Seric while (*cp) /* find and */
4872143Seric cp++; /* zero newline */
4882143Seric *--cp = '\0'; /* character */
4892143Seric
4902143Seric if (equal(enames[k],&gpkt.p_line)) {
4912143Seric /*
4922143Seric Tell getline not to output
4932143Seric previously read line.
4942143Seric */
4952143Seric gpkt.p_wrttn = 1;
4962143Seric break;
4972143Seric }
4982143Seric else
4992143Seric *cp = '\n'; /* restore newline */
5002143Seric }
5012143Seric }
5022143Seric
5032143Seric if (HADN) { /* N E W F I L E */
5042143Seric
5052143Seric /*
5062143Seric End of user-name section.
5072143Seric */
508*33423Sbostic sprintf(line,CTLSTR,CTLCHAR,EUSERNAM);
509*33423Sbostic putline(&gpkt,line);
5102143Seric }
5112143Seric else
5122143Seric /*
5132143Seric For old file, copy to x-file until end of
5142143Seric user-names section is found.
5152143Seric */
5162143Seric if (!HADE)
5172143Seric flushto(&gpkt,EUSERNAM,COPY);
5182143Seric
5192143Seric /*
5202143Seric For old file, read flags and their values (if any), and
5212143Seric store them. Check to see if the flag read is one that
5222143Seric should be deleted.
5232143Seric */
5242143Seric if (!HADN)
5252143Seric while ((cp = getline(&gpkt)) &&
5262143Seric (*cp++ == CTLCHAR && *cp == FLAG)) {
5272143Seric
5282143Seric gpkt.p_wrttn = 1; /* don't write previous line */
5292143Seric
53030503Slepreau cp += 2; /* point to flag character */
5312143Seric k = *cp - 'a';
5322143Seric
5332143Seric if (!had_flag[k] && !rm_flag[k]) {
5342143Seric had_flag[k] = 2; /* indicate flag is */
5352143Seric /* from file, not */
5362143Seric /* from arg list */
5372143Seric
5382143Seric if (*++cp != '\n') { /* get flag value */
5392143Seric q = alloc(size(gpkt.p_line)-5);
5402143Seric copy(++cp,q);
5412143Seric flag_p[k] = q;
5422143Seric while (*q) /* find and */
5432143Seric q++; /* zero newline */
5442143Seric *--q = '\0'; /* character */
5452143Seric }
5462143Seric }
5472143Seric else
5482143Seric if (rm_flag[k])
5492143Seric had_flag[k] = 0;
5502143Seric }
5512143Seric
5522143Seric
5532143Seric /*
5542143Seric Write out flags.
5552143Seric */
5562143Seric for (k = 0; k < 26; k++)
5572143Seric if (had_flag[k]) {
5582143Seric if (flag_p[k])
5592143Seric sprintf(line,"%c%c %c %s\n",
5602143Seric CTLCHAR,FLAG,'a'+k,flag_p[k]);
5612143Seric else
5622143Seric sprintf(line,"%c%c %c\n",
5632143Seric CTLCHAR,FLAG,'a'+k);
5642143Seric
5652143Seric putline(&gpkt,line);
5662143Seric
5672143Seric if (had_flag[k] == 2) { /* flag was taken from file */
5682143Seric had_flag[k] = 0;
5692143Seric if (flag_p[k]) {
5702143Seric free(flag_p[k]);
5712143Seric flag_p[k] = 0;
5722143Seric }
5732143Seric }
5742143Seric }
5752143Seric
576*33423Sbostic if (HADN) {
5772143Seric /*
5782143Seric Beginning of descriptive (user) text.
5792143Seric */
580*33423Sbostic sprintf(line,CTLSTR,CTLCHAR,BUSERTXT);
581*33423Sbostic putline(&gpkt,line);
582*33423Sbostic }
5832143Seric else
5842143Seric /*
5852143Seric Write out BUSERTXT record which was read in
5862143Seric above loop that processes flags.
5872143Seric */
5882143Seric gpkt.p_wrttn = 0;
5892143Seric putline(&gpkt,0);
5902143Seric
5912143Seric /*
5922143Seric Get user description, copy to x-file.
5932143Seric */
5942143Seric if (HADT) {
5952143Seric if (*tfile) {
5962143Seric iptr = xfopen(tfile,0);
5972143Seric fgetchk(line,512,iptr,tfile,&gpkt);
5982143Seric fclose(iptr);
5992143Seric }
6002143Seric
6012143Seric /*
6022143Seric If old file, ignore any previously supplied
6032143Seric commentary. (i.e., don't copy it to x-file.)
6042143Seric */
6052143Seric if (!HADN)
6062143Seric flushto(&gpkt,EUSERTXT,NOCOPY);
6072143Seric }
6082143Seric
6092143Seric if (HADN) { /* N E W F I L E */
6102143Seric
6112143Seric /*
6122143Seric End of user description.
6132143Seric */
614*33423Sbostic sprintf(line,CTLSTR,CTLCHAR,EUSERTXT);
615*33423Sbostic putline(&gpkt,line);
6162143Seric
6172143Seric /*
6182143Seric Beginning of body (text) of first delta.
6192143Seric */
620*33423Sbostic sprintf(line,"%c%c %u\n",CTLCHAR,INS,1);
621*33423Sbostic putline(&gpkt,line);
6222143Seric
6232143Seric if (HADI) { /* get body */
6242143Seric
6252143Seric /*
6262143Seric Set indicator to check lines of body of file for
6272143Seric keyword definitions.
6282143Seric If no keywords are found, a warning
6292143Seric will be produced.
6302143Seric */
6312143Seric check_id = 1;
6322143Seric /*
6332143Seric Set indicator that tells whether there
6342143Seric were any keywords to 'no'.
6352143Seric */
6362143Seric Did_id = 0;
6372143Seric if (*ifile)
6382143Seric iptr = xfopen(ifile,0); /* from a file */
6392143Seric else
6402143Seric iptr = stdin; /* from standard input */
6412143Seric
6422143Seric /*
6432143Seric Read and copy to x-file, while checking
6442143Seric first character of each line to see that it
6452143Seric is not the control character (octal 1).
6462143Seric Also, count lines read, and set statistics'
6472143Seric structure appropriately.
6482143Seric The 'fgetchk' routine will check for keywords.
6492143Seric */
6502143Seric stats.s_ins = fgetchk(line,512,iptr,ifile,&gpkt);
6512143Seric stats.s_del = stats.s_unc = 0;
6522143Seric
6532143Seric /*
6542143Seric If no keywords were found, issue warning.
6552143Seric */
6562143Seric if (!Did_id) {
6572143Seric if (had_flag[IDFLAG - 'a'])
6582143Seric fatal("no id keywords (cm6)");
6592143Seric else
6602143Seric fprintf(stderr,"%s\n","No id keywords (cm7)");
6612143Seric }
6622143Seric
6632143Seric check_id = 0;
6642143Seric Did_id = 0;
6652143Seric }
6662143Seric
6672143Seric /*
6682143Seric End of body of first delta.
6692143Seric */
670*33423Sbostic sprintf(line,"%c%c %u\n",CTLCHAR,END,1);
671*33423Sbostic putline(&gpkt,line);
6722143Seric }
6732143Seric else {
6742143Seric /*
6752143Seric Indicate that EOF at this point is ok, and
6762143Seric flush rest of (old) s-file to x-file.
6772143Seric */
6782143Seric gpkt.p_chkeof = 1;
6792143Seric while (getline(&gpkt)) ;
6802143Seric }
6812143Seric
6822143Seric /*
6832143Seric Flush the buffer, take care of rewinding to insert
6842143Seric checksum and statistics in file, and close.
6852143Seric */
6862143Seric flushline(&gpkt,&stats);
6872143Seric
6882143Seric /*
6892143Seric Change x-file name to s-file, and delete old file.
6902143Seric Unlock file before returning.
6912143Seric */
6922143Seric if (!HADH) {
6932143Seric rename(auxf(&gpkt,'x'),&gpkt);
6942143Seric xrm(&gpkt);
6952143Seric unlockit(auxf(afile,'z'),getpid());
6962143Seric }
6972143Seric }
6982143Seric
6992143Seric
fgetchk(strp,len,inptr,file,pkt)7002143Seric fgetchk(strp,len,inptr,file,pkt)
7012143Seric register char *strp;
7022143Seric register int len;
7032143Seric FILE *inptr;
7042143Seric register char *file;
7052143Seric register struct packet *pkt;
7062143Seric {
7072143Seric register int k;
7082143Seric
7092143Seric for (k = 1; fgets(strp,len,inptr); k++) {
710*33423Sbostic if (*strp == CTLCHAR) {
7112143Seric sprintf(Error,"%s illegal data on line %d (ad21)",
712*33423Sbostic file,k);
713*33423Sbostic fatal(Error);
714*33423Sbostic }
7152143Seric
7162143Seric if (check_id)
7172143Seric chkid(strp);
7182143Seric
7192143Seric putline(pkt,strp);
7202143Seric }
7212143Seric return(k - 1);
7222143Seric }
7232143Seric
7242143Seric
clean_up()7252143Seric clean_up()
7262143Seric {
7272143Seric xrm(&gpkt);
7282143Seric if (!HADH)
7292143Seric unlockit(Zhold,getpid());
7302143Seric if (HADN)
7312143Seric unlink(&gpkt);
7322143Seric }
7332143Seric
7342143Seric
cmt_ba(dt,str)7352143Seric cmt_ba(dt,str)
7362143Seric register struct deltab *dt;
7372143Seric char *str;
7382143Seric {
7392143Seric register char *p;
7402143Seric
7412143Seric p = str;
7422143Seric *p++ = CTLCHAR;
7432143Seric *p++ = COMMENTS;
7442143Seric *p++ = ' ';
7452143Seric copy("date and time created",p);
7462143Seric while (*p++)
7472143Seric ;
7482143Seric --p;
7492143Seric *p++ = ' ';
7502143Seric date_ba(&dt->d_datetime,p);
7512143Seric while (*p++)
7522143Seric ;
7532143Seric --p;
7542143Seric *p++ = ' ';
7552143Seric copy("by",p);
7562143Seric while (*p++)
7572143Seric ;
7582143Seric --p;
7592143Seric *p++ = ' ';
7602143Seric copy(dt->d_pgmr,p);
7612143Seric while (*p++)
7622143Seric ;
7632143Seric --p;
7642143Seric *p++ = '\n';
7652143Seric *p = 0;
7662143Seric return(str);
7672143Seric }
7682143Seric
7692143Seric
7702143Seric putmrs(pkt)
7712143Seric struct packet *pkt;
7722143Seric {
7732143Seric register char **argv;
7742143Seric char str[64];
7752143Seric extern char *Varg[];
7762143Seric
7772143Seric for (argv = &Varg[VSTART]; *argv; argv++)
778*33423Sbostic sprintf(str,"%c%c %s\n",CTLCHAR,MRNUM,*argv);
779*33423Sbostic putline(pkt,str);
7802143Seric }
781