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