1*2145Seric # include	"../hdr/defines.h"
2*2145Seric # include	"../hdr/had.h"
3*2145Seric 
4*2145Seric SCCSID(@(#)cmt.c	4.1);
5*2145Seric 
6*2145Seric struct packet gpkt;
7*2145Seric int	num_files, had_ffile;
8*2145Seric int	F_Opened, Opened, Domrs, First;
9*2145Seric char	*Comments, *Mrs, *ffile;
10*2145Seric char	Cstr[BUFSIZ], Mstr[BUFSIZ], Line[BUFSIZ], had[26];
11*2145Seric FILE	*iop, *Xiop;
12*2145Seric static	char	ifde[]	"initial file does not exists";
13*2145Seric 
14*2145Seric main(argc,argv)
15*2145Seric int argc;
16*2145Seric register char *argv[];
17*2145Seric {
18*2145Seric 	register int i;
19*2145Seric 	register char *p;
20*2145Seric 	char c;
21*2145Seric 	extern cmt();
22*2145Seric 	extern int Fcnt;
23*2145Seric 
24*2145Seric 	/*
25*2145Seric 	Flags for 'fatal'.
26*2145Seric 	*/
27*2145Seric 	Fflags = FTLEXIT | FTLMSG | FTLCLN;
28*2145Seric 
29*2145Seric 	/*
30*2145Seric 	Process arguments.
31*2145Seric 	*/
32*2145Seric 	for (i = 1; i < argc; i++)
33*2145Seric 		if (argv[i][0] == '-' && (c = argv[i][1])) {
34*2145Seric 			p = &argv[i][2];
35*2145Seric 			switch (c) {
36*2145Seric 			case 'f':
37*2145Seric 				if (*p) {
38*2145Seric 					ffile = p;
39*2145Seric 					++had_ffile;
40*2145Seric 					if (!exists(ffile))
41*2145Seric 						fatal(ifde);
42*2145Seric 				}
43*2145Seric 				break;
44*2145Seric 			default:
45*2145Seric 				fatal("unknown key letter (cm1)");
46*2145Seric 			}
47*2145Seric 			if (had[c - 'a']++)
48*2145Seric 				fatal("key letter twice (cm2)");
49*2145Seric 			argv[i] = 0;
50*2145Seric 		}
51*2145Seric 		else num_files++;
52*2145Seric 
53*2145Seric 	if(num_files == 0)
54*2145Seric 		fatal("missing file arg (cm3)");
55*2145Seric 
56*2145Seric 	setsig();
57*2145Seric 	/*
58*2145Seric 	Reset flags for 'fatal' so that it will return to 'main'
59*2145Seric 	rather than exiting.
60*2145Seric 	*/
61*2145Seric 	Fflags =& ~FTLEXIT;
62*2145Seric 	Fflags =| FTLJMP;
63*2145Seric 
64*2145Seric 	/*
65*2145Seric 	Invoke 'cmt' for each file argument.
66*2145Seric 	*/
67*2145Seric 	for (i = 1; i < argc; i++)
68*2145Seric 		if (p = argv[i])
69*2145Seric 			do_file(p,cmt);
70*2145Seric 
71*2145Seric 	exit(Fcnt ? 1 : 0);
72*2145Seric }
73*2145Seric 
74*2145Seric 
75*2145Seric static char s_warn[] "WARNING: MR flag is set; `%s' should contain both MR line and comment line\n";
76*2145Seric 
77*2145Seric static char ns_warn[] "WARNING: MR flag is not set; `%s' should only contain comment line\n";
78*2145Seric 
79*2145Seric cmt(file)
80*2145Seric register char *file;
81*2145Seric {
82*2145Seric 	extern char had_dir, had_standinp;
83*2145Seric 	extern	char	*Sflags[];
84*2145Seric 	extern	char	Pgmr[8];
85*2145Seric 	char	line[BUFSIZ];
86*2145Seric 	int	fowner, downer, user;
87*2145Seric 
88*2145Seric 	/*
89*2145Seric 	Set up to return to caller ('main') from 'fatal'.
90*2145Seric 	*/
91*2145Seric 	if (setjmp(Fjmp))
92*2145Seric 		return;
93*2145Seric 
94*2145Seric 	sinit(&gpkt,file,1);	/* init packet and open file */
95*2145Seric 
96*2145Seric 	if (lockit(auxf(gpkt.p_file,'z'),2,getpid()))
97*2145Seric 		fatal("cannot create lock file (cm4)");
98*2145Seric 
99*2145Seric 	if (num_files > 1 || had_dir || had_standinp)
100*2145Seric 		printf("\n%s:\n",gpkt.p_file);
101*2145Seric 
102*2145Seric 	First = 1;
103*2145Seric 	gpkt.p_reopen = 1;
104*2145Seric 	do_delt(&gpkt);		/* read delta table for First time */
105*2145Seric 	finduser(&gpkt);
106*2145Seric 	doflags(&gpkt);		/* get flags (see if v flag is set) */
107*2145Seric 	permiss(&gpkt);
108*2145Seric 
109*2145Seric 	/*
110*2145Seric 	Check that user is either owner of file or
111*2145Seric 	directory, or is one who made the initial delta
112*2145Seric 	*/
113*2145Seric 
114*2145Seric 	fstat(fileno(gpkt.p_iop),&Statbuf);
115*2145Seric 	fowner = Statbuf.st_uid & 0377;
116*2145Seric 	copy(gpkt.p_file,line);		/* temporary for dname() */
117*2145Seric 	if (stat(dname(line),&Statbuf))
118*2145Seric 		downer = -1;
119*2145Seric 	else downer = Statbuf.st_uid & 0377;
120*2145Seric 	user = getuid() & 0377;
121*2145Seric 	if (user != fowner || user != downer)
122*2145Seric 		if (!equal(Pgmr,logname()))
123*2145Seric 			fatal(sprintf(Error,
124*2145Seric 				"you are neither owner nor '%s' (rc4)",Pgmr));
125*2145Seric 
126*2145Seric 	if ((HADF && had_ffile)) {
127*2145Seric 		if (Sflags[VALFLAG - 'a'])
128*2145Seric 			fprintf(stderr,s_warn,ffile);
129*2145Seric 		else fprintf(stderr,ns_warn,ffile);
130*2145Seric 		sleep(5);
131*2145Seric 	}
132*2145Seric 	flushto(&gpkt,EUSERTXT,1);
133*2145Seric 	gpkt.p_chkeof = 1;	/* indicate that EOF is okay */
134*2145Seric 	while (getline(&gpkt))	/* this will read body checking for cor */
135*2145Seric 		;
136*2145Seric 
137*2145Seric 	gpkt.p_upd = 1;		/* x-file is to be used */
138*2145Seric 	gpkt.p_wrttn = 1;	/* prevent printing of header line */
139*2145Seric 	getline(&gpkt);		/* skip over old header record */
140*2145Seric 	gpkt.p_wrttn = 1;
141*2145Seric 
142*2145Seric 	/*
143*2145Seric 	Write new header.
144*2145Seric 	*/
145*2145Seric 	putline(&gpkt,sprintf(Line,"%c%c00000\n",CTLCHAR,HEAD));
146*2145Seric 	do_delt(&gpkt);		/* read delta table second time */
147*2145Seric 
148*2145Seric 	flushto(&gpkt,EUSERNAM,0);
149*2145Seric 	flushto(&gpkt,EUSERTXT,0);
150*2145Seric 	while(getline(&gpkt))
151*2145Seric 		;
152*2145Seric 
153*2145Seric 	flushline(&gpkt,0);	/* flush buffer, fix header, and close */
154*2145Seric 	rename(auxf(gpkt.p_file,'x'),gpkt.p_file);
155*2145Seric 	xrm(&gpkt);
156*2145Seric 	unlockit(auxf(gpkt.p_file,'z'),getpid());
157*2145Seric 	return;
158*2145Seric }
159*2145Seric 
160*2145Seric 
161*2145Seric static	char	cle[]	"comment line for initial delta already exists";
162*2145Seric 
163*2145Seric do_delt(pkt)
164*2145Seric register struct packet *pkt;
165*2145Seric {
166*2145Seric 	int	n;
167*2145Seric 	int	did_zero 0;
168*2145Seric 	struct deltab dt;
169*2145Seric 	struct stats stats;
170*2145Seric 
171*2145Seric 	while(getstats(pkt,&stats)) {
172*2145Seric 		if(getadel(pkt,&dt) != BDELTAB)
173*2145Seric 			fmterr(pkt);
174*2145Seric 		if(dt.d_type == 'D' && dt.d_pred == 0) {
175*2145Seric 			copy(dt.d_pgmr,Pgmr);
176*2145Seric 			if (First)
177*2145Seric 				did_zero++;
178*2145Seric 			else {
179*2145Seric 				putline(pkt,0);
180*2145Seric 				fixintdel();
181*2145Seric 			}
182*2145Seric 		}
183*2145Seric 		while((n = getline(pkt)) != NULL)
184*2145Seric 			if (pkt->p_line[0] != CTLCHAR)
185*2145Seric 				break;
186*2145Seric 			else {
187*2145Seric 				switch(pkt->p_line[1]) {
188*2145Seric 				case EDELTAB:
189*2145Seric 					break;
190*2145Seric 				case INCLUDE:
191*2145Seric 				case EXCLUDE:
192*2145Seric 				case IGNORE:
193*2145Seric 				case MRNUM:
194*2145Seric 					continue;
195*2145Seric 				case COMMENTS:
196*2145Seric 					if (First)
197*2145Seric 						if(did_zero)
198*2145Seric 							fatal(cle);
199*2145Seric 					continue;
200*2145Seric 				default:
201*2145Seric 					fmterr(pkt);
202*2145Seric 				}
203*2145Seric 				break;
204*2145Seric 			}
205*2145Seric 		if (n ==NULL || pkt->p_line[0] != CTLCHAR)
206*2145Seric 			fmterr(pkt);
207*2145Seric 	}
208*2145Seric 	First = 0;
209*2145Seric }
210*2145Seric 
211*2145Seric 
212*2145Seric getadel(pkt,dt)
213*2145Seric register struct packet *pkt;
214*2145Seric register struct deltab *dt;
215*2145Seric {
216*2145Seric 	if (getline(pkt) == NULL)
217*2145Seric 		fmterr(pkt);
218*2145Seric 	return(del_ab(pkt->p_line,dt,pkt));
219*2145Seric }
220*2145Seric 
221*2145Seric 
222*2145Seric getstats(pkt,statp)
223*2145Seric register struct packet *pkt;
224*2145Seric register struct stats *statp;
225*2145Seric {
226*2145Seric 	register char *p;
227*2145Seric 	extern	char	*satoi();
228*2145Seric 
229*2145Seric 	p = pkt->p_line;
230*2145Seric 	if (getline(pkt) == NULL || *p++ != CTLCHAR || *p++ != STATS)
231*2145Seric 		return(0);
232*2145Seric 	NONBLANK(p);
233*2145Seric 	p = satoi(p,&statp->s_ins);
234*2145Seric 	p = satoi(++p,&statp->s_del);
235*2145Seric 	satoi(++p,&statp->s_unc);
236*2145Seric 	return(1);
237*2145Seric }
238*2145Seric 
239*2145Seric clean_up(n)
240*2145Seric {
241*2145Seric 	if (gpkt.p_file[0])
242*2145Seric 		unlockit(auxf(gpkt.p_file,'z'),getpid());
243*2145Seric 	if (gpkt.p_iop)
244*2145Seric 		fclose(gpkt.p_iop);
245*2145Seric 
246*2145Seric 	xrm(&gpkt);
247*2145Seric 	if (exists(auxf(gpkt.p_file,'x')))
248*2145Seric 		remove(auxf(gpkt.p_file,'x'));	/* remove x-file */
249*2145Seric 	Xiop = 0;
250*2145Seric 	if (F_Opened)
251*2145Seric 		fclose(iop);
252*2145Seric 	iop = F_Opened = Opened = 0;
253*2145Seric 	xfreeall();
254*2145Seric }
255*2145Seric 
256*2145Seric 
257*2145Seric fixintdel()
258*2145Seric {
259*2145Seric 
260*2145Seric 	register char	*p;
261*2145Seric 	register int	doprmt;
262*2145Seric 	int	tty[3];
263*2145Seric 	char	str[128];
264*2145Seric 
265*2145Seric 	doprmt = 0;
266*2145Seric 	if (gtty(0,tty) >= 0)
267*2145Seric 		doprmt++;
268*2145Seric 
269*2145Seric 	if (!HADF && !had_ffile) {
270*2145Seric 		Opened++;
271*2145Seric 		iop = stdin;
272*2145Seric 	}
273*2145Seric 	else if (HADF && had_ffile) {
274*2145Seric 		iop = xfopen(ffile,0);
275*2145Seric 		doprmt = 0;
276*2145Seric 		Opened++;
277*2145Seric 		F_Opened++;
278*2145Seric 	}
279*2145Seric 	else if (HADF && !had_ffile)
280*2145Seric 		doprmt = 0;
281*2145Seric 
282*2145Seric 	if ((p = Sflags[VALFLAG - 'a'])) {
283*2145Seric 		if (doprmt)
284*2145Seric 			printf("MRs? ");
285*2145Seric 		if (Opened) {
286*2145Seric 			Mrs = getinput(" ",Mstr);
287*2145Seric 			mrfixup();
288*2145Seric 			if (*p && valmrs(&gpkt,p))
289*2145Seric 				fatal("invalid MRs (de9)");
290*2145Seric 			putmrs(&gpkt);
291*2145Seric 		}
292*2145Seric 		else putline(&gpkt,sprintf(Line,CTLSTR,CTLCHAR,MRNUM));
293*2145Seric 	}
294*2145Seric 	if (doprmt)
295*2145Seric 		printf("comments? ");
296*2145Seric 	if (Opened) {
297*2145Seric 		Comments = getinput(sprintf(Line,"\n%c%c ",CTLCHAR,COMMENTS),
298*2145Seric 			   Cstr);
299*2145Seric 		putline(&gpkt,sprintf(str,"%c%c ",CTLCHAR,COMMENTS));
300*2145Seric 		putline(&gpkt,Comments);
301*2145Seric 		putline(&gpkt,"\n");
302*2145Seric 	}
303*2145Seric 	else putline(&gpkt,sprintf(Line,CTLSTR,CTLCHAR,COMMENTS));
304*2145Seric 
305*2145Seric 	if (F_Opened)
306*2145Seric 		fclose(iop);
307*2145Seric 	F_Opened = Opened = 0;
308*2145Seric }
309*2145Seric 
310*2145Seric 
311*2145Seric getinput(repstr,result)
312*2145Seric char *repstr;
313*2145Seric char *result;
314*2145Seric {
315*2145Seric 	char line[BUFSIZ];
316*2145Seric 	register int done, sz;
317*2145Seric 	register char *p;
318*2145Seric 
319*2145Seric 	result[0] = 0;
320*2145Seric 	done = 0;
321*2145Seric 	setbuf(iop,NULL);
322*2145Seric 	sz = sizeof(line) - size(repstr);
323*2145Seric 	while (!done && fgets(line,sz,iop) != NULL) {
324*2145Seric 		p = strend(line);
325*2145Seric 		if (*--p == '\n') {
326*2145Seric 			if (*--p == '\\') {
327*2145Seric 				copy(repstr,p);
328*2145Seric 			}
329*2145Seric 			else {
330*2145Seric 				*++p = 0;
331*2145Seric 				++done;
332*2145Seric 			}
333*2145Seric 		}
334*2145Seric 		else
335*2145Seric 			fatal("line too long (co18)");
336*2145Seric 		if ((size(line) + size(result)) > RESPSIZE)
337*2145Seric 			fatal("response too long (co19)");
338*2145Seric 		strcat(result,line);
339*2145Seric 	}
340*2145Seric 	return(result);
341*2145Seric }
342*2145Seric 
343*2145Seric 
344*2145Seric putmrs(pkt)
345*2145Seric struct packet *pkt;
346*2145Seric {
347*2145Seric 	register char **argv;
348*2145Seric 	char str[64];
349*2145Seric 	extern char *Varg[];
350*2145Seric 
351*2145Seric 	for (argv = &Varg[VSTART]; *argv; argv++)
352*2145Seric 		putline(pkt,sprintf(str,"%c%c %s\n",CTLCHAR,MRNUM,*argv));
353*2145Seric }
354