xref: /csrg-svn/sys/stand.att/sys.c (revision 30768)
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*30768Skarels  *	@(#)sys.c	7.3 (Berkeley) 04/02/87
723243Smckusick  */
8327Sbill 
9*30768Skarels #include "param.h"
10*30768Skarels #include "inode.h"
11*30768Skarels #include "fs.h"
12*30768Skarels #include "dir.h"
13*30768Skarels #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;
46*30768Skarels 	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 	}
59*30768Skarels 	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 
70*30768Skarels 		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
164*30768Skarels dlook(s, io, dir)
1656068Smckusic 	char *s;
1666068Smckusic 	register struct iob *io;
167*30768Skarels 	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) {
178327Sbill 		printf("not a directory\n");
179*30768Skarels 		printf("%s: not a directory\n", dir);
18010022Ssam 		return (0);
181327Sbill 	}
1826068Smckusic 	if (ip->i_size == 0) {
183*30768Skarels 		printf("%s: zero length directory\n", dir);
18410022Ssam 		return (0);
185327Sbill 	}
1866068Smckusic 	len = strlen(s);
1876068Smckusic 	dirp.loc = 0;
1886068Smckusic 	dirp.io = io;
1896068Smckusic 	for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) {
1906068Smckusic 		if(dp->d_ino == 0)
1916068Smckusic 			continue;
1926068Smckusic 		if (dp->d_namlen == len && !strcmp(s, dp->d_name))
19310022Ssam 			return (dp->d_ino);
194327Sbill 	}
19510022Ssam 	return (0);
196327Sbill }
197327Sbill 
1986068Smckusic /*
1996068Smckusic  * get next entry in a directory.
2006068Smckusic  */
2016068Smckusic struct direct *
2026068Smckusic readdir(dirp)
2036068Smckusic 	register struct dirstuff *dirp;
204327Sbill {
2056068Smckusic 	register struct direct *dp;
2066068Smckusic 	register struct iob *io;
2076068Smckusic 	daddr_t lbn, d;
2086068Smckusic 	int off;
209327Sbill 
2106068Smckusic 	io = dirp->io;
2116068Smckusic 	for(;;) {
2126068Smckusic 		if (dirp->loc >= io->i_ino.i_size)
21311083Ssam 			return (NULL);
2146068Smckusic 		off = blkoff(&io->i_fs, dirp->loc);
2156068Smckusic 		if (off == 0) {
2166068Smckusic 			lbn = lblkno(&io->i_fs, dirp->loc);
2176068Smckusic 			d = sbmap(io, lbn);
2186068Smckusic 			if(d == 0)
2196068Smckusic 				return NULL;
2206068Smckusic 			io->i_bn = fsbtodb(&io->i_fs, d) + io->i_boff;
2216068Smckusic 			io->i_ma = io->i_buf;
2226068Smckusic 			io->i_cc = blksize(&io->i_fs, &io->i_ino, lbn);
22311083Ssam 			if (devread(io) < 0) {
22411083Ssam 				errno = io->i_error;
22525166Skarels 				printf("bn %D: directory read error\n",
22625166Skarels 					io->i_bn);
22711083Ssam 				return (NULL);
22811083Ssam 			}
2296068Smckusic 		}
2306068Smckusic 		dp = (struct direct *)(io->i_buf + off);
2316068Smckusic 		dirp->loc += dp->d_reclen;
2326068Smckusic 		if (dp->d_ino == 0)
2336068Smckusic 			continue;
2346068Smckusic 		return (dp);
235327Sbill 	}
236327Sbill }
237327Sbill 
238327Sbill lseek(fdesc, addr, ptr)
23910022Ssam 	int fdesc, ptr;
24010022Ssam 	off_t addr;
241327Sbill {
242327Sbill 	register struct iob *io;
243327Sbill 
24425442Skarels #ifndef	SMALL
245327Sbill 	if (ptr != 0) {
246327Sbill 		printf("Seek not from beginning of file\n");
24710022Ssam 		errno = EOFFSET;
24810022Ssam 		return (-1);
249327Sbill 	}
25025442Skarels #endif SMALL
251327Sbill 	fdesc -= 3;
2526068Smckusic 	if (fdesc < 0 || fdesc >= NFILES ||
25310022Ssam 	    ((io = &iob[fdesc])->i_flgs & F_ALLOC) == 0) {
25410022Ssam 		errno = EBADF;
25510022Ssam 		return (-1);
25610022Ssam 	}
257327Sbill 	io->i_offset = addr;
2586068Smckusic 	io->i_bn = addr / DEV_BSIZE;
259327Sbill 	io->i_cc = 0;
26010022Ssam 	return (0);
261327Sbill }
262327Sbill 
263327Sbill getc(fdesc)
26410022Ssam 	int fdesc;
265327Sbill {
266327Sbill 	register struct iob *io;
2676068Smckusic 	register struct fs *fs;
268327Sbill 	register char *p;
2696068Smckusic 	int c, lbn, off, size, diff;
270327Sbill 
271327Sbill 
272327Sbill 	if (fdesc >= 0 && fdesc <= 2)
27310022Ssam 		return (getchar());
274327Sbill 	fdesc -= 3;
2756068Smckusic 	if (fdesc < 0 || fdesc >= NFILES ||
27610022Ssam 	    ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
27710022Ssam 		errno = EBADF;
27810022Ssam 		return (-1);
27910022Ssam 	}
280327Sbill 	p = io->i_ma;
281327Sbill 	if (io->i_cc <= 0) {
2826068Smckusic 		if ((io->i_flgs & F_FILE) != 0) {
2836068Smckusic 			diff = io->i_ino.i_size - io->i_offset;
2846068Smckusic 			if (diff <= 0)
2856068Smckusic 				return (-1);
2866068Smckusic 			fs = &io->i_fs;
2876068Smckusic 			lbn = lblkno(fs, io->i_offset);
2886068Smckusic 			io->i_bn = fsbtodb(fs, sbmap(io, lbn)) + io->i_boff;
2896068Smckusic 			off = blkoff(fs, io->i_offset);
2906068Smckusic 			size = blksize(fs, &io->i_ino, lbn);
2916068Smckusic 		} else {
2926068Smckusic 			io->i_bn = io->i_offset / DEV_BSIZE;
2936068Smckusic 			off = 0;
2946068Smckusic 			size = DEV_BSIZE;
2956068Smckusic 		}
296327Sbill 		io->i_ma = io->i_buf;
2976068Smckusic 		io->i_cc = size;
29811083Ssam 		if (devread(io) < 0) {
29911083Ssam 			errno = io->i_error;
30011083Ssam 			return (-1);
30111083Ssam 		}
3026068Smckusic 		if ((io->i_flgs & F_FILE) != 0) {
3036068Smckusic 			if (io->i_offset - off + size >= io->i_ino.i_size)
3046068Smckusic 				io->i_cc = diff + off;
305327Sbill 			io->i_cc -= off;
3066068Smckusic 		}
307327Sbill 		p = &io->i_buf[off];
308327Sbill 	}
309327Sbill 	io->i_cc--;
310327Sbill 	io->i_offset++;
311327Sbill 	c = (unsigned)*p++;
312327Sbill 	io->i_ma = p;
31310022Ssam 	return (c);
314327Sbill }
3156068Smckusic 
31610022Ssam int	errno;
317327Sbill 
318327Sbill read(fdesc, buf, count)
31910022Ssam 	int fdesc, count;
32010022Ssam 	char *buf;
321327Sbill {
32225166Skarels 	register i, size;
323327Sbill 	register struct iob *file;
32425166Skarels 	register struct fs *fs;
32525166Skarels 	int lbn, off;
326327Sbill 
32710022Ssam 	errno = 0;
328327Sbill 	if (fdesc >= 0 & fdesc <= 2) {
329327Sbill 		i = count;
330327Sbill 		do {
331327Sbill 			*buf = getchar();
332327Sbill 		} while (--i && *buf++ != '\n');
33310022Ssam 		return (count - i);
334327Sbill 	}
335327Sbill 	fdesc -= 3;
3366068Smckusic 	if (fdesc < 0 || fdesc >= NFILES ||
33710022Ssam 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
33810022Ssam 		errno = EBADF;
33910022Ssam 		return (-1);
34010022Ssam 	}
34110022Ssam 	if ((file->i_flgs&F_READ) == 0) {
34210022Ssam 		errno = EBADF;
34310022Ssam 		return (-1);
34410022Ssam 	}
34525442Skarels #ifndef	SMALL
3466068Smckusic 	if ((file->i_flgs & F_FILE) == 0) {
347327Sbill 		file->i_cc = count;
348327Sbill 		file->i_ma = buf;
3497446Sroot 		file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE);
350327Sbill 		i = devread(file);
35110022Ssam 		if (i < 0)
35210022Ssam 			errno = file->i_error;
35330547Skarels 		else
35430547Skarels 			file->i_offset += i;
35510022Ssam 		return (i);
356327Sbill 	}
35725442Skarels #endif SMALL
35825166Skarels 	if (file->i_offset+count > file->i_ino.i_size)
35925166Skarels 		count = file->i_ino.i_size - file->i_offset;
36025166Skarels 	if ((i = count) <= 0)
36125166Skarels 		return (0);
36225166Skarels 	/*
36325166Skarels 	 * While reading full blocks, do I/O into user buffer.
36425166Skarels 	 * Anything else uses getc().
36525166Skarels 	 */
36625166Skarels 	fs = &file->i_fs;
36725166Skarels 	while (i) {
36825166Skarels 		off = blkoff(fs, file->i_offset);
36925166Skarels 		lbn = lblkno(fs, file->i_offset);
37025166Skarels 		size = blksize(fs, &file->i_ino, lbn);
37125166Skarels 		if (off == 0 && size <= i) {
37225166Skarels 			file->i_bn = fsbtodb(fs, sbmap(file, lbn)) +
37325166Skarels 			    file->i_boff;
37425166Skarels 			file->i_cc = size;
37525166Skarels 			file->i_ma = buf;
37625166Skarels 			if (devread(file) < 0) {
37725166Skarels 				errno = file->i_error;
37825166Skarels 				return (-1);
37925166Skarels 			}
38025166Skarels 			file->i_offset += size;
38125166Skarels 			file->i_cc = 0;
38225166Skarels 			buf += size;
38325166Skarels 			i -= size;
38425166Skarels 		} else {
38525166Skarels 			size -= off;
38625166Skarels 			if (size > i)
38725166Skarels 				size = i;
38825166Skarels 			i -= size;
38925166Skarels 			do {
39025166Skarels 				*buf++ = getc(fdesc+3);
39125166Skarels 			} while (--size);
39225166Skarels 		}
39325166Skarels 	}
39425166Skarels 	return (count);
395327Sbill }
396327Sbill 
39725442Skarels #ifndef	SMALL
398327Sbill write(fdesc, buf, count)
39910022Ssam 	int fdesc, count;
40010022Ssam 	char *buf;
401327Sbill {
402327Sbill 	register i;
403327Sbill 	register struct iob *file;
404327Sbill 
40510022Ssam 	errno = 0;
406327Sbill 	if (fdesc >= 0 && fdesc <= 2) {
407327Sbill 		i = count;
408327Sbill 		while (i--)
409327Sbill 			putchar(*buf++);
41010022Ssam 		return (count);
411327Sbill 	}
412327Sbill 	fdesc -= 3;
4136068Smckusic 	if (fdesc < 0 || fdesc >= NFILES ||
41410022Ssam 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
41510022Ssam 		errno = EBADF;
41610022Ssam 		return (-1);
41710022Ssam 	}
41810022Ssam 	if ((file->i_flgs&F_WRITE) == 0) {
41910022Ssam 		errno = EBADF;
42010022Ssam 		return (-1);
42110022Ssam 	}
422327Sbill 	file->i_cc = count;
423327Sbill 	file->i_ma = buf;
4247446Sroot 	file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE);
425327Sbill 	i = devwrite(file);
4267446Sroot 	file->i_offset += count;
42710022Ssam 	if (i < 0)
42810022Ssam 		errno = file->i_error;
42910022Ssam 	return (i);
430327Sbill }
43125442Skarels #endif SMALL
432327Sbill 
4333349Swnj int	openfirst = 1;
43430547Skarels unsigned opendev;		/* last device opened */
43530547Skarels extern	unsigned bootdev;
4363349Swnj 
437327Sbill open(str, how)
4386068Smckusic 	char *str;
43910022Ssam 	int how;
440327Sbill {
441327Sbill 	register char *cp;
44230547Skarels 	register int i;
443327Sbill 	register struct iob *file;
44410022Ssam 	int fdesc;
44510022Ssam 	long atol();
446327Sbill 
4473349Swnj 	if (openfirst) {
448327Sbill 		for (i = 0; i < NFILES; i++)
449327Sbill 			iob[i].i_flgs = 0;
4503349Swnj 		openfirst = 0;
451327Sbill 	}
452327Sbill 
453327Sbill 	for (fdesc = 0; fdesc < NFILES; fdesc++)
454327Sbill 		if (iob[fdesc].i_flgs == 0)
455327Sbill 			goto gotfile;
456327Sbill 	_stop("No more file slots");
457327Sbill gotfile:
458327Sbill 	(file = &iob[fdesc])->i_flgs |= F_ALLOC;
459327Sbill 
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++)
46930547Skarels 			if (*cp == NULL) {
47030547Skarels 				errno = EOFFSET;
47130547Skarels 				goto badspec;
47230547Skarels 			}
473*30768Skarels 		file->i_boff = atol(++cp);
47430547Skarels 		for (;;) {
47530547Skarels 			if (*cp == ')')
47630547Skarels 				break;
47730547Skarels 			if (*cp++)
47830547Skarels 				continue;
47930547Skarels 			goto badspec;
48030547Skarels 		}
481*30768Skarels 		cp++;
48230547Skarels 	} else if (*cp != ':') {
48325166Skarels 		/* default bootstrap unit and device */
48430547Skarels 		file->i_ino.i_dev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK;
48530547Skarels 		file->i_unit = ((bootdev >> B_UNITSHIFT) & B_UNITMASK) +
48630547Skarels 		     (8 * ((bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK));
48730547Skarels 		file->i_boff = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK;
48825166Skarels 		cp = str;
48925166Skarels 	} else {
49025166Skarels # define isdigit(n)	((n>='0') && (n<='9'))
49130547Skarels 		if (cp == str)
49230547Skarels 			goto badspec;
49325166Skarels 		/*
49425166Skarels 	 	 * syntax for possible device name:
49525166Skarels 	 	 *	<alpha-string><digit-string><letter>:
49625166Skarels 	 	 */
49725166Skarels 		for (cp = str; *cp != ':' && !isdigit(*cp); cp++)
49825166Skarels 			;
49930547Skarels 		if ((file->i_ino.i_dev = getdev(str, cp - str)) == -1)
50030547Skarels 			goto bad;
50130547Skarels 		if ((file->i_unit = getunit(cp)) == -1)
50230547Skarels 			goto bad;
50330547Skarels 		while (isdigit(*cp))
50430547Skarels 			cp++;
50530547Skarels 		file->i_boff = 0;
50630547Skarels 		if (*cp >= 'a' && *cp <= 'h')
50730547Skarels 			file->i_boff = *cp++ - 'a';
50825166Skarels 		if (*cp++ != ':') {
50925166Skarels 			errno = EOFFSET;
51030547Skarels 			goto badspec;
51125166Skarels 		}
51225166Skarels 	}
51330547Skarels 	opendev = file->i_ino.i_dev << B_TYPESHIFT;
51430547Skarels 	opendev |= ((file->i_unit % 8) << B_UNITSHIFT);
51530547Skarels 	opendev |= ((file->i_unit / 8) << B_ADAPTORSHIFT);
51630547Skarels 	opendev |= file->i_boff << B_PARTITIONSHIFT;
517*30768Skarels 	opendev |= B_DEVMAGIC;
51830547Skarels 	if (errno = devopen(file))
51930547Skarels 		goto bad;
52025166Skarels 	if (cp != str && *cp == '\0') {
52125166Skarels 		file->i_flgs |= how+1;
52225166Skarels 		file->i_cc = 0;
52325166Skarels 		file->i_offset = 0;
52425166Skarels 		return (fdesc+3);
52525166Skarels 	}
5266068Smckusic 	file->i_ma = (char *)(&file->i_fs);
5276068Smckusic 	file->i_cc = SBSIZE;
528*30768Skarels 	file->i_bn = SBOFF / DEV_BSIZE + file->i_boff;
5296068Smckusic 	file->i_offset = 0;
53011083Ssam 	if (devread(file) < 0) {
53111083Ssam 		errno = file->i_error;
53211083Ssam 		printf("super block read error\n");
53330547Skarels 		goto bad;
53411083Ssam 	}
535327Sbill 	if ((i = find(cp, file)) == 0) {
53610022Ssam 		errno = ESRCH;
53730547Skarels 		goto bad;
538327Sbill 	}
53925442Skarels #ifndef	SMALL
540327Sbill 	if (how != 0) {
541327Sbill 		printf("Can't write files yet.. Sorry\n");
54210022Ssam 		errno = EIO;
54330547Skarels 		goto bad;
544327Sbill 	}
54525442Skarels #endif SMALL
54611083Ssam 	if (openi(i, file) < 0) {
54711083Ssam 		errno = file->i_error;
54830547Skarels 		goto bad;
54911083Ssam 	}
550327Sbill 	file->i_offset = 0;
551327Sbill 	file->i_cc = 0;
552327Sbill 	file->i_flgs |= F_FILE | (how+1);
55310022Ssam 	return (fdesc+3);
55430547Skarels 
55530547Skarels badspec:
55630547Skarels 	printf("malformed device specification\n");
55730547Skarels bad:
55830547Skarels 	file->i_flgs = 0;
55930547Skarels 	return (-1);
560327Sbill }
561327Sbill 
56230547Skarels static
56330547Skarels getdev(str, len)
56430547Skarels 	char *str;
56530547Skarels 	int len;
56630547Skarels {
56730547Skarels 	register struct devsw *dp;
56830547Skarels 
56930547Skarels 	for (dp = devsw; dp->dv_name; dp++) {
57030547Skarels 		if (!strncmp(str, dp->dv_name, len))
57130547Skarels 			return (dp - devsw);
57230547Skarels 	}
57330547Skarels 	printf("Unknown device\n");
57430547Skarels 	errno = ENXIO;
57530547Skarels 	return (-1);
57630547Skarels }
57730547Skarels 
57830547Skarels static
57930547Skarels getunit(cp)
58030547Skarels 	register char *cp;
58130547Skarels {
58230547Skarels 	register int i = 0;
58330547Skarels 
58430547Skarels 	while (*cp >= '0' && *cp <= '9')
58530547Skarels 		i = i * 10 + *cp++ - '0';
58630547Skarels 	if ((unsigned) i > 255) {
58730547Skarels 		printf("minor device number out of range (0-255)\n");
58830547Skarels 		errno = EUNIT;
58930547Skarels 		i = -1;
59030547Skarels 	}
59130547Skarels 	return (i);
59230547Skarels }
59330547Skarels 
594327Sbill close(fdesc)
59510022Ssam 	int fdesc;
596327Sbill {
597327Sbill 	struct iob *file;
598327Sbill 
599327Sbill 	fdesc -= 3;
6006068Smckusic 	if (fdesc < 0 || fdesc >= NFILES ||
60110022Ssam 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
60210022Ssam 		errno = EBADF;
60310022Ssam 		return (-1);
60410022Ssam 	}
605327Sbill 	if ((file->i_flgs&F_FILE) == 0)
606327Sbill 		devclose(file);
607327Sbill 	file->i_flgs = 0;
60810022Ssam 	return (0);
609327Sbill }
610327Sbill 
61125442Skarels #ifndef	SMALL
61210022Ssam ioctl(fdesc, cmd, arg)
61310022Ssam 	int fdesc, cmd;
61410022Ssam 	char *arg;
61510022Ssam {
61610022Ssam 	register struct iob *file;
61710022Ssam 	int error = 0;
61810022Ssam 
61910331Shelge 	fdesc -= 3;
62010022Ssam 	if (fdesc < 0 || fdesc >= NFILES ||
62110022Ssam 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
62210022Ssam 		errno = EBADF;
62310022Ssam 		return (-1);
62410022Ssam 	}
62510022Ssam 	switch (cmd) {
62610022Ssam 
62710022Ssam 	case SAIOHDR:
62810022Ssam 		file->i_flgs |= F_HDR;
62910022Ssam 		break;
63010022Ssam 
63110022Ssam 	case SAIOCHECK:
63210022Ssam 		file->i_flgs |= F_CHECK;
63310022Ssam 		break;
63410022Ssam 
63510022Ssam 	case SAIOHCHECK:
63610022Ssam 		file->i_flgs |= F_HCHECK;
63710022Ssam 		break;
63810022Ssam 
63910331Shelge 	case SAIONOBAD:
64010331Shelge 		file->i_flgs |= F_NBSF;
64110331Shelge 		break;
64210331Shelge 
64310331Shelge 	case SAIODOBAD:
64410331Shelge 		file->i_flgs &= ~F_NBSF;
64510331Shelge 		break;
64610331Shelge 
64710022Ssam 	default:
64810022Ssam 		error = devioctl(file, cmd, arg);
64910022Ssam 		break;
65010022Ssam 	}
65110022Ssam 	if (error < 0)
65210022Ssam 		errno = file->i_error;
65310022Ssam 	return (error);
65410022Ssam }
65525442Skarels #endif SMALL
65610022Ssam 
657327Sbill exit()
658327Sbill {
659327Sbill 	_stop("Exit called");
660327Sbill }
661327Sbill 
662327Sbill _stop(s)
66310022Ssam 	char *s;
664327Sbill {
6652391Stoy 	int i;
6662391Stoy 
6672391Stoy 	for (i = 0; i < NFILES; i++)
6682391Stoy 		if (iob[i].i_flgs != 0)
6692391Stoy 			close(i);
670327Sbill 	printf("%s\n", s);
671327Sbill 	_rtt();
672327Sbill }
673