12145Seric # include	"../hdr/defines.h"
22145Seric # include	"../hdr/had.h"
32145Seric 
4*30498Slepreau static char Sccsid[] = "@(#)cmt.c	4.4	02/15/87";
52145Seric 
62145Seric struct packet gpkt;
72145Seric int	num_files, had_ffile;
82145Seric int	F_Opened, Opened, Domrs, First;
92145Seric char	*Comments, *Mrs, *ffile;
102145Seric char	Cstr[BUFSIZ], Mstr[BUFSIZ], Line[BUFSIZ], had[26];
112145Seric FILE	*iop, *Xiop;
12*30498Slepreau static	char ifde[] = "initial file does not exists";
132145Seric 
142145Seric main(argc,argv)
152145Seric int argc;
162145Seric register char *argv[];
172145Seric {
182145Seric 	register int i;
192145Seric 	register char *p;
202145Seric 	char c;
212145Seric 	extern cmt();
222145Seric 	extern int Fcnt;
232145Seric 
242145Seric 	/*
252145Seric 	Flags for 'fatal'.
262145Seric 	*/
272145Seric 	Fflags = FTLEXIT | FTLMSG | FTLCLN;
282145Seric 
292145Seric 	/*
302145Seric 	Process arguments.
312145Seric 	*/
322145Seric 	for (i = 1; i < argc; i++)
332145Seric 		if (argv[i][0] == '-' && (c = argv[i][1])) {
342145Seric 			p = &argv[i][2];
352145Seric 			switch (c) {
362145Seric 			case 'f':
372145Seric 				if (*p) {
382145Seric 					ffile = p;
392145Seric 					++had_ffile;
402145Seric 					if (!exists(ffile))
412145Seric 						fatal(ifde);
422145Seric 				}
432145Seric 				break;
442145Seric 			default:
452145Seric 				fatal("unknown key letter (cm1)");
462145Seric 			}
472145Seric 			if (had[c - 'a']++)
482145Seric 				fatal("key letter twice (cm2)");
492145Seric 			argv[i] = 0;
502145Seric 		}
512145Seric 		else num_files++;
522145Seric 
532145Seric 	if(num_files == 0)
542145Seric 		fatal("missing file arg (cm3)");
552145Seric 
562145Seric 	setsig();
572145Seric 	/*
582145Seric 	Reset flags for 'fatal' so that it will return to 'main'
592145Seric 	rather than exiting.
602145Seric 	*/
61*30498Slepreau 	Fflags &= ~FTLEXIT;
62*30498Slepreau 	Fflags |= FTLJMP;
632145Seric 
642145Seric 	/*
652145Seric 	Invoke 'cmt' for each file argument.
662145Seric 	*/
672145Seric 	for (i = 1; i < argc; i++)
682145Seric 		if (p = argv[i])
692145Seric 			do_file(p,cmt);
702145Seric 
712145Seric 	exit(Fcnt ? 1 : 0);
722145Seric }
732145Seric 
742145Seric 
75*30498Slepreau static char s_warn[] = "WARNING: MR flag is set; `%s' should contain both MR line and comment line\n";
762145Seric 
77*30498Slepreau static char ns_warn[] = "WARNING: MR flag is not set; `%s' should only contain comment line\n";
782145Seric 
792145Seric cmt(file)
802145Seric register char *file;
812145Seric {
822145Seric 	extern char had_dir, had_standinp;
832145Seric 	extern	char	*Sflags[];
846173Seric 	extern	char	Pgmr[SZLNAM];
852145Seric 	char	line[BUFSIZ];
862145Seric 	int	fowner, downer, user;
872145Seric 
882145Seric 	/*
892145Seric 	Set up to return to caller ('main') from 'fatal'.
902145Seric 	*/
912145Seric 	if (setjmp(Fjmp))
922145Seric 		return;
932145Seric 
942145Seric 	sinit(&gpkt,file,1);	/* init packet and open file */
952145Seric 
962145Seric 	if (lockit(auxf(gpkt.p_file,'z'),2,getpid()))
972145Seric 		fatal("cannot create lock file (cm4)");
982145Seric 
992145Seric 	if (num_files > 1 || had_dir || had_standinp)
1002145Seric 		printf("\n%s:\n",gpkt.p_file);
1012145Seric 
1022145Seric 	First = 1;
1032145Seric 	gpkt.p_reopen = 1;
1042145Seric 	do_delt(&gpkt);		/* read delta table for First time */
1052145Seric 	finduser(&gpkt);
1062145Seric 	doflags(&gpkt);		/* get flags (see if v flag is set) */
1072145Seric 	permiss(&gpkt);
1082145Seric 
1092145Seric 	/*
1102145Seric 	Check that user is either owner of file or
1112145Seric 	directory, or is one who made the initial delta
1122145Seric 	*/
1132145Seric 
1142145Seric 	fstat(fileno(gpkt.p_iop),&Statbuf);
1152145Seric 	fowner = Statbuf.st_uid & 0377;
1162145Seric 	copy(gpkt.p_file,line);		/* temporary for dname() */
1172145Seric 	if (stat(dname(line),&Statbuf))
1182145Seric 		downer = -1;
1192145Seric 	else downer = Statbuf.st_uid & 0377;
1202145Seric 	user = getuid() & 0377;
1212145Seric 	if (user != fowner || user != downer)
1222145Seric 		if (!equal(Pgmr,logname()))
1232145Seric 			fatal(sprintf(Error,
1242145Seric 				"you are neither owner nor '%s' (rc4)",Pgmr));
1252145Seric 
1262145Seric 	if ((HADF && had_ffile)) {
1272145Seric 		if (Sflags[VALFLAG - 'a'])
1282145Seric 			fprintf(stderr,s_warn,ffile);
1292145Seric 		else fprintf(stderr,ns_warn,ffile);
1302145Seric 		sleep(5);
1312145Seric 	}
1322145Seric 	flushto(&gpkt,EUSERTXT,1);
1332145Seric 	gpkt.p_chkeof = 1;	/* indicate that EOF is okay */
1342145Seric 	while (getline(&gpkt))	/* this will read body checking for cor */
1352145Seric 		;
1362145Seric 
1372145Seric 	gpkt.p_upd = 1;		/* x-file is to be used */
1382145Seric 	gpkt.p_wrttn = 1;	/* prevent printing of header line */
1392145Seric 	getline(&gpkt);		/* skip over old header record */
1402145Seric 	gpkt.p_wrttn = 1;
1412145Seric 
1422145Seric 	/*
1432145Seric 	Write new header.
1442145Seric 	*/
1452145Seric 	putline(&gpkt,sprintf(Line,"%c%c00000\n",CTLCHAR,HEAD));
1462145Seric 	do_delt(&gpkt);		/* read delta table second time */
1472145Seric 
1482145Seric 	flushto(&gpkt,EUSERNAM,0);
1492145Seric 	flushto(&gpkt,EUSERTXT,0);
1502145Seric 	while(getline(&gpkt))
1512145Seric 		;
1522145Seric 
1532145Seric 	flushline(&gpkt,0);	/* flush buffer, fix header, and close */
1542145Seric 	rename(auxf(gpkt.p_file,'x'),gpkt.p_file);
1552145Seric 	xrm(&gpkt);
1562145Seric 	unlockit(auxf(gpkt.p_file,'z'),getpid());
1572145Seric 	return;
1582145Seric }
1592145Seric 
1602145Seric 
161*30498Slepreau static	char cle[] = "comment line for initial delta already exists";
1622145Seric 
1632145Seric do_delt(pkt)
1642145Seric register struct packet *pkt;
1652145Seric {
1662145Seric 	int	n;
167*30498Slepreau 	int	did_zero = 0;
1682145Seric 	struct deltab dt;
1692145Seric 	struct stats stats;
1702145Seric 
1712145Seric 	while(getstats(pkt,&stats)) {
1722145Seric 		if(getadel(pkt,&dt) != BDELTAB)
1732145Seric 			fmterr(pkt);
1742145Seric 		if(dt.d_type == 'D' && dt.d_pred == 0) {
1752145Seric 			copy(dt.d_pgmr,Pgmr);
1762145Seric 			if (First)
1772145Seric 				did_zero++;
1782145Seric 			else {
1792145Seric 				putline(pkt,0);
1802145Seric 				fixintdel();
1812145Seric 			}
1822145Seric 		}
1832145Seric 		while((n = getline(pkt)) != NULL)
1842145Seric 			if (pkt->p_line[0] != CTLCHAR)
1852145Seric 				break;
1862145Seric 			else {
1872145Seric 				switch(pkt->p_line[1]) {
1882145Seric 				case EDELTAB:
1892145Seric 					break;
1902145Seric 				case INCLUDE:
1912145Seric 				case EXCLUDE:
1922145Seric 				case IGNORE:
1932145Seric 				case MRNUM:
1942145Seric 					continue;
1952145Seric 				case COMMENTS:
1962145Seric 					if (First)
1972145Seric 						if(did_zero)
1982145Seric 							fatal(cle);
1992145Seric 					continue;
2002145Seric 				default:
2012145Seric 					fmterr(pkt);
2022145Seric 				}
2032145Seric 				break;
2042145Seric 			}
2052145Seric 		if (n ==NULL || pkt->p_line[0] != CTLCHAR)
2062145Seric 			fmterr(pkt);
2072145Seric 	}
2082145Seric 	First = 0;
2092145Seric }
2102145Seric 
2112145Seric 
2122145Seric getadel(pkt,dt)
2132145Seric register struct packet *pkt;
2142145Seric register struct deltab *dt;
2152145Seric {
2162145Seric 	if (getline(pkt) == NULL)
2172145Seric 		fmterr(pkt);
2182145Seric 	return(del_ab(pkt->p_line,dt,pkt));
2192145Seric }
2202145Seric 
2212145Seric 
2222145Seric getstats(pkt,statp)
2232145Seric register struct packet *pkt;
2242145Seric register struct stats *statp;
2252145Seric {
2262145Seric 	register char *p;
2272145Seric 	extern	char	*satoi();
2282145Seric 
2292145Seric 	p = pkt->p_line;
2302145Seric 	if (getline(pkt) == NULL || *p++ != CTLCHAR || *p++ != STATS)
2312145Seric 		return(0);
2322145Seric 	NONBLANK(p);
2332145Seric 	p = satoi(p,&statp->s_ins);
2342145Seric 	p = satoi(++p,&statp->s_del);
2352145Seric 	satoi(++p,&statp->s_unc);
2362145Seric 	return(1);
2372145Seric }
2382145Seric 
2392145Seric clean_up(n)
2402145Seric {
2412145Seric 	if (gpkt.p_file[0])
2422145Seric 		unlockit(auxf(gpkt.p_file,'z'),getpid());
2432145Seric 	if (gpkt.p_iop)
2442145Seric 		fclose(gpkt.p_iop);
2452145Seric 
2462145Seric 	xrm(&gpkt);
2472145Seric 	if (exists(auxf(gpkt.p_file,'x')))
2482145Seric 		remove(auxf(gpkt.p_file,'x'));	/* remove x-file */
2492145Seric 	Xiop = 0;
2502145Seric 	if (F_Opened)
2512145Seric 		fclose(iop);
2522145Seric 	iop = F_Opened = Opened = 0;
2532145Seric 	xfreeall();
2542145Seric }
2552145Seric 
2562145Seric 
2572145Seric fixintdel()
2582145Seric {
2592145Seric 
2602145Seric 	register char	*p;
2612145Seric 	register int	doprmt;
2622145Seric 	int	tty[3];
2632145Seric 	char	str[128];
2642145Seric 
2652145Seric 	doprmt = 0;
2662145Seric 	if (gtty(0,tty) >= 0)
2672145Seric 		doprmt++;
2682145Seric 
2692145Seric 	if (!HADF && !had_ffile) {
2702145Seric 		Opened++;
2712145Seric 		iop = stdin;
2722145Seric 	}
2732145Seric 	else if (HADF && had_ffile) {
2742145Seric 		iop = xfopen(ffile,0);
2752145Seric 		doprmt = 0;
2762145Seric 		Opened++;
2772145Seric 		F_Opened++;
2782145Seric 	}
2792145Seric 	else if (HADF && !had_ffile)
2802145Seric 		doprmt = 0;
2812145Seric 
2822145Seric 	if ((p = Sflags[VALFLAG - 'a'])) {
2832145Seric 		if (doprmt)
2842145Seric 			printf("MRs? ");
2852145Seric 		if (Opened) {
2862145Seric 			Mrs = getinput(" ",Mstr);
2872145Seric 			mrfixup();
2882145Seric 			if (*p && valmrs(&gpkt,p))
2892145Seric 				fatal("invalid MRs (de9)");
2902145Seric 			putmrs(&gpkt);
2912145Seric 		}
2922145Seric 		else putline(&gpkt,sprintf(Line,CTLSTR,CTLCHAR,MRNUM));
2932145Seric 	}
2942145Seric 	if (doprmt)
2952145Seric 		printf("comments? ");
2962145Seric 	if (Opened) {
2972145Seric 		Comments = getinput(sprintf(Line,"\n%c%c ",CTLCHAR,COMMENTS),
2982145Seric 			   Cstr);
2992145Seric 		putline(&gpkt,sprintf(str,"%c%c ",CTLCHAR,COMMENTS));
3002145Seric 		putline(&gpkt,Comments);
3012145Seric 		putline(&gpkt,"\n");
3022145Seric 	}
3032145Seric 	else putline(&gpkt,sprintf(Line,CTLSTR,CTLCHAR,COMMENTS));
3042145Seric 
3052145Seric 	if (F_Opened)
3062145Seric 		fclose(iop);
3072145Seric 	F_Opened = Opened = 0;
3082145Seric }
3092145Seric 
3102145Seric 
3112145Seric getinput(repstr,result)
3122145Seric char *repstr;
3132145Seric char *result;
3142145Seric {
3152145Seric 	char line[BUFSIZ];
3162145Seric 	register int done, sz;
3172145Seric 	register char *p;
3182145Seric 
3192145Seric 	result[0] = 0;
3202145Seric 	done = 0;
3212145Seric 	setbuf(iop,NULL);
3222145Seric 	sz = sizeof(line) - size(repstr);
3232145Seric 	while (!done && fgets(line,sz,iop) != NULL) {
32419941Ssam 		p = index(line, '\0');
3252145Seric 		if (*--p == '\n') {
3262145Seric 			if (*--p == '\\') {
3272145Seric 				copy(repstr,p);
3282145Seric 			}
3292145Seric 			else {
3302145Seric 				*++p = 0;
3312145Seric 				++done;
3322145Seric 			}
3332145Seric 		}
3342145Seric 		else
3352145Seric 			fatal("line too long (co18)");
3362145Seric 		if ((size(line) + size(result)) > RESPSIZE)
3372145Seric 			fatal("response too long (co19)");
3382145Seric 		strcat(result,line);
3392145Seric 	}
3402145Seric 	return(result);
3412145Seric }
3422145Seric 
3432145Seric 
3442145Seric putmrs(pkt)
3452145Seric struct packet *pkt;
3462145Seric {
3472145Seric 	register char **argv;
3482145Seric 	char str[64];
3492145Seric 	extern char *Varg[];
3502145Seric 
3512145Seric 	for (argv = &Varg[VSTART]; *argv; argv++)
3522145Seric 		putline(pkt,sprintf(str,"%c%c %s\n",CTLCHAR,MRNUM,*argv));
3532145Seric }
354