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
main(argc,argv)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
cmt(file)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
do_delt(pkt)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
getadel(pkt,dt)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
getstats(pkt,statp)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
clean_up(n)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
fixintdel()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
getinput(repstr,result)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() */
escdodelt()367 escdodelt()
368 {}
369