xref: /csrg-svn/sys/stand.att/sys.c (revision 33408)
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*33408Skarels  *	@(#)sys.c	7.5 (Berkeley) 01/28/88
723243Smckusick  */
8327Sbill 
930768Skarels #include "param.h"
1030768Skarels #include "inode.h"
1130768Skarels #include "fs.h"
1230768Skarels #include "dir.h"
1330768Skarels #include "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;
4630768Skarels 	char *dir;
47327Sbill 	char c;
48327Sbill 	int n;
49327Sbill 
50327Sbill 	if (path==NULL || *path=='\0') {
51327Sbill 		printf("null path\n");
5210022Ssam 		return (0);
53327Sbill 	}
54327Sbill 
5511083Ssam 	if (openi((ino_t) ROOTINO, file) < 0) {
5611083Ssam 		printf("can't read root inode\n");
5711083Ssam 		return (0);
5811083Ssam 	}
5930768Skarels 	dir = path;
60327Sbill 	while (*path) {
61327Sbill 		while (*path == '/')
62327Sbill 			path++;
63327Sbill 		q = path;
64327Sbill 		while(*q != '/' && *q != '\0')
65327Sbill 			q++;
66327Sbill 		c = *q;
67327Sbill 		*q = '\0';
6825166Skarels 		if (q == path) path = "." ;	/* "/" means "/." */
69327Sbill 
7030768Skarels 		if ((n = dlook(path, file, dir)) != 0) {
7111083Ssam 			if (c == '\0')
72327Sbill 				break;
7311083Ssam 			if (openi(n, file) < 0)
7411083Ssam 				return (0);
75327Sbill 			*q = c;
76327Sbill 			path = q;
77327Sbill 			continue;
78327Sbill 		} else {
7925166Skarels 			printf("%s: not found\n", path);
8010022Ssam 			return (0);
81327Sbill 		}
82327Sbill 	}
8310022Ssam 	return (n);
84327Sbill }
85327Sbill 
86327Sbill static daddr_t
87327Sbill sbmap(io, bn)
886068Smckusic 	register struct iob *io;
896068Smckusic 	daddr_t bn;
90327Sbill {
91327Sbill 	register struct inode *ip;
926068Smckusic 	int i, j, sh;
93327Sbill 	daddr_t nb, *bap;
94327Sbill 
95327Sbill 	ip = &io->i_ino;
966068Smckusic 	if (bn < 0) {
97327Sbill 		printf("bn negative\n");
9810022Ssam 		return ((daddr_t)0);
99327Sbill 	}
100327Sbill 
101327Sbill 	/*
1026068Smckusic 	 * blocks 0..NDADDR are direct blocks
103327Sbill 	 */
1046068Smckusic 	if(bn < NDADDR) {
1056068Smckusic 		nb = ip->i_db[bn];
10610022Ssam 		return (nb);
107327Sbill 	}
108327Sbill 
109327Sbill 	/*
1106068Smckusic 	 * addresses NIADDR have single and double indirect blocks.
1116068Smckusic 	 * the first step is to determine how many levels of indirection.
112327Sbill 	 */
1136068Smckusic 	sh = 1;
1146068Smckusic 	bn -= NDADDR;
1156068Smckusic 	for (j = NIADDR; j > 0; j--) {
1166068Smckusic 		sh *= NINDIR(&io->i_fs);
1176068Smckusic 		if (bn < sh)
118327Sbill 			break;
1196068Smckusic 		bn -= sh;
120327Sbill 	}
1216068Smckusic 	if (j == 0) {
1226068Smckusic 		printf("bn ovf %D\n", bn);
1236068Smckusic 		return ((daddr_t)0);
124327Sbill 	}
125327Sbill 
126327Sbill 	/*
1276068Smckusic 	 * fetch the first indirect block address from the inode
128327Sbill 	 */
1296068Smckusic 	nb = ip->i_ib[NIADDR - j];
1306068Smckusic 	if (nb == 0) {
131327Sbill 		printf("bn void %D\n",bn);
13210022Ssam 		return ((daddr_t)0);
133327Sbill 	}
134327Sbill 
135327Sbill 	/*
136327Sbill 	 * fetch through the indirect blocks
137327Sbill 	 */
1386068Smckusic 	for (; j <= NIADDR; j++) {
139327Sbill 		if (blknos[j] != nb) {
1406068Smckusic 			io->i_bn = fsbtodb(&io->i_fs, nb) + io->i_boff;
141327Sbill 			io->i_ma = b[j];
1426068Smckusic 			io->i_cc = io->i_fs.fs_bsize;
14311083Ssam 			if (devread(io) != io->i_fs.fs_bsize) {
14411083Ssam 				if (io->i_error)
14511083Ssam 					errno = io->i_error;
14611083Ssam 				printf("bn %D: read error\n", io->i_bn);
14711083Ssam 				return ((daddr_t)0);
14811083Ssam 			}
149327Sbill 			blknos[j] = nb;
150327Sbill 		}
151327Sbill 		bap = (daddr_t *)b[j];
1526068Smckusic 		sh /= NINDIR(&io->i_fs);
1536068Smckusic 		i = (bn / sh) % NINDIR(&io->i_fs);
154327Sbill 		nb = bap[i];
155327Sbill 		if(nb == 0) {
156327Sbill 			printf("bn void %D\n",bn);
15710022Ssam 			return ((daddr_t)0);
158327Sbill 		}
159327Sbill 	}
16010022Ssam 	return (nb);
161327Sbill }
162327Sbill 
163327Sbill static ino_t
16430768Skarels dlook(s, io, dir)
1656068Smckusic 	char *s;
1666068Smckusic 	register struct iob *io;
16730768Skarels 	char *dir;
168327Sbill {
169327Sbill 	register struct direct *dp;
170327Sbill 	register struct inode *ip;
1716068Smckusic 	struct dirstuff dirp;
1726068Smckusic 	int len;
173327Sbill 
1746068Smckusic 	if (s == NULL || *s == '\0')
17510022Ssam 		return (0);
176327Sbill 	ip = &io->i_ino;
1776068Smckusic 	if ((ip->i_mode&IFMT) != IFDIR) {
17830768Skarels 		printf("%s: not a directory\n", dir);
17910022Ssam 		return (0);
180327Sbill 	}
1816068Smckusic 	if (ip->i_size == 0) {
18230768Skarels 		printf("%s: zero length directory\n", dir);
18310022Ssam 		return (0);
184327Sbill 	}
1856068Smckusic 	len = strlen(s);
1866068Smckusic 	dirp.loc = 0;
1876068Smckusic 	dirp.io = io;
1886068Smckusic 	for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) {
1896068Smckusic 		if(dp->d_ino == 0)
1906068Smckusic 			continue;
1916068Smckusic 		if (dp->d_namlen == len && !strcmp(s, dp->d_name))
19210022Ssam 			return (dp->d_ino);
193327Sbill 	}
19410022Ssam 	return (0);
195327Sbill }
196327Sbill 
1976068Smckusic /*
1986068Smckusic  * get next entry in a directory.
1996068Smckusic  */
2006068Smckusic struct direct *
2016068Smckusic readdir(dirp)
2026068Smckusic 	register struct dirstuff *dirp;
203327Sbill {
2046068Smckusic 	register struct direct *dp;
2056068Smckusic 	register struct iob *io;
2066068Smckusic 	daddr_t lbn, d;
2076068Smckusic 	int off;
208327Sbill 
2096068Smckusic 	io = dirp->io;
2106068Smckusic 	for(;;) {
2116068Smckusic 		if (dirp->loc >= io->i_ino.i_size)
21211083Ssam 			return (NULL);
2136068Smckusic 		off = blkoff(&io->i_fs, dirp->loc);
2146068Smckusic 		if (off == 0) {
2156068Smckusic 			lbn = lblkno(&io->i_fs, dirp->loc);
2166068Smckusic 			d = sbmap(io, lbn);
2176068Smckusic 			if(d == 0)
2186068Smckusic 				return NULL;
2196068Smckusic 			io->i_bn = fsbtodb(&io->i_fs, d) + io->i_boff;
2206068Smckusic 			io->i_ma = io->i_buf;
2216068Smckusic 			io->i_cc = blksize(&io->i_fs, &io->i_ino, lbn);
22211083Ssam 			if (devread(io) < 0) {
22311083Ssam 				errno = io->i_error;
22425166Skarels 				printf("bn %D: directory read error\n",
22525166Skarels 					io->i_bn);
22611083Ssam 				return (NULL);
22711083Ssam 			}
2286068Smckusic 		}
2296068Smckusic 		dp = (struct direct *)(io->i_buf + off);
2306068Smckusic 		dirp->loc += dp->d_reclen;
2316068Smckusic 		if (dp->d_ino == 0)
2326068Smckusic 			continue;
2336068Smckusic 		return (dp);
234327Sbill 	}
235327Sbill }
236327Sbill 
237327Sbill lseek(fdesc, addr, ptr)
23810022Ssam 	int fdesc, ptr;
23910022Ssam 	off_t addr;
240327Sbill {
241327Sbill 	register struct iob *io;
242327Sbill 
24325442Skarels #ifndef	SMALL
244327Sbill 	if (ptr != 0) {
245327Sbill 		printf("Seek not from beginning of file\n");
24610022Ssam 		errno = EOFFSET;
24710022Ssam 		return (-1);
248327Sbill 	}
24925442Skarels #endif SMALL
250327Sbill 	fdesc -= 3;
2516068Smckusic 	if (fdesc < 0 || fdesc >= NFILES ||
25210022Ssam 	    ((io = &iob[fdesc])->i_flgs & F_ALLOC) == 0) {
25310022Ssam 		errno = EBADF;
25410022Ssam 		return (-1);
25510022Ssam 	}
256327Sbill 	io->i_offset = addr;
2576068Smckusic 	io->i_bn = addr / DEV_BSIZE;
258327Sbill 	io->i_cc = 0;
25910022Ssam 	return (0);
260327Sbill }
261327Sbill 
262327Sbill getc(fdesc)
26310022Ssam 	int fdesc;
264327Sbill {
265327Sbill 	register struct iob *io;
2666068Smckusic 	register struct fs *fs;
267327Sbill 	register char *p;
2686068Smckusic 	int c, lbn, off, size, diff;
269327Sbill 
270327Sbill 
271327Sbill 	if (fdesc >= 0 && fdesc <= 2)
27210022Ssam 		return (getchar());
273327Sbill 	fdesc -= 3;
2746068Smckusic 	if (fdesc < 0 || fdesc >= NFILES ||
27510022Ssam 	    ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
27610022Ssam 		errno = EBADF;
27710022Ssam 		return (-1);
27810022Ssam 	}
279327Sbill 	p = io->i_ma;
280327Sbill 	if (io->i_cc <= 0) {
2816068Smckusic 		if ((io->i_flgs & F_FILE) != 0) {
2826068Smckusic 			diff = io->i_ino.i_size - io->i_offset;
2836068Smckusic 			if (diff <= 0)
2846068Smckusic 				return (-1);
2856068Smckusic 			fs = &io->i_fs;
2866068Smckusic 			lbn = lblkno(fs, io->i_offset);
2876068Smckusic 			io->i_bn = fsbtodb(fs, sbmap(io, lbn)) + io->i_boff;
2886068Smckusic 			off = blkoff(fs, io->i_offset);
2896068Smckusic 			size = blksize(fs, &io->i_ino, lbn);
2906068Smckusic 		} else {
2916068Smckusic 			io->i_bn = io->i_offset / DEV_BSIZE;
2926068Smckusic 			off = 0;
2936068Smckusic 			size = DEV_BSIZE;
2946068Smckusic 		}
295327Sbill 		io->i_ma = io->i_buf;
2966068Smckusic 		io->i_cc = size;
29711083Ssam 		if (devread(io) < 0) {
29811083Ssam 			errno = io->i_error;
29911083Ssam 			return (-1);
30011083Ssam 		}
3016068Smckusic 		if ((io->i_flgs & F_FILE) != 0) {
3026068Smckusic 			if (io->i_offset - off + size >= io->i_ino.i_size)
3036068Smckusic 				io->i_cc = diff + off;
304327Sbill 			io->i_cc -= off;
3056068Smckusic 		}
306327Sbill 		p = &io->i_buf[off];
307327Sbill 	}
308327Sbill 	io->i_cc--;
309327Sbill 	io->i_offset++;
310327Sbill 	c = (unsigned)*p++;
311327Sbill 	io->i_ma = p;
31210022Ssam 	return (c);
313327Sbill }
3146068Smckusic 
31510022Ssam int	errno;
316327Sbill 
317327Sbill read(fdesc, buf, count)
31810022Ssam 	int fdesc, count;
31910022Ssam 	char *buf;
320327Sbill {
32125166Skarels 	register i, size;
322327Sbill 	register struct iob *file;
32325166Skarels 	register struct fs *fs;
32425166Skarels 	int lbn, off;
325327Sbill 
32610022Ssam 	errno = 0;
327327Sbill 	if (fdesc >= 0 & fdesc <= 2) {
328327Sbill 		i = count;
329327Sbill 		do {
330327Sbill 			*buf = getchar();
331327Sbill 		} while (--i && *buf++ != '\n');
33210022Ssam 		return (count - i);
333327Sbill 	}
334327Sbill 	fdesc -= 3;
3356068Smckusic 	if (fdesc < 0 || fdesc >= NFILES ||
33610022Ssam 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
33710022Ssam 		errno = EBADF;
33810022Ssam 		return (-1);
33910022Ssam 	}
34010022Ssam 	if ((file->i_flgs&F_READ) == 0) {
34110022Ssam 		errno = EBADF;
34210022Ssam 		return (-1);
34310022Ssam 	}
34425442Skarels #ifndef	SMALL
3456068Smckusic 	if ((file->i_flgs & F_FILE) == 0) {
346327Sbill 		file->i_cc = count;
347327Sbill 		file->i_ma = buf;
3487446Sroot 		file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE);
349327Sbill 		i = devread(file);
35010022Ssam 		if (i < 0)
35110022Ssam 			errno = file->i_error;
35230547Skarels 		else
35330547Skarels 			file->i_offset += i;
35410022Ssam 		return (i);
355327Sbill 	}
35625442Skarels #endif SMALL
35725166Skarels 	if (file->i_offset+count > file->i_ino.i_size)
35825166Skarels 		count = file->i_ino.i_size - file->i_offset;
35925166Skarels 	if ((i = count) <= 0)
36025166Skarels 		return (0);
36125166Skarels 	/*
36225166Skarels 	 * While reading full blocks, do I/O into user buffer.
36325166Skarels 	 * Anything else uses getc().
36425166Skarels 	 */
36525166Skarels 	fs = &file->i_fs;
36625166Skarels 	while (i) {
36725166Skarels 		off = blkoff(fs, file->i_offset);
36825166Skarels 		lbn = lblkno(fs, file->i_offset);
36925166Skarels 		size = blksize(fs, &file->i_ino, lbn);
37025166Skarels 		if (off == 0 && size <= i) {
37125166Skarels 			file->i_bn = fsbtodb(fs, sbmap(file, lbn)) +
37225166Skarels 			    file->i_boff;
37325166Skarels 			file->i_cc = size;
37425166Skarels 			file->i_ma = buf;
37525166Skarels 			if (devread(file) < 0) {
37625166Skarels 				errno = file->i_error;
37725166Skarels 				return (-1);
37825166Skarels 			}
37925166Skarels 			file->i_offset += size;
38025166Skarels 			file->i_cc = 0;
38125166Skarels 			buf += size;
38225166Skarels 			i -= size;
38325166Skarels 		} else {
38425166Skarels 			size -= off;
38525166Skarels 			if (size > i)
38625166Skarels 				size = i;
38725166Skarels 			i -= size;
38825166Skarels 			do {
38925166Skarels 				*buf++ = getc(fdesc+3);
39025166Skarels 			} while (--size);
39125166Skarels 		}
39225166Skarels 	}
39325166Skarels 	return (count);
394327Sbill }
395327Sbill 
39625442Skarels #ifndef	SMALL
397327Sbill write(fdesc, buf, count)
39810022Ssam 	int fdesc, count;
39910022Ssam 	char *buf;
400327Sbill {
401327Sbill 	register i;
402327Sbill 	register struct iob *file;
403327Sbill 
40410022Ssam 	errno = 0;
405327Sbill 	if (fdesc >= 0 && fdesc <= 2) {
406327Sbill 		i = count;
407327Sbill 		while (i--)
408327Sbill 			putchar(*buf++);
40910022Ssam 		return (count);
410327Sbill 	}
411327Sbill 	fdesc -= 3;
4126068Smckusic 	if (fdesc < 0 || fdesc >= NFILES ||
41310022Ssam 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
41410022Ssam 		errno = EBADF;
41510022Ssam 		return (-1);
41610022Ssam 	}
41710022Ssam 	if ((file->i_flgs&F_WRITE) == 0) {
41810022Ssam 		errno = EBADF;
41910022Ssam 		return (-1);
42010022Ssam 	}
421327Sbill 	file->i_cc = count;
422327Sbill 	file->i_ma = buf;
4237446Sroot 	file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE);
424327Sbill 	i = devwrite(file);
4257446Sroot 	file->i_offset += count;
42610022Ssam 	if (i < 0)
42710022Ssam 		errno = file->i_error;
42810022Ssam 	return (i);
429327Sbill }
43025442Skarels #endif SMALL
431327Sbill 
4323349Swnj int	openfirst = 1;
43330547Skarels unsigned opendev;		/* last device opened */
43430547Skarels extern	unsigned bootdev;
4353349Swnj 
436327Sbill open(str, how)
4376068Smckusic 	char *str;
43810022Ssam 	int how;
439327Sbill {
440327Sbill 	register char *cp;
44130547Skarels 	register int i;
442327Sbill 	register struct iob *file;
44310022Ssam 	int fdesc;
44410022Ssam 	long atol();
445327Sbill 
4463349Swnj 	if (openfirst) {
447327Sbill 		for (i = 0; i < NFILES; i++)
448327Sbill 			iob[i].i_flgs = 0;
4493349Swnj 		openfirst = 0;
450327Sbill 	}
451327Sbill 
452327Sbill 	for (fdesc = 0; fdesc < NFILES; fdesc++)
453327Sbill 		if (iob[fdesc].i_flgs == 0)
454327Sbill 			goto gotfile;
455327Sbill 	_stop("No more file slots");
456327Sbill gotfile:
457327Sbill 	(file = &iob[fdesc])->i_flgs |= F_ALLOC;
458327Sbill 
45930924Skarels #ifndef	SMALL
46030547Skarels 	for (cp = str; *cp && *cp != '/' && *cp != ':' && *cp != '('; cp++)
46130547Skarels 		;
46230547Skarels 	if (*cp == '(') {
46330547Skarels 		if ((file->i_ino.i_dev = getdev(str, cp - str)) == -1)
46430547Skarels 			goto bad;
46530547Skarels 		cp++;
46630547Skarels 		if ((file->i_unit = getunit(cp)) == -1)
46730547Skarels 			goto bad;
46830547Skarels 		for (; *cp != ','; cp++)
469*33408Skarels 			if (*cp == 0) {
47030547Skarels 				errno = EOFFSET;
47130547Skarels 				goto badspec;
47230547Skarels 			}
47330768Skarels 		file->i_boff = atol(++cp);
47430547Skarels 		for (;;) {
47530547Skarels 			if (*cp == ')')
47630547Skarels 				break;
47730547Skarels 			if (*cp++)
47830547Skarels 				continue;
47930547Skarels 			goto badspec;
48030547Skarels 		}
48130768Skarels 		cp++;
48230547Skarels 	} else if (*cp != ':') {
48330924Skarels #endif
48425166Skarels 		/* default bootstrap unit and device */
48530547Skarels 		file->i_ino.i_dev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK;
48630547Skarels 		file->i_unit = ((bootdev >> B_UNITSHIFT) & B_UNITMASK) +
48730547Skarels 		     (8 * ((bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK));
48830547Skarels 		file->i_boff = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK;
48925166Skarels 		cp = str;
49030924Skarels #ifndef	SMALL
49125166Skarels 	} else {
49225166Skarels # define isdigit(n)	((n>='0') && (n<='9'))
49330547Skarels 		if (cp == str)
49430547Skarels 			goto badspec;
49525166Skarels 		/*
49625166Skarels 	 	 * syntax for possible device name:
49725166Skarels 	 	 *	<alpha-string><digit-string><letter>:
49825166Skarels 	 	 */
49925166Skarels 		for (cp = str; *cp != ':' && !isdigit(*cp); cp++)
50025166Skarels 			;
50130547Skarels 		if ((file->i_ino.i_dev = getdev(str, cp - str)) == -1)
50230547Skarels 			goto bad;
50330547Skarels 		if ((file->i_unit = getunit(cp)) == -1)
50430547Skarels 			goto bad;
50530547Skarels 		while (isdigit(*cp))
50630547Skarels 			cp++;
50730547Skarels 		file->i_boff = 0;
50830547Skarels 		if (*cp >= 'a' && *cp <= 'h')
50930547Skarels 			file->i_boff = *cp++ - 'a';
51025166Skarels 		if (*cp++ != ':') {
51125166Skarels 			errno = EOFFSET;
51230547Skarels 			goto badspec;
51325166Skarels 		}
51425166Skarels 	}
51530924Skarels #endif
51630547Skarels 	opendev = file->i_ino.i_dev << B_TYPESHIFT;
517*33408Skarels 	opendev |= (file->i_unit % 8) << B_UNITSHIFT;
518*33408Skarels 	opendev |= (file->i_unit / 8) << B_ADAPTORSHIFT;
51930547Skarels 	opendev |= file->i_boff << B_PARTITIONSHIFT;
52030768Skarels 	opendev |= B_DEVMAGIC;
52130547Skarels 	if (errno = devopen(file))
52230547Skarels 		goto bad;
523*33408Skarels #ifndef SMALL
52425166Skarels 	if (cp != str && *cp == '\0') {
52525166Skarels 		file->i_flgs |= how+1;
52625166Skarels 		file->i_cc = 0;
52725166Skarels 		file->i_offset = 0;
52825166Skarels 		return (fdesc+3);
52925166Skarels 	}
530*33408Skarels #endif
5316068Smckusic 	file->i_ma = (char *)(&file->i_fs);
5326068Smckusic 	file->i_cc = SBSIZE;
53330768Skarels 	file->i_bn = SBOFF / DEV_BSIZE + file->i_boff;
5346068Smckusic 	file->i_offset = 0;
53511083Ssam 	if (devread(file) < 0) {
53611083Ssam 		errno = file->i_error;
53711083Ssam 		printf("super block read error\n");
53830547Skarels 		goto bad;
53911083Ssam 	}
540327Sbill 	if ((i = find(cp, file)) == 0) {
54110022Ssam 		errno = ESRCH;
54230547Skarels 		goto bad;
543327Sbill 	}
54425442Skarels #ifndef	SMALL
545327Sbill 	if (how != 0) {
546327Sbill 		printf("Can't write files yet.. Sorry\n");
54710022Ssam 		errno = EIO;
54830547Skarels 		goto bad;
549327Sbill 	}
55025442Skarels #endif SMALL
55111083Ssam 	if (openi(i, file) < 0) {
55211083Ssam 		errno = file->i_error;
55330547Skarels 		goto bad;
55411083Ssam 	}
555327Sbill 	file->i_offset = 0;
556327Sbill 	file->i_cc = 0;
557327Sbill 	file->i_flgs |= F_FILE | (how+1);
55810022Ssam 	return (fdesc+3);
55930547Skarels 
560*33408Skarels #ifndef SMALL
56130547Skarels badspec:
56230547Skarels 	printf("malformed device specification\n");
563*33408Skarels #endif
56430547Skarels bad:
56530547Skarels 	file->i_flgs = 0;
56630547Skarels 	return (-1);
567327Sbill }
568327Sbill 
56930924Skarels #ifndef SMALL
57030547Skarels static
57130547Skarels getdev(str, len)
572*33408Skarels 	register char *str;
57330547Skarels 	int len;
57430547Skarels {
57530547Skarels 	register struct devsw *dp;
576*33408Skarels 	register int i;
577*33408Skarels 	char c = str[len];
57830547Skarels 
579*33408Skarels 	str[len] = 0;
580*33408Skarels 	for (dp = devsw, i = 0; i < ndevs; dp++, i++)
581*33408Skarels 		if (dp->dv_name && strcmp(str, dp->dv_name) == 0) {
582*33408Skarels 			str[len] = c;
583*33408Skarels 			return (i);
584*33408Skarels 		}
585*33408Skarels 	printf("Unknown device\nKnown devices are:\n");
586*33408Skarels 	for (dp = devsw, i = 0; i < ndevs; dp++, i++)
587*33408Skarels 		if (dp->dv_name)
588*33408Skarels 			printf(" %s", dp->dv_name);
58930547Skarels 	errno = ENXIO;
59030547Skarels 	return (-1);
59130547Skarels }
59230547Skarels 
59330547Skarels static
59430547Skarels getunit(cp)
59530547Skarels 	register char *cp;
59630547Skarels {
59730547Skarels 	register int i = 0;
59830547Skarels 
59930547Skarels 	while (*cp >= '0' && *cp <= '9')
60030547Skarels 		i = i * 10 + *cp++ - '0';
60130547Skarels 	if ((unsigned) i > 255) {
60230547Skarels 		printf("minor device number out of range (0-255)\n");
60330547Skarels 		errno = EUNIT;
60430547Skarels 		i = -1;
60530547Skarels 	}
60630547Skarels 	return (i);
60730547Skarels }
60830924Skarels #endif
60930547Skarels 
610327Sbill close(fdesc)
61110022Ssam 	int fdesc;
612327Sbill {
613327Sbill 	struct iob *file;
614327Sbill 
615327Sbill 	fdesc -= 3;
6166068Smckusic 	if (fdesc < 0 || fdesc >= NFILES ||
61710022Ssam 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
61810022Ssam 		errno = EBADF;
61910022Ssam 		return (-1);
62010022Ssam 	}
621327Sbill 	if ((file->i_flgs&F_FILE) == 0)
622327Sbill 		devclose(file);
623327Sbill 	file->i_flgs = 0;
62410022Ssam 	return (0);
625327Sbill }
626327Sbill 
62725442Skarels #ifndef	SMALL
62810022Ssam ioctl(fdesc, cmd, arg)
62910022Ssam 	int fdesc, cmd;
63010022Ssam 	char *arg;
63110022Ssam {
63210022Ssam 	register struct iob *file;
63310022Ssam 	int error = 0;
63410022Ssam 
63510331Shelge 	fdesc -= 3;
63610022Ssam 	if (fdesc < 0 || fdesc >= NFILES ||
63710022Ssam 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
63810022Ssam 		errno = EBADF;
63910022Ssam 		return (-1);
64010022Ssam 	}
64110022Ssam 	switch (cmd) {
64210022Ssam 
64310022Ssam 	case SAIOHDR:
64410022Ssam 		file->i_flgs |= F_HDR;
64510022Ssam 		break;
64610022Ssam 
64710022Ssam 	case SAIOCHECK:
64810022Ssam 		file->i_flgs |= F_CHECK;
64910022Ssam 		break;
65010022Ssam 
65110022Ssam 	case SAIOHCHECK:
65210022Ssam 		file->i_flgs |= F_HCHECK;
65310022Ssam 		break;
65410022Ssam 
65510331Shelge 	case SAIONOBAD:
65610331Shelge 		file->i_flgs |= F_NBSF;
65710331Shelge 		break;
65810331Shelge 
65910331Shelge 	case SAIODOBAD:
66010331Shelge 		file->i_flgs &= ~F_NBSF;
66110331Shelge 		break;
66210331Shelge 
66310022Ssam 	default:
66410022Ssam 		error = devioctl(file, cmd, arg);
66510022Ssam 		break;
66610022Ssam 	}
66710022Ssam 	if (error < 0)
66810022Ssam 		errno = file->i_error;
66910022Ssam 	return (error);
67010022Ssam }
67125442Skarels #endif SMALL
67210022Ssam 
673327Sbill exit()
674327Sbill {
675327Sbill 	_stop("Exit called");
676327Sbill }
677327Sbill 
678327Sbill _stop(s)
67910022Ssam 	char *s;
680327Sbill {
6812391Stoy 	int i;
6822391Stoy 
6832391Stoy 	for (i = 0; i < NFILES; i++)
6842391Stoy 		if (iob[i].i_flgs != 0)
6852391Stoy 			close(i);
686327Sbill 	printf("%s\n", s);
687327Sbill 	_rtt();
688327Sbill }
689