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