xref: /csrg-svn/sys/stand.att/sys.c (revision 30547)
123243Smckusick /*
229310Smckusick  * Copyright (c) 1982, 1986 Regents of the University of California.
323243Smckusick  * All rights reserved.  The Berkeley software License Agreement
423243Smckusick  * specifies the terms and conditions for redistribution.
523243Smckusick  *
6*30547Skarels  *	@(#)sys.c	7.2 (Berkeley) 02/21/87
723243Smckusick  */
8327Sbill 
96068Smckusic #include "../h/param.h"
106068Smckusic #include "../h/inode.h"
116068Smckusic #include "../h/fs.h"
127446Sroot #include "../h/dir.h"
13*30547Skarels #include "../h/reboot.h"
14327Sbill #include "saio.h"
15327Sbill 
16327Sbill ino_t	dlook();
17327Sbill 
186068Smckusic struct dirstuff {
196068Smckusic 	int loc;
206068Smckusic 	struct iob *io;
216068Smckusic };
226068Smckusic 
23327Sbill static
2410022Ssam openi(n, io)
256068Smckusic 	register struct iob *io;
26327Sbill {
27327Sbill 	register struct dinode *dp;
2811083Ssam 	int cc;
29327Sbill 
30327Sbill 	io->i_offset = 0;
316068Smckusic 	io->i_bn = fsbtodb(&io->i_fs, itod(&io->i_fs, n)) + io->i_boff;
326068Smckusic 	io->i_cc = io->i_fs.fs_bsize;
33327Sbill 	io->i_ma = io->i_buf;
3411083Ssam 	cc = devread(io);
35327Sbill 	dp = (struct dinode *)io->i_buf;
366068Smckusic 	io->i_ino.i_ic = dp[itoo(&io->i_fs, n)].di_ic;
3711083Ssam 	return (cc);
38327Sbill }
39327Sbill 
40327Sbill static
41327Sbill find(path, file)
426068Smckusic 	register char *path;
436068Smckusic 	struct iob *file;
44327Sbill {
45327Sbill 	register char *q;
46327Sbill 	char c;
47327Sbill 	int n;
48327Sbill 
49327Sbill 	if (path==NULL || *path=='\0') {
50327Sbill 		printf("null path\n");
5110022Ssam 		return (0);
52327Sbill 	}
53327Sbill 
5411083Ssam 	if (openi((ino_t) ROOTINO, file) < 0) {
5511083Ssam 		printf("can't read root inode\n");
5611083Ssam 		return (0);
5711083Ssam 	}
58327Sbill 	while (*path) {
59327Sbill 		while (*path == '/')
60327Sbill 			path++;
61327Sbill 		q = path;
62327Sbill 		while(*q != '/' && *q != '\0')
63327Sbill 			q++;
64327Sbill 		c = *q;
65327Sbill 		*q = '\0';
6625166Skarels 		if (q == path) path = "." ;	/* "/" means "/." */
67327Sbill 
6811083Ssam 		if ((n = dlook(path, file)) != 0) {
6911083Ssam 			if (c == '\0')
70327Sbill 				break;
7111083Ssam 			if (openi(n, file) < 0)
7211083Ssam 				return (0);
73327Sbill 			*q = c;
74327Sbill 			path = q;
75327Sbill 			continue;
76327Sbill 		} else {
7725166Skarels 			printf("%s: not found\n", path);
7810022Ssam 			return (0);
79327Sbill 		}
80327Sbill 	}
8110022Ssam 	return (n);
82327Sbill }
83327Sbill 
84327Sbill static daddr_t
85327Sbill sbmap(io, bn)
866068Smckusic 	register struct iob *io;
876068Smckusic 	daddr_t bn;
88327Sbill {
89327Sbill 	register struct inode *ip;
906068Smckusic 	int i, j, sh;
91327Sbill 	daddr_t nb, *bap;
92327Sbill 
93327Sbill 	ip = &io->i_ino;
946068Smckusic 	if (bn < 0) {
95327Sbill 		printf("bn negative\n");
9610022Ssam 		return ((daddr_t)0);
97327Sbill 	}
98327Sbill 
99327Sbill 	/*
1006068Smckusic 	 * blocks 0..NDADDR are direct blocks
101327Sbill 	 */
1026068Smckusic 	if(bn < NDADDR) {
1036068Smckusic 		nb = ip->i_db[bn];
10410022Ssam 		return (nb);
105327Sbill 	}
106327Sbill 
107327Sbill 	/*
1086068Smckusic 	 * addresses NIADDR have single and double indirect blocks.
1096068Smckusic 	 * the first step is to determine how many levels of indirection.
110327Sbill 	 */
1116068Smckusic 	sh = 1;
1126068Smckusic 	bn -= NDADDR;
1136068Smckusic 	for (j = NIADDR; j > 0; j--) {
1146068Smckusic 		sh *= NINDIR(&io->i_fs);
1156068Smckusic 		if (bn < sh)
116327Sbill 			break;
1176068Smckusic 		bn -= sh;
118327Sbill 	}
1196068Smckusic 	if (j == 0) {
1206068Smckusic 		printf("bn ovf %D\n", bn);
1216068Smckusic 		return ((daddr_t)0);
122327Sbill 	}
123327Sbill 
124327Sbill 	/*
1256068Smckusic 	 * fetch the first indirect block address from the inode
126327Sbill 	 */
1276068Smckusic 	nb = ip->i_ib[NIADDR - j];
1286068Smckusic 	if (nb == 0) {
129327Sbill 		printf("bn void %D\n",bn);
13010022Ssam 		return ((daddr_t)0);
131327Sbill 	}
132327Sbill 
133327Sbill 	/*
134327Sbill 	 * fetch through the indirect blocks
135327Sbill 	 */
1366068Smckusic 	for (; j <= NIADDR; j++) {
137327Sbill 		if (blknos[j] != nb) {
1386068Smckusic 			io->i_bn = fsbtodb(&io->i_fs, nb) + io->i_boff;
139327Sbill 			io->i_ma = b[j];
1406068Smckusic 			io->i_cc = io->i_fs.fs_bsize;
14111083Ssam 			if (devread(io) != io->i_fs.fs_bsize) {
14211083Ssam 				if (io->i_error)
14311083Ssam 					errno = io->i_error;
14411083Ssam 				printf("bn %D: read error\n", io->i_bn);
14511083Ssam 				return ((daddr_t)0);
14611083Ssam 			}
147327Sbill 			blknos[j] = nb;
148327Sbill 		}
149327Sbill 		bap = (daddr_t *)b[j];
1506068Smckusic 		sh /= NINDIR(&io->i_fs);
1516068Smckusic 		i = (bn / sh) % NINDIR(&io->i_fs);
152327Sbill 		nb = bap[i];
153327Sbill 		if(nb == 0) {
154327Sbill 			printf("bn void %D\n",bn);
15510022Ssam 			return ((daddr_t)0);
156327Sbill 		}
157327Sbill 	}
15810022Ssam 	return (nb);
159327Sbill }
160327Sbill 
161327Sbill static ino_t
162327Sbill dlook(s, io)
1636068Smckusic 	char *s;
1646068Smckusic 	register struct iob *io;
165327Sbill {
166327Sbill 	register struct direct *dp;
167327Sbill 	register struct inode *ip;
1686068Smckusic 	struct dirstuff dirp;
1696068Smckusic 	int len;
170327Sbill 
1716068Smckusic 	if (s == NULL || *s == '\0')
17210022Ssam 		return (0);
173327Sbill 	ip = &io->i_ino;
1746068Smckusic 	if ((ip->i_mode&IFMT) != IFDIR) {
175327Sbill 		printf("not a directory\n");
17625166Skarels 		printf("%s: not a directory\n", s);
17710022Ssam 		return (0);
178327Sbill 	}
1796068Smckusic 	if (ip->i_size == 0) {
18025166Skarels 		printf("%s: zero length directory\n", s);
18110022Ssam 		return (0);
182327Sbill 	}
1836068Smckusic 	len = strlen(s);
1846068Smckusic 	dirp.loc = 0;
1856068Smckusic 	dirp.io = io;
1866068Smckusic 	for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) {
1876068Smckusic 		if(dp->d_ino == 0)
1886068Smckusic 			continue;
1896068Smckusic 		if (dp->d_namlen == len && !strcmp(s, dp->d_name))
19010022Ssam 			return (dp->d_ino);
191327Sbill 	}
19210022Ssam 	return (0);
193327Sbill }
194327Sbill 
1956068Smckusic /*
1966068Smckusic  * get next entry in a directory.
1976068Smckusic  */
1986068Smckusic struct direct *
1996068Smckusic readdir(dirp)
2006068Smckusic 	register struct dirstuff *dirp;
201327Sbill {
2026068Smckusic 	register struct direct *dp;
2036068Smckusic 	register struct iob *io;
2046068Smckusic 	daddr_t lbn, d;
2056068Smckusic 	int off;
206327Sbill 
2076068Smckusic 	io = dirp->io;
2086068Smckusic 	for(;;) {
2096068Smckusic 		if (dirp->loc >= io->i_ino.i_size)
21011083Ssam 			return (NULL);
2116068Smckusic 		off = blkoff(&io->i_fs, dirp->loc);
2126068Smckusic 		if (off == 0) {
2136068Smckusic 			lbn = lblkno(&io->i_fs, dirp->loc);
2146068Smckusic 			d = sbmap(io, lbn);
2156068Smckusic 			if(d == 0)
2166068Smckusic 				return NULL;
2176068Smckusic 			io->i_bn = fsbtodb(&io->i_fs, d) + io->i_boff;
2186068Smckusic 			io->i_ma = io->i_buf;
2196068Smckusic 			io->i_cc = blksize(&io->i_fs, &io->i_ino, lbn);
22011083Ssam 			if (devread(io) < 0) {
22111083Ssam 				errno = io->i_error;
22225166Skarels 				printf("bn %D: directory read error\n",
22325166Skarels 					io->i_bn);
22411083Ssam 				return (NULL);
22511083Ssam 			}
2266068Smckusic 		}
2276068Smckusic 		dp = (struct direct *)(io->i_buf + off);
2286068Smckusic 		dirp->loc += dp->d_reclen;
2296068Smckusic 		if (dp->d_ino == 0)
2306068Smckusic 			continue;
2316068Smckusic 		return (dp);
232327Sbill 	}
233327Sbill }
234327Sbill 
235327Sbill lseek(fdesc, addr, ptr)
23610022Ssam 	int fdesc, ptr;
23710022Ssam 	off_t addr;
238327Sbill {
239327Sbill 	register struct iob *io;
240327Sbill 
24125442Skarels #ifndef	SMALL
242327Sbill 	if (ptr != 0) {
243327Sbill 		printf("Seek not from beginning of file\n");
24410022Ssam 		errno = EOFFSET;
24510022Ssam 		return (-1);
246327Sbill 	}
24725442Skarels #endif SMALL
248327Sbill 	fdesc -= 3;
2496068Smckusic 	if (fdesc < 0 || fdesc >= NFILES ||
25010022Ssam 	    ((io = &iob[fdesc])->i_flgs & F_ALLOC) == 0) {
25110022Ssam 		errno = EBADF;
25210022Ssam 		return (-1);
25310022Ssam 	}
254327Sbill 	io->i_offset = addr;
2556068Smckusic 	io->i_bn = addr / DEV_BSIZE;
256327Sbill 	io->i_cc = 0;
25710022Ssam 	return (0);
258327Sbill }
259327Sbill 
260327Sbill getc(fdesc)
26110022Ssam 	int fdesc;
262327Sbill {
263327Sbill 	register struct iob *io;
2646068Smckusic 	register struct fs *fs;
265327Sbill 	register char *p;
2666068Smckusic 	int c, lbn, off, size, diff;
267327Sbill 
268327Sbill 
269327Sbill 	if (fdesc >= 0 && fdesc <= 2)
27010022Ssam 		return (getchar());
271327Sbill 	fdesc -= 3;
2726068Smckusic 	if (fdesc < 0 || fdesc >= NFILES ||
27310022Ssam 	    ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
27410022Ssam 		errno = EBADF;
27510022Ssam 		return (-1);
27610022Ssam 	}
277327Sbill 	p = io->i_ma;
278327Sbill 	if (io->i_cc <= 0) {
2796068Smckusic 		if ((io->i_flgs & F_FILE) != 0) {
2806068Smckusic 			diff = io->i_ino.i_size - io->i_offset;
2816068Smckusic 			if (diff <= 0)
2826068Smckusic 				return (-1);
2836068Smckusic 			fs = &io->i_fs;
2846068Smckusic 			lbn = lblkno(fs, io->i_offset);
2856068Smckusic 			io->i_bn = fsbtodb(fs, sbmap(io, lbn)) + io->i_boff;
2866068Smckusic 			off = blkoff(fs, io->i_offset);
2876068Smckusic 			size = blksize(fs, &io->i_ino, lbn);
2886068Smckusic 		} else {
2896068Smckusic 			io->i_bn = io->i_offset / DEV_BSIZE;
2906068Smckusic 			off = 0;
2916068Smckusic 			size = DEV_BSIZE;
2926068Smckusic 		}
293327Sbill 		io->i_ma = io->i_buf;
2946068Smckusic 		io->i_cc = size;
29511083Ssam 		if (devread(io) < 0) {
29611083Ssam 			errno = io->i_error;
29711083Ssam 			return (-1);
29811083Ssam 		}
2996068Smckusic 		if ((io->i_flgs & F_FILE) != 0) {
3006068Smckusic 			if (io->i_offset - off + size >= io->i_ino.i_size)
3016068Smckusic 				io->i_cc = diff + off;
302327Sbill 			io->i_cc -= off;
3036068Smckusic 		}
304327Sbill 		p = &io->i_buf[off];
305327Sbill 	}
306327Sbill 	io->i_cc--;
307327Sbill 	io->i_offset++;
308327Sbill 	c = (unsigned)*p++;
309327Sbill 	io->i_ma = p;
31010022Ssam 	return (c);
311327Sbill }
3126068Smckusic 
31310022Ssam int	errno;
314327Sbill 
315327Sbill read(fdesc, buf, count)
31610022Ssam 	int fdesc, count;
31710022Ssam 	char *buf;
318327Sbill {
31925166Skarels 	register i, size;
320327Sbill 	register struct iob *file;
32125166Skarels 	register struct fs *fs;
32225166Skarels 	int lbn, off;
323327Sbill 
32410022Ssam 	errno = 0;
325327Sbill 	if (fdesc >= 0 & fdesc <= 2) {
326327Sbill 		i = count;
327327Sbill 		do {
328327Sbill 			*buf = getchar();
329327Sbill 		} while (--i && *buf++ != '\n');
33010022Ssam 		return (count - i);
331327Sbill 	}
332327Sbill 	fdesc -= 3;
3336068Smckusic 	if (fdesc < 0 || fdesc >= NFILES ||
33410022Ssam 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
33510022Ssam 		errno = EBADF;
33610022Ssam 		return (-1);
33710022Ssam 	}
33810022Ssam 	if ((file->i_flgs&F_READ) == 0) {
33910022Ssam 		errno = EBADF;
34010022Ssam 		return (-1);
34110022Ssam 	}
34225442Skarels #ifndef	SMALL
3436068Smckusic 	if ((file->i_flgs & F_FILE) == 0) {
344327Sbill 		file->i_cc = count;
345327Sbill 		file->i_ma = buf;
3467446Sroot 		file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE);
347327Sbill 		i = devread(file);
34810022Ssam 		if (i < 0)
34910022Ssam 			errno = file->i_error;
350*30547Skarels 		else
351*30547Skarels 			file->i_offset += i;
35210022Ssam 		return (i);
353327Sbill 	}
35425442Skarels #endif SMALL
35525166Skarels 	if (file->i_offset+count > file->i_ino.i_size)
35625166Skarels 		count = file->i_ino.i_size - file->i_offset;
35725166Skarels 	if ((i = count) <= 0)
35825166Skarels 		return (0);
35925166Skarels 	/*
36025166Skarels 	 * While reading full blocks, do I/O into user buffer.
36125166Skarels 	 * Anything else uses getc().
36225166Skarels 	 */
36325166Skarels 	fs = &file->i_fs;
36425166Skarels 	while (i) {
36525166Skarels 		off = blkoff(fs, file->i_offset);
36625166Skarels 		lbn = lblkno(fs, file->i_offset);
36725166Skarels 		size = blksize(fs, &file->i_ino, lbn);
36825166Skarels 		if (off == 0 && size <= i) {
36925166Skarels 			file->i_bn = fsbtodb(fs, sbmap(file, lbn)) +
37025166Skarels 			    file->i_boff;
37125166Skarels 			file->i_cc = size;
37225166Skarels 			file->i_ma = buf;
37325166Skarels 			if (devread(file) < 0) {
37425166Skarels 				errno = file->i_error;
37525166Skarels 				return (-1);
37625166Skarels 			}
37725166Skarels 			file->i_offset += size;
37825166Skarels 			file->i_cc = 0;
37925166Skarels 			buf += size;
38025166Skarels 			i -= size;
38125166Skarels 		} else {
38225166Skarels 			size -= off;
38325166Skarels 			if (size > i)
38425166Skarels 				size = i;
38525166Skarels 			i -= size;
38625166Skarels 			do {
38725166Skarels 				*buf++ = getc(fdesc+3);
38825166Skarels 			} while (--size);
38925166Skarels 		}
39025166Skarels 	}
39125166Skarels 	return (count);
392327Sbill }
393327Sbill 
39425442Skarels #ifndef	SMALL
395327Sbill write(fdesc, buf, count)
39610022Ssam 	int fdesc, count;
39710022Ssam 	char *buf;
398327Sbill {
399327Sbill 	register i;
400327Sbill 	register struct iob *file;
401327Sbill 
40210022Ssam 	errno = 0;
403327Sbill 	if (fdesc >= 0 && fdesc <= 2) {
404327Sbill 		i = count;
405327Sbill 		while (i--)
406327Sbill 			putchar(*buf++);
40710022Ssam 		return (count);
408327Sbill 	}
409327Sbill 	fdesc -= 3;
4106068Smckusic 	if (fdesc < 0 || fdesc >= NFILES ||
41110022Ssam 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
41210022Ssam 		errno = EBADF;
41310022Ssam 		return (-1);
41410022Ssam 	}
41510022Ssam 	if ((file->i_flgs&F_WRITE) == 0) {
41610022Ssam 		errno = EBADF;
41710022Ssam 		return (-1);
41810022Ssam 	}
419327Sbill 	file->i_cc = count;
420327Sbill 	file->i_ma = buf;
4217446Sroot 	file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE);
422327Sbill 	i = devwrite(file);
4237446Sroot 	file->i_offset += count;
42410022Ssam 	if (i < 0)
42510022Ssam 		errno = file->i_error;
42610022Ssam 	return (i);
427327Sbill }
42825442Skarels #endif SMALL
429327Sbill 
4303349Swnj int	openfirst = 1;
431*30547Skarels unsigned opendev;		/* last device opened */
432*30547Skarels extern	unsigned bootdev;
4333349Swnj 
434327Sbill open(str, how)
4356068Smckusic 	char *str;
43610022Ssam 	int how;
437327Sbill {
438327Sbill 	register char *cp;
439*30547Skarels 	register int i;
440327Sbill 	register struct iob *file;
44110022Ssam 	int fdesc;
44210022Ssam 	long atol();
443327Sbill 
4443349Swnj 	if (openfirst) {
445327Sbill 		for (i = 0; i < NFILES; i++)
446327Sbill 			iob[i].i_flgs = 0;
4473349Swnj 		openfirst = 0;
448327Sbill 	}
449327Sbill 
450327Sbill 	for (fdesc = 0; fdesc < NFILES; fdesc++)
451327Sbill 		if (iob[fdesc].i_flgs == 0)
452327Sbill 			goto gotfile;
453327Sbill 	_stop("No more file slots");
454327Sbill gotfile:
455327Sbill 	(file = &iob[fdesc])->i_flgs |= F_ALLOC;
456327Sbill 
457*30547Skarels 	for (cp = str; *cp && *cp != '/' && *cp != ':' && *cp != '('; cp++)
458*30547Skarels 		;
459*30547Skarels 	if (*cp == '(') {
460*30547Skarels 		if ((file->i_ino.i_dev = getdev(str, cp - str)) == -1)
461*30547Skarels 			goto bad;
462*30547Skarels 		cp++;
463*30547Skarels 		if ((file->i_unit = getunit(cp)) == -1)
464*30547Skarels 			goto bad;
465*30547Skarels 		for (; *cp != ','; cp++)
466*30547Skarels 			if (*cp == NULL) {
467*30547Skarels 				errno = EOFFSET;
468*30547Skarels 				goto badspec;
469*30547Skarels 			}
470*30547Skarels 		file->i_boff = atol(cp);
471*30547Skarels 		for (;;) {
472*30547Skarels 			if (*cp == ')')
473*30547Skarels 				break;
474*30547Skarels 			if (*cp++)
475*30547Skarels 				continue;
476*30547Skarels 			goto badspec;
477*30547Skarels 		}
478*30547Skarels 	} else if (*cp != ':') {
47925166Skarels 		/* default bootstrap unit and device */
480*30547Skarels 		file->i_ino.i_dev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK;
481*30547Skarels 		file->i_unit = ((bootdev >> B_UNITSHIFT) & B_UNITMASK) +
482*30547Skarels 		     (8 * ((bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK));
483*30547Skarels 		file->i_boff = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK;
48425166Skarels 		cp = str;
48525166Skarels 	} else {
48625166Skarels # define isdigit(n)	((n>='0') && (n<='9'))
487*30547Skarels 		if (cp == str)
488*30547Skarels 			goto badspec;
48925166Skarels 		/*
49025166Skarels 	 	 * syntax for possible device name:
49125166Skarels 	 	 *	<alpha-string><digit-string><letter>:
49225166Skarels 	 	 */
49325166Skarels 		for (cp = str; *cp != ':' && !isdigit(*cp); cp++)
49425166Skarels 			;
495*30547Skarels 		if ((file->i_ino.i_dev = getdev(str, cp - str)) == -1)
496*30547Skarels 			goto bad;
497*30547Skarels 		if ((file->i_unit = getunit(cp)) == -1)
498*30547Skarels 			goto bad;
499*30547Skarels 		while (isdigit(*cp))
500*30547Skarels 			cp++;
501*30547Skarels 		file->i_boff = 0;
502*30547Skarels 		if (*cp >= 'a' && *cp <= 'h')
503*30547Skarels 			file->i_boff = *cp++ - 'a';
50425166Skarels 		if (*cp++ != ':') {
50525166Skarels 			errno = EOFFSET;
506*30547Skarels 			goto badspec;
50725166Skarels 		}
50825166Skarels 	}
509*30547Skarels 	opendev = file->i_ino.i_dev << B_TYPESHIFT;
510*30547Skarels 	opendev |= ((file->i_unit % 8) << B_UNITSHIFT);
511*30547Skarels 	opendev |= ((file->i_unit / 8) << B_ADAPTORSHIFT);
512*30547Skarels 	opendev |= file->i_boff << B_PARTITIONSHIFT;
513*30547Skarels 	if (errno = devopen(file))
514*30547Skarels 		goto bad;
51525166Skarels 	if (cp != str && *cp == '\0') {
51625166Skarels 		file->i_flgs |= how+1;
51725166Skarels 		file->i_cc = 0;
51825166Skarels 		file->i_offset = 0;
51925166Skarels 		return (fdesc+3);
52025166Skarels 	}
5216068Smckusic 	file->i_ma = (char *)(&file->i_fs);
5226068Smckusic 	file->i_cc = SBSIZE;
5237446Sroot 	file->i_bn = SBLOCK + file->i_boff;
5246068Smckusic 	file->i_offset = 0;
52511083Ssam 	if (devread(file) < 0) {
52611083Ssam 		errno = file->i_error;
52711083Ssam 		printf("super block read error\n");
528*30547Skarels 		goto bad;
52911083Ssam 	}
530327Sbill 	if ((i = find(cp, file)) == 0) {
53110022Ssam 		errno = ESRCH;
532*30547Skarels 		goto bad;
533327Sbill 	}
53425442Skarels #ifndef	SMALL
535327Sbill 	if (how != 0) {
536327Sbill 		printf("Can't write files yet.. Sorry\n");
53710022Ssam 		errno = EIO;
538*30547Skarels 		goto bad;
539327Sbill 	}
54025442Skarels #endif SMALL
54111083Ssam 	if (openi(i, file) < 0) {
54211083Ssam 		errno = file->i_error;
543*30547Skarels 		goto bad;
54411083Ssam 	}
545327Sbill 	file->i_offset = 0;
546327Sbill 	file->i_cc = 0;
547327Sbill 	file->i_flgs |= F_FILE | (how+1);
54810022Ssam 	return (fdesc+3);
549*30547Skarels 
550*30547Skarels badspec:
551*30547Skarels 	printf("malformed device specification\n");
552*30547Skarels bad:
553*30547Skarels 	file->i_flgs = 0;
554*30547Skarels 	return (-1);
555327Sbill }
556327Sbill 
557*30547Skarels static
558*30547Skarels getdev(str, len)
559*30547Skarels 	char *str;
560*30547Skarels 	int len;
561*30547Skarels {
562*30547Skarels 	register struct devsw *dp;
563*30547Skarels 
564*30547Skarels 	for (dp = devsw; dp->dv_name; dp++) {
565*30547Skarels 		if (!strncmp(str, dp->dv_name, len))
566*30547Skarels 			return (dp - devsw);
567*30547Skarels 	}
568*30547Skarels 	printf("Unknown device\n");
569*30547Skarels 	errno = ENXIO;
570*30547Skarels 	return (-1);
571*30547Skarels }
572*30547Skarels 
573*30547Skarels static
574*30547Skarels getunit(cp)
575*30547Skarels 	register char *cp;
576*30547Skarels {
577*30547Skarels 	register int i = 0;
578*30547Skarels 
579*30547Skarels 	while (*cp >= '0' && *cp <= '9')
580*30547Skarels 		i = i * 10 + *cp++ - '0';
581*30547Skarels 	if ((unsigned) i > 255) {
582*30547Skarels 		printf("minor device number out of range (0-255)\n");
583*30547Skarels 		errno = EUNIT;
584*30547Skarels 		i = -1;
585*30547Skarels 	}
586*30547Skarels 	return (i);
587*30547Skarels }
588*30547Skarels 
589327Sbill close(fdesc)
59010022Ssam 	int fdesc;
591327Sbill {
592327Sbill 	struct iob *file;
593327Sbill 
594327Sbill 	fdesc -= 3;
5956068Smckusic 	if (fdesc < 0 || fdesc >= NFILES ||
59610022Ssam 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
59710022Ssam 		errno = EBADF;
59810022Ssam 		return (-1);
59910022Ssam 	}
600327Sbill 	if ((file->i_flgs&F_FILE) == 0)
601327Sbill 		devclose(file);
602327Sbill 	file->i_flgs = 0;
60310022Ssam 	return (0);
604327Sbill }
605327Sbill 
60625442Skarels #ifndef	SMALL
60710022Ssam ioctl(fdesc, cmd, arg)
60810022Ssam 	int fdesc, cmd;
60910022Ssam 	char *arg;
61010022Ssam {
61110022Ssam 	register struct iob *file;
61210022Ssam 	int error = 0;
61310022Ssam 
61410331Shelge 	fdesc -= 3;
61510022Ssam 	if (fdesc < 0 || fdesc >= NFILES ||
61610022Ssam 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
61710022Ssam 		errno = EBADF;
61810022Ssam 		return (-1);
61910022Ssam 	}
62010022Ssam 	switch (cmd) {
62110022Ssam 
62210022Ssam 	case SAIOHDR:
62310022Ssam 		file->i_flgs |= F_HDR;
62410022Ssam 		break;
62510022Ssam 
62610022Ssam 	case SAIOCHECK:
62710022Ssam 		file->i_flgs |= F_CHECK;
62810022Ssam 		break;
62910022Ssam 
63010022Ssam 	case SAIOHCHECK:
63110022Ssam 		file->i_flgs |= F_HCHECK;
63210022Ssam 		break;
63310022Ssam 
63410331Shelge 	case SAIONOBAD:
63510331Shelge 		file->i_flgs |= F_NBSF;
63610331Shelge 		break;
63710331Shelge 
63810331Shelge 	case SAIODOBAD:
63910331Shelge 		file->i_flgs &= ~F_NBSF;
64010331Shelge 		break;
64110331Shelge 
64210022Ssam 	default:
64310022Ssam 		error = devioctl(file, cmd, arg);
64410022Ssam 		break;
64510022Ssam 	}
64610022Ssam 	if (error < 0)
64710022Ssam 		errno = file->i_error;
64810022Ssam 	return (error);
64910022Ssam }
65025442Skarels #endif SMALL
65110022Ssam 
652327Sbill exit()
653327Sbill {
654327Sbill 	_stop("Exit called");
655327Sbill }
656327Sbill 
657327Sbill _stop(s)
65810022Ssam 	char *s;
659327Sbill {
6602391Stoy 	int i;
6612391Stoy 
6622391Stoy 	for (i = 0; i < NFILES; i++)
6632391Stoy 		if (iob[i].i_flgs != 0)
6642391Stoy 			close(i);
665327Sbill 	printf("%s\n", s);
666327Sbill 	_rtt();
667327Sbill }
668