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