BSD 3 development
[unix-history] / usr / src / cmd / arff.c
CommitLineData
33f45be6
KS
1#include <sys/types.h>
2#include <sys/stat.h>
3#include <time.h>
4#include <signal.h>
5#include <stdio.h>
6#define dbprintf printf
7struct rt_dat {
8unsigned short int rt_yr:5; /*Year - 1972 */
9unsigned short int rt_dy:5; /*day */
10unsigned short int rt_mo:5; /*month */
11};
12struct rt_axent {
13 char rt_sent[14];
14};
15
16struct rt_ent {
17 char rt_pad; /*unusued */
18 char rt_stat; /*Type of entry, or end of seg*/
19 unsigned short rt_name[3]; /*Name, 3 words in rad50 form */
20 short rt_len; /*Length of file */
21 char rt_chan; /*Only used in temporary files*/
22 char rt_job; /*Only used in temporary files*/
23 struct rt_dat rt_date; /*Creation Date */
24};
25#define RT_TEMP 1
26#define RT_NULL 2
27#define RT_FILE 4
28#define RT_ESEG 8
29#define RT_BLOCK 512
30struct rt_head {
31 short rt_numseg; /*number of segments available*/
32 short rt_nxtseg; /*segment no of next log. seg */
33 short rt_lstseg; /*highest seg currenltly open */
34 unsigned short rt_entpad; /*extra words/dir. entry */
35 short rt_stfile; /*block no where files begin */
36};
37struct rt_dir {
38 struct rt_head rt_axhead;
39 struct rt_ent rt_ents[72];
40 char _dirpad[6];
41};
42extern struct rt_dir rt_dir;
43extern int rt_entsiz;
44extern int floppydes;
45extern char *rt_last;
46typedef struct fldope {
47 int startad;
48 int count;
49struct rt_ent *rtdope;
50} FLDOPE;
51FLDOPE *lookup();
52#define rt(p) ((struct rt_ent *) p )
53#define Ain1 03100
54#define Ain2 050
55#define flag(c) (flg[(c) - 'a'])
56
57char *man = { "rxtd" };
58
59char zeroes[512];
60extern char *val;
61extern char table[256];
62struct rt_dir rt_dir = {{4,0,1,0,14},{0,RT_NULL,{0,0,0},494,0}, {0,RT_ESEG}};
63int rt_entsiz;
64int rt_nleft;
65struct rt_ent *rt_curend;
66int floppydes;
67int dirdirty;
68char *rt_last;
69char *defdev = "/dev/floppy";
70
71char *opt = { "vf" };
72
73int signum[] = {SIGHUP, SIGINT, SIGQUIT, 0};
74long lseek();
75int rcmd();
76int dcmd();
77int xcmd();
78int tcmd();
79int (*comfun)();
80char flg[26];
81char **namv;
82int namc;
83int file;
84
85
86main(argc, argv)
87char *argv[];
88{
89 register char *cp;
90
91 /*register i;
92 for(i=0; signum[i]; i++)
93 if(signal(signum[i], SIG_IGN) != SIG_IGN)
94 signal(signum[i], sigdone);*/
95 if(argc < 2)
96 usage();
97 cp = argv[1];
98 for(cp = argv[1]; *cp; cp++)
99 switch(*cp) {
100 case 'm':
101 case 'v':
102 case 'u':
103 case 'w':
104 flg[*cp - 'a']++;
105 continue;
106 case 'c':
107 {
108#define SURE "Are you sure you want to clobber the floppy?\n"
109 int tty;
110 char response[2];
111 tty = open("/dev/tty",2);
112 write(tty,SURE,sizeof(SURE));
113 read(tty,response,2);
114 if(*response!='y')
115 exit(50);
116 flag('c')++;
117 close(tty);
118 }
119 dirdirty++;
120 continue;
121
122 case 'r':
123 setcom(rcmd);
124 flag('r')++;
125 continue;
126
127 case 'd':
128 setcom(dcmd);
129 flag('d')++;
130 continue;
131
132 case 'x':
133 setcom(xcmd);
134 continue;
135
136 case 't':
137 setcom(tcmd);
138 continue;
139
140 case 'f':
141 defdev = argv[2];
142 argv++;
143 argc--;
144 continue;
145
146
147 default:
148 fprintf(stderr, "arff: bad option `%c'\n", *cp);
149 exit(1);
150 }
151 namv = argv+2;
152 namc = argc-2;
153 if(comfun == 0) {
154 if(flg['u'-'a'] == 0) {
155 fprintf(stderr, "arff: one of [%s] must be specified\n", man);
156 exit(1);
157 }
158 setcom(rcmd);
159 }
160 (*comfun)();
161 exit(notfound());
162}
163
164setcom(fun)
165int (*fun)();
166{
167
168 if(comfun != 0) {
169 fprintf(stderr, "arff: only one of [%s] allowed\n", man);
170 exit(1);
171 }
172 comfun = fun;
173}
174
175
176
177
178
179
180
181
182usage()
183{
184 printf("usage: ar [%s][%s] archive files ...\n", opt, man);
185 exit(1);
186}
187
188
189
190notfound()
191{
192 register i, n;
193
194 n = 0;
195 for(i=0; i<namc; i++)
196 if(namv[i]) {
197 fprintf(stderr, "arff: %s not found\n", namv[i]);
198 n++;
199 }
200 return(n);
201}
202
203
204
205phserr()
206{
207
208 fprintf(stderr, "arff: phase error on %s\n", file);
209}
210
211mesg(c)
212{
213
214 if(flg['v'-'a'])
215 if(c != 'c' || flg['v'-'a'] > 1)
216 printf("%c - %s\n", c, file);
217}
218
219tcmd()
220{
221 register char *de;
222 FLDOPE *lookup(), *dope;
223 int nleft; register i;
224 register struct rt_ent *rde;
225
226 rt_init();
227 if(namc==0)
228 for(de=((char *)&rt_dir)+10; de <= rt_last; de += rt_entsiz) {
229 if(rtls(rt(de))) {
230 nleft = (rt_last - de) / rt_entsiz;
231 printf("\n\n%d entries remaining.\n",nleft);
232 break;
233 }
234 }
235 else
236 for(i = 0; i < namc; i++) {
237 if(dope = lookup(namv[i])) {
238 rde = dope->rtdope;
239 rtls(rde);
240 namv[i] = 0;
241 }
242 }
243}
244rtls(de)
245register struct rt_ent *de;
246{
247 int month,day,year;
248 char name[12], ext[4];
249
250 if(flg['v'-'a'])
251 switch(de->rt_stat) {
252 case RT_TEMP:
253 printf("Tempfile:\n");
254 case RT_FILE:
255 unrad50(2,de->rt_name,name);
256 unrad50(1,&(de->rt_name[2]),ext);
257 day = de->rt_date.rt_dy;
258 year = de->rt_date.rt_yr + 72;
259 month = de->rt_date.rt_mo;
260 printf("%6.6s %3.3s %02d/%02d/%02d %d\n",name,
261 ext,month,day,year,de->rt_len);
262 break;
263
264 case RT_NULL:
265 printf("%-25.9s %d\n","<UNUSED>",de->rt_len);
266 break;
267
268 case RT_ESEG:
269 return(1);
270 }
271 else {
272 switch(de->rt_stat) {
273 case RT_TEMP:
274 case RT_FILE:
275 sunrad50(name,de->rt_name);
276 printf(name);putchar('\n');
277 break;
278
279 case RT_ESEG:
280 return(1);
281
282 case RT_NULL:
283 ;
284 }
285 }
286 return(0);
287}
288xcmd()
289{
290 register char *de;
291 char name[12];
292 register int i;
293
294 rt_init();
295 if(namc==0)
296 for(de=((char *)&rt_dir)+10; de <= rt_last; de += rt_entsiz) {
297 sunrad50(name,rt(de)->rt_name);
298 rtx(name);
299 }
300
301 else
302 for(i = 0; i < namc; i++)
303 if(rtx(namv[i])==0) namv[i] = 0;
304}
305rtx(name)
306char *name;
307{
308 register FLDOPE *dope;
309 FLDOPE *lookup();
310 register startad, count;
311 int file; char buff[512];
312
313
314 if(dope = lookup(name)) {
315 if(flg['v' - 'a'])
316 rtls(dope->rtdope);
317 else
318 printf("x - %s\n",name);
319
320 file = creat(name, 0666);
321 if(file < 0) return(1);
322 count = dope->count;
323 startad = dope->startad;
324 for( ; count > 0 ; count -= 512) {
325 lread(startad,512,buff);
326 write(file,buff,512);
327 startad += 512;
328 }
329 close(file);
330 return(0);
331 }
332 return(1);
333}
334rt_init()
335{
336 static initized = 0;
337 register char *de;
338 int mode;
339
340 if(initized) return;
341 initized = 1;
342 if(flag('c') || flag('d') || flag('r'))
343 mode = 2;
344 else
345 mode = 0;
346 if((floppydes = open(defdev,mode)) < 0)
347 dbprintf("Floppy open failed\n");
348 if(flag('c')==0)
349 lread(6*RT_BLOCK,2*RT_BLOCK,(char *)&rt_dir);
350
351 rt_entsiz = 2*rt_dir.rt_axhead.rt_entpad + 14;
352 rt_entsiz = 14;
353 rt_last = ((char *) &rt_dir) + 10 + 1014/rt_entsiz*rt_entsiz;
354 for(de=((char *)&rt_dir)+10; de <= rt_last; de += rt_entsiz) {
355 if(rt(de)->rt_stat==RT_ESEG) break;
356 }
357 rt_curend = rt(de);
358 rt_nleft = (rt_last - de) / rt_entsiz;
359}
360
361static FLDOPE result;
362FLDOPE *
363lookup(name)
364char * name;
365{
366 unsigned short rname[3];
367 register char *de;
368 register index;
369
370 srad50(name,rname);
371
372 /*
373 * Search for name, accumulate blocks in index
374 */
375 rt_init();
376 index = 0;
377 for(de = ((char *) &rt_dir) + 10; de <= rt_last; de += rt_entsiz) {
378 switch(rt(de)->rt_stat) {
379 case RT_ESEG:
380 return((FLDOPE *) 0);
381 case RT_FILE:
382 case RT_TEMP:
383 if(samename(rname,rt(de)->rt_name))
384 goto found;
385 case RT_NULL:
386 index += rt(de)->rt_len;
387 }
388 }
389 return((FLDOPE *) 0);
390found: result.count = rt(de)->rt_len * 512;
391 result.startad = 512 * (rt_dir.rt_axhead.rt_stfile + index);
392 result.rtdope = (struct rt_ent *) de;
393 return(&result);
394}
395static
396samename(a,b)
397unsigned short a[3],b[3];
398{
399 return( a[0]==b[0] && a[1]==b[1] && a[2]==b[2] );
400}
401
402
403rad50(cp,out)
404register unsigned char *cp;
405unsigned short *out;
406{
407 register index;
408 register temp;
409
410 for(index = 0;*cp; index++) {
411
412 temp = Ain1 * table[*cp++];
413 if(*cp!=0) {
414 temp += Ain2 * table[*cp++];
415
416 if(*cp!=0)
417 temp += table[*cp++];
418 }
419
420 out[index] = temp;
421 }
422}
423#define reduce(x,p,q) \
424 (x = v[p/q], p %= q);
425
426unrad50(count,in,cp)
427unsigned short *in;
428register char *cp;
429{
430 register i, temp; register unsigned char *v = (unsigned char *) val;
431
432 for(i = 0; i < count; i++) {
433 temp = in[i];
434
435 reduce (*cp++,temp,Ain1);
436 reduce (*cp++,temp,Ain2);
437 reduce (*cp++,temp,1);
438 }
439 *cp=0;
440}
441
442srad50(name,rname)
443register char * name;
444register unsigned short *rname;
445{
446 register index; register char *cp;
447 char file[7],ext[4];
448 /*
449 * Find end of pathname
450 */
451 for(cp = name; *cp++; );
452 while(cp >= name && *--cp != '/');
453 cp++;
454 /*
455 * Change to rad50
456 *
457 */
458 for(index = 0; *cp; ){
459 file[index++] = *cp++;
460 if(*cp=='.') {
461 cp++;
462 break;
463 }
464 if(index>=6) {
465 break;
466 }
467 }
468 file[index] = 0;
469 for(index = 0; *cp; ){
470 ext[index++] = *cp++;
471 if(*cp=='.' || index>=3) {
472 break;
473 }
474 }
475 ext[index]=0;
476 rname[0] = 0;
477 rname[1] = 0;
478 rname[2] = 0;
479 rad50((unsigned char *)file,rname);
480 rad50((unsigned char *)ext,rname+2);
481}
482sunrad50(name,rname)
483unsigned short rname[3];
484register char *name;
485{
486 register char *cp, *cp2;
487 char ext[4];
488
489 unrad50(2,rname,name);
490 unrad50(1,rname + 2,ext);
491 /* Jam name and extension together with a dot
492 deleting white space */
493 for(cp = name; *cp++;);--cp; while(*--cp==' ' && cp>=name);
494 *++cp = '.';cp++;
495 for(cp2=ext; *cp2!=' ' && cp2 < ext + 3;) {
496 *cp++ = *cp2++;
497 }
498 *cp=0;
499 if(cp[-1]=='.') cp[-1] = 0;
500}
501
502static char *oval = " ABCDEFGHIJKLMNOPQRSTUVWXYZ$.@0123456789";
503static char *val = " abcdefghijklmnopqrstuvwxyz$.@0123456789";
504static char table[256] = {
50529, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
50629, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
5070, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29,
50830, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29,
50929, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
51016, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
51129, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
51216, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
51329, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
51429, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
5150, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29,
51630, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29,
51729, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
51816, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
51929, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
52016, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29 };
521
522long trans(logical)
523register int logical;
524{
525 /* Logical to physical adress translation */
526 register int sector, bytes, track;
527
528 logical += 26 * 128;
529 bytes = (logical & 127);
530 logical >>= 7;
531 sector = logical % 26;
532 if(sector >= 13)
533 sector = sector *2 +1;
534 else
535 sector *= 2;
536 sector += 26 + ((track = (logical / 26)) - 1) * 6;
537 sector %= 26;
538 return( (((track *26) + sector) << 7) + bytes);
539}
540lread(startad,count,obuff)
541register startad, count;
542register char * obuff;
543{
544 long trans();
545 extern floppydes;
546 rt_init();
547 if(flg['m'-'a']==0)
548 while( (count -= 128) >= 0) {
549 lseek(floppydes, trans(startad), 0);
550 read(floppydes,obuff,128);
551 obuff += 128;
552 startad += 128;
553 }
554 else
555 while( (count -= 512) >= 0) {
556 lseek(floppydes,(long) (startad), 0);
557 read(floppydes,obuff,512);
558 obuff += 512;
559 startad += 512;
560 }
561}
562lwrite(startad,count,obuff)
563register startad, count;
564register char * obuff;
565{
566 long trans();
567 extern floppydes;
568 rt_init();
569 if(flg['m'-'a']==0)
570 while( (count -= 128) >= 0) {
571 lseek(floppydes, trans(startad), 0);
572 write(floppydes,obuff,128);
573 obuff += 128;
574 startad += 128;
575 }
576 else
577 while( (count -= 512) >= 0) {
578 lseek(floppydes,(long) (startad), 0);
579 write(floppydes,obuff,512);
580 obuff += 512;
581 startad += 512;
582 }
583}
584
585rcmd()
586{
587 register int i;
588
589 rt_init();
590 if(namc>0)
591 for(i = 0; i < namc; i++)
592 if(rtr(namv[i])==0) namv[i]=0;
593
594
595}
596
597rtr(name)
598char *name;
599{
600 register FLDOPE *dope; register struct rt_ent *de;
601 struct stat buf; register struct stat *bufp = &buf;
602
603 if(stat(name,bufp)<0) return(1);
604 if(dope = lookup(name)) {
605 /* can replace, no problem */
606 de = dope->rtdope;
607 if(bufp->st_size <= (de->rt_len * 512))
608 printf("r - %s\n",name),
609 toflop(name,bufp->st_size,dope);
610 else {
611 printf("%s will not fit in currently used file on floppy\n",name);
612 return(1);
613 }
614 } else {
615 /* Search for vacant spot */
616 for(de = rt_dir.rt_ents; (char *) de <= rt_last; de++) {
617 switch((de)->rt_stat) {
618 case RT_NULL:
619 if(bufp->st_size <= (de->rt_len * 512)) {
620 printf("a - %s\n",name),
621 mkent(de,bufp,name);
622 goto found;
623 }
624 continue;
625 case RT_ESEG:
626 return(3);
627 }
628 }
629 return(5);
630 }
631found: if(dope=lookup(name)) {
632 toflop(name,bufp->st_size,dope);
633 return(0);
634 }
635 return(7);
636
637}
638mkent(de,bufp,name)
639register struct rt_ent *de;
640register struct stat *bufp;
641char *name;
642{
643 struct tm *localtime(); register struct tm *timp;
644 register struct rt_ent *workp; int count;
645
646 count = (((bufp->st_size -1) >>9) + 1);
647 /* Make sure there is room */
648 if(de->rt_len==count)
649 goto overwrite;
650 if(rt_nleft==0) {
651 if(flg['o'-'a'])
652 goto overwrite;
653 fprintf(stderr,"Directory full on %s\n",defdev);
654 exit(1);
655 }
656 /* copy directory entries up */
657 for(workp = rt_curend+1; workp > de; workp--)
658 *workp = workp[-1];
659 de[1].rt_len -= count;
660 de->rt_len = count;
661 rt_curend++;
662 rt_nleft--;
663overwrite:
664 srad50(name,de->rt_name);
665 timp = localtime(&bufp->st_mtime);
666 de->rt_date.rt_dy = timp->tm_mday + 1;
667 de->rt_date.rt_mo = timp->tm_mon + 1;
668 de->rt_date.rt_yr = timp->tm_year - 72;
669 de->rt_stat = RT_FILE;
670 de->rt_pad = 0;
671 de->rt_chan = 0;
672 de->rt_job = 0;
673 lwrite(6*RT_BLOCK,2*RT_BLOCK,(char *)&rt_dir);
674
675}
676
677toflop(name,ocount,dope)
678char *name;
679register FLDOPE *dope;
680long ocount;
681{
682 register file, n, startad = dope->startad, count = ocount;
683 char buff[512];
684
685 file = open(name,0);
686 if(file < 0) {
687 printf("arff: couldn't open %s\n",name);exit(1);}
688 for( ; count >= 512; count -= 512) {
689 read(file,buff,512);
690 lwrite(startad,512,buff);
691 startad += 512;
692 }
693 read(file,buff,count);
694 close(file);
695 if(count <= 0) return;
696 for(n = count; n < 512; n ++) buff[n] = 0;
697 lwrite(startad,512,buff);
698 count = (dope->rtdope->rt_len * 512 - ocount) / 512 ;
699 if(count <= 0) return;
700 for( ; count > 0 ; count--) {
701 startad += 512;
702 lwrite(startad,512,zeroes);
703 }
704
705}
706dcmd()
707{
708 register int i;
709
710 rt_init();
711 if(namc)
712 for(i = 0; i < namc; i++)
713 if(rtk(namv[i])==0) namv[i]=0;
714 if(dirdirty)
715 scrunch();
716
717}
718rtk(name)
719char *name;
720{
721 register FLDOPE *dope;
722 register struct rt_ent *de;
723 FLDOPE *lookup();
724
725 if(dope = lookup(name)) {
726 printf("d - %s\n",name);
727 de = dope->rtdope;
728 de->rt_stat = RT_NULL;
729 de->rt_name[0] = 0;
730 de->rt_name[1] = 0;
731 de->rt_name[2] = 0;
732 * ((unsigned short *) & (de->rt_date)) = 0;
733 dirdirty = 1;
734 return(0);
735 }
736 return(1);
737}
738scrunch() {
739 register struct rt_ent *de = rt_dir.rt_ents, *workp;
740 for(de = rt_dir.rt_ents; de <= rt_curend; de++) {
741 if(de->rt_stat==RT_NULL && de[1].rt_stat==RT_NULL) {
742 (de+1)->rt_len += de->rt_len;
743 for(workp = de; workp < rt_curend; workp++)
744 *workp = workp[1];
745 de--;
746 rt_curend--;
747 rt_nleft++;
748 }
749 }
750 lwrite(6*RT_BLOCK,2*RT_BLOCK,(char *)&rt_dir);
751}