xref: /csrg-svn/old/arff/arff.c (revision 1735)
1*1735Sbill static char *sccsid = "@(#)arff.c	4.2 (Berkeley) 11/03/80";
2954Sbill #include <sys/types.h>
3954Sbill #include <sys/stat.h>
4954Sbill #include <time.h>
5954Sbill #include <signal.h>
6954Sbill #include <stdio.h>
7954Sbill #define dbprintf printf
8954Sbill struct rt_dat {
9954Sbill unsigned short	int	rt_yr:5;	/*Year - 1972			*/
10954Sbill unsigned short	int	rt_dy:5;	/*day				*/
11954Sbill unsigned short	int	rt_mo:5;	/*month				*/
12954Sbill };
13954Sbill struct	rt_axent {
14954Sbill 	char	rt_sent[14];
15954Sbill };
16954Sbill 
17954Sbill struct rt_ent {
18954Sbill 	char  rt_pad;			/*unusued		     */
19954Sbill 	char  rt_stat;			/*Type of entry, or end of seg*/
20954Sbill 	unsigned short rt_name[3];	/*Name, 3 words in rad50 form */
21954Sbill 	short rt_len;			/*Length of file	      */
22954Sbill 	char  rt_chan;			/*Only used in temporary files*/
23954Sbill 	char  rt_job;			/*Only used in temporary files*/
24954Sbill 	struct rt_dat rt_date;		/*Creation Date			*/
25954Sbill };
26954Sbill #define RT_TEMP 1
27954Sbill #define RT_NULL 2
28954Sbill #define RT_FILE 4
29954Sbill #define RT_ESEG 8
30954Sbill #define RT_BLOCK 512
31954Sbill struct rt_head {
32954Sbill 	short	rt_numseg;		/*number of segments available*/
33954Sbill 	short	rt_nxtseg;		/*segment no of next log. seg */
34954Sbill 	short	rt_lstseg;		/*highest seg currenltly open */
35954Sbill 	unsigned short	rt_entpad;	/*extra words/dir. entry      */
36954Sbill 	short	rt_stfile;		/*block no where files begin  */
37954Sbill };
38954Sbill struct	rt_dir {
39954Sbill 	struct rt_head	rt_axhead;
40954Sbill 	struct rt_ent	rt_ents[72];
41954Sbill 	char	_dirpad[6];
42954Sbill };
43954Sbill extern struct rt_dir	rt_dir;
44954Sbill extern int		rt_entsiz;
45954Sbill extern int		floppydes;
46954Sbill extern char		*rt_last;
47954Sbill typedef struct fldope {
48954Sbill 	int	startad;
49954Sbill 	int	count;
50954Sbill struct	rt_ent	*rtdope;
51954Sbill } FLDOPE;
52954Sbill FLDOPE *lookup();
53954Sbill #define rt(p) ((struct rt_ent *) p )
54954Sbill #define Ain1 03100
55954Sbill #define Ain2 050
56954Sbill #define flag(c) (flg[(c) - 'a'])
57954Sbill 
58954Sbill char	*man	=	{ "rxtd" };
59954Sbill 
60954Sbill char zeroes[512];
61954Sbill extern char *val;
62954Sbill extern char table[256];
63954Sbill struct rt_dir	rt_dir = {{4,0,1,0,14},{0,RT_NULL,{0,0,0},494,0}, {0,RT_ESEG}};
64954Sbill int		rt_entsiz;
65954Sbill int		rt_nleft;
66954Sbill struct rt_ent	*rt_curend;
67954Sbill int		floppydes;
68954Sbill int		dirdirty;
69954Sbill char		*rt_last;
70954Sbill char		*defdev = "/dev/floppy";
71954Sbill 
72954Sbill char	*opt	=	{ "vf" };
73954Sbill 
74954Sbill int	signum[] = {SIGHUP, SIGINT, SIGQUIT, 0};
75954Sbill long	lseek();
76954Sbill int	rcmd();
77954Sbill int	dcmd();
78954Sbill int	xcmd();
79954Sbill int	tcmd();
80954Sbill int	(*comfun)();
81954Sbill char	flg[26];
82954Sbill char	**namv;
83954Sbill int	namc;
84954Sbill int	file;
85954Sbill 
86954Sbill 
87954Sbill main(argc, argv)
88954Sbill char *argv[];
89954Sbill {
90954Sbill 	register char *cp;
91954Sbill 
92954Sbill 	/*register i;
93954Sbill 	for(i=0; signum[i]; i++)
94954Sbill 		if(signal(signum[i], SIG_IGN) != SIG_IGN)
95954Sbill 			signal(signum[i], sigdone);*/
96954Sbill 	if(argc < 2)
97954Sbill 		usage();
98954Sbill 	cp = argv[1];
99954Sbill 	for(cp = argv[1]; *cp; cp++)
100954Sbill 	switch(*cp) {
101954Sbill 	case 'm':
102954Sbill 	case 'v':
103954Sbill 	case 'u':
104954Sbill 	case 'w':
105954Sbill 		flg[*cp - 'a']++;
106954Sbill 		continue;
107954Sbill 	case 'c':
108954Sbill 		{
109954Sbill #define SURE	"Are you sure you want to clobber the floppy?\n"
110954Sbill 			int tty;
111*1735Sbill 			char response[128];
112954Sbill 			tty = open("/dev/tty",2);
113954Sbill 			write(tty,SURE,sizeof(SURE));
114*1735Sbill 			read(tty,response,128);
115954Sbill 			if(*response!='y')
116954Sbill 				exit(50);
117954Sbill 			flag('c')++;
118954Sbill 			close(tty);
119954Sbill 		}
120954Sbill 		dirdirty++;
121954Sbill 		continue;
122954Sbill 
123954Sbill 	case 'r':
124954Sbill 		setcom(rcmd);
125954Sbill 		flag('r')++;
126954Sbill 		continue;
127954Sbill 
128954Sbill 	case 'd':
129954Sbill 		setcom(dcmd);
130954Sbill 		flag('d')++;
131954Sbill 		continue;
132954Sbill 
133954Sbill 	case 'x':
134954Sbill 		setcom(xcmd);
135954Sbill 		continue;
136954Sbill 
137954Sbill 	case 't':
138954Sbill 		setcom(tcmd);
139954Sbill 		continue;
140954Sbill 
141954Sbill 	case 'f':
142954Sbill 		defdev = argv[2];
143954Sbill 		argv++;
144954Sbill 		argc--;
145954Sbill 		continue;
146954Sbill 
147954Sbill 
148954Sbill 	default:
149954Sbill 		fprintf(stderr, "arff: bad option `%c'\n", *cp);
150954Sbill 		exit(1);
151954Sbill 	}
152954Sbill 	namv = argv+2;
153954Sbill 	namc = argc-2;
154954Sbill 	if(comfun == 0) {
155954Sbill 		if(flg['u'-'a'] == 0) {
156954Sbill 			fprintf(stderr, "arff: one of [%s] must be specified\n", man);
157954Sbill 			exit(1);
158954Sbill 		}
159954Sbill 		setcom(rcmd);
160954Sbill 	}
161954Sbill 	(*comfun)();
162954Sbill 	exit(notfound());
163954Sbill }
164954Sbill 
165954Sbill setcom(fun)
166954Sbill int (*fun)();
167954Sbill {
168954Sbill 
169954Sbill 	if(comfun != 0) {
170954Sbill 		fprintf(stderr, "arff: only one of [%s] allowed\n", man);
171954Sbill 		exit(1);
172954Sbill 	}
173954Sbill 	comfun = fun;
174954Sbill }
175954Sbill 
176954Sbill 
177954Sbill 
178954Sbill 
179954Sbill 
180954Sbill 
181954Sbill 
182954Sbill 
183954Sbill usage()
184954Sbill {
185954Sbill 	printf("usage: ar [%s][%s] archive files ...\n", opt, man);
186954Sbill 	exit(1);
187954Sbill }
188954Sbill 
189954Sbill 
190954Sbill 
191954Sbill notfound()
192954Sbill {
193954Sbill 	register i, n;
194954Sbill 
195954Sbill 	n = 0;
196954Sbill 	for(i=0; i<namc; i++)
197954Sbill 		if(namv[i]) {
198954Sbill 			fprintf(stderr, "arff: %s not found\n", namv[i]);
199954Sbill 			n++;
200954Sbill 		}
201954Sbill 	return(n);
202954Sbill }
203954Sbill 
204954Sbill 
205954Sbill 
206954Sbill phserr()
207954Sbill {
208954Sbill 
209954Sbill 	fprintf(stderr, "arff: phase error on %s\n", file);
210954Sbill }
211954Sbill 
212954Sbill mesg(c)
213954Sbill {
214954Sbill 
215954Sbill 	if(flg['v'-'a'])
216954Sbill 		if(c != 'c' || flg['v'-'a'] > 1)
217954Sbill 			printf("%c - %s\n", c, file);
218954Sbill }
219954Sbill 
220954Sbill tcmd()
221954Sbill {
222954Sbill 	register char *de;
223954Sbill 	FLDOPE *lookup(), *dope;
224954Sbill 	int nleft; register i;
225954Sbill 	register struct rt_ent *rde;
226954Sbill 
227954Sbill 	rt_init();
228954Sbill 	if(namc==0)
229954Sbill 		for(de=((char *)&rt_dir)+10; de <= rt_last; de += rt_entsiz) {
230954Sbill 			if(rtls(rt(de))) {
231954Sbill 				nleft = (rt_last - de) / rt_entsiz;
232954Sbill 				printf("\n\n%d entries remaining.\n",nleft);
233954Sbill 				break;
234954Sbill 			}
235954Sbill 		}
236954Sbill 	else
237954Sbill 		for(i = 0; i < namc; i++) {
238954Sbill 			if(dope = lookup(namv[i])) {
239954Sbill 				rde = dope->rtdope;
240954Sbill 				rtls(rde);
241954Sbill 				namv[i] = 0;
242954Sbill 			}
243954Sbill 		}
244954Sbill }
245954Sbill rtls(de)
246954Sbill register struct rt_ent *de;
247954Sbill {
248954Sbill 	int month,day,year;
249954Sbill 	char name[12], ext[4];
250954Sbill 
251954Sbill 	if(flg['v'-'a'])
252954Sbill 		switch(de->rt_stat) {
253954Sbill 		case RT_TEMP:
254954Sbill 			printf("Tempfile:\n");
255954Sbill 		case RT_FILE:
256954Sbill 			unrad50(2,de->rt_name,name);
257954Sbill 			unrad50(1,&(de->rt_name[2]),ext);
258954Sbill 			day = de->rt_date.rt_dy;
259954Sbill 			year = de->rt_date.rt_yr + 72;
260954Sbill 			month = de->rt_date.rt_mo;
261954Sbill 			printf("%6.6s  %3.3s	%02d/%02d/%02d	%d\n",name,
262954Sbill 				ext,month,day,year,de->rt_len);
263954Sbill 			break;
264954Sbill 
265954Sbill 		case RT_NULL:
266954Sbill 			printf("%-25.9s	%d\n","<UNUSED>",de->rt_len);
267954Sbill 			break;
268954Sbill 
269954Sbill 		case RT_ESEG:
270954Sbill 			return(1);
271954Sbill 		}
272954Sbill 	else {
273954Sbill 		switch(de->rt_stat) {
274954Sbill 		case RT_TEMP:
275954Sbill 		case RT_FILE:
276954Sbill 			sunrad50(name,de->rt_name);
277954Sbill 			printf(name);putchar('\n');
278954Sbill 			break;
279954Sbill 
280954Sbill 		case RT_ESEG:
281954Sbill 			return(1);
282954Sbill 
283954Sbill 		case RT_NULL:
284954Sbill 			;
285954Sbill 		}
286954Sbill 	}
287954Sbill 	return(0);
288954Sbill }
289954Sbill xcmd()
290954Sbill {
291954Sbill 	register char *de;
292954Sbill 	char name[12];
293954Sbill 	register int i;
294954Sbill 
295954Sbill 	rt_init();
296954Sbill 	if(namc==0)
297954Sbill 		for(de=((char *)&rt_dir)+10; de <= rt_last; de += rt_entsiz) {
298954Sbill 			sunrad50(name,rt(de)->rt_name);
299954Sbill 			rtx(name);
300954Sbill 		}
301954Sbill 
302954Sbill 	else
303954Sbill 		for(i = 0; i < namc; i++)
304954Sbill 		if(rtx(namv[i])==0) namv[i] = 0;
305954Sbill }
306954Sbill rtx(name)
307954Sbill char *name;
308954Sbill {
309954Sbill 	register FLDOPE *dope;
310954Sbill 	FLDOPE *lookup();
311954Sbill 	register startad, count;
312954Sbill 	int file; char buff[512];
313954Sbill 
314954Sbill 
315954Sbill 	if(dope = lookup(name)) {
316954Sbill 		if(flg['v' - 'a'])
317954Sbill 			rtls(dope->rtdope);
318954Sbill 		else
319954Sbill 			printf("x - %s\n",name);
320954Sbill 
321954Sbill 		file = creat(name, 0666);
322954Sbill 		if(file < 0) return(1);
323954Sbill 		count = dope->count;
324954Sbill 		startad = dope->startad;
325954Sbill 		for( ; count > 0 ; count -= 512) {
326954Sbill 			lread(startad,512,buff);
327954Sbill 			write(file,buff,512);
328954Sbill 			startad += 512;
329954Sbill 		}
330954Sbill 		close(file);
331954Sbill 		return(0);
332954Sbill 	}
333954Sbill 	return(1);
334954Sbill }
335954Sbill rt_init()
336954Sbill {
337954Sbill 	static initized = 0;
338954Sbill 	register char *de;
339954Sbill 	int mode;
340954Sbill 
341954Sbill 	if(initized) return;
342954Sbill 	initized = 1;
343954Sbill 	if(flag('c') || flag('d') || flag('r'))
344954Sbill 		mode = 2;
345954Sbill 	else
346954Sbill 		mode = 0;
347954Sbill 	if((floppydes = open(defdev,mode)) < 0)
348954Sbill 		dbprintf("Floppy open failed\n");
349954Sbill 	if(flag('c')==0)
350954Sbill 		lread(6*RT_BLOCK,2*RT_BLOCK,(char *)&rt_dir);
351954Sbill 
352954Sbill 	rt_entsiz = 2*rt_dir.rt_axhead.rt_entpad + 14;
353954Sbill 	rt_entsiz = 14;
354954Sbill 	rt_last = ((char *) &rt_dir) + 10 + 1014/rt_entsiz*rt_entsiz;
355954Sbill 	for(de=((char *)&rt_dir)+10; de <= rt_last; de += rt_entsiz) {
356954Sbill 		if(rt(de)->rt_stat==RT_ESEG) break;
357954Sbill 	}
358954Sbill 	rt_curend = rt(de);
359954Sbill 	rt_nleft = (rt_last - de) / rt_entsiz;
360954Sbill }
361954Sbill 
362954Sbill static FLDOPE result;
363954Sbill FLDOPE *
364954Sbill lookup(name)
365954Sbill char * name;
366954Sbill {
367954Sbill 	unsigned short rname[3];
368954Sbill 	register char *de;
369954Sbill 	register index;
370954Sbill 
371954Sbill 	srad50(name,rname);
372954Sbill 
373954Sbill 	/*
374954Sbill 	 *  Search for name, accumulate blocks in index
375954Sbill 	 */
376954Sbill 	rt_init();
377954Sbill 	index = 0;
378954Sbill 	for(de = ((char *) &rt_dir) + 10; de <= rt_last; de += rt_entsiz) {
379954Sbill 		switch(rt(de)->rt_stat) {
380954Sbill 		case RT_ESEG:
381954Sbill 			return((FLDOPE *) 0);
382954Sbill 		case RT_FILE:
383954Sbill 		case RT_TEMP:
384954Sbill 		if(samename(rname,rt(de)->rt_name))
385954Sbill 			goto found;
386954Sbill 		case RT_NULL:
387954Sbill 			index += rt(de)->rt_len;
388954Sbill 		}
389954Sbill 	}
390954Sbill 	return((FLDOPE *) 0);
391954Sbill found:	result.count = rt(de)->rt_len * 512;
392954Sbill 	result.startad = 512 * (rt_dir.rt_axhead.rt_stfile + index);
393954Sbill 	result.rtdope = (struct rt_ent *) de;
394954Sbill 	return(&result);
395954Sbill }
396954Sbill static
397954Sbill samename(a,b)
398954Sbill unsigned short a[3],b[3];
399954Sbill {
400954Sbill 	return( a[0]==b[0] && a[1]==b[1] && a[2]==b[2] );
401954Sbill }
402954Sbill 
403954Sbill 
404954Sbill rad50(cp,out)
405954Sbill register unsigned char *cp;
406954Sbill unsigned short *out;
407954Sbill {
408954Sbill 	register index;
409954Sbill 	register temp;
410954Sbill 
411954Sbill 	for(index = 0;*cp; index++) {
412954Sbill 
413954Sbill 		temp = Ain1 * table[*cp++];
414954Sbill 		if(*cp!=0) {
415954Sbill 			temp += Ain2 * table[*cp++];
416954Sbill 
417954Sbill 			if(*cp!=0)
418954Sbill 				temp += table[*cp++];
419954Sbill 		}
420954Sbill 
421954Sbill 		out[index] = temp;
422954Sbill 	}
423954Sbill }
424954Sbill #define reduce(x,p,q) \
425954Sbill 	(x = v[p/q], p %= q);
426954Sbill 
427954Sbill unrad50(count,in,cp)
428954Sbill unsigned short *in;
429954Sbill register char *cp;
430954Sbill {
431954Sbill 	register i, temp; register unsigned char *v = (unsigned char *) val;
432954Sbill 
433954Sbill 	for(i = 0; i < count; i++) {
434954Sbill 		temp = in[i];
435954Sbill 
436954Sbill 		reduce (*cp++,temp,Ain1);
437954Sbill 		reduce (*cp++,temp,Ain2);
438954Sbill 		reduce (*cp++,temp,1);
439954Sbill 	}
440954Sbill 	*cp=0;
441954Sbill }
442954Sbill 
443954Sbill srad50(name,rname)
444954Sbill register char * name;
445954Sbill register unsigned short *rname;
446954Sbill {
447954Sbill 	register index; register char *cp;
448954Sbill 	char file[7],ext[4];
449954Sbill 	/*
450954Sbill 	 * Find end of pathname
451954Sbill 	 */
452954Sbill 	for(cp = name; *cp++; );
453954Sbill 	while(cp >= name && *--cp != '/');
454954Sbill 	cp++;
455954Sbill 	/*
456954Sbill 	 * Change to rad50
457954Sbill 	 *
458954Sbill 	 */
459954Sbill 	for(index = 0; *cp; ){
460954Sbill 		file[index++] = *cp++;
461954Sbill 		if(*cp=='.') {
462954Sbill 			cp++;
463954Sbill 			break;
464954Sbill 		}
465954Sbill 		if(index>=6) {
466954Sbill 			break;
467954Sbill 		}
468954Sbill 	}
469954Sbill 	file[index] = 0;
470954Sbill 	for(index = 0; *cp; ){
471954Sbill 		ext[index++] = *cp++;
472954Sbill 		if(*cp=='.' || index>=3) {
473954Sbill 			break;
474954Sbill 		}
475954Sbill 	}
476954Sbill 	ext[index]=0;
477954Sbill 	rname[0] = 0;
478954Sbill 	rname[1] = 0;
479954Sbill 	rname[2] = 0;
480954Sbill 	rad50((unsigned char *)file,rname);
481954Sbill 	rad50((unsigned char *)ext,rname+2);
482954Sbill }
483954Sbill sunrad50(name,rname)
484954Sbill unsigned short rname[3];
485954Sbill register char *name;
486954Sbill {
487954Sbill 	register char *cp, *cp2;
488954Sbill 	char ext[4];
489954Sbill 
490954Sbill 	unrad50(2,rname,name);
491954Sbill 	unrad50(1,rname + 2,ext);
492954Sbill 	/* Jam name and extension together with a dot
493954Sbill 	   deleting white space */
494954Sbill 	for(cp = name; *cp++;);--cp;  while(*--cp==' ' && cp>=name);
495954Sbill 	*++cp = '.';cp++;
496954Sbill 	for(cp2=ext; *cp2!=' ' && cp2 < ext + 3;) {
497954Sbill 		*cp++ = *cp2++;
498954Sbill 	}
499954Sbill 	*cp=0;
500954Sbill 	if(cp[-1]=='.') cp[-1] = 0;
501954Sbill }
502954Sbill 
503954Sbill static char *oval = " ABCDEFGHIJKLMNOPQRSTUVWXYZ$.@0123456789";
504954Sbill static char *val = " abcdefghijklmnopqrstuvwxyz$.@0123456789";
505954Sbill static char table[256] = {
506954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
507954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
508954Sbill 0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29,
509954Sbill 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29,
510954Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
511954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
512954Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
513954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
514954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
515954Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
516954Sbill 0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29,
517954Sbill 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29,
518954Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
519954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
520954Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
521954Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29 };
522954Sbill 
523954Sbill long trans(logical)
524954Sbill register int logical;
525954Sbill {
526954Sbill 	/*  Logical to physical adress translation */
527954Sbill 	register int sector, bytes, track;
528954Sbill 
529954Sbill 	logical += 26 * 128;
530954Sbill 	bytes = (logical & 127);
531954Sbill 	logical >>= 7;
532954Sbill 	sector = logical % 26;
533954Sbill 	if(sector >= 13)
534954Sbill 		sector = sector *2 +1;
535954Sbill 	else
536954Sbill 		sector *= 2;
537954Sbill 	sector += 26 + ((track = (logical / 26)) - 1) * 6;
538954Sbill 	sector %= 26;
539954Sbill 	return( (((track *26) + sector) << 7) + bytes);
540954Sbill }
541954Sbill lread(startad,count,obuff)
542954Sbill register startad, count;
543954Sbill register char * obuff;
544954Sbill {
545954Sbill 	long trans();
546954Sbill 	extern floppydes;
547954Sbill 	rt_init();
548954Sbill 	if(flg['m'-'a']==0)
549954Sbill 		while( (count -= 128) >= 0) {
550954Sbill 			lseek(floppydes, trans(startad), 0);
551954Sbill 			read(floppydes,obuff,128);
552954Sbill 			obuff += 128;
553954Sbill 			startad += 128;
554954Sbill 		}
555954Sbill 	else
556954Sbill 		while( (count -= 512) >= 0) {
557954Sbill 			lseek(floppydes,(long) (startad), 0);
558954Sbill 			read(floppydes,obuff,512);
559954Sbill 			obuff += 512;
560954Sbill 			startad += 512;
561954Sbill 		}
562954Sbill }
563954Sbill lwrite(startad,count,obuff)
564954Sbill register startad, count;
565954Sbill register char * obuff;
566954Sbill {
567954Sbill 	long trans();
568954Sbill 	extern floppydes;
569954Sbill 	rt_init();
570954Sbill 	if(flg['m'-'a']==0)
571954Sbill 		while( (count -= 128) >= 0) {
572954Sbill 			lseek(floppydes, trans(startad), 0);
573954Sbill 			write(floppydes,obuff,128);
574954Sbill 			obuff += 128;
575954Sbill 			startad += 128;
576954Sbill 		}
577954Sbill 	else
578954Sbill 		while( (count -= 512) >= 0) {
579954Sbill 			lseek(floppydes,(long) (startad), 0);
580954Sbill 			write(floppydes,obuff,512);
581954Sbill 			obuff += 512;
582954Sbill 			startad += 512;
583954Sbill 		}
584954Sbill }
585954Sbill 
586954Sbill rcmd()
587954Sbill {
588954Sbill 	register int i;
589954Sbill 
590954Sbill 	rt_init();
591954Sbill 	if(namc>0)
592954Sbill 		for(i = 0; i < namc; i++)
593954Sbill 			if(rtr(namv[i])==0) namv[i]=0;
594954Sbill 
595954Sbill 
596954Sbill }
597954Sbill 
598954Sbill rtr(name)
599954Sbill char *name;
600954Sbill {
601954Sbill 	register FLDOPE *dope; register struct rt_ent *de;
602954Sbill 	struct stat buf; register struct stat *bufp = &buf;
603954Sbill 
604954Sbill 	if(stat(name,bufp)<0) return(1);
605954Sbill 	if(dope = lookup(name)) {
606954Sbill 		/* can replace, no problem */
607954Sbill 		de = dope->rtdope;
608954Sbill 		if(bufp->st_size <= (de->rt_len * 512))
609954Sbill 			printf("r - %s\n",name),
610954Sbill 			toflop(name,bufp->st_size,dope);
611954Sbill 		else {
612954Sbill 			printf("%s will not fit in currently used file on floppy\n",name);
613954Sbill 			return(1);
614954Sbill 		}
615954Sbill 	} else {
616954Sbill 		/* Search for vacant spot */
617954Sbill 		for(de = rt_dir.rt_ents; (char *) de <= rt_last; de++) {
618954Sbill 			switch((de)->rt_stat) {
619954Sbill 			case RT_NULL:
620954Sbill 				if(bufp->st_size <= (de->rt_len * 512)) {
621954Sbill 					printf("a - %s\n",name),
622954Sbill 					mkent(de,bufp,name);
623954Sbill 					goto found;
624954Sbill 				}
625954Sbill 				continue;
626954Sbill 			case RT_ESEG:
627954Sbill 				return(3);
628954Sbill 			}
629954Sbill 		}
630954Sbill 		return(5);
631954Sbill 	}
632954Sbill found:	if(dope=lookup(name)) {
633954Sbill 		toflop(name,bufp->st_size,dope);
634954Sbill 		return(0);
635954Sbill 	}
636954Sbill 	return(7);
637954Sbill 
638954Sbill }
639954Sbill mkent(de,bufp,name)
640954Sbill register struct rt_ent *de;
641954Sbill register struct stat *bufp;
642954Sbill char *name;
643954Sbill {
644954Sbill 	struct tm *localtime(); register struct tm *timp;
645954Sbill 	register struct rt_ent *workp; int count;
646954Sbill 
647954Sbill 	count = (((bufp->st_size -1) >>9) + 1);
648954Sbill 						/* Make sure there is room */
649954Sbill 	if(de->rt_len==count)
650954Sbill 		goto overwrite;
651954Sbill 	if(rt_nleft==0) {
652954Sbill 		if(flg['o'-'a'])
653954Sbill 			goto overwrite;
654954Sbill 		fprintf(stderr,"Directory full on  %s\n",defdev);
655954Sbill 		exit(1);
656954Sbill 	}
657954Sbill 					/* copy directory entries up */
658954Sbill 	for(workp = rt_curend+1; workp > de; workp--)
659954Sbill 		*workp = workp[-1];
660954Sbill 	de[1].rt_len -= count;
661954Sbill 	de->rt_len = count;
662954Sbill 	rt_curend++;
663954Sbill 	rt_nleft--;
664954Sbill overwrite:
665954Sbill 	srad50(name,de->rt_name);
666954Sbill 	timp = localtime(&bufp->st_mtime);
667954Sbill 	de->rt_date.rt_dy = timp->tm_mday + 1;
668954Sbill 	de->rt_date.rt_mo = timp->tm_mon + 1;
669954Sbill 	de->rt_date.rt_yr = timp->tm_year - 72;
670954Sbill 	de->rt_stat = RT_FILE;
671954Sbill 	de->rt_pad = 0;
672954Sbill 	de->rt_chan = 0;
673954Sbill 	de->rt_job = 0;
674954Sbill 	lwrite(6*RT_BLOCK,2*RT_BLOCK,(char *)&rt_dir);
675954Sbill 
676954Sbill }
677954Sbill 
678954Sbill toflop(name,ocount,dope)
679954Sbill char *name;
680954Sbill register FLDOPE *dope;
681954Sbill long ocount;
682954Sbill {
683954Sbill 	register file, n, startad = dope->startad, count = ocount;
684954Sbill 	char buff[512];
685954Sbill 
686954Sbill 	file = open(name,0);
687954Sbill 	if(file < 0) {
688954Sbill 		printf("arff: couldn't open %s\n",name);exit(1);}
689954Sbill 	for( ; count >= 512; count -= 512) {
690954Sbill 		read(file,buff,512);
691954Sbill 		lwrite(startad,512,buff);
692954Sbill 		startad += 512;
693954Sbill 	}
694954Sbill 	read(file,buff,count);
695954Sbill 	close(file);
696954Sbill 	if(count <= 0) return;
697954Sbill 	for(n = count; n < 512; n ++) buff[n] = 0;
698954Sbill 	lwrite(startad,512,buff);
699954Sbill 	count = (dope->rtdope->rt_len * 512 - ocount) / 512 ;
700954Sbill 	if(count <= 0) return;
701954Sbill 	for( ; count > 0 ; count--) {
702954Sbill 		startad += 512;
703954Sbill 		lwrite(startad,512,zeroes);
704954Sbill 	}
705954Sbill 
706954Sbill }
707954Sbill dcmd()
708954Sbill {
709954Sbill 	register int i;
710954Sbill 
711954Sbill 	rt_init();
712954Sbill 	if(namc)
713954Sbill 		for(i = 0; i < namc; i++)
714954Sbill 			if(rtk(namv[i])==0) namv[i]=0;
715954Sbill 	if(dirdirty)
716954Sbill 		scrunch();
717954Sbill 
718954Sbill }
719954Sbill rtk(name)
720954Sbill char *name;
721954Sbill {
722954Sbill 	register FLDOPE *dope;
723954Sbill 	register struct rt_ent *de;
724954Sbill 	FLDOPE *lookup();
725954Sbill 
726954Sbill 	if(dope = lookup(name)) {
727954Sbill 		printf("d - %s\n",name);
728954Sbill 		de = dope->rtdope;
729954Sbill 		de->rt_stat = RT_NULL;
730954Sbill 		de->rt_name[0] = 0;
731954Sbill 		de->rt_name[1] = 0;
732954Sbill 		de->rt_name[2] = 0;
733954Sbill 		* ((unsigned short *) & (de->rt_date)) = 0;
734954Sbill 		dirdirty = 1;
735954Sbill 		return(0);
736954Sbill 	}
737954Sbill 	return(1);
738954Sbill }
739954Sbill scrunch() {
740954Sbill 	register struct rt_ent *de = rt_dir.rt_ents, *workp;
741954Sbill 	for(de = rt_dir.rt_ents; de <= rt_curend; de++) {
742954Sbill 		if(de->rt_stat==RT_NULL && de[1].rt_stat==RT_NULL) {
743954Sbill 			(de+1)->rt_len += de->rt_len;
744954Sbill 			for(workp = de; workp < rt_curend; workp++)
745954Sbill 				*workp = workp[1];
746954Sbill 			de--;
747954Sbill 			rt_curend--;
748954Sbill 			rt_nleft++;
749954Sbill 		}
750954Sbill 	}
751954Sbill 	lwrite(6*RT_BLOCK,2*RT_BLOCK,(char *)&rt_dir);
752954Sbill }
753