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