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