1 # include	"../hdr/defines.h"
2 # include	"../hdr/had.h"
3 
4 SCCSID(@(#)cmt.c	4.1);
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[8];
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 			fatal(sprintf(Error,
124 				"you are neither owner nor '%s' (rc4)",Pgmr));
125 
126 	if ((HADF && had_ffile)) {
127 		if (Sflags[VALFLAG - 'a'])
128 			fprintf(stderr,s_warn,ffile);
129 		else fprintf(stderr,ns_warn,ffile);
130 		sleep(5);
131 	}
132 	flushto(&gpkt,EUSERTXT,1);
133 	gpkt.p_chkeof = 1;	/* indicate that EOF is okay */
134 	while (getline(&gpkt))	/* this will read body checking for cor */
135 		;
136 
137 	gpkt.p_upd = 1;		/* x-file is to be used */
138 	gpkt.p_wrttn = 1;	/* prevent printing of header line */
139 	getline(&gpkt);		/* skip over old header record */
140 	gpkt.p_wrttn = 1;
141 
142 	/*
143 	Write new header.
144 	*/
145 	putline(&gpkt,sprintf(Line,"%c%c00000\n",CTLCHAR,HEAD));
146 	do_delt(&gpkt);		/* read delta table second time */
147 
148 	flushto(&gpkt,EUSERNAM,0);
149 	flushto(&gpkt,EUSERTXT,0);
150 	while(getline(&gpkt))
151 		;
152 
153 	flushline(&gpkt,0);	/* flush buffer, fix header, and close */
154 	rename(auxf(gpkt.p_file,'x'),gpkt.p_file);
155 	xrm(&gpkt);
156 	unlockit(auxf(gpkt.p_file,'z'),getpid());
157 	return;
158 }
159 
160 
161 static	char	cle[]	"comment line for initial delta already exists";
162 
163 do_delt(pkt)
164 register struct packet *pkt;
165 {
166 	int	n;
167 	int	did_zero 0;
168 	struct deltab dt;
169 	struct stats stats;
170 
171 	while(getstats(pkt,&stats)) {
172 		if(getadel(pkt,&dt) != BDELTAB)
173 			fmterr(pkt);
174 		if(dt.d_type == 'D' && dt.d_pred == 0) {
175 			copy(dt.d_pgmr,Pgmr);
176 			if (First)
177 				did_zero++;
178 			else {
179 				putline(pkt,0);
180 				fixintdel();
181 			}
182 		}
183 		while((n = getline(pkt)) != NULL)
184 			if (pkt->p_line[0] != CTLCHAR)
185 				break;
186 			else {
187 				switch(pkt->p_line[1]) {
188 				case EDELTAB:
189 					break;
190 				case INCLUDE:
191 				case EXCLUDE:
192 				case IGNORE:
193 				case MRNUM:
194 					continue;
195 				case COMMENTS:
196 					if (First)
197 						if(did_zero)
198 							fatal(cle);
199 					continue;
200 				default:
201 					fmterr(pkt);
202 				}
203 				break;
204 			}
205 		if (n ==NULL || pkt->p_line[0] != CTLCHAR)
206 			fmterr(pkt);
207 	}
208 	First = 0;
209 }
210 
211 
212 getadel(pkt,dt)
213 register struct packet *pkt;
214 register struct deltab *dt;
215 {
216 	if (getline(pkt) == NULL)
217 		fmterr(pkt);
218 	return(del_ab(pkt->p_line,dt,pkt));
219 }
220 
221 
222 getstats(pkt,statp)
223 register struct packet *pkt;
224 register struct stats *statp;
225 {
226 	register char *p;
227 	extern	char	*satoi();
228 
229 	p = pkt->p_line;
230 	if (getline(pkt) == NULL || *p++ != CTLCHAR || *p++ != STATS)
231 		return(0);
232 	NONBLANK(p);
233 	p = satoi(p,&statp->s_ins);
234 	p = satoi(++p,&statp->s_del);
235 	satoi(++p,&statp->s_unc);
236 	return(1);
237 }
238 
239 clean_up(n)
240 {
241 	if (gpkt.p_file[0])
242 		unlockit(auxf(gpkt.p_file,'z'),getpid());
243 	if (gpkt.p_iop)
244 		fclose(gpkt.p_iop);
245 
246 	xrm(&gpkt);
247 	if (exists(auxf(gpkt.p_file,'x')))
248 		remove(auxf(gpkt.p_file,'x'));	/* remove x-file */
249 	Xiop = 0;
250 	if (F_Opened)
251 		fclose(iop);
252 	iop = F_Opened = Opened = 0;
253 	xfreeall();
254 }
255 
256 
257 fixintdel()
258 {
259 
260 	register char	*p;
261 	register int	doprmt;
262 	int	tty[3];
263 	char	str[128];
264 
265 	doprmt = 0;
266 	if (gtty(0,tty) >= 0)
267 		doprmt++;
268 
269 	if (!HADF && !had_ffile) {
270 		Opened++;
271 		iop = stdin;
272 	}
273 	else if (HADF && had_ffile) {
274 		iop = xfopen(ffile,0);
275 		doprmt = 0;
276 		Opened++;
277 		F_Opened++;
278 	}
279 	else if (HADF && !had_ffile)
280 		doprmt = 0;
281 
282 	if ((p = Sflags[VALFLAG - 'a'])) {
283 		if (doprmt)
284 			printf("MRs? ");
285 		if (Opened) {
286 			Mrs = getinput(" ",Mstr);
287 			mrfixup();
288 			if (*p && valmrs(&gpkt,p))
289 				fatal("invalid MRs (de9)");
290 			putmrs(&gpkt);
291 		}
292 		else putline(&gpkt,sprintf(Line,CTLSTR,CTLCHAR,MRNUM));
293 	}
294 	if (doprmt)
295 		printf("comments? ");
296 	if (Opened) {
297 		Comments = getinput(sprintf(Line,"\n%c%c ",CTLCHAR,COMMENTS),
298 			   Cstr);
299 		putline(&gpkt,sprintf(str,"%c%c ",CTLCHAR,COMMENTS));
300 		putline(&gpkt,Comments);
301 		putline(&gpkt,"\n");
302 	}
303 	else putline(&gpkt,sprintf(Line,CTLSTR,CTLCHAR,COMMENTS));
304 
305 	if (F_Opened)
306 		fclose(iop);
307 	F_Opened = Opened = 0;
308 }
309 
310 
311 getinput(repstr,result)
312 char *repstr;
313 char *result;
314 {
315 	char line[BUFSIZ];
316 	register int done, sz;
317 	register char *p;
318 
319 	result[0] = 0;
320 	done = 0;
321 	setbuf(iop,NULL);
322 	sz = sizeof(line) - size(repstr);
323 	while (!done && fgets(line,sz,iop) != NULL) {
324 		p = strend(line);
325 		if (*--p == '\n') {
326 			if (*--p == '\\') {
327 				copy(repstr,p);
328 			}
329 			else {
330 				*++p = 0;
331 				++done;
332 			}
333 		}
334 		else
335 			fatal("line too long (co18)");
336 		if ((size(line) + size(result)) > RESPSIZE)
337 			fatal("response too long (co19)");
338 		strcat(result,line);
339 	}
340 	return(result);
341 }
342 
343 
344 putmrs(pkt)
345 struct packet *pkt;
346 {
347 	register char **argv;
348 	char str[64];
349 	extern char *Varg[];
350 
351 	for (argv = &Varg[VSTART]; *argv; argv++)
352 		putline(pkt,sprintf(str,"%c%c %s\n",CTLCHAR,MRNUM,*argv));
353 }
354