Commit | Line | Data |
---|---|---|
39d149fd EA |
1 | # |
2 | /* | |
3 | Program to convert release 3 (or release 2 or even 1) SCCS files | |
4 | to release 4 SCCS files. | |
5 | Usage: | |
6 | scv arg ... | |
7 | arg is any argument acceptable as an SCCS file | |
8 | name argument to the get command. E.g.: | |
9 | scv mysccsdir | |
10 | will convert every release 3 (or 2 or 1 but NOT 4) SCCS file in the | |
11 | directory "mysccsdir". | |
12 | */ | |
13 | # include "../hdr/defines.h" | |
14 | # include "dir.h" | |
15 | ||
e56daa2a | 16 | SCCSID(@(#)scv.c 4.4); |
823cadbb | 17 | |
39d149fd EA |
18 | |
19 | /* | |
20 | Release 3 SCCS File Structures (2.1 78/06/05 17:31:17) | |
21 | See osccsfile(V). | |
22 | */ | |
23 | ||
24 | struct Header { | |
25 | short Hmagicno; | |
26 | char Htype[10]; | |
27 | char Hpers[14]; | |
28 | char Hdesc[100]; | |
29 | short Hfloor; | |
30 | short Hceil; | |
31 | short Hsw[5]; | |
32 | short Hrdef; | |
33 | char Hulist[32]; | |
34 | char Hexpand[50]; | |
35 | short Hash; | |
36 | }; | |
37 | #define MAGICNO (7) | |
38 | #define HASHADDR (226) | |
39 | ||
40 | ||
41 | struct Reltab { | |
42 | short Rrel; | |
43 | short Rlevs; | |
44 | }; | |
45 | ||
46 | ||
47 | struct Deltab { | |
48 | short Drel; | |
49 | short Dlev; | |
50 | char Dtype; /*'D': delta,'P','U': non-prop,'I': incl,'E': excl */ | |
51 | char Dfill; /* Used to be option letter */ | |
52 | /* compiler once forced unfortunate alignment here. | |
53 | /* also, fp-11c high/low long goof strikes again. | |
54 | /* long Ddatetime; | |
55 | */ | |
56 | short Ddthi,Ddtlo; | |
e56daa2a | 57 | char Dpgmr[SZLNAM]; |
39d149fd EA |
58 | char Dhist[200]; |
59 | }; | |
60 | ||
61 | ||
62 | struct Control { | |
63 | short Crel; | |
64 | short Clev; | |
65 | char Cctl; /* -11: ins, -12: del, -13: end */ | |
66 | }; | |
67 | #define SIZEOFCONTROL (5) | |
68 | #define OINS (-11) | |
69 | #define ODEL (-12) | |
70 | #define OEND (-13) | |
71 | ||
72 | ||
73 | struct Line { | |
74 | char Lline [256]; | |
75 | }; | |
76 | ||
77 | ||
78 | /* | |
79 | Structure for use with buffered I/O routines opnl, opnr, | |
80 | getl and getr. | |
81 | */ | |
82 | struct Ibufr { | |
83 | short Ifildes; | |
84 | char *Irecptr; | |
85 | char *Iend; | |
86 | char Ibuff1[256]; | |
87 | char Ibuff2[512]; | |
88 | char Ibuff3[2]; | |
89 | short Ilen; | |
90 | short Ihflag; | |
91 | short Ihcnt; | |
92 | short Ihtot; | |
93 | }; | |
94 | ||
95 | ||
96 | /* | |
97 | Structure for use with buffered I/O routines crtr, crtl, putl, | |
98 | putr, flshr and buflsh. | |
99 | */ | |
100 | struct Obufr { | |
101 | short Ofildes; | |
102 | char *Orecptr; | |
103 | char *Oend; | |
104 | char Obuff1[512]; | |
105 | short Ohflag; | |
106 | short Ohcnt; | |
107 | }; | |
108 | ||
109 | ||
110 | /* | |
111 | * structure to access an | |
112 | * shorteger in bytes | |
113 | */ | |
114 | struct | |
115 | { | |
116 | char lobyte; | |
117 | char hibyte; | |
118 | }; | |
119 | ||
120 | ||
121 | /* | |
122 | * structure to access an shorteger | |
123 | */ | |
124 | struct | |
125 | { | |
126 | short shorteg; | |
127 | }; | |
128 | ||
129 | ||
130 | /* | |
131 | * structure to access a long as shortegers | |
132 | */ | |
133 | struct { | |
134 | short hiword; | |
135 | short loword; | |
136 | }; | |
137 | ||
138 | ||
139 | /* | |
140 | Structure for referencing pieces of localtime(). | |
141 | */ | |
142 | struct Time { | |
143 | short Tseconds; | |
144 | short Tminutes; | |
145 | short Thours; | |
146 | short Tday_month; | |
147 | short Tmonth; | |
148 | short Tyear; | |
149 | short Tday_week; | |
150 | short Tday_year; | |
151 | short Tflag; | |
152 | }; | |
153 | /* | |
154 | SCCS Internal Structures (used by get and delta). (2.1) | |
155 | */ | |
156 | ||
157 | struct Apply { | |
158 | short Adt; /* pseudo date-time */ | |
159 | short Acode; /* APPLY, NOAPPLY or EMPTY */ | |
160 | }; | |
161 | #define APPLY (1) | |
162 | #define NOAPPLY (-1) | |
163 | #define EMPTY (0) | |
164 | ||
165 | ||
166 | struct Queue { | |
167 | struct Queue *Qnext; | |
168 | short Qrel; /* release */ | |
169 | short Qlev; /* level */ | |
170 | short Qdt; /* pseudo date-time */ | |
171 | short Qkeep; /* keep switch setting */ | |
172 | }; | |
173 | #define YES (1) | |
174 | #define NO (-1) | |
175 | ||
176 | #define SIZEOFPfile (50) | |
177 | ||
178 | ||
179 | struct Packet { | |
180 | char Pfile[SIZEOFPfile]; /* file name containing module */ | |
181 | /* | |
182 | Note: the order of the next two words | |
183 | can not\b\b\b___ be changed! | |
184 | This is because the release and level together | |
185 | are treated as a long. | |
186 | */ | |
187 | short Prel; /* specified release (-1 = not spec.) */ | |
188 | short Plev; /* specified level (-1 = not spec.)*/ | |
189 | char Pverbose; /* verbose flags (see #define's below) */ | |
190 | char Pupd; /* update flag (!0 = update mode) */ | |
191 | long Pcutoff; /* specified cutoff date-time */ | |
192 | struct Header Phdr; /* header from module */ | |
193 | short Plnno; /* line number of current line */ | |
194 | short Precno; /* record number of current rec */ | |
195 | char Pwrttn; /* written flag (!0 = written) */ | |
196 | char Pkeep; /* keep switch for readmod() */ | |
197 | struct Apply **Papply; /* ptr to apply array */ | |
198 | struct Queue *Pq; /* ptr to control queue */ | |
199 | struct Ibufr Pibuf; /* input buffer */ | |
200 | long Pcdt; /* date/time of newest applied delta */ | |
201 | char *Plfile; /* 0 = no l-file; else ptr to l arg */ | |
202 | char Punack; /* !0 if unacknowledged non-prop deltas */ | |
203 | char Pnoprop; /* !0 if new delta is to be non-prop */ | |
204 | short Pirel; /* rel which inserted current rec */ | |
205 | short Pilev; /* lev which inserted current rec */ | |
206 | }; | |
207 | /* | |
208 | Masks for Pverbose | |
209 | */ | |
210 | ||
211 | # define RLACCESS (1) | |
212 | # define NLINES (2) | |
213 | # define DOLIST (4) | |
214 | # define UNACK (8) | |
215 | # define NEWRL (16) | |
216 | # define WARNING (32) | |
217 | ||
218 | /* | |
219 | size of login name | |
220 | */ | |
221 | ||
222 | ||
223 | USXALLOC(); | |
224 | ||
225 | main(argc,argv) | |
226 | char **argv; | |
227 | { | |
228 | register short i; | |
229 | register char *p; | |
230 | extern conv(); | |
231 | extern short Fcnt; | |
232 | ||
233 | setsig(); | |
234 | Fflags = FTLMSG | FTLCLN | FTLJMP; | |
235 | for (i = 1; i < argc; i++) | |
236 | if (p = argv[i]) | |
237 | odo_file(p,conv); | |
238 | exit(Fcnt ? 1 : 0); | |
239 | } | |
240 | ||
241 | ||
242 | struct packet npkt; | |
243 | ||
244 | conv(ofile) | |
245 | char *ofile; | |
246 | { | |
247 | struct Packet opkt; | |
248 | struct deltab *dt; | |
249 | char **hists; | |
250 | short **rlp; | |
251 | char statstr[32]; | |
252 | short ndels; | |
253 | char *line; | |
254 | short n; | |
255 | char *p; | |
256 | ||
257 | if (setjmp(Fjmp)) | |
258 | return; | |
259 | printf("%s:\n",ofile); | |
260 | ckpfile(auxf(ofile,'p')); | |
261 | zero(&opkt,sizeof(opkt)); | |
262 | opnr(&opkt.Pibuf,ofile); | |
263 | dohead(&opkt); | |
264 | rlp = 0; | |
265 | ndels = doreltab(&opkt,&rlp); | |
266 | hists = alloc((ndels + 1) * sizeof(*hists)); | |
267 | dt = alloc((ndels + 1) * sizeof(*dt)); | |
268 | dodelt(&opkt,dt,hists,ndels); | |
269 | fixup(dt,ndels,rlp); | |
270 | sinit(&npkt,ofile,0); | |
271 | npkt.p_upd = 1; | |
272 | line = npkt.p_line; | |
273 | putline(&npkt,sprintf(line,"%c%c00000\n",CTLCHAR,HEAD),0); | |
274 | statstr[0] = 0; | |
275 | for (n = ndels; n; n--) { | |
276 | if (!statstr[0]) | |
277 | newstats(&npkt,statstr,"?"); | |
278 | else | |
279 | putline(&npkt,statstr); | |
280 | putline(&npkt,del_ba(&dt[n],line)); | |
281 | putline(&npkt,sprintf(line,"%c%c %s\n",CTLCHAR,COMMENTS, | |
282 | hists[n])); | |
283 | putline(&npkt,sprintf(line,CTLSTR,CTLCHAR,EDELTAB)); | |
284 | } | |
285 | putline(&npkt,sprintf(line,CTLSTR,CTLCHAR,BUSERNAM)); | |
286 | dousers(opkt.Phdr.Hulist,&npkt); | |
287 | putline(&npkt,sprintf(line,CTLSTR,CTLCHAR,EUSERNAM)); | |
288 | if (*(p = opkt.Phdr.Htype)) | |
289 | putline(&npkt,sprintf(line,"%c%c %c %s\n",CTLCHAR,FLAG, | |
290 | TYPEFLAG,p)); | |
291 | if (n = opkt.Phdr.Hfloor) | |
292 | putline(&npkt,sprintf(line,"%c%c %c %d\n",CTLCHAR,FLAG, | |
293 | FLORFLAG,n)); | |
294 | if (n = opkt.Phdr.Hceil) | |
295 | putline(&npkt,sprintf(line,"%c%c %c %d\n",CTLCHAR,FLAG, | |
296 | CEILFLAG,n)); | |
297 | if (n = opkt.Phdr.Hrdef) | |
298 | putline(&npkt,sprintf(line,"%c%c %c %d\n",CTLCHAR,FLAG, | |
299 | DEFTFLAG,n)); | |
300 | putline(&npkt,sprintf(line,CTLSTR,CTLCHAR,BUSERTXT)); | |
301 | if (*(p = opkt.Phdr.Hpers)) | |
302 | putline(&npkt,sprintf(line,"%s\n",p)); | |
303 | if (*(p = opkt.Phdr.Hdesc)) | |
304 | putline(&npkt,sprintf(line,"%s\n",p)); | |
305 | putline(&npkt,sprintf(line,CTLSTR,CTLCHAR,EUSERTXT)); | |
306 | dobod(&opkt,&npkt,rlp,line); | |
307 | convflush(&npkt); | |
308 | close(opkt.Pibuf.Ifildes); | |
309 | for (n = ndels; n; n--) | |
310 | free(hists[n]); | |
311 | free(hists); | |
312 | free(dt); | |
313 | /* [compiler bug, ignore this for now ] | |
314 | if (rlp) { | |
315 | for (n = (short) (*rlp); n; n--) | |
316 | if (rlp[n]) | |
317 | free(rlp[n]); | |
318 | free(rlp); | |
319 | } | |
320 | */ | |
321 | rename(auxf(npkt.p_file,'x'),npkt.p_file); | |
322 | xrm(&npkt); | |
323 | } | |
324 | ||
325 | ||
326 | getline() | |
327 | { | |
328 | } | |
329 | ||
330 | ||
331 | clean_up() | |
332 | { | |
333 | xrm(&npkt); | |
334 | } | |
335 | ||
336 | ||
337 | ||
338 | fixup(dt,ndels,rlp) | |
339 | struct deltab *dt; | |
340 | short ndels; | |
341 | short **rlp; | |
342 | { | |
343 | short m, n; | |
344 | short maxr; | |
345 | short seqcnt; | |
346 | short pred; | |
347 | register struct deltab *p1, *p2; | |
348 | register short *brp; | |
349 | ||
350 | for (m = ndels; m; m--) { | |
351 | p1 = &dt[m]; | |
352 | if (p1->d_sid.s_lev > 1) { | |
353 | for (n = m - 1; n; n--) { | |
354 | if (p1->d_sid.s_rel == dt[n].d_sid.s_rel) | |
355 | break; | |
356 | } | |
357 | pred = n; | |
358 | } | |
359 | else { | |
360 | maxr = pred = 0; | |
361 | for (n = m - 1; n; n--) { | |
362 | p2 = &dt[n]; | |
363 | if (p1->d_sid.s_rel > p2->d_sid.s_rel && | |
364 | p2->d_type == 'D' && | |
365 | p2->d_sid.s_rel > maxr) { | |
366 | maxr = p2->d_sid.s_rel; | |
367 | pred = n; | |
368 | } | |
369 | } | |
370 | } | |
371 | p1->d_pred = pred; | |
372 | rlp[p1->d_sid.s_rel][p1->d_sid.s_lev] = m; | |
373 | } | |
374 | brp = alloca(n = (ndels + 1) * sizeof(*brp)); | |
375 | zero(brp,n); | |
376 | for (m = 1; m <= ndels; m++) { | |
377 | p1 = &dt[m]; | |
378 | if (p1->d_type != 'D') { | |
379 | seqcnt = 0; | |
380 | p2 = &dt[p1->d_pred]; | |
381 | p1->d_type = 'D'; | |
382 | p1->d_sid.s_rel = p2->d_sid.s_rel; | |
383 | p1->d_sid.s_lev = p2->d_sid.s_lev; | |
384 | p1->d_sid.s_br = ++brp[p1->d_pred]; | |
385 | p1->d_sid.s_seq = ++seqcnt; | |
386 | pred = m; | |
387 | for (n = m + 1; n <= ndels; n++) { | |
388 | if (dt[n].d_pred == pred) { | |
389 | p2 = &dt[n]; | |
390 | p2->d_type = 'D'; | |
391 | p2->d_sid.s_rel = p1->d_sid.s_rel; | |
392 | p2->d_sid.s_lev = p1->d_sid.s_lev; | |
393 | p2->d_sid.s_br = p1->d_sid.s_br; | |
394 | p2->d_sid.s_seq = ++seqcnt; | |
395 | pred = n; | |
396 | } | |
397 | } | |
398 | } | |
399 | } | |
400 | } | |
401 | ||
402 | ||
403 | ||
404 | struct names { | |
405 | struct names *n_next; | |
406 | char n_name[SZLNAM]; | |
407 | short n_uid; | |
408 | }; | |
409 | ||
410 | struct names *names; | |
411 | ||
412 | dousers(up,pkt) | |
413 | register char *up; | |
414 | struct packet *pkt; | |
415 | { | |
416 | short i, j; | |
417 | register char mask, c; | |
418 | char *p; | |
419 | char str[16]; | |
420 | ||
421 | for (i = 0; i < 32; i++) | |
422 | if (c = *up++) { | |
423 | j = 0; | |
424 | for (mask = 1; mask; mask =<< 1) { | |
e56daa2a | 425 | if ((c & mask) && (p = getlnam(i * SZLNAM + j))) |
39d149fd EA |
426 | putline(pkt,sprintf(str,"%s\n",p)); |
427 | j++; | |
428 | } | |
429 | } | |
430 | } | |
431 | ||
432 | ||
433 | getlnam(uid) | |
434 | short uid; | |
435 | { | |
436 | char str[128]; | |
437 | register struct names *cur, *prev; | |
438 | register char *p; | |
439 | ||
440 | for (cur = &names; cur = (prev = cur)->n_next; ) | |
441 | if (cur->n_uid == uid) | |
442 | return(cur->n_name); | |
443 | if (getpw(uid,str)) | |
444 | return(0); | |
445 | prev->n_next = cur = alloc(sizeof(*cur)); | |
446 | cur->n_next = 0; | |
447 | cur->n_uid = uid; | |
448 | for (p = str; *p++ != ':'; ) | |
449 | ; | |
450 | *--p = 0; | |
451 | str[SZLNAM] = 0; | |
452 | copy(str,cur->n_name); | |
453 | return(cur->n_name); | |
454 | } | |
455 | ||
456 | ||
457 | ||
458 | /* | |
459 | Routine to process the module header. All that's necessary is | |
460 | to slide it shorto the packet. | |
461 | */ | |
462 | ||
463 | dohead(pkt) | |
464 | register struct Packet *pkt; | |
465 | { | |
466 | register struct Header *hdr; | |
467 | ||
468 | if(rdrec(pkt) == 1) fatal("premature eof (58)"); | |
469 | hdr = pkt->Pibuf.Irecptr; | |
470 | if(hdr->Hmagicno != MAGICNO) fatal("not an SCCS file (53)"); | |
471 | move(hdr,&pkt->Phdr,sizeof(*hdr)); | |
472 | } | |
473 | ||
474 | ||
475 | doreltab(pkt,rlp) | |
476 | register struct Packet *pkt; | |
477 | register short ***rlp; | |
478 | { | |
479 | short n; | |
480 | short sz; | |
481 | register struct Reltab *rt; | |
482 | ||
483 | n = 0; | |
484 | while (rdrec(pkt) != 1 && (rt = pkt->Pibuf.Irecptr)->Rrel) { | |
485 | if (n == 0) { | |
486 | *rlp = alloc(sz = (rt->Rrel + 1) * sizeof(**rlp)); | |
487 | zero(*rlp,sz); | |
488 | **rlp = rt->Rrel; | |
489 | } | |
490 | (*rlp)[rt->Rrel] = alloc((rt->Rlevs + 1) * sizeof(***rlp)); | |
491 | (*rlp)[rt->Rrel][0] = rt->Rlevs; | |
492 | n =+ rt->Rlevs; | |
493 | } | |
494 | return(n); | |
495 | } | |
496 | ||
497 | ||
498 | dodelt(pkt,dt,hists,ndels) | |
499 | struct Packet *pkt; | |
500 | register struct deltab *dt; | |
501 | char **hists; | |
502 | short ndels; | |
503 | { | |
504 | short n; | |
505 | register struct deltab *ndt; | |
506 | register struct Deltab *odt; | |
507 | ||
508 | for (; rdrec(pkt) != 1 && (odt = pkt->Pibuf.Irecptr)->Drel; --ndels) { | |
509 | if (!(odt->Dtype == 'D' || odt->Dtype == 'P' || odt->Dtype == 'U')) { | |
510 | ++ndels; | |
511 | continue; | |
512 | } | |
513 | if (!ndels) | |
514 | return(fatal("internal error in dodeltab")); | |
515 | ndt = &dt[ndels]; | |
516 | ndt->d_type = odt->Dtype; | |
517 | move(odt->Dpgmr,ndt->d_pgmr,sizeof(ndt->d_pgmr)); | |
518 | ndt->d_datetime = (odt->Ddthi<<16)+(unsigned)odt->Ddtlo; | |
519 | ndt->d_sid.s_rel = odt->Drel; | |
520 | ndt->d_sid.s_lev = odt->Dlev; | |
521 | ndt->d_sid.s_br = 0; | |
522 | ndt->d_sid.s_seq = 0; | |
523 | ndt->d_serial = ndels; | |
524 | ndt->d_pred = 0; | |
525 | n = size(odt->Dhist); | |
526 | n++; | |
527 | n =& ~1; | |
528 | if (odt->Dtype == 'P' || odt->Dtype == 'U') { | |
529 | hists[ndels] = alloc(n + 16); | |
530 | sprintf(hists[ndels],"[was %d.%d] ",odt->Drel,odt->Dlev); | |
531 | } | |
532 | else { | |
533 | hists[ndels] = alloc(n); | |
534 | hists[ndels][0] = 0; | |
535 | } | |
536 | move(odt->Dhist,strend(hists[ndels]),n); | |
537 | } | |
538 | if (ndels) { | |
539 | fatal("in dodelt"); | |
540 | } | |
541 | } | |
542 | ||
543 | ||
544 | dobod(opkt,npkt,rlp,line) | |
545 | struct Packet *opkt; | |
546 | struct packet *npkt; | |
547 | short **rlp; | |
548 | char *line; | |
549 | { | |
550 | register struct Control *octl; | |
551 | register char *p, c; | |
552 | ||
553 | while (rdrec(opkt) != 1 && (octl = opkt->Pibuf.Irecptr)->Crel) { | |
554 | if (octlrec(octl,opkt->Pibuf.Ilen)) | |
555 | putline(npkt,sprintf(line,"%c%c %u\n",CTLCHAR, | |
556 | "EDI"[octl->Cctl-OEND], | |
557 | rlp[octl->Crel][octl->Clev])); | |
558 | else { | |
559 | c = (p = octl)[opkt->Pibuf.Ilen]; | |
560 | p[opkt->Pibuf.Ilen] = 0; | |
561 | putline(npkt,sprintf(line,"%s\n",p)); | |
562 | p[opkt->Pibuf.Ilen] = c; | |
563 | } | |
564 | } | |
565 | } | |
566 | ||
567 | ||
568 | octlrec(ctl,len) | |
569 | register struct Control *ctl; | |
570 | short len; | |
571 | { | |
572 | register short ch; | |
573 | ||
574 | if (len==SIZEOFCONTROL && | |
575 | ((ch=ctl->Cctl)==OINS || ch==ODEL || ch==OEND)) | |
576 | return(1); | |
577 | return(0); | |
578 | } | |
579 | ||
580 | ||
581 | rdrec(pkt) | |
582 | register struct Packet *pkt; | |
583 | { | |
584 | register n; | |
585 | ||
586 | if ((n = getr(&pkt->Pibuf)) != 1) | |
587 | pkt->Precno++; | |
588 | return(n); | |
589 | } | |
590 | ||
591 | ||
592 | xwrite(a,b,c) | |
593 | { | |
594 | return(write(a,b,c)); | |
595 | } | |
596 | ||
597 | ||
598 | ||
39d149fd EA |
599 | |
600 | # define CALL(p,func,cnt) Ffile=p; (*func)(p); cnt++; | |
601 | short nfiles; | |
602 | char had_dir; | |
603 | char had_standinp; | |
604 | ||
605 | ||
606 | odo_file(p,func) | |
607 | register char *p; | |
608 | short (*func)(); | |
609 | { | |
610 | extern char *Ffile; | |
611 | char str[FILESIZE]; | |
612 | char ibuf[FILESIZE]; | |
613 | FILE *iop; | |
614 | struct dir dir[2]; | |
615 | register char *s; | |
616 | short fd; | |
617 | ||
618 | if (p[0] == '-') { | |
619 | had_standinp = 1; | |
620 | while (gets(ibuf) != NULL) { | |
621 | if (osccsfile(ibuf)) { | |
622 | CALL(ibuf,func,nfiles); | |
623 | } | |
624 | } | |
625 | } | |
626 | else if (exists(p) && (Statbuf.st_mode & S_IFMT) == S_IFDIR) { | |
627 | had_dir = 1; | |
628 | Ffile = p; | |
629 | if((iop = fopen(p,"r")) == NULL) | |
630 | return; | |
631 | dir[1].d_ino = 0; | |
632 | fread(dir,sizeof(dir[0]),1,iop); /* skip "." */ | |
633 | fread(dir,sizeof(dir[0]),1,iop); /* skip ".." */ | |
634 | while(fread(dir,sizeof(dir[0]),1,iop) == 1) { | |
635 | if(dir[0].d_ino == 0) continue; | |
636 | sprintf(str,"%s/%s",p,dir[0].d_name); | |
637 | if(osccsfile(str)) { | |
638 | CALL(str,func,nfiles); | |
639 | } | |
640 | } | |
641 | fclose(iop); | |
642 | } | |
643 | else { | |
644 | CALL(p,func,nfiles); | |
645 | } | |
646 | } | |
647 | ||
648 | ||
649 | osccsfile(file) | |
650 | register char *file; | |
651 | { | |
652 | register short ff, result; | |
653 | short magic[2]; | |
654 | ||
655 | result = (ff=open(file,0)) > 0 | |
656 | && read(ff,magic,4) == 4 | |
657 | && magic[1] == MAGICNO; | |
658 | close(ff); | |
659 | return(result); | |
660 | } | |
661 | ||
662 | ||
663 | ||
664 | /* | |
665 | Routine to write out either the current line in the packet | |
666 | (if newline is zero) or the line specified by newline. | |
667 | A line is actually written (and the x-file is only | |
668 | opened) if pkt->p_upd is non-zero. When the current line from | |
669 | the packet is written, pkt->p_wrttn is set non-zero, and | |
670 | further attempts to write it are ignored. When a line is | |
671 | read shorto the packet, pkt->p_wrttn must be turned off. | |
672 | */ | |
673 | ||
674 | short Xcreate; | |
675 | FILE *Xiop; | |
676 | ||
677 | ||
678 | putline(pkt,newline) | |
679 | register struct packet *pkt; | |
680 | char *newline; | |
681 | { | |
682 | static char obf[BUFSIZ]; | |
683 | char *xf; | |
684 | register char *p; | |
685 | ||
686 | if(pkt->p_upd == 0) return; | |
687 | ||
688 | if(!Xcreate) { | |
689 | stat(pkt->p_file,&Statbuf); | |
690 | xf = auxf(pkt->p_file,'x'); | |
691 | Xiop = xfcreat(xf,Statbuf.st_mode); | |
692 | setbuf(Xiop,obf); | |
693 | chown(xf,(Statbuf.st_gid<<8)|Statbuf.st_uid); | |
694 | } | |
695 | if (newline) | |
696 | p = newline; | |
697 | else { | |
698 | if(!pkt->p_wrttn++) | |
699 | p = pkt->p_line; | |
700 | else | |
701 | p = 0; | |
702 | } | |
703 | if (p) { | |
704 | fputs(p,Xiop); | |
705 | if (Xcreate) | |
706 | while (*p) | |
707 | pkt->p_nhash =+ *p++; | |
708 | } | |
709 | Xcreate = 1; | |
710 | } | |
711 | ||
712 | ||
713 | convflush(pkt) | |
714 | register struct packet *pkt; | |
715 | { | |
716 | register char *p; | |
717 | char hash[6]; | |
718 | ||
719 | if (pkt->p_upd == 0) | |
720 | return; | |
721 | putline(pkt,0); | |
722 | rewind(Xiop); | |
723 | sprintf(hash,"%5u",pkt->p_nhash&0xFFFF); | |
724 | zeropad(hash); | |
725 | fprintf(Xiop,"%c%c%s\n",CTLCHAR,HEAD,hash); | |
726 | fclose(Xiop); | |
727 | } | |
728 | ||
729 | ||
730 | xrm(pkt) | |
731 | struct packet *pkt; | |
732 | { | |
733 | if (Xiop) | |
734 | fclose(Xiop); | |
735 | if(Xcreate) | |
736 | unlink(auxf(pkt,'x')); | |
737 | Xiop = Xcreate = 0; | |
738 | } | |
739 | ||
740 | ||
741 | char bpf[] "bad p-file (216)"; | |
742 | ||
743 | rdpfile(f,rp,un) | |
744 | char f[], un[]; | |
745 | short *rp; | |
746 | { | |
747 | register short fd, i; | |
748 | register char *p; | |
749 | char s[65], *name; | |
750 | ||
751 | fd = xopen(f,0); | |
752 | if ((i=read(fd,s,64))<=0) | |
753 | fatal(bpf); | |
754 | close(fd); | |
755 | p = s; | |
756 | p[i] = 0; | |
757 | for (; *p != ' '; p++) | |
758 | if (*p == 0) | |
759 | fatal(bpf); | |
760 | *p = 0; | |
761 | if ((*rp=patoi(s)) == -1) | |
762 | fatal(bpf); | |
763 | ++p; | |
764 | while (*p++ == ' ') ; | |
765 | name = --p; | |
766 | for (; *p != '\n'; p++) | |
767 | if (*p == 0) | |
768 | fatal(bpf); | |
769 | *p = 0; | |
770 | if ((p-name)>SZLNAM) | |
771 | fatal(bpf); | |
772 | copy(name,un); | |
773 | } | |
774 | ||
775 | ||
776 | ckpfile(file) | |
777 | register char *file; | |
778 | { | |
779 | short r; | |
780 | char un[SZLNAM]; | |
781 | ||
782 | if(exists(file)) { | |
783 | rdpfile(file,&r,un); | |
784 | fatal(sprintf(Error,"being edited at release %d by `%s' (scv1)", | |
785 | r,un)); | |
786 | } | |
787 | } | |
788 | ||
789 | ||
790 | /* | |
791 | Bottom level read routines for release 3 SCCS files. | |
792 | ||
793 | Usage: | |
794 | struct Ibufr ib; | |
795 | ... | |
796 | opnr(&ib,"filename"); | |
797 | ... | |
798 | if(getr(&ib) == 1) [end-of-file]; | |
799 | [ib.Irecptr is addr of record (always on word boundary)] | |
800 | [ib.Ilen is length] | |
801 | ||
802 | Address HASHADDR of the file must contain a 1-word stored hash count. | |
803 | If this count is non-zero, then on end-of-file a computed hash count | |
804 | is compared with it and a fatal error is issued if they aren't equal. | |
805 | */ | |
806 | ||
807 | opnr(buf,file) | |
808 | register struct Ibufr *buf; | |
809 | char file[]; | |
810 | { | |
811 | buf->Ifildes = xopen(file,0); | |
812 | buf->Irecptr = buf->Ibuff2 + 2; | |
813 | buf->Iend = buf->Irecptr + 510; | |
814 | buf->Ilen = 510; | |
815 | buf->Ibuff3[1] = -128; | |
816 | buf->Ihcnt = buf->Ihtot = buf->Ihflag = 0; | |
817 | } | |
818 | ||
819 | ||
820 | getr(buf) | |
821 | register struct Ibufr *buf; | |
822 | { | |
823 | register char *p, *q; | |
824 | short *w; | |
825 | short i, n; | |
826 | ||
827 | buf->Irecptr =+ buf->Ilen + !(buf->Ilen & 1); | |
828 | ||
829 | i = 0; | |
830 | while(1) { | |
831 | buf->Ilen = 0; | |
832 | buf->Ilen = *buf->Irecptr + 128; | |
833 | ||
834 | if(buf->Irecptr <= buf->Iend - (buf->Ilen+!(buf->Ilen&1))) | |
835 | return(++buf->Irecptr); | |
836 | ||
837 | if(i++ == 1) return(1); | |
838 | ||
839 | q = buf->Irecptr; | |
840 | p = buf->Irecptr =- 512; | |
841 | ||
842 | while(q <= buf->Iend) *p++ = *q++; | |
843 | ||
844 | if((n = read(buf->Ifildes,buf->Ibuff2,512)) <= 0) | |
845 | return(1); | |
846 | ||
847 | buf->Iend = buf->Ibuff2 + n - 1; | |
848 | *(buf->Iend + 1) = -128; | |
849 | ||
850 | w = buf->Ibuff2; | |
851 | if(buf->Ihflag == 0) { | |
852 | buf->Ihflag = 1; | |
853 | buf->Ihtot = w[HASHADDR>>1]; | |
854 | w[HASHADDR>>1] = 0; | |
855 | } | |
856 | if(n < 512) buf->Ibuff2[n] = 0; | |
857 | ||
858 | buf->Ihcnt =+ sumr(w,&w[(n&1?n-1:n-2)>>1]); | |
859 | ||
860 | if(n<512 && buf->Ihtot && buf->Ihcnt != buf->Ihtot) | |
861 | fatal("corrupted file (201)"); | |
862 | } | |
863 | } | |
864 | ||
865 | ||
866 | sumr(from,to) | |
867 | register short *from, *to; | |
868 | { | |
869 | register short sum; | |
870 | ||
871 | for (sum=0; from<=to; ) | |
872 | sum =+ *from++; | |
873 | return(sum); | |
874 | } |