1 # include	"../hdr/defines.h"
2 # include	"../hdr/had.h"
3 
4 SCCSID(@(#)get.c	4.3);
5 USXALLOC();
6 
7 int	Debug	0;
8 struct packet gpkt;
9 struct sid sid;
10 unsigned	Ser;
11 int	num_files;
12 char	had[26];
13 char	*ilist, *elist, *lfile;
14 long	cutoff	0X7FFFFFFFL;	/* max positive long */
15 int verbosity;
16 char	Gfile[16];
17 char	*Type;
18 int	Did_id;
19 
20 main(argc,argv)
21 int argc;
22 register char *argv[];
23 {
24 	register int i;
25 	register char *p;
26 	char c;
27 	int testmore;
28 	extern int Fcnt;
29 	extern get();
30 
31 	Fflags = FTLEXIT | FTLMSG | FTLCLN;
32 	for(i=1; i<argc; i++)
33 		if(argv[i][0] == '-' && (c=argv[i][1])) {
34 			p = &argv[i][2];
35 			testmore = 0;
36 			switch (c) {
37 
38 			case 'a':
39 				if (!p[0]) {
40 					argv[i] = 0;
41 					continue;
42 				}
43 				Ser = patoi(p);
44 				break;
45 			case 'r':
46 				if (!p[0]) {
47 					argv[i] = 0;
48 					continue;
49 				}
50 				chksid(sid_ab(p,&sid),&sid);
51 				break;
52 			case 'c':
53 				if (!p[0]) {
54 					argv[i] = 0;
55 					continue;
56 				}
57 				if (date_ab(p,&cutoff))
58 					fatal("bad date/time (cm5)");
59 				break;
60 			case 'l':
61 				lfile = p;
62 				break;
63 			case 'i':
64 				if (!p[0]) {
65 					argv[i] = 0;
66 					continue;
67 				}
68 				ilist = p;
69 				break;
70 			case 'x':
71 				if (!p[0]) {
72 					argv[i] = 0;
73 					continue;
74 				}
75 				elist = p;
76 				break;
77 			case 'b':
78 			case 'g':
79 			case 'e':
80 			case 'p':
81 			case 'k':
82 			case 'm':
83 			case 'n':
84 			case 's':
85 			case 't':
86 				testmore++;
87 				break;
88 			default:
89 				fatal("unknown key letter (cm1)");
90 			}
91 
92 			if (testmore) {
93 				testmore = 0;
94 				if (*p)
95 					fatal(sprintf(Error,
96 					  "value after %c arg (cm8)",c));
97 			}
98 			if (had[c - 'a']++)
99 				fatal("key letter twice (cm2)");
100 			argv[i] = 0;
101 		}
102 		else num_files++;
103 
104 	if(num_files == 0)
105 		fatal("missing file arg (cm3)");
106 	if (HADE && HADM)
107 		fatal("e not allowed with m (ge3)");
108 	if (HADE || HADI || HADX)
109 		HADK = 1;
110 	if (!HADS)
111 		verbosity = -1;
112 	setsig();
113 	Fflags =& ~FTLEXIT;
114 	Fflags =| FTLJMP;
115 	for (i=1; i<argc; i++)
116 		if (p=argv[i])
117 			do_file(p,get);
118 	exit(Fcnt ? 1 : 0);
119 }
120 
121 
122 get(file)
123 {
124 	register char *p;
125 	register unsigned ser;
126 	extern char had_dir, had_standinp;
127 	extern char *Sflags[];
128 	struct stats stats;
129 	char	str[32];
130 
131 	if (setjmp(Fjmp))
132 		return;
133 	sinit(&gpkt,file,1);
134 	gpkt.p_ixuser = (HADI | HADX);
135 	gpkt.p_reqsid.s_rel = sid.s_rel;
136 	gpkt.p_reqsid.s_lev = sid.s_lev;
137 	gpkt.p_reqsid.s_br = sid.s_br;
138 	gpkt.p_reqsid.s_seq = sid.s_seq;
139 	gpkt.p_verbose = verbosity;
140 	gpkt.p_stdout = (HADP ? stderr : stdout);
141 	gpkt.p_cutoff = cutoff;
142 	gpkt.p_lfile = lfile;
143 	copy(auxf(gpkt.p_file,'g'),Gfile);
144 
145 	if (gpkt.p_verbose && (num_files > 1 || had_dir || had_standinp))
146 		fprintf(gpkt.p_stdout,"\n%s:\n",gpkt.p_file);
147 	if (dodelt(&gpkt,&stats,0,0) == 0)
148 		fmterr(&gpkt);
149 	finduser(&gpkt);
150 	doflags(&gpkt);
151 	if (!HADA)
152 		ser = getser(&gpkt);
153 	else {
154 		if ((ser = Ser) > maxser(&gpkt))
155 			fatal("serial number too large (ge19)");
156 		move(&gpkt.p_idel[ser].i_sid, &gpkt.p_gotsid, sizeof(sid));
157 		if (HADR && sid.s_rel != gpkt.p_gotsid.s_rel) {
158 			zero(&gpkt.p_reqsid, sizeof(gpkt.p_reqsid));
159 			gpkt.p_reqsid.s_rel = sid.s_rel;
160 		}
161 		else
162 			move(&gpkt.p_gotsid, &gpkt.p_reqsid, sizeof(sid));
163 	}
164 	doie(&gpkt,ilist,elist,0);
165 	setup(&gpkt,ser);
166 	if (!(Type = Sflags[TYPEFLAG - 'a']))
167 		Type = Null;
168 	if (!(HADP || HADG) && writable(Gfile))
169 		fatal(sprintf(Error,"writable `%s' exists (ge4)",Gfile));
170 	if (gpkt.p_verbose) {
171 		sid_ba(&gpkt.p_gotsid,str);
172 		fprintf(gpkt.p_stdout,"%s\n",str);
173 	}
174 	if (HADE) {
175 		if (!HADR)
176 			move(&gpkt.p_gotsid,&gpkt.p_reqsid,
177 			     sizeof(gpkt.p_reqsid));
178 		newsid(&gpkt,Sflags[BRCHFLAG - 'a'] && HADB);
179 		permiss(&gpkt);
180 		wrtpfile(&gpkt,ilist,elist);
181 	}
182 	setuid(getuid());
183 	if (HADL)
184 		gen_lfile(&gpkt);
185 	if (HADG) {
186 		fclose(gpkt.p_iop);
187 		xfreeall();
188 		return;
189 	}
190 	flushto(&gpkt,EUSERTXT,1);
191 	idsetup(&gpkt);
192 	gpkt.p_chkeof = 1;
193 	Did_id = 0;
194 	while(readmod(&gpkt)) {
195 		if (gpkt.p_gout == 0) {
196 			if (HADP)
197 				gpkt.p_gout = stdout;
198 			else
199 				gpkt.p_gout = xfcreat(Gfile,HADK ? 0666 : 0444);
200 		}
201 		prfx(&gpkt);
202 		p = idsubst(&gpkt,gpkt.p_line);
203 		fputs(p,gpkt.p_gout);
204 	}
205 	fflush(gpkt.p_gout);
206 	if (gpkt.p_gout && gpkt.p_gout != stdout)
207 		fclose(gpkt.p_gout);
208 	if (gpkt.p_verbose)
209 		fprintf(gpkt.p_stdout,"%u lines\n",gpkt.p_glnno);
210 	if (!Did_id && !HADK)
211 		if (Sflags[IDFLAG - 'a'])
212 			fatal("no id keywords (cm6)");
213 		else if (gpkt.p_verbose)
214 			fprintf(stderr,"No id keywords (cm7)\n");
215 	xfreeall();
216 }
217 
218 writable(fn)
219 char *fn;
220 {
221 	struct stat s;
222 
223 	return (stat(fn, &s) >= 0 && (s.st_mode & 0222) != 0);
224 }
225 
226 
227 newsid(pkt,branch)
228 register struct packet *pkt;
229 int branch;
230 {
231 	int chkbr;
232 
233 	chkbr = 0;
234 	if (pkt->p_reqsid.s_br == 0) {
235 		pkt->p_reqsid.s_lev =+ 1;
236 		if (sidtoser(&pkt->p_reqsid,pkt) ||
237 			pkt->p_maxr > pkt->p_reqsid.s_rel || branch) {
238 				pkt->p_reqsid.s_rel = pkt->p_gotsid.s_rel;
239 				pkt->p_reqsid.s_lev = pkt->p_gotsid.s_lev;
240 				pkt->p_reqsid.s_br = pkt->p_gotsid.s_br + 1;
241 				pkt->p_reqsid.s_seq = 1;
242 				chkbr++;
243 		}
244 	}
245 	else if (pkt->p_reqsid.s_seq == 0 && !branch)
246 		pkt->p_reqsid.s_seq = pkt->p_gotsid.s_seq + 1;
247 	else {
248 		pkt->p_reqsid.s_seq =+ 1;
249 		if (branch || sidtoser(&pkt->p_reqsid,pkt)) {
250 			pkt->p_reqsid.s_br =+ 1;
251 			pkt->p_reqsid.s_seq = 1;
252 			chkbr++;
253 		}
254 	}
255 	if (chkbr)
256 		while (sidtoser(&pkt->p_reqsid,pkt))
257 			pkt->p_reqsid.s_br =+ 1;
258 	if (sidtoser(&pkt->p_reqsid,pkt))
259 		fatal("internal error in newsid()");
260 }
261 
262 
263 enter(pkt,ch,n,sidp)
264 struct packet *pkt;
265 char ch;
266 int n;
267 struct sid *sidp;
268 {
269 	char str[32];
270 	register struct apply *ap;
271 
272 	sid_ba(sidp,str);
273 	if (pkt->p_verbose)
274 		fprintf(pkt->p_stdout,"%s\n",str);
275 	ap = &pkt->p_apply[n];
276 	switch(ap->a_code) {
277 
278 	case EMPTY:
279 		if (ch == INCLUDE)
280 			condset(ap,APPLY,INCLUSER);
281 		else
282 			condset(ap,NOAPPLY,EXCLUSER);
283 		break;
284 	case APPLY:
285 		sid_ba(sidp,str);
286 		fatal(sprintf(Error,"%s already included (ge9)",str));
287 		break;
288 	case NOAPPLY:
289 		sid_ba(sidp,str);
290 		fatal(sprintf(Error,"%s already excluded (ge10)",str));
291 		break;
292 	default:
293 		fatal("internal error in get/enter() (ge11)");
294 		break;
295 	}
296 }
297 
298 
299 gen_lfile(pkt)
300 register struct packet *pkt;
301 {
302 	int n;
303 	int reason;
304 	char str[32];
305 	char line[BUFSIZ];
306 	struct deltab dt;
307 	FILE *in;
308 	FILE *out;
309 
310 	in = xfopen(pkt->p_file,0);
311 	if (*pkt->p_lfile)
312 		out = stdout;
313 	else
314 		out = xfcreat(auxf(pkt->p_file,'l'),0444);
315 	fgets(line,sizeof(line),in);
316 	while (fgets(line,sizeof(line),in) != NULL && line[0] == CTLCHAR && line[1] == STATS) {
317 		fgets(line,sizeof(line),in);
318 		del_ab(line,&dt);
319 		if (dt.d_type == 'D') {
320 			reason = pkt->p_apply[dt.d_serial].a_reason;
321 			if (pkt->p_apply[dt.d_serial].a_code == APPLY) {
322 				putc(' ',out);
323 				putc(' ',out);
324 			}
325 			else {
326 				putc('*',out);
327 				if (reason & IGNR)
328 					putc(' ',out);
329 				else
330 					putc('*',out);
331 			}
332 			switch (reason & (INCL | EXCL | CUTOFF)) {
333 
334 			case INCL:
335 				putc('I',out);
336 				break;
337 			case EXCL:
338 				putc('X',out);
339 				break;
340 			case CUTOFF:
341 				putc('C',out);
342 				break;
343 			default:
344 				putc(' ',out);
345 				break;
346 			}
347 			putc(' ',out);
348 			sid_ba(&dt.d_sid,str);
349 			fprintf(out,"%s\t",str);
350 			date_ba(&dt.d_datetime,str);
351 			fprintf(out,"%s %s\n",str,dt.d_pgmr);
352 		}
353 		while ((n = fgets(line,sizeof(line),in)) != NULL)
354 			if (line[0] != CTLCHAR)
355 				break;
356 			else {
357 				switch (line[1]) {
358 
359 				case EDELTAB:
360 					break;
361 				default:
362 					continue;
363 				case MRNUM:
364 				case COMMENTS:
365 					if (dt.d_type == 'D')
366 						fprintf(out,"\t%s",&line[3]);
367 					continue;
368 				}
369 				break;
370 			}
371 		if (n == NULL || line[0] != CTLCHAR)
372 			break;
373 		putc('\n',out);
374 	}
375 	fclose(in);
376 	if (out != stdout)
377 		fclose(out);
378 }
379 
380 
381 char	Curdate[18];
382 char	*Curtime;
383 char	Gdate[9];
384 char	Chgdate[18];
385 char	*Chgtime;
386 char	Gchgdate[9];
387 char	Sid[32];
388 char	Mod[16];
389 char	Olddir[BUFSIZ];
390 char	Pname[BUFSIZ];
391 char	Dir[BUFSIZ];
392 
393 idsetup(pkt)
394 register struct packet *pkt;
395 {
396 	extern long Timenow;
397 	register int n;
398 	register char *p;
399 
400 	date_ba(&Timenow,Curdate);
401 	Curtime = &Curdate[9];
402 	Curdate[8] = 0;
403 	copy(pkt->p_file,Dir);
404 	dname(Dir);
405 	if(curdir(Olddir) != 0)
406 		fatal("curdir failed (ge20)");
407 	if(chdir(Dir) != 0)
408 		fatal("cannot change directory (ge22)");
409 	if(curdir(Pname) != 0)
410 		fatal("curdir failed (ge21)");
411 	if(chdir(Olddir) != 0)
412 		fatal("cannot change directory (ge23)");
413 	makgdate(Curdate,Gdate);
414 	for (n = maxser(pkt); n; n--)
415 		if (pkt->p_apply[n].a_code == APPLY)
416 			break;
417 	if (n)
418 		date_ba(&pkt->p_idel[n].i_datetime,Chgdate);
419 	Chgtime = &Chgdate[9];
420 	Chgdate[8] = 0;
421 	makgdate(Chgdate,Gchgdate);
422 	sid_ba(&pkt->p_gotsid,Sid);
423 	if (p = Sflags[MODFLAG - 'a'])
424 		copy(p,Mod);
425 	else
426 		copy(Gfile,Mod);
427 }
428 
429 
430 makgdate(old,new)
431 register char *old, *new;
432 {
433 	if ((*new = old[3]) != '0')
434 		new++;
435 	*new++ = old[4];
436 	*new++ = '/';
437 	if ((*new = old[6]) != '0')
438 		new++;
439 	*new++ = old[7];
440 	*new++ = '/';
441 	*new++ = old[0];
442 	*new++ = old[1];
443 	*new = 0;
444 }
445 
446 
447 static char Zkeywd[5]	"@(#)";
448 
449 idsubst(pkt,line)
450 register struct packet *pkt;
451 char line[];
452 {
453 	static char tline[BUFSIZ];
454 	static char str[32];
455 	register char *lp, *tp;
456 	extern char *Type;
457 	extern char *Sflags[];
458 
459 	if (HADK || !any('%',line))
460 		return(line);
461 
462 	tp = tline;
463 	for(lp=line; *lp != 0; lp++) {
464 		if(lp[0] == '%' && lp[1] != 0 && lp[2] == '%') {
465 			switch(*++lp) {
466 
467 			case 'M':
468 				tp = trans(tp,Mod);
469 				break;
470 			case 'R':
471 				sprintf(str,"%u",pkt->p_gotsid.s_rel);
472 				tp = trans(tp,str);
473 				break;
474 			case 'L':
475 				sprintf(str,"%u",pkt->p_gotsid.s_lev);
476 				tp = trans(tp,str);
477 				break;
478 			case 'B':
479 				sprintf(str,"%u",pkt->p_gotsid.s_br);
480 				tp = trans(tp,str);
481 				break;
482 			case 'S':
483 				sprintf(str,"%u",pkt->p_gotsid.s_seq);
484 				tp = trans(tp,str);
485 				break;
486 			case 'D':
487 				tp = trans(tp,Curdate);
488 				break;
489 			case 'H':
490 				tp = trans(tp,Gdate);
491 				break;
492 			case 'T':
493 				tp = trans(tp,Curtime);
494 				break;
495 			case 'E':
496 				tp = trans(tp,Chgdate);
497 				break;
498 			case 'G':
499 				tp = trans(tp,Gchgdate);
500 				break;
501 			case 'U':
502 				tp = trans(tp,Chgtime);
503 				break;
504 			case 'Z':
505 				tp = trans(tp,Zkeywd);
506 				break;
507 			case 'Y':
508 				tp = trans(tp,Type);
509 				break;
510 			case 'W':
511 				tp = trans(tp,Zkeywd);
512 				tp = trans(tp,Mod);
513 				*tp++ = '\t';
514 			case 'I':
515 				tp = trans(tp,Sid);
516 				break;
517 			case 'P':
518 				tp = trans(tp,Pname);
519 				*tp++ = '/';
520 				tp = trans(tp,(sname(pkt->p_file)));
521 				break;
522 			case 'F':
523 				tp = trans(tp,pkt->p_file);
524 				break;
525 			case 'C':
526 				sprintf(str,"%u",pkt->p_glnno);
527 				tp = trans(tp,str);
528 				break;
529 			case 'A':
530 				tp = trans(tp,Zkeywd);
531 				tp = trans(tp,Type);
532 				*tp++ = ' ';
533 				tp = trans(tp,Mod);
534 				*tp++ = ' ';
535 				tp = trans(tp,Sid);
536 				tp = trans(tp,Zkeywd);
537 				break;
538 			default:
539 				*tp++ = '%';
540 				*tp++ = *lp;
541 				continue;
542 			}
543 			lp++;
544 		}
545 		else
546 			*tp++ = *lp;
547 	}
548 
549 	*tp = 0;
550 	return(tline);
551 }
552 
553 
554 trans(tp,str)
555 register char *tp, *str;
556 {
557 	Did_id = 1;
558 	while(*tp++ = *str++)
559 		;
560 	return(tp-1);
561 }
562 
563 
564 prfx(pkt)
565 register struct packet *pkt;
566 {
567 	char str[32];
568 
569 	if (HADN)
570 		fprintf(pkt->p_gout,"%s\t",Mod);
571 	if (HADM) {
572 		sid_ba(&pkt->p_inssid,str);
573 		fprintf(pkt->p_gout,"%s\t",str);
574 	}
575 }
576 
577 
578 clean_up(n)
579 {
580 	if (gpkt.p_file[0])
581 		unlockit(auxf(gpkt.p_file,'z'),getpid());
582 	if (gpkt.p_iop)
583 		fclose(gpkt.p_iop);
584 	xfreeall();
585 }
586 
587 
588 wrtpfile(pkt,inc,exc)
589 register struct packet *pkt;
590 char *inc, *exc;
591 {
592 	char line[64], str1[32], str2[32];
593 	char *user;
594 	FILE *in, *out;
595 	struct pfile pf;
596 	register char *p;
597 	int fd;
598 	int i;
599 	extern long Timenow;
600 
601 	user = logname();
602 	if (lockit(auxf(pkt->p_file,'z'),2,getpid()))
603 		fatal("cannot create lock file (cm4)");
604 	if (exists(p = auxf(pkt->p_file,'p'))) {
605 		fd = xopen(p,2);
606 		in = fdfopen(fd,0);
607 		while (fgets(line,sizeof(line),in) != NULL) {
608 			p = line;
609 			p[length(p) - 1] = 0;
610 			pf_ab(p,&pf,0);
611 			if ((pf.pf_gsid.s_rel == pkt->p_gotsid.s_rel &&
612 				pf.pf_gsid.s_lev == pkt->p_gotsid.s_lev &&
613 				pf.pf_gsid.s_br == pkt->p_gotsid.s_br &&
614 				pf.pf_gsid.s_seq == pkt->p_gotsid.s_seq) ||
615 				(pf.pf_nsid.s_rel == pkt->p_reqsid.s_rel &&
616 				pf.pf_nsid.s_lev == pkt->p_reqsid.s_lev &&
617 				pf.pf_nsid.s_br == pkt->p_reqsid.s_br &&
618 				pf.pf_nsid.s_seq == pkt->p_reqsid.s_seq)) {
619 				fclose(in);
620 				fatal(sprintf(Error,"being edited: `%s' (ge17)",
621 					line));
622 				}
623 			if (!equal(pf.pf_user,user))
624 				fprintf(stderr,"WARNING: being edited: `%s' (ge18)\n",line);
625 		}
626 		out = fdfopen(dup(fd),1);
627 		fclose(in);
628 	}
629 	else
630 		out = xfcreat(p,0666);
631 	fseek(out,0L,2);
632 	sid_ba(&pkt->p_gotsid,str1);
633 	sid_ba(&pkt->p_reqsid,str2);
634 	date_ba(&Timenow,line);
635 	fprintf(out,"%s %s %s %s",str1,str2,user,line);
636 	if (inc)
637 		fprintf(out," -i%s",inc);
638 	if (exc)
639 		fprintf(out," -x%s",exc);
640 	fprintf(out,"\n");
641 	fclose(out);
642 	if (pkt->p_verbose)
643 		fprintf(pkt->p_stdout,"new delta %s\n",str2);
644 	unlockit(auxf(pkt->p_file,'z'),getpid());
645 }
646 
647 
648 getser(pkt)
649 register struct packet *pkt;
650 {
651 	register struct idel *rdp;
652 	int n, ser, def;
653 	char *p;
654 	extern char *Sflags[];
655 
656 	def = 0;
657 	if (pkt->p_reqsid.s_rel == 0) {
658 		if (p = Sflags[DEFTFLAG - 'a'])
659 			chksid(sid_ab(p, &pkt->p_reqsid), &pkt->p_reqsid);
660 		else {
661 			pkt->p_reqsid.s_rel = MAX;
662 			def = 1;
663 		}
664 	}
665 	ser = 0;
666 	if (pkt->p_reqsid.s_lev == 0) {
667 		for (n = maxser(pkt); n; n--) {
668 			rdp = &pkt->p_idel[n];
669 			if ((rdp->i_sid.s_br == 0 || HADT) &&
670 				pkt->p_reqsid.s_rel >= rdp->i_sid.s_rel &&
671 				rdp->i_sid.s_rel > pkt->p_gotsid.s_rel) {
672 					ser = n;
673 					pkt->p_gotsid.s_rel = rdp->i_sid.s_rel;
674 			}
675 		}
676 	}
677 	else if (pkt->p_reqsid.s_br && pkt->p_reqsid.s_seq == 0) {
678 		for (n = maxser(pkt); n; n--) {
679 			rdp = &pkt->p_idel[n];
680 			if (rdp->i_sid.s_rel == pkt->p_reqsid.s_rel &&
681 				rdp->i_sid.s_lev == pkt->p_reqsid.s_lev &&
682 				rdp->i_sid.s_br == pkt->p_reqsid.s_br)
683 					break;
684 		}
685 		ser = n;
686 	}
687 	else {
688 		ser = sidtoser(&pkt->p_reqsid,pkt);
689 	}
690 	if (ser == 0)
691 		fatal("nonexistent sid (ge5)");
692 	rdp = &pkt->p_idel[ser];
693 	move(&rdp->i_sid, &pkt->p_gotsid, sizeof(pkt->p_gotsid));
694 	if (def || (pkt->p_reqsid.s_lev == 0 && pkt->p_reqsid.s_rel == pkt->p_gotsid.s_rel))
695 		move(&pkt->p_gotsid, &pkt->p_reqsid, sizeof(pkt->p_gotsid));
696 	return(ser);
697 }
698 
699 
700 /* Null routine to satisfy external reference from dodelt() */
701 
702 escdodelt()
703 {
704 }
705