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