xref: /csrg-svn/sys/stand.att/sys.c (revision 41542)
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*41542Smckusick  *	@(#)sys.c	7.11 (Berkeley) 05/10/90
723243Smckusick  */
8327Sbill 
940498Sroot #include "sys/param.h"
1040498Sroot #include "ufs/dir.h"
1140498Sroot #include "sys/reboot.h"
12327Sbill #include "saio.h"
13327Sbill 
1434942Sbostic #define	isdigit(c)	((u_int)((c) - '0') <= 9)
1534463Sbostic #define	isspace(c)	((c) == ' ' || (c) == '\t')
1634942Sbostic #define	isupper(c)	((u_int)((c) - 'A') <= 'Z' - 'A')
1734463Sbostic #define	tolower(c)	((c) - 'A' + 'a')
1834463Sbostic 
19327Sbill ino_t	dlook();
20327Sbill 
216068Smckusic struct dirstuff {
226068Smckusic 	int loc;
236068Smckusic 	struct iob *io;
246068Smckusic };
256068Smckusic 
2634463Sbostic struct iob iob[NFILES];
2734463Sbostic 
28327Sbill static
2910022Ssam openi(n, io)
306068Smckusic 	register struct iob *io;
31327Sbill {
32327Sbill 	register struct dinode *dp;
3311083Ssam 	int cc;
34327Sbill 
35327Sbill 	io->i_offset = 0;
366068Smckusic 	io->i_bn = fsbtodb(&io->i_fs, itod(&io->i_fs, n)) + io->i_boff;
376068Smckusic 	io->i_cc = io->i_fs.fs_bsize;
38327Sbill 	io->i_ma = io->i_buf;
3911083Ssam 	cc = devread(io);
40327Sbill 	dp = (struct dinode *)io->i_buf;
4140500Smckusick 	io->i_ino = dp[itoo(&io->i_fs, n)];
4211083Ssam 	return (cc);
43327Sbill }
44327Sbill 
45327Sbill static
46327Sbill find(path, file)
476068Smckusic 	register char *path;
486068Smckusic 	struct iob *file;
49327Sbill {
50327Sbill 	register char *q;
5134463Sbostic 	char *dir, c;
52327Sbill 	int n;
53327Sbill 
5434463Sbostic 	if (path == NULL || *path == '\0') {
55327Sbill 		printf("null path\n");
5610022Ssam 		return (0);
57327Sbill 	}
58327Sbill 
5911083Ssam 	if (openi((ino_t) ROOTINO, file) < 0) {
6011083Ssam 		printf("can't read root inode\n");
6111083Ssam 		return (0);
6211083Ssam 	}
6330768Skarels 	dir = path;
64327Sbill 	while (*path) {
65327Sbill 		while (*path == '/')
66327Sbill 			path++;
67327Sbill 		q = path;
68327Sbill 		while(*q != '/' && *q != '\0')
69327Sbill 			q++;
70327Sbill 		c = *q;
71327Sbill 		*q = '\0';
7225166Skarels 		if (q == path) path = "." ;	/* "/" means "/." */
73327Sbill 
7430768Skarels 		if ((n = dlook(path, file, dir)) != 0) {
7511083Ssam 			if (c == '\0')
76327Sbill 				break;
7711083Ssam 			if (openi(n, file) < 0)
7811083Ssam 				return (0);
79327Sbill 			*q = c;
80327Sbill 			path = q;
81327Sbill 			continue;
82327Sbill 		} else {
8325166Skarels 			printf("%s: not found\n", path);
8410022Ssam 			return (0);
85327Sbill 		}
86327Sbill 	}
8710022Ssam 	return (n);
88327Sbill }
89327Sbill 
9034463Sbostic #define	NBUFS	4
9134463Sbostic static char	b[NBUFS][MAXBSIZE];
9234463Sbostic static daddr_t	blknos[NBUFS];
9334463Sbostic 
94327Sbill static daddr_t
95327Sbill sbmap(io, bn)
966068Smckusic 	register struct iob *io;
976068Smckusic 	daddr_t bn;
98327Sbill {
9940500Smckusick 	register struct dinode *ip;
1006068Smckusic 	int i, j, sh;
101327Sbill 	daddr_t nb, *bap;
102327Sbill 
103327Sbill 	ip = &io->i_ino;
1046068Smckusic 	if (bn < 0) {
105327Sbill 		printf("bn negative\n");
10610022Ssam 		return ((daddr_t)0);
107327Sbill 	}
108327Sbill 
109327Sbill 	/*
1106068Smckusic 	 * blocks 0..NDADDR are direct blocks
111327Sbill 	 */
1126068Smckusic 	if(bn < NDADDR) {
11340500Smckusick 		nb = ip->di_db[bn];
11410022Ssam 		return (nb);
115327Sbill 	}
116327Sbill 
117327Sbill 	/*
1186068Smckusic 	 * addresses NIADDR have single and double indirect blocks.
1196068Smckusic 	 * the first step is to determine how many levels of indirection.
120327Sbill 	 */
1216068Smckusic 	sh = 1;
1226068Smckusic 	bn -= NDADDR;
1236068Smckusic 	for (j = NIADDR; j > 0; j--) {
1246068Smckusic 		sh *= NINDIR(&io->i_fs);
1256068Smckusic 		if (bn < sh)
126327Sbill 			break;
1276068Smckusic 		bn -= sh;
128327Sbill 	}
1296068Smckusic 	if (j == 0) {
1306068Smckusic 		printf("bn ovf %D\n", bn);
1316068Smckusic 		return ((daddr_t)0);
132327Sbill 	}
133327Sbill 
134327Sbill 	/*
1356068Smckusic 	 * fetch the first indirect block address from the inode
136327Sbill 	 */
13740500Smckusick 	nb = ip->di_ib[NIADDR - j];
1386068Smckusic 	if (nb == 0) {
139327Sbill 		printf("bn void %D\n",bn);
14010022Ssam 		return ((daddr_t)0);
141327Sbill 	}
142327Sbill 
143327Sbill 	/*
144327Sbill 	 * fetch through the indirect blocks
145327Sbill 	 */
1466068Smckusic 	for (; j <= NIADDR; j++) {
147327Sbill 		if (blknos[j] != nb) {
1486068Smckusic 			io->i_bn = fsbtodb(&io->i_fs, nb) + io->i_boff;
149327Sbill 			io->i_ma = b[j];
1506068Smckusic 			io->i_cc = io->i_fs.fs_bsize;
15111083Ssam 			if (devread(io) != io->i_fs.fs_bsize) {
15211083Ssam 				if (io->i_error)
15311083Ssam 					errno = io->i_error;
15411083Ssam 				printf("bn %D: read error\n", io->i_bn);
15511083Ssam 				return ((daddr_t)0);
15611083Ssam 			}
157327Sbill 			blknos[j] = nb;
158327Sbill 		}
159327Sbill 		bap = (daddr_t *)b[j];
1606068Smckusic 		sh /= NINDIR(&io->i_fs);
1616068Smckusic 		i = (bn / sh) % NINDIR(&io->i_fs);
162327Sbill 		nb = bap[i];
163327Sbill 		if(nb == 0) {
164327Sbill 			printf("bn void %D\n",bn);
16510022Ssam 			return ((daddr_t)0);
166327Sbill 		}
167327Sbill 	}
16810022Ssam 	return (nb);
169327Sbill }
170327Sbill 
1716068Smckusic /*
1726068Smckusic  * get next entry in a directory.
1736068Smckusic  */
1746068Smckusic struct direct *
1756068Smckusic readdir(dirp)
1766068Smckusic 	register struct dirstuff *dirp;
177327Sbill {
1786068Smckusic 	register struct direct *dp;
1796068Smckusic 	register struct iob *io;
1806068Smckusic 	daddr_t lbn, d;
1816068Smckusic 	int off;
182327Sbill 
1836068Smckusic 	io = dirp->io;
1846068Smckusic 	for(;;) {
18540500Smckusick 		if (dirp->loc >= io->i_ino.di_size)
18611083Ssam 			return (NULL);
1876068Smckusic 		off = blkoff(&io->i_fs, dirp->loc);
1886068Smckusic 		if (off == 0) {
1896068Smckusic 			lbn = lblkno(&io->i_fs, dirp->loc);
1906068Smckusic 			d = sbmap(io, lbn);
1916068Smckusic 			if(d == 0)
19234463Sbostic 				return (NULL);
1936068Smckusic 			io->i_bn = fsbtodb(&io->i_fs, d) + io->i_boff;
1946068Smckusic 			io->i_ma = io->i_buf;
19540500Smckusick 			io->i_cc = dblksize(&io->i_fs, &io->i_ino, lbn);
19611083Ssam 			if (devread(io) < 0) {
19711083Ssam 				errno = io->i_error;
19825166Skarels 				printf("bn %D: directory read error\n",
19925166Skarels 					io->i_bn);
20011083Ssam 				return (NULL);
20111083Ssam 			}
2026068Smckusic 		}
2036068Smckusic 		dp = (struct direct *)(io->i_buf + off);
2046068Smckusic 		dirp->loc += dp->d_reclen;
2056068Smckusic 		if (dp->d_ino == 0)
2066068Smckusic 			continue;
2076068Smckusic 		return (dp);
208327Sbill 	}
209327Sbill }
210327Sbill 
21140500Smckusick static ino_t
21240500Smckusick dlook(s, io, dir)
21340500Smckusick 	char *s;
21440500Smckusick 	register struct iob *io;
21540500Smckusick 	char *dir;
21640500Smckusick {
21740500Smckusick 	register struct direct *dp;
21840500Smckusick 	register struct dinode *ip;
21940500Smckusick 	struct dirstuff dirp;
22040500Smckusick 	int len;
22140500Smckusick 
22240500Smckusick 	if (s == NULL || *s == '\0')
22340500Smckusick 		return (0);
22440500Smckusick 	ip = &io->i_ino;
22540500Smckusick 	if ((ip->di_mode&IFMT) != IFDIR) {
22640500Smckusick 		printf("%s: not a directory\n", dir);
22740500Smckusick 		return (0);
22840500Smckusick 	}
22940500Smckusick 	if (ip->di_size == 0) {
23040500Smckusick 		printf("%s: zero length directory\n", dir);
23140500Smckusick 		return (0);
23240500Smckusick 	}
23340500Smckusick 	len = strlen(s);
23440500Smckusick 	dirp.loc = 0;
23540500Smckusick 	dirp.io = io;
23640500Smckusick 	for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) {
23740500Smckusick 		if(dp->d_ino == 0)
23840500Smckusick 			continue;
23940500Smckusick 		if (dp->d_namlen == len && !strcmp(s, dp->d_name))
24040500Smckusick 			return (dp->d_ino);
24140500Smckusick 	}
24240500Smckusick 	return (0);
24340500Smckusick }
24440500Smckusick 
245327Sbill lseek(fdesc, addr, ptr)
24610022Ssam 	int fdesc, ptr;
24710022Ssam 	off_t addr;
248327Sbill {
249327Sbill 	register struct iob *io;
250327Sbill 
25134463Sbostic #ifndef SMALL
25234463Sbostic 	if (ptr != L_SET) {
253327Sbill 		printf("Seek not from beginning of file\n");
25410022Ssam 		errno = EOFFSET;
25510022Ssam 		return (-1);
256327Sbill 	}
25734463Sbostic #endif
258327Sbill 	fdesc -= 3;
2596068Smckusic 	if (fdesc < 0 || fdesc >= NFILES ||
26010022Ssam 	    ((io = &iob[fdesc])->i_flgs & F_ALLOC) == 0) {
26110022Ssam 		errno = EBADF;
26210022Ssam 		return (-1);
26310022Ssam 	}
264327Sbill 	io->i_offset = addr;
2656068Smckusic 	io->i_bn = addr / DEV_BSIZE;
266327Sbill 	io->i_cc = 0;
26710022Ssam 	return (0);
268327Sbill }
269327Sbill 
270327Sbill getc(fdesc)
27110022Ssam 	int fdesc;
272327Sbill {
273327Sbill 	register struct iob *io;
2746068Smckusic 	register struct fs *fs;
275327Sbill 	register char *p;
2766068Smckusic 	int c, lbn, off, size, diff;
277327Sbill 
278327Sbill 
279327Sbill 	if (fdesc >= 0 && fdesc <= 2)
28010022Ssam 		return (getchar());
281327Sbill 	fdesc -= 3;
2826068Smckusic 	if (fdesc < 0 || fdesc >= NFILES ||
28310022Ssam 	    ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
28410022Ssam 		errno = EBADF;
28510022Ssam 		return (-1);
28610022Ssam 	}
287327Sbill 	p = io->i_ma;
288327Sbill 	if (io->i_cc <= 0) {
2896068Smckusic 		if ((io->i_flgs & F_FILE) != 0) {
29040500Smckusick 			diff = io->i_ino.di_size - io->i_offset;
2916068Smckusic 			if (diff <= 0)
2926068Smckusic 				return (-1);
2936068Smckusic 			fs = &io->i_fs;
2946068Smckusic 			lbn = lblkno(fs, io->i_offset);
2956068Smckusic 			io->i_bn = fsbtodb(fs, sbmap(io, lbn)) + io->i_boff;
2966068Smckusic 			off = blkoff(fs, io->i_offset);
29740500Smckusick 			size = dblksize(fs, &io->i_ino, lbn);
2986068Smckusic 		} else {
2996068Smckusic 			io->i_bn = io->i_offset / DEV_BSIZE;
3006068Smckusic 			off = 0;
3016068Smckusic 			size = DEV_BSIZE;
3026068Smckusic 		}
303327Sbill 		io->i_ma = io->i_buf;
3046068Smckusic 		io->i_cc = size;
30511083Ssam 		if (devread(io) < 0) {
30611083Ssam 			errno = io->i_error;
30711083Ssam 			return (-1);
30811083Ssam 		}
3096068Smckusic 		if ((io->i_flgs & F_FILE) != 0) {
31040500Smckusick 			if (io->i_offset - off + size >= io->i_ino.di_size)
3116068Smckusic 				io->i_cc = diff + off;
312327Sbill 			io->i_cc -= off;
3136068Smckusic 		}
314327Sbill 		p = &io->i_buf[off];
315327Sbill 	}
316327Sbill 	io->i_cc--;
317327Sbill 	io->i_offset++;
318327Sbill 	c = (unsigned)*p++;
319327Sbill 	io->i_ma = p;
32010022Ssam 	return (c);
321327Sbill }
3226068Smckusic 
32310022Ssam int	errno;
324327Sbill 
325327Sbill read(fdesc, buf, count)
32610022Ssam 	int fdesc, count;
32710022Ssam 	char *buf;
328327Sbill {
32925166Skarels 	register i, size;
330327Sbill 	register struct iob *file;
33125166Skarels 	register struct fs *fs;
33225166Skarels 	int lbn, off;
333327Sbill 
33410022Ssam 	errno = 0;
335327Sbill 	if (fdesc >= 0 & fdesc <= 2) {
336327Sbill 		i = count;
337327Sbill 		do {
338327Sbill 			*buf = getchar();
339327Sbill 		} while (--i && *buf++ != '\n');
34010022Ssam 		return (count - i);
341327Sbill 	}
342327Sbill 	fdesc -= 3;
3436068Smckusic 	if (fdesc < 0 || fdesc >= NFILES ||
34410022Ssam 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
34510022Ssam 		errno = EBADF;
34610022Ssam 		return (-1);
34710022Ssam 	}
34810022Ssam 	if ((file->i_flgs&F_READ) == 0) {
34910022Ssam 		errno = EBADF;
35010022Ssam 		return (-1);
35110022Ssam 	}
35234463Sbostic #ifndef SMALL
3536068Smckusic 	if ((file->i_flgs & F_FILE) == 0) {
354327Sbill 		file->i_cc = count;
355327Sbill 		file->i_ma = buf;
3567446Sroot 		file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE);
357327Sbill 		i = devread(file);
35810022Ssam 		if (i < 0)
35910022Ssam 			errno = file->i_error;
36030547Skarels 		else
36130547Skarels 			file->i_offset += i;
36210022Ssam 		return (i);
363327Sbill 	}
36434463Sbostic #endif
36540500Smckusick 	if (file->i_offset+count > file->i_ino.di_size)
36640500Smckusick 		count = file->i_ino.di_size - file->i_offset;
36725166Skarels 	if ((i = count) <= 0)
36825166Skarels 		return (0);
36925166Skarels 	/*
37025166Skarels 	 * While reading full blocks, do I/O into user buffer.
37125166Skarels 	 * Anything else uses getc().
37225166Skarels 	 */
37325166Skarels 	fs = &file->i_fs;
37425166Skarels 	while (i) {
37525166Skarels 		off = blkoff(fs, file->i_offset);
37625166Skarels 		lbn = lblkno(fs, file->i_offset);
37740500Smckusick 		size = dblksize(fs, &file->i_ino, lbn);
37825166Skarels 		if (off == 0 && size <= i) {
37925166Skarels 			file->i_bn = fsbtodb(fs, sbmap(file, lbn)) +
38025166Skarels 			    file->i_boff;
38125166Skarels 			file->i_cc = size;
38225166Skarels 			file->i_ma = buf;
38325166Skarels 			if (devread(file) < 0) {
38425166Skarels 				errno = file->i_error;
38525166Skarels 				return (-1);
38625166Skarels 			}
38725166Skarels 			file->i_offset += size;
38825166Skarels 			file->i_cc = 0;
38925166Skarels 			buf += size;
39025166Skarels 			i -= size;
39125166Skarels 		} else {
39225166Skarels 			size -= off;
39325166Skarels 			if (size > i)
39425166Skarels 				size = i;
39525166Skarels 			i -= size;
39625166Skarels 			do {
39725166Skarels 				*buf++ = getc(fdesc+3);
39825166Skarels 			} while (--size);
39925166Skarels 		}
40025166Skarels 	}
40125166Skarels 	return (count);
402327Sbill }
403327Sbill 
40434463Sbostic #ifndef SMALL
405327Sbill write(fdesc, buf, count)
40610022Ssam 	int fdesc, count;
40710022Ssam 	char *buf;
408327Sbill {
409327Sbill 	register i;
410327Sbill 	register struct iob *file;
411327Sbill 
41210022Ssam 	errno = 0;
413327Sbill 	if (fdesc >= 0 && fdesc <= 2) {
414327Sbill 		i = count;
415327Sbill 		while (i--)
416327Sbill 			putchar(*buf++);
41710022Ssam 		return (count);
418327Sbill 	}
419327Sbill 	fdesc -= 3;
4206068Smckusic 	if (fdesc < 0 || fdesc >= NFILES ||
42110022Ssam 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
42210022Ssam 		errno = EBADF;
42310022Ssam 		return (-1);
42410022Ssam 	}
42510022Ssam 	if ((file->i_flgs&F_WRITE) == 0) {
42610022Ssam 		errno = EBADF;
42710022Ssam 		return (-1);
42810022Ssam 	}
429327Sbill 	file->i_cc = count;
430327Sbill 	file->i_ma = buf;
4317446Sroot 	file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE);
432327Sbill 	i = devwrite(file);
4337446Sroot 	file->i_offset += count;
43410022Ssam 	if (i < 0)
43510022Ssam 		errno = file->i_error;
43610022Ssam 	return (i);
437327Sbill }
43834463Sbostic #endif
439327Sbill 
4403349Swnj int	openfirst = 1;
44134463Sbostic u_int	opendev;		/* last device opened */
44234463Sbostic extern u_int bootdev;
4433349Swnj 
444327Sbill open(str, how)
4456068Smckusic 	char *str;
44610022Ssam 	int how;
447327Sbill {
44834463Sbostic 	register char *t;
44934463Sbostic 	register int cnt;
450327Sbill 	register struct iob *file;
45134463Sbostic 	int fdesc, args[8], *argp;
452327Sbill 
4533349Swnj 	if (openfirst) {
45434463Sbostic 		for (cnt = 0; cnt < NFILES; cnt++)
45534463Sbostic 			iob[cnt].i_flgs = 0;
4563349Swnj 		openfirst = 0;
457327Sbill 	}
458327Sbill 
45934463Sbostic 	for (fdesc = 0;; fdesc++) {
46034463Sbostic 		if (fdesc == NFILES)
46134463Sbostic 			_stop("No more file slots");
46234463Sbostic 		if (iob[fdesc].i_flgs == 0) {
46334463Sbostic 			file = &iob[fdesc];
46434463Sbostic 			file->i_flgs |= F_ALLOC;
46534463Sbostic 			file->i_adapt = file->i_ctlr = file->i_unit =
46634463Sbostic 			    file->i_part = 0;
46734463Sbostic 			break;
46834463Sbostic 		}
46934463Sbostic 	}
470327Sbill 
47134463Sbostic 	for (cnt = 0; cnt < sizeof(args)/sizeof(args[0]); args[cnt++] = 0);
47234463Sbostic #ifndef SMALL
47334463Sbostic 	for (t = str; *t && *t != '/' && *t != ':' && *t != '('; ++t)
47434463Sbostic 		if (isupper(*t))
47534463Sbostic 			*t = tolower(*t);
47634463Sbostic 	switch(*t) {
47734463Sbostic 	case '(':	/* type(adapt, ctlr, drive, partition)file */
47840500Smckusick 		if ((file->i_dev = getdev(str, t - str)) == -1)
47930547Skarels 			goto bad;
48034463Sbostic 		for (argp = args + 4, cnt = 0; *t != ')'; ++cnt) {
48134463Sbostic 			for (++t; isspace(*t); ++t);
48234463Sbostic 			if (*t == ')')
48334463Sbostic 				break;
48434463Sbostic 			if (!isdigit(*t))
48530547Skarels 				goto badspec;
48634463Sbostic 			*argp++ = atoi(t);
48734463Sbostic 			for (++t; isdigit(*t); ++t);
48834463Sbostic 			if (*t != ',' && *t != ')' || cnt == 4)
48934463Sbostic 				goto badspec;
49030547Skarels 		}
49134463Sbostic 		for (++t; isspace(*t); ++t);
49234463Sbostic 		argp -= 4;
49334463Sbostic 		file->i_adapt = *argp++;
49434463Sbostic 		file->i_ctlr = *argp++;
49534463Sbostic 		file->i_unit = *argp++;
49634463Sbostic 		file->i_part = *argp;
49734463Sbostic 		break;
49834463Sbostic 	case ':':	/* [A-Za-z]*[0-9]*[A-Za-z]:file */
49934463Sbostic 		for (t = str; *t != ':' && !isdigit(*t); ++t);
50040500Smckusick 		if ((file->i_dev = getdev(str, t - str)) == -1)
50130547Skarels 			goto bad;
50234463Sbostic 		if ((file->i_unit = getunit(t)) == -1)
50330547Skarels 			goto bad;
50434463Sbostic 		for (; isdigit(*t); ++t);
50534463Sbostic 		if (*t >= 'a' && *t <= 'h')
50634463Sbostic 			file->i_part = *t++ - 'a';
50734463Sbostic 		if (*t != ':') {
50825166Skarels 			errno = EOFFSET;
50930547Skarels 			goto badspec;
51025166Skarels 		}
51134463Sbostic 		for (++t; isspace(*t); ++t);
51234463Sbostic 		break;
51334463Sbostic 	case '/':
51434463Sbostic 	default:		/* default bootstrap unit and device */
51534463Sbostic #else
51634463Sbostic 	{
51734463Sbostic #endif /* SMALL */
51840500Smckusick 		file->i_dev = B_TYPE(bootdev);
51934463Sbostic 		file->i_adapt = B_ADAPTOR(bootdev);
52034463Sbostic 		file->i_ctlr = B_CONTROLLER(bootdev);
52134463Sbostic 		file->i_unit = B_UNIT(bootdev);
52234463Sbostic 		file->i_part = B_PARTITION(bootdev);
52334463Sbostic 		t = str;
52425166Skarels 	}
52534463Sbostic 
52640500Smckusick 	opendev = MAKEBOOTDEV(file->i_dev, file->i_adapt, file->i_ctlr,
52734463Sbostic 	    file->i_unit, file->i_part);
52834463Sbostic 
52930547Skarels 	if (errno = devopen(file))
53030547Skarels 		goto bad;
53134463Sbostic 
53234463Sbostic 	if (*t == '\0') {
53334463Sbostic 		file->i_flgs |= how + 1;
53425166Skarels 		file->i_cc = 0;
53525166Skarels 		file->i_offset = 0;
53625166Skarels 		return (fdesc+3);
53725166Skarels 	}
53834463Sbostic #ifndef SMALL
53934463Sbostic 	else if (how != 0) {
54034463Sbostic 		printf("Can't write files yet.. Sorry\n");
54134463Sbostic 		errno = EIO;
54234463Sbostic 		goto bad;
54334463Sbostic 	}
54433408Skarels #endif
5456068Smckusic 	file->i_ma = (char *)(&file->i_fs);
5466068Smckusic 	file->i_cc = SBSIZE;
54730768Skarels 	file->i_bn = SBOFF / DEV_BSIZE + file->i_boff;
5486068Smckusic 	file->i_offset = 0;
54911083Ssam 	if (devread(file) < 0) {
55011083Ssam 		errno = file->i_error;
55111083Ssam 		printf("super block read error\n");
55230547Skarels 		goto bad;
55311083Ssam 	}
55434463Sbostic 	if ((cnt = find(t, file)) == 0) {
55510022Ssam 		errno = ESRCH;
55630547Skarels 		goto bad;
557327Sbill 	}
55834463Sbostic 	if (openi(cnt, file) < 0) {
55911083Ssam 		errno = file->i_error;
56030547Skarels 		goto bad;
56111083Ssam 	}
562327Sbill 	file->i_offset = 0;
563327Sbill 	file->i_cc = 0;
564327Sbill 	file->i_flgs |= F_FILE | (how+1);
56510022Ssam 	return (fdesc+3);
56630547Skarels 
56733408Skarels #ifndef SMALL
56830547Skarels badspec:
56934463Sbostic 	printf("malformed device specification\nusage: device(adaptor, controller, drive, partition)file\n");
57033408Skarels #endif
57130547Skarels bad:
57230547Skarels 	file->i_flgs = 0;
57330547Skarels 	return (-1);
574327Sbill }
575327Sbill 
57630924Skarels #ifndef SMALL
57730547Skarels static
57830547Skarels getdev(str, len)
57933408Skarels 	register char *str;
58030547Skarels 	int len;
58130547Skarels {
58230547Skarels 	register struct devsw *dp;
58333408Skarels 	register int i;
58434463Sbostic 	char savedch = str[len];
58530547Skarels 
58634463Sbostic 	str[len] = '\0';
58733408Skarels 	for (dp = devsw, i = 0; i < ndevs; dp++, i++)
58833408Skarels 		if (dp->dv_name && strcmp(str, dp->dv_name) == 0) {
58934463Sbostic 			str[len] = savedch;
59033408Skarels 			return (i);
59133408Skarels 		}
59233408Skarels 	printf("Unknown device\nKnown devices are:\n");
59333408Skarels 	for (dp = devsw, i = 0; i < ndevs; dp++, i++)
59433408Skarels 		if (dp->dv_name)
59533408Skarels 			printf(" %s", dp->dv_name);
59634463Sbostic 	printf("\n");
59730547Skarels 	errno = ENXIO;
59830547Skarels 	return (-1);
59930547Skarels }
60030547Skarels 
60130547Skarels static
60230547Skarels getunit(cp)
60330547Skarels 	register char *cp;
60430547Skarels {
60534463Sbostic 	int unit;
60630547Skarels 
60734463Sbostic 	unit = atoi(cp);
60834463Sbostic 	if ((u_int)unit > 255) {
60930547Skarels 		printf("minor device number out of range (0-255)\n");
61030547Skarels 		errno = EUNIT;
61134463Sbostic 		return (-1);
61230547Skarels 	}
61334463Sbostic 	return (unit);
61430547Skarels }
61534463Sbostic #endif /* SMALL */
61630547Skarels 
617327Sbill close(fdesc)
61810022Ssam 	int fdesc;
619327Sbill {
620327Sbill 	struct iob *file;
621327Sbill 
622327Sbill 	fdesc -= 3;
6236068Smckusic 	if (fdesc < 0 || fdesc >= NFILES ||
62410022Ssam 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
62510022Ssam 		errno = EBADF;
62610022Ssam 		return (-1);
62710022Ssam 	}
628327Sbill 	if ((file->i_flgs&F_FILE) == 0)
629327Sbill 		devclose(file);
630327Sbill 	file->i_flgs = 0;
63110022Ssam 	return (0);
632327Sbill }
633327Sbill 
63434463Sbostic #ifndef SMALL
63510022Ssam ioctl(fdesc, cmd, arg)
63610022Ssam 	int fdesc, cmd;
63710022Ssam 	char *arg;
63810022Ssam {
63910022Ssam 	register struct iob *file;
64010022Ssam 	int error = 0;
64110022Ssam 
64210331Shelge 	fdesc -= 3;
64310022Ssam 	if (fdesc < 0 || fdesc >= NFILES ||
64410022Ssam 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
64510022Ssam 		errno = EBADF;
64610022Ssam 		return (-1);
64710022Ssam 	}
64810022Ssam 	switch (cmd) {
64910022Ssam 
65010022Ssam 	case SAIOHDR:
65110022Ssam 		file->i_flgs |= F_HDR;
65210022Ssam 		break;
65310022Ssam 
65410022Ssam 	case SAIOCHECK:
65510022Ssam 		file->i_flgs |= F_CHECK;
65610022Ssam 		break;
65710022Ssam 
65810022Ssam 	case SAIOHCHECK:
65910022Ssam 		file->i_flgs |= F_HCHECK;
66010022Ssam 		break;
66110022Ssam 
66210331Shelge 	case SAIONOBAD:
66310331Shelge 		file->i_flgs |= F_NBSF;
66410331Shelge 		break;
66510331Shelge 
66610331Shelge 	case SAIODOBAD:
66710331Shelge 		file->i_flgs &= ~F_NBSF;
66810331Shelge 		break;
66910331Shelge 
67010022Ssam 	default:
67110022Ssam 		error = devioctl(file, cmd, arg);
67210022Ssam 		break;
67310022Ssam 	}
67410022Ssam 	if (error < 0)
67510022Ssam 		errno = file->i_error;
67610022Ssam 	return (error);
67710022Ssam }
67834463Sbostic #endif /* SMALL */
67910022Ssam 
680327Sbill exit()
681327Sbill {
682327Sbill 	_stop("Exit called");
683327Sbill }
684327Sbill 
685327Sbill _stop(s)
68610022Ssam 	char *s;
687327Sbill {
6882391Stoy 	int i;
689*41542Smckusick 	static int stopped = 0;
6902391Stoy 
691*41542Smckusick 	if (!stopped) {
692*41542Smckusick 		stopped++;
693*41542Smckusick 		for (i = 0; i < NFILES; i++)
694*41542Smckusick 			if (iob[i].i_flgs != 0)
695*41542Smckusick 				close(i);
696*41542Smckusick 	}
697327Sbill 	printf("%s\n", s);
698327Sbill 	_rtt();
699327Sbill }
700