xref: /original-bsd/old/arff/arff.c (revision 6c57d260)
1 static	char *sccsid = "@(#)arff.c	4.5 (Berkeley) 81/04/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 mode, dirnum;
347 	register char *last;
348 
349 	if(initized) return;
350 	initized = 1;
351 	if(flag('c') || flag('d') || flag('r'))
352 		mode = 2;
353 	else
354 		mode = 0;
355 	if((floppydes = open(defdev,mode)) < 0) {
356 		dbprintf("Floppy open failed\n");
357 		exit(1);
358 	}
359 	if(flag('c')==0) {
360 		lread(6*RT_BLOCK,2*RT_BLOCK,(char *)&rt_dir[0]);
361 		dirnum = rt_dir[0].rt_axhead.rt_numseg;
362 		if (dirnum > RT_DIRSIZE) {
363 		   fprintf(stderr,"arff: too many directory segments\n");
364 		   exit(1);
365 		}
366 		for (i=1; i<dirnum; i++)
367 		   lread((6+2*i)*RT_BLOCK,2*RT_BLOCK,(char *)&rt_dir[i]);
368 	} else
369 		dirnum = 1;
370 
371 	rt_entsiz = 2*rt_dir[0].rt_axhead.rt_entpad + 14;
372 	rt_entsiz = 14;			/* assume rt_entpad = 0 ??? */
373 	rt_last = ((char *) &rt_dir[0]) + 10 + 1014/rt_entsiz*rt_entsiz;
374 	rt_nleft = 0;
375 
376 	for (i=0; i<dirnum; i++) {
377   	    last = rt_last + i*2*RT_BLOCK;
378 	    for(de=((char *)&rt_dir[i])+10; de <= last; de += rt_entsiz) {
379 		if(rt(de)->rt_stat==RT_ESEG) break;
380 	    }
381 	    rt_curend[i] = rt(de);
382 	    rt_nleft += (last - de) / rt_entsiz;
383 	}
384 }
385 
386 static FLDOPE result;
387 FLDOPE *
388 lookup(name)
389 char * name;
390 {
391 	unsigned short rname[3];
392 	register char *de;
393 	int segnum;
394 	register char *last;
395 	register index;
396 
397 	srad50(name,rname);
398 
399 	/*
400 	 *  Search for name, accumulate blocks in index
401 	 */
402 	rt_init();
403 	for (segnum=0; segnum != -1;    /* for all dir. segments */
404              segnum = rt_dir[segnum].rt_axhead.rt_nxtseg - 1) {
405 	    index = 0;
406 	    last = rt_last + segnum*2*RT_BLOCK;
407 	    for(de=((char *)&rt_dir[segnum])+10;
408 		rt(de)->rt_stat != RT_ESEG; de += rt_entsiz) {
409 		switch(rt(de)->rt_stat) {
410 		case RT_FILE:
411 		case RT_TEMP:
412 		if(samename(rname,rt(de)->rt_name))
413 			goto found;
414 		case RT_NULL:
415 			index += rt(de)->rt_len;
416 		}
417 	    }
418         }
419 	return((FLDOPE *) 0);
420 found:	result.count = rt(de)->rt_len * 512;
421 	result.startad = 512 * (rt_dir[segnum].rt_axhead.rt_stfile + index);
422 	result.rtdope = (struct rt_ent *) de;
423 	return(&result);
424 }
425 static
426 samename(a,b)
427 unsigned short a[3],b[3];
428 {
429 	return( a[0]==b[0] && a[1]==b[1] && a[2]==b[2] );
430 }
431 
432 
433 rad50(cp,out)
434 register unsigned char *cp;
435 unsigned short *out;
436 {
437 	register index;
438 	register temp;
439 
440 	for(index = 0;*cp; index++) {
441 
442 		temp = Ain1 * table[*cp++];
443 		if(*cp!=0) {
444 			temp += Ain2 * table[*cp++];
445 
446 			if(*cp!=0)
447 				temp += table[*cp++];
448 		}
449 
450 		out[index] = temp;
451 	}
452 }
453 #define reduce(x,p,q) \
454 	(x = v[p/q], p %= q);
455 
456 unrad50(count,in,cp)
457 unsigned short *in;
458 register char *cp;
459 {
460 	register i, temp; register unsigned char *v = (unsigned char *) val;
461 
462 	for(i = 0; i < count; i++) {
463 		temp = in[i];
464 
465 		reduce (*cp++,temp,Ain1);
466 		reduce (*cp++,temp,Ain2);
467 		reduce (*cp++,temp,1);
468 	}
469 	*cp=0;
470 }
471 
472 srad50(name,rname)
473 register char * name;
474 register unsigned short *rname;
475 {
476 	register index; register char *cp;
477 	char file[7],ext[4];
478 	/*
479 	 * Find end of pathname
480 	 */
481 	for(cp = name; *cp++; );
482 	while(cp >= name && *--cp != '/');
483 	cp++;
484 	/*
485 	 * Change to rad50
486 	 *
487 	 */
488 	for(index = 0; *cp; ){
489 		file[index++] = *cp++;
490 		if(*cp=='.') {
491 			cp++;
492 			break;
493 		}
494 		if(index>=6) {
495 			break;
496 		}
497 	}
498 	file[index] = 0;
499 	for(index = 0; *cp; ){
500 		ext[index++] = *cp++;
501 		if(*cp=='.' || index>=3) {
502 			break;
503 		}
504 	}
505 	ext[index]=0;
506 	rname[0] = 0;
507 	rname[1] = 0;
508 	rname[2] = 0;
509 	rad50((unsigned char *)file,rname);
510 	rad50((unsigned char *)ext,rname+2);
511 }
512 sunrad50(name,rname)
513 unsigned short rname[3];
514 register char *name;
515 {
516 	register char *cp, *cp2;
517 	char ext[4];
518 
519 	unrad50(2,rname,name);
520 	unrad50(1,rname + 2,ext);
521 	/* Jam name and extension together with a dot
522 	   deleting white space */
523 	for(cp = name; *cp++;);--cp;  while(*--cp==' ' && cp>=name);
524 	*++cp = '.';cp++;
525 	for(cp2=ext; *cp2!=' ' && cp2 < ext + 3;) {
526 		*cp++ = *cp2++;
527 	}
528 	*cp=0;
529 	if(cp[-1]=='.') cp[-1] = 0;
530 }
531 
532 static char *oval = " ABCDEFGHIJKLMNOPQRSTUVWXYZ$.@0123456789";
533 static char *val = " abcdefghijklmnopqrstuvwxyz$.@0123456789";
534 static char table[256] = {
535 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
536 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
537 0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29,
538 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29,
539 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
540 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
541 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
542 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
543 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
544 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
545 0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29,
546 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29,
547 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
548 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
549 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
550 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29 };
551 
552 long trans(logical)
553 register int logical;
554 {
555 	/*  Logical to physical adress translation */
556 	register int sector, bytes, track;
557 
558 	logical += 26 * 128;
559 	bytes = (logical & 127);
560 	logical >>= 7;
561 	sector = logical % 26;
562 	if(sector >= 13)
563 		sector = sector *2 +1;
564 	else
565 		sector *= 2;
566 	sector += 26 + ((track = (logical / 26)) - 1) * 6;
567 	sector %= 26;
568 	return( (((track *26) + sector) << 7) + bytes);
569 }
570 lread(startad,count,obuff)
571 register startad, count;
572 register char * obuff;
573 {
574 	long trans();
575 	extern floppydes;
576 	rt_init();
577 	if(flg['m'-'a']==0)
578 		while( (count -= 128) >= 0) {
579 			lseek(floppydes, trans(startad), 0);
580 			 if (read(floppydes,obuff,128) != 128)
581 				fprintf(stderr, "arff: read error block %d\n",startad/128);
582 			obuff += 128;
583 			startad += 128;
584 		}
585 	else
586 		while( (count -= 512) >= 0) {
587 			lseek(floppydes,(long) (startad), 0);
588 				fprintf(stderr, "arff: read error block %d\n",startad/512);
589 			obuff += 512;
590 			startad += 512;
591 		}
592 }
593 lwrite(startad,count,obuff)
594 register startad, count;
595 register char * obuff;
596 {
597 	long trans();
598 	extern floppydes;
599 	rt_init();
600 	if(flg['m'-'a']==0)
601 		while( (count -= 128) >= 0) {
602 			lseek(floppydes, trans(startad), 0);
603 			if ( write(floppydes,obuff,128) != 128)
604 				fprintf(stderr, "arff: write error block %d\n",startad/128);
605 			obuff += 128;
606 			startad += 128;
607 		}
608 	else
609 		while( (count -= 512) >= 0) {
610 			lseek(floppydes,(long) (startad), 0);
611 			if ( write(floppydes,obuff,512) != 512)
612 				fprintf(stderr, "arff: write error block %d\n",startad/512);
613 			obuff += 512;
614 			startad += 512;
615 		}
616 }
617 
618 rcmd()
619 {
620 	register int i;
621 
622 	rt_init();
623 	if (namc>0)
624 		for(i = 0; i < namc; i++)
625 			if(rtr(namv[i])==0) namv[i]=0;
626 }
627 
628 rtr(name)
629 char *name;
630 {
631 	register FLDOPE *dope; register struct rt_ent *de;
632 	struct stat buf; register struct stat *bufp = &buf;
633 	int segnum;
634 	register char *last;
635 
636 	if(stat(name,bufp)<0) {
637 		perror(name);
638 		return(-1);
639 	}
640 	if(dope = lookup(name)) {
641 		/* can replace, no problem */
642 		de = dope->rtdope;
643 		if(bufp->st_size <= (de->rt_len * 512))
644 			printf("r - %s\n",name),
645 			toflop(name,bufp->st_size,dope);
646 		else {
647 			fprintf(stderr, "%s will not fit in currently used file on floppy\n",name);
648 			return(-1);
649 		}
650 	} else {
651 	    /* Search for vacant spot */
652 	    for (segnum=0; segnum != -1;    /* for all dir. segments */
653 		 segnum = rt_dir[segnum].rt_axhead.rt_nxtseg - 1) {
654 		last = rt_last + segnum*2*RT_BLOCK;
655 		for(de = rt_dir[segnum].rt_ents;
656 		    rt(de)->rt_stat != RT_ESEG; de++) {
657 			switch((de)->rt_stat) {
658 			case RT_NULL:
659 				if(bufp->st_size <= (de->rt_len * 512)) {
660 					printf("a - %s\n",name),
661 					mkent(de,segnum,bufp,name);
662 					goto found;
663 				}
664 				continue;
665 			}
666 		}
667 	    }
668 	    printf("%s: no slot for file\n", name);
669 	    return (-1);
670 	}
671 found:	if(dope=lookup(name)) {
672 		toflop(name,bufp->st_size,dope);
673 		return (0);
674 	}
675 	printf("%s: internal error, added then not found\n", name);
676 	return (-1);
677 
678 }
679 mkent(de,segnum,bufp,name)
680 register struct rt_ent *de;
681 int segnum;
682 register struct stat *bufp;
683 char *name;
684 {
685 	struct tm *localtime(); register struct tm *timp;
686 	register struct rt_ent *workp; int count;
687 
688 	count = (((bufp->st_size -1) >>9) + 1);
689 						/* Make sure there is room */
690 	if(de->rt_len==count)
691 		goto overwrite;
692 	if(rt_curend[segnum] == (rt_last + (segnum*2*RT_BLOCK))) {
693 						/* no entries left on segment */
694 		if(flg['o'-'a'])
695 			goto overwrite;
696 		fprintf(stderr,"Directory segment #%d full on  %s\n",segnum+1,
697                     defdev);
698 		exit(1);
699 	}
700 					/* copy directory entries up */
701 	for(workp = rt_curend[segnum]+1; workp > de; workp--)
702 		*workp = workp[-1];
703 	de[1].rt_len -= count;
704 	de->rt_len = count;
705 	rt_curend[segnum]++;
706 	rt_nleft--;
707 overwrite:
708 	srad50(name,de->rt_name);
709 	timp = localtime(&bufp->st_mtime);
710 	de->rt_date.rt_dy = timp->tm_mday + 1;
711 	de->rt_date.rt_mo = timp->tm_mon + 1;
712 	de->rt_date.rt_yr = timp->tm_year - 72;
713 	de->rt_stat = RT_FILE;
714 	de->rt_pad = 0;
715 	de->rt_chan = 0;
716 	de->rt_job = 0;
717 	lwrite((6+segnum*2)*RT_BLOCK,2*RT_BLOCK,(char *)&rt_dir[segnum]);
718 }
719 
720 toflop(name,ocount,dope)
721 char *name;
722 register FLDOPE *dope;
723 long ocount;
724 {
725 	register file, n, startad = dope->startad, count = ocount;
726 	char buff[512];
727 
728 	file = open(name,0);
729 	if(file < 0) {
730 		fprintf(stderr, "arff: couldn't open %s\n",name);exit(1);}
731 	for( ; count >= 512; count -= 512) {
732 		read(file,buff,512);
733 		lwrite(startad,512,buff);
734 		startad += 512;
735 	}
736 	read(file,buff,count);
737 	close(file);
738 	if(count <= 0) return;
739 	for(n = count; n < 512; n ++) buff[n] = 0;
740 	lwrite(startad,512,buff);
741 	count = (dope->rtdope->rt_len * 512 - ocount) / 512 ;
742 	if(count <= 0) return;
743 	for( ; count > 0 ; count--) {
744 		startad += 512;
745 		lwrite(startad,512,zeroes);
746 	}
747 
748 }
749 dcmd()
750 {
751 	register int i;
752 
753 	rt_init();
754 	if(namc)
755 		for(i = 0; i < namc; i++)
756 			if(rtk(namv[i])==0) namv[i]=0;
757 	if(dirdirty)
758 		scrunch();
759 
760 }
761 rtk(name)
762 char *name;
763 {
764 	register FLDOPE *dope;
765 	register struct rt_ent *de;
766 	FLDOPE *lookup();
767 
768 	if(dope = lookup(name)) {
769 		printf("d - %s\n",name);
770 		de = dope->rtdope;
771 		de->rt_stat = RT_NULL;
772 		de->rt_name[0] = 0;
773 		de->rt_name[1] = 0;
774 		de->rt_name[2] = 0;
775 		* ((unsigned short *) & (de->rt_date)) = 0;
776 		dirdirty = 1;
777 		return(0);
778 	}
779 	return(1);
780 }
781 scrunch() {
782 	register struct rt_ent *de , *workp;
783 	register segnum;
784 	for (segnum=0; segnum != -1;    /* for all dir. segments */
785 	     segnum = rt_dir[segnum].rt_axhead.rt_nxtseg - 1) {
786 	    dirdirty = 0;
787 	    for(de = rt_dir[segnum].rt_ents; de <= rt_curend[segnum]; de++) {
788 		if(de->rt_stat==RT_NULL && de[1].rt_stat==RT_NULL) {
789 			(de+1)->rt_len += de->rt_len;
790 			for(workp = de; workp < rt_curend[segnum]; workp++)
791 				*workp = workp[1];
792 			de--;
793 			rt_curend[segnum]--;
794 			rt_nleft++;
795 			dirdirty = 1;
796 		}
797 	    }
798 	    if (dirdirty)
799 	    lwrite((6+segnum*2)*RT_BLOCK,2*RT_BLOCK,(char *)&rt_dir[segnum]);
800 	}
801 }
802