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*40498Sroot * @(#)sys.c 7.8 (Berkeley) 03/15/90 723243Smckusick */ 8327Sbill 9*40498Sroot #include "sys/param.h" 10*40498Sroot #include "sys/time.h" 11*40498Sroot #include "sys/vnode.h" 12*40498Sroot #include "ufs/inode.h" 13*40498Sroot #include "ufs/fs.h" 14*40498Sroot #include "ufs/dir.h" 15*40498Sroot #include "sys/reboot.h" 16327Sbill #include "saio.h" 17327Sbill 1834942Sbostic #define isdigit(c) ((u_int)((c) - '0') <= 9) 1934463Sbostic #define isspace(c) ((c) == ' ' || (c) == '\t') 2034942Sbostic #define isupper(c) ((u_int)((c) - 'A') <= 'Z' - 'A') 2134463Sbostic #define tolower(c) ((c) - 'A' + 'a') 2234463Sbostic 23327Sbill ino_t dlook(); 24327Sbill 256068Smckusic struct dirstuff { 266068Smckusic int loc; 276068Smckusic struct iob *io; 286068Smckusic }; 296068Smckusic 3034463Sbostic struct iob iob[NFILES]; 3134463Sbostic 32327Sbill static 3310022Ssam openi(n, io) 346068Smckusic register struct iob *io; 35327Sbill { 36327Sbill register struct dinode *dp; 3711083Ssam int cc; 38327Sbill 39327Sbill io->i_offset = 0; 406068Smckusic io->i_bn = fsbtodb(&io->i_fs, itod(&io->i_fs, n)) + io->i_boff; 416068Smckusic io->i_cc = io->i_fs.fs_bsize; 42327Sbill io->i_ma = io->i_buf; 4311083Ssam cc = devread(io); 44327Sbill dp = (struct dinode *)io->i_buf; 456068Smckusic io->i_ino.i_ic = dp[itoo(&io->i_fs, n)].di_ic; 4611083Ssam return (cc); 47327Sbill } 48327Sbill 49327Sbill static 50327Sbill find(path, file) 516068Smckusic register char *path; 526068Smckusic struct iob *file; 53327Sbill { 54327Sbill register char *q; 5534463Sbostic char *dir, c; 56327Sbill int n; 57327Sbill 5834463Sbostic if (path == NULL || *path == '\0') { 59327Sbill printf("null path\n"); 6010022Ssam return (0); 61327Sbill } 62327Sbill 6311083Ssam if (openi((ino_t) ROOTINO, file) < 0) { 6411083Ssam printf("can't read root inode\n"); 6511083Ssam return (0); 6611083Ssam } 6730768Skarels dir = path; 68327Sbill while (*path) { 69327Sbill while (*path == '/') 70327Sbill path++; 71327Sbill q = path; 72327Sbill while(*q != '/' && *q != '\0') 73327Sbill q++; 74327Sbill c = *q; 75327Sbill *q = '\0'; 7625166Skarels if (q == path) path = "." ; /* "/" means "/." */ 77327Sbill 7830768Skarels if ((n = dlook(path, file, dir)) != 0) { 7911083Ssam if (c == '\0') 80327Sbill break; 8111083Ssam if (openi(n, file) < 0) 8211083Ssam return (0); 83327Sbill *q = c; 84327Sbill path = q; 85327Sbill continue; 86327Sbill } else { 8725166Skarels printf("%s: not found\n", path); 8810022Ssam return (0); 89327Sbill } 90327Sbill } 9110022Ssam return (n); 92327Sbill } 93327Sbill 9434463Sbostic #define NBUFS 4 9534463Sbostic static char b[NBUFS][MAXBSIZE]; 9634463Sbostic static daddr_t blknos[NBUFS]; 9734463Sbostic 98327Sbill static daddr_t 99327Sbill sbmap(io, bn) 1006068Smckusic register struct iob *io; 1016068Smckusic daddr_t bn; 102327Sbill { 103327Sbill register struct inode *ip; 1046068Smckusic int i, j, sh; 105327Sbill daddr_t nb, *bap; 106327Sbill 107327Sbill ip = &io->i_ino; 1086068Smckusic if (bn < 0) { 109327Sbill printf("bn negative\n"); 11010022Ssam return ((daddr_t)0); 111327Sbill } 112327Sbill 113327Sbill /* 1146068Smckusic * blocks 0..NDADDR are direct blocks 115327Sbill */ 1166068Smckusic if(bn < NDADDR) { 1176068Smckusic nb = ip->i_db[bn]; 11810022Ssam return (nb); 119327Sbill } 120327Sbill 121327Sbill /* 1226068Smckusic * addresses NIADDR have single and double indirect blocks. 1236068Smckusic * the first step is to determine how many levels of indirection. 124327Sbill */ 1256068Smckusic sh = 1; 1266068Smckusic bn -= NDADDR; 1276068Smckusic for (j = NIADDR; j > 0; j--) { 1286068Smckusic sh *= NINDIR(&io->i_fs); 1296068Smckusic if (bn < sh) 130327Sbill break; 1316068Smckusic bn -= sh; 132327Sbill } 1336068Smckusic if (j == 0) { 1346068Smckusic printf("bn ovf %D\n", bn); 1356068Smckusic return ((daddr_t)0); 136327Sbill } 137327Sbill 138327Sbill /* 1396068Smckusic * fetch the first indirect block address from the inode 140327Sbill */ 1416068Smckusic nb = ip->i_ib[NIADDR - j]; 1426068Smckusic if (nb == 0) { 143327Sbill printf("bn void %D\n",bn); 14410022Ssam return ((daddr_t)0); 145327Sbill } 146327Sbill 147327Sbill /* 148327Sbill * fetch through the indirect blocks 149327Sbill */ 1506068Smckusic for (; j <= NIADDR; j++) { 151327Sbill if (blknos[j] != nb) { 1526068Smckusic io->i_bn = fsbtodb(&io->i_fs, nb) + io->i_boff; 153327Sbill io->i_ma = b[j]; 1546068Smckusic io->i_cc = io->i_fs.fs_bsize; 15511083Ssam if (devread(io) != io->i_fs.fs_bsize) { 15611083Ssam if (io->i_error) 15711083Ssam errno = io->i_error; 15811083Ssam printf("bn %D: read error\n", io->i_bn); 15911083Ssam return ((daddr_t)0); 16011083Ssam } 161327Sbill blknos[j] = nb; 162327Sbill } 163327Sbill bap = (daddr_t *)b[j]; 1646068Smckusic sh /= NINDIR(&io->i_fs); 1656068Smckusic i = (bn / sh) % NINDIR(&io->i_fs); 166327Sbill nb = bap[i]; 167327Sbill if(nb == 0) { 168327Sbill printf("bn void %D\n",bn); 16910022Ssam return ((daddr_t)0); 170327Sbill } 171327Sbill } 17210022Ssam return (nb); 173327Sbill } 174327Sbill 175327Sbill static ino_t 17630768Skarels dlook(s, io, dir) 1776068Smckusic char *s; 1786068Smckusic register struct iob *io; 17930768Skarels char *dir; 180327Sbill { 181327Sbill register struct direct *dp; 182327Sbill register struct inode *ip; 1836068Smckusic struct dirstuff dirp; 1846068Smckusic int len; 185327Sbill 1866068Smckusic if (s == NULL || *s == '\0') 18710022Ssam return (0); 188327Sbill ip = &io->i_ino; 1896068Smckusic if ((ip->i_mode&IFMT) != IFDIR) { 19030768Skarels printf("%s: not a directory\n", dir); 19110022Ssam return (0); 192327Sbill } 1936068Smckusic if (ip->i_size == 0) { 19430768Skarels printf("%s: zero length directory\n", dir); 19510022Ssam return (0); 196327Sbill } 1976068Smckusic len = strlen(s); 1986068Smckusic dirp.loc = 0; 1996068Smckusic dirp.io = io; 2006068Smckusic for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) { 2016068Smckusic if(dp->d_ino == 0) 2026068Smckusic continue; 2036068Smckusic if (dp->d_namlen == len && !strcmp(s, dp->d_name)) 20410022Ssam return (dp->d_ino); 205327Sbill } 20610022Ssam return (0); 207327Sbill } 208327Sbill 2096068Smckusic /* 2106068Smckusic * get next entry in a directory. 2116068Smckusic */ 2126068Smckusic struct direct * 2136068Smckusic readdir(dirp) 2146068Smckusic register struct dirstuff *dirp; 215327Sbill { 2166068Smckusic register struct direct *dp; 2176068Smckusic register struct iob *io; 2186068Smckusic daddr_t lbn, d; 2196068Smckusic int off; 220327Sbill 2216068Smckusic io = dirp->io; 2226068Smckusic for(;;) { 2236068Smckusic if (dirp->loc >= io->i_ino.i_size) 22411083Ssam return (NULL); 2256068Smckusic off = blkoff(&io->i_fs, dirp->loc); 2266068Smckusic if (off == 0) { 2276068Smckusic lbn = lblkno(&io->i_fs, dirp->loc); 2286068Smckusic d = sbmap(io, lbn); 2296068Smckusic if(d == 0) 23034463Sbostic return (NULL); 2316068Smckusic io->i_bn = fsbtodb(&io->i_fs, d) + io->i_boff; 2326068Smckusic io->i_ma = io->i_buf; 2336068Smckusic io->i_cc = blksize(&io->i_fs, &io->i_ino, lbn); 23411083Ssam if (devread(io) < 0) { 23511083Ssam errno = io->i_error; 23625166Skarels printf("bn %D: directory read error\n", 23725166Skarels io->i_bn); 23811083Ssam return (NULL); 23911083Ssam } 2406068Smckusic } 2416068Smckusic dp = (struct direct *)(io->i_buf + off); 2426068Smckusic dirp->loc += dp->d_reclen; 2436068Smckusic if (dp->d_ino == 0) 2446068Smckusic continue; 2456068Smckusic return (dp); 246327Sbill } 247327Sbill } 248327Sbill 249327Sbill lseek(fdesc, addr, ptr) 25010022Ssam int fdesc, ptr; 25110022Ssam off_t addr; 252327Sbill { 253327Sbill register struct iob *io; 254327Sbill 25534463Sbostic #ifndef SMALL 25634463Sbostic if (ptr != L_SET) { 257327Sbill printf("Seek not from beginning of file\n"); 25810022Ssam errno = EOFFSET; 25910022Ssam return (-1); 260327Sbill } 26134463Sbostic #endif 262327Sbill fdesc -= 3; 2636068Smckusic if (fdesc < 0 || fdesc >= NFILES || 26410022Ssam ((io = &iob[fdesc])->i_flgs & F_ALLOC) == 0) { 26510022Ssam errno = EBADF; 26610022Ssam return (-1); 26710022Ssam } 268327Sbill io->i_offset = addr; 2696068Smckusic io->i_bn = addr / DEV_BSIZE; 270327Sbill io->i_cc = 0; 27110022Ssam return (0); 272327Sbill } 273327Sbill 274327Sbill getc(fdesc) 27510022Ssam int fdesc; 276327Sbill { 277327Sbill register struct iob *io; 2786068Smckusic register struct fs *fs; 279327Sbill register char *p; 2806068Smckusic int c, lbn, off, size, diff; 281327Sbill 282327Sbill 283327Sbill if (fdesc >= 0 && fdesc <= 2) 28410022Ssam return (getchar()); 285327Sbill fdesc -= 3; 2866068Smckusic if (fdesc < 0 || fdesc >= NFILES || 28710022Ssam ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { 28810022Ssam errno = EBADF; 28910022Ssam return (-1); 29010022Ssam } 291327Sbill p = io->i_ma; 292327Sbill if (io->i_cc <= 0) { 2936068Smckusic if ((io->i_flgs & F_FILE) != 0) { 2946068Smckusic diff = io->i_ino.i_size - io->i_offset; 2956068Smckusic if (diff <= 0) 2966068Smckusic return (-1); 2976068Smckusic fs = &io->i_fs; 2986068Smckusic lbn = lblkno(fs, io->i_offset); 2996068Smckusic io->i_bn = fsbtodb(fs, sbmap(io, lbn)) + io->i_boff; 3006068Smckusic off = blkoff(fs, io->i_offset); 3016068Smckusic size = blksize(fs, &io->i_ino, lbn); 3026068Smckusic } else { 3036068Smckusic io->i_bn = io->i_offset / DEV_BSIZE; 3046068Smckusic off = 0; 3056068Smckusic size = DEV_BSIZE; 3066068Smckusic } 307327Sbill io->i_ma = io->i_buf; 3086068Smckusic io->i_cc = size; 30911083Ssam if (devread(io) < 0) { 31011083Ssam errno = io->i_error; 31111083Ssam return (-1); 31211083Ssam } 3136068Smckusic if ((io->i_flgs & F_FILE) != 0) { 3146068Smckusic if (io->i_offset - off + size >= io->i_ino.i_size) 3156068Smckusic io->i_cc = diff + off; 316327Sbill io->i_cc -= off; 3176068Smckusic } 318327Sbill p = &io->i_buf[off]; 319327Sbill } 320327Sbill io->i_cc--; 321327Sbill io->i_offset++; 322327Sbill c = (unsigned)*p++; 323327Sbill io->i_ma = p; 32410022Ssam return (c); 325327Sbill } 3266068Smckusic 32710022Ssam int errno; 328327Sbill 329327Sbill read(fdesc, buf, count) 33010022Ssam int fdesc, count; 33110022Ssam char *buf; 332327Sbill { 33325166Skarels register i, size; 334327Sbill register struct iob *file; 33525166Skarels register struct fs *fs; 33625166Skarels int lbn, off; 337327Sbill 33810022Ssam errno = 0; 339327Sbill if (fdesc >= 0 & fdesc <= 2) { 340327Sbill i = count; 341327Sbill do { 342327Sbill *buf = getchar(); 343327Sbill } while (--i && *buf++ != '\n'); 34410022Ssam return (count - i); 345327Sbill } 346327Sbill fdesc -= 3; 3476068Smckusic if (fdesc < 0 || fdesc >= NFILES || 34810022Ssam ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { 34910022Ssam errno = EBADF; 35010022Ssam return (-1); 35110022Ssam } 35210022Ssam if ((file->i_flgs&F_READ) == 0) { 35310022Ssam errno = EBADF; 35410022Ssam return (-1); 35510022Ssam } 35634463Sbostic #ifndef SMALL 3576068Smckusic if ((file->i_flgs & F_FILE) == 0) { 358327Sbill file->i_cc = count; 359327Sbill file->i_ma = buf; 3607446Sroot file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE); 361327Sbill i = devread(file); 36210022Ssam if (i < 0) 36310022Ssam errno = file->i_error; 36430547Skarels else 36530547Skarels file->i_offset += i; 36610022Ssam return (i); 367327Sbill } 36834463Sbostic #endif 36925166Skarels if (file->i_offset+count > file->i_ino.i_size) 37025166Skarels count = file->i_ino.i_size - file->i_offset; 37125166Skarels if ((i = count) <= 0) 37225166Skarels return (0); 37325166Skarels /* 37425166Skarels * While reading full blocks, do I/O into user buffer. 37525166Skarels * Anything else uses getc(). 37625166Skarels */ 37725166Skarels fs = &file->i_fs; 37825166Skarels while (i) { 37925166Skarels off = blkoff(fs, file->i_offset); 38025166Skarels lbn = lblkno(fs, file->i_offset); 38125166Skarels size = blksize(fs, &file->i_ino, lbn); 38225166Skarels if (off == 0 && size <= i) { 38325166Skarels file->i_bn = fsbtodb(fs, sbmap(file, lbn)) + 38425166Skarels file->i_boff; 38525166Skarels file->i_cc = size; 38625166Skarels file->i_ma = buf; 38725166Skarels if (devread(file) < 0) { 38825166Skarels errno = file->i_error; 38925166Skarels return (-1); 39025166Skarels } 39125166Skarels file->i_offset += size; 39225166Skarels file->i_cc = 0; 39325166Skarels buf += size; 39425166Skarels i -= size; 39525166Skarels } else { 39625166Skarels size -= off; 39725166Skarels if (size > i) 39825166Skarels size = i; 39925166Skarels i -= size; 40025166Skarels do { 40125166Skarels *buf++ = getc(fdesc+3); 40225166Skarels } while (--size); 40325166Skarels } 40425166Skarels } 40525166Skarels return (count); 406327Sbill } 407327Sbill 40834463Sbostic #ifndef SMALL 409327Sbill write(fdesc, buf, count) 41010022Ssam int fdesc, count; 41110022Ssam char *buf; 412327Sbill { 413327Sbill register i; 414327Sbill register struct iob *file; 415327Sbill 41610022Ssam errno = 0; 417327Sbill if (fdesc >= 0 && fdesc <= 2) { 418327Sbill i = count; 419327Sbill while (i--) 420327Sbill putchar(*buf++); 42110022Ssam return (count); 422327Sbill } 423327Sbill fdesc -= 3; 4246068Smckusic if (fdesc < 0 || fdesc >= NFILES || 42510022Ssam ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { 42610022Ssam errno = EBADF; 42710022Ssam return (-1); 42810022Ssam } 42910022Ssam if ((file->i_flgs&F_WRITE) == 0) { 43010022Ssam errno = EBADF; 43110022Ssam return (-1); 43210022Ssam } 433327Sbill file->i_cc = count; 434327Sbill file->i_ma = buf; 4357446Sroot file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE); 436327Sbill i = devwrite(file); 4377446Sroot file->i_offset += count; 43810022Ssam if (i < 0) 43910022Ssam errno = file->i_error; 44010022Ssam return (i); 441327Sbill } 44234463Sbostic #endif 443327Sbill 4443349Swnj int openfirst = 1; 44534463Sbostic u_int opendev; /* last device opened */ 44634463Sbostic extern u_int bootdev; 4473349Swnj 448327Sbill open(str, how) 4496068Smckusic char *str; 45010022Ssam int how; 451327Sbill { 45234463Sbostic register char *t; 45334463Sbostic register int cnt; 454327Sbill register struct iob *file; 45534463Sbostic int fdesc, args[8], *argp; 456327Sbill 4573349Swnj if (openfirst) { 45834463Sbostic for (cnt = 0; cnt < NFILES; cnt++) 45934463Sbostic iob[cnt].i_flgs = 0; 4603349Swnj openfirst = 0; 461327Sbill } 462327Sbill 46334463Sbostic for (fdesc = 0;; fdesc++) { 46434463Sbostic if (fdesc == NFILES) 46534463Sbostic _stop("No more file slots"); 46634463Sbostic if (iob[fdesc].i_flgs == 0) { 46734463Sbostic file = &iob[fdesc]; 46834463Sbostic file->i_flgs |= F_ALLOC; 46934463Sbostic file->i_adapt = file->i_ctlr = file->i_unit = 47034463Sbostic file->i_part = 0; 47134463Sbostic break; 47234463Sbostic } 47334463Sbostic } 474327Sbill 47534463Sbostic for (cnt = 0; cnt < sizeof(args)/sizeof(args[0]); args[cnt++] = 0); 47634463Sbostic #ifndef SMALL 47734463Sbostic for (t = str; *t && *t != '/' && *t != ':' && *t != '('; ++t) 47834463Sbostic if (isupper(*t)) 47934463Sbostic *t = tolower(*t); 48034463Sbostic switch(*t) { 48134463Sbostic case '(': /* type(adapt, ctlr, drive, partition)file */ 48234463Sbostic if ((file->i_ino.i_dev = getdev(str, t - str)) == -1) 48330547Skarels goto bad; 48434463Sbostic for (argp = args + 4, cnt = 0; *t != ')'; ++cnt) { 48534463Sbostic for (++t; isspace(*t); ++t); 48634463Sbostic if (*t == ')') 48734463Sbostic break; 48834463Sbostic if (!isdigit(*t)) 48930547Skarels goto badspec; 49034463Sbostic *argp++ = atoi(t); 49134463Sbostic for (++t; isdigit(*t); ++t); 49234463Sbostic if (*t != ',' && *t != ')' || cnt == 4) 49334463Sbostic goto badspec; 49430547Skarels } 49534463Sbostic for (++t; isspace(*t); ++t); 49634463Sbostic argp -= 4; 49734463Sbostic file->i_adapt = *argp++; 49834463Sbostic file->i_ctlr = *argp++; 49934463Sbostic file->i_unit = *argp++; 50034463Sbostic file->i_part = *argp; 50134463Sbostic break; 50234463Sbostic case ':': /* [A-Za-z]*[0-9]*[A-Za-z]:file */ 50334463Sbostic for (t = str; *t != ':' && !isdigit(*t); ++t); 50434463Sbostic if ((file->i_ino.i_dev = getdev(str, t - str)) == -1) 50530547Skarels goto bad; 50634463Sbostic if ((file->i_unit = getunit(t)) == -1) 50730547Skarels goto bad; 50834463Sbostic for (; isdigit(*t); ++t); 50934463Sbostic if (*t >= 'a' && *t <= 'h') 51034463Sbostic file->i_part = *t++ - 'a'; 51134463Sbostic if (*t != ':') { 51225166Skarels errno = EOFFSET; 51330547Skarels goto badspec; 51425166Skarels } 51534463Sbostic for (++t; isspace(*t); ++t); 51634463Sbostic break; 51734463Sbostic case '/': 51834463Sbostic default: /* default bootstrap unit and device */ 51934463Sbostic #else 52034463Sbostic { 52134463Sbostic #endif /* SMALL */ 52234463Sbostic file->i_ino.i_dev = B_TYPE(bootdev); 52334463Sbostic file->i_adapt = B_ADAPTOR(bootdev); 52434463Sbostic file->i_ctlr = B_CONTROLLER(bootdev); 52534463Sbostic file->i_unit = B_UNIT(bootdev); 52634463Sbostic file->i_part = B_PARTITION(bootdev); 52734463Sbostic t = str; 52825166Skarels } 52934463Sbostic 53034463Sbostic opendev = MAKEBOOTDEV(file->i_ino.i_dev, file->i_adapt, file->i_ctlr, 53134463Sbostic file->i_unit, file->i_part); 53234463Sbostic 53330547Skarels if (errno = devopen(file)) 53430547Skarels goto bad; 53534463Sbostic 53634463Sbostic if (*t == '\0') { 53734463Sbostic file->i_flgs |= how + 1; 53825166Skarels file->i_cc = 0; 53925166Skarels file->i_offset = 0; 54025166Skarels return (fdesc+3); 54125166Skarels } 54234463Sbostic #ifndef SMALL 54334463Sbostic else if (how != 0) { 54434463Sbostic printf("Can't write files yet.. Sorry\n"); 54534463Sbostic errno = EIO; 54634463Sbostic goto bad; 54734463Sbostic } 54833408Skarels #endif 5496068Smckusic file->i_ma = (char *)(&file->i_fs); 5506068Smckusic file->i_cc = SBSIZE; 55130768Skarels file->i_bn = SBOFF / DEV_BSIZE + file->i_boff; 5526068Smckusic file->i_offset = 0; 55311083Ssam if (devread(file) < 0) { 55411083Ssam errno = file->i_error; 55511083Ssam printf("super block read error\n"); 55630547Skarels goto bad; 55711083Ssam } 55834463Sbostic if ((cnt = find(t, file)) == 0) { 55910022Ssam errno = ESRCH; 56030547Skarels goto bad; 561327Sbill } 56234463Sbostic if (openi(cnt, file) < 0) { 56311083Ssam errno = file->i_error; 56430547Skarels goto bad; 56511083Ssam } 566327Sbill file->i_offset = 0; 567327Sbill file->i_cc = 0; 568327Sbill file->i_flgs |= F_FILE | (how+1); 56910022Ssam return (fdesc+3); 57030547Skarels 57133408Skarels #ifndef SMALL 57230547Skarels badspec: 57334463Sbostic printf("malformed device specification\nusage: device(adaptor, controller, drive, partition)file\n"); 57433408Skarels #endif 57530547Skarels bad: 57630547Skarels file->i_flgs = 0; 57730547Skarels return (-1); 578327Sbill } 579327Sbill 58030924Skarels #ifndef SMALL 58130547Skarels static 58230547Skarels getdev(str, len) 58333408Skarels register char *str; 58430547Skarels int len; 58530547Skarels { 58630547Skarels register struct devsw *dp; 58733408Skarels register int i; 58834463Sbostic char savedch = str[len]; 58930547Skarels 59034463Sbostic str[len] = '\0'; 59133408Skarels for (dp = devsw, i = 0; i < ndevs; dp++, i++) 59233408Skarels if (dp->dv_name && strcmp(str, dp->dv_name) == 0) { 59334463Sbostic str[len] = savedch; 59433408Skarels return (i); 59533408Skarels } 59633408Skarels printf("Unknown device\nKnown devices are:\n"); 59733408Skarels for (dp = devsw, i = 0; i < ndevs; dp++, i++) 59833408Skarels if (dp->dv_name) 59933408Skarels printf(" %s", dp->dv_name); 60034463Sbostic printf("\n"); 60130547Skarels errno = ENXIO; 60230547Skarels return (-1); 60330547Skarels } 60430547Skarels 60530547Skarels static 60630547Skarels getunit(cp) 60730547Skarels register char *cp; 60830547Skarels { 60934463Sbostic int unit; 61030547Skarels 61134463Sbostic unit = atoi(cp); 61234463Sbostic if ((u_int)unit > 255) { 61330547Skarels printf("minor device number out of range (0-255)\n"); 61430547Skarels errno = EUNIT; 61534463Sbostic return (-1); 61630547Skarels } 61734463Sbostic return (unit); 61830547Skarels } 61934463Sbostic #endif /* SMALL */ 62030547Skarels 621327Sbill close(fdesc) 62210022Ssam int fdesc; 623327Sbill { 624327Sbill struct iob *file; 625327Sbill 626327Sbill fdesc -= 3; 6276068Smckusic if (fdesc < 0 || fdesc >= NFILES || 62810022Ssam ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { 62910022Ssam errno = EBADF; 63010022Ssam return (-1); 63110022Ssam } 632327Sbill if ((file->i_flgs&F_FILE) == 0) 633327Sbill devclose(file); 634327Sbill file->i_flgs = 0; 63510022Ssam return (0); 636327Sbill } 637327Sbill 63834463Sbostic #ifndef SMALL 63910022Ssam ioctl(fdesc, cmd, arg) 64010022Ssam int fdesc, cmd; 64110022Ssam char *arg; 64210022Ssam { 64310022Ssam register struct iob *file; 64410022Ssam int error = 0; 64510022Ssam 64610331Shelge fdesc -= 3; 64710022Ssam if (fdesc < 0 || fdesc >= NFILES || 64810022Ssam ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { 64910022Ssam errno = EBADF; 65010022Ssam return (-1); 65110022Ssam } 65210022Ssam switch (cmd) { 65310022Ssam 65410022Ssam case SAIOHDR: 65510022Ssam file->i_flgs |= F_HDR; 65610022Ssam break; 65710022Ssam 65810022Ssam case SAIOCHECK: 65910022Ssam file->i_flgs |= F_CHECK; 66010022Ssam break; 66110022Ssam 66210022Ssam case SAIOHCHECK: 66310022Ssam file->i_flgs |= F_HCHECK; 66410022Ssam break; 66510022Ssam 66610331Shelge case SAIONOBAD: 66710331Shelge file->i_flgs |= F_NBSF; 66810331Shelge break; 66910331Shelge 67010331Shelge case SAIODOBAD: 67110331Shelge file->i_flgs &= ~F_NBSF; 67210331Shelge break; 67310331Shelge 67410022Ssam default: 67510022Ssam error = devioctl(file, cmd, arg); 67610022Ssam break; 67710022Ssam } 67810022Ssam if (error < 0) 67910022Ssam errno = file->i_error; 68010022Ssam return (error); 68110022Ssam } 68234463Sbostic #endif /* SMALL */ 68310022Ssam 684327Sbill exit() 685327Sbill { 686327Sbill _stop("Exit called"); 687327Sbill } 688327Sbill 689327Sbill _stop(s) 69010022Ssam char *s; 691327Sbill { 6922391Stoy int i; 6932391Stoy 6942391Stoy for (i = 0; i < NFILES; i++) 6952391Stoy if (iob[i].i_flgs != 0) 6962391Stoy close(i); 697327Sbill printf("%s\n", s); 698327Sbill _rtt(); 699327Sbill } 700