1 # include "../hdr/defines.h" 2 # include "../hdr/had.h" 3 4 SCCSID(@(#)cmt.c 4.2); 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 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