📄 doio.c
字号:
if (stio->dirp) closedir(stio->dirp); if (!(stio->dirp = opendir(str_get(st[sp+1])))) goto nope; break; case O_READDIR: if (gimme == G_ARRAY) { --sp; /*SUPPRESS 560*/ while (dp = readdir(stio->dirp)) {#ifdef DIRNAMLEN (void)astore(ary,++sp, str_2mortal(str_make(dp->d_name,dp->d_namlen)));#else (void)astore(ary,++sp, str_2mortal(str_make(dp->d_name,0)));#endif } } else { if (!(dp = readdir(stio->dirp))) goto nope; st[sp] = str_mortal(&str_undef);#ifdef DIRNAMLEN str_nset(st[sp], dp->d_name, dp->d_namlen);#else str_set(st[sp], dp->d_name);#endif } break;#if defined(HAS_TELLDIR) || defined(telldir) case O_TELLDIR: {#ifndef telldir long telldir();#endif st[sp] = str_mortal(&str_undef); str_numset(st[sp], (double)telldir(stio->dirp)); break; }#endif#if defined(HAS_SEEKDIR) || defined(seekdir) case O_SEEKDIR: st[sp] = str_mortal(&str_undef); along = (long)str_gnum(st[sp+1]); (void)seekdir(stio->dirp,along); break;#endif#if defined(HAS_REWINDDIR) || defined(rewinddir) case O_REWINDDIR: st[sp] = str_mortal(&str_undef); (void)rewinddir(stio->dirp); break;#endif case O_CLOSEDIR: st[sp] = str_mortal(&str_undef); (void)closedir(stio->dirp); stio->dirp = 0; break; default: goto phooey; } return sp;nope: st[sp] = &str_undef; if (!errno) errno = EBADF; return sp;#endifphooey: fatal("Unimplemented directory operation");}intapply(type,arglast)int type;int *arglast;{ register STR **st = stack->ary_array; register int sp = arglast[1]; register int items = arglast[2] - sp; register int val; register int val2; register int tot = 0; char *s;#ifdef TAINT for (st += ++sp; items--; st++) tainted |= (*st)->str_tainted; st = stack->ary_array; sp = arglast[1]; items = arglast[2] - sp;#endif switch (type) { case O_CHMOD:#ifdef TAINT taintproper("Insecure dependency in chmod");#endif if (--items > 0) { tot = items; val = (int)str_gnum(st[++sp]); while (items--) { if (chmod(str_get(st[++sp]),val)) tot--; } } break;#ifdef HAS_CHOWN case O_CHOWN:#ifdef TAINT taintproper("Insecure dependency in chown");#endif if (items > 2) { items -= 2; tot = items; val = (int)str_gnum(st[++sp]); val2 = (int)str_gnum(st[++sp]); while (items--) { if (chown(str_get(st[++sp]),val,val2)) tot--; } } break;#endif#ifdef HAS_KILL case O_KILL:#ifdef TAINT taintproper("Insecure dependency in kill");#endif if (--items > 0) { tot = items; s = str_get(st[++sp]); if (isUPPER(*s)) { if (*s == 'S' && s[1] == 'I' && s[2] == 'G') s += 3; if (!(val = whichsig(s))) fatal("Unrecognized signal name \"%s\"",s); } else val = (int)str_gnum(st[sp]); if (val < 0) { val = -val; while (items--) { int proc = (int)str_gnum(st[++sp]);#ifdef HAS_KILLPG if (killpg(proc,val)) /* BSD */#else if (kill(-proc,val)) /* SYSV */#endif tot--; } } else { while (items--) { if (kill((int)(str_gnum(st[++sp])),val)) tot--; } } } break;#endif case O_UNLINK:#ifdef TAINT taintproper("Insecure dependency in unlink");#endif tot = items; while (items--) { s = str_get(st[++sp]); if (euid || unsafe) { if (UNLINK(s)) tot--; } else { /* don't let root wipe out directories without -U */#ifdef HAS_LSTAT if (lstat(s,&statbuf) < 0 || S_ISDIR(statbuf.st_mode))#else if (stat(s,&statbuf) < 0 || S_ISDIR(statbuf.st_mode))#endif tot--; else { if (UNLINK(s)) tot--; } } } break; case O_UTIME:#ifdef TAINT taintproper("Insecure dependency in utime");#endif if (items > 2) {#ifdef I_UTIME struct utimbuf utbuf;#else struct { long actime; long modtime; } utbuf;#endif Zero(&utbuf, sizeof utbuf, char); utbuf.actime = (long)str_gnum(st[++sp]); /* time accessed */ utbuf.modtime = (long)str_gnum(st[++sp]); /* time modified */ items -= 2;#ifndef lint tot = items; while (items--) { if (utime(str_get(st[++sp]),&utbuf)) tot--; }#endif } else items = 0; break; } return tot;}/* Do the permissions allow some operation? Assumes statcache already set. */intcando(bit, effective, statbufp)int bit;int effective;register struct stat *statbufp;{#ifdef DOSISH /* [Comments and code from Len Reed] * MS-DOS "user" is similar to UNIX's "superuser," but can't write * to write-protected files. The execute permission bit is set * by the Miscrosoft C library stat() function for the following: * .exe files * .com files * .bat files * directories * All files and directories are readable. * Directories and special files, e.g. "CON", cannot be * write-protected. * [Comment by Tom Dinger -- a directory can have the write-protect * bit set in the file system, but DOS permits changes to * the directory anyway. In addition, all bets are off * here for networked software, such as Novell and * Sun's PC-NFS.] */ /* Atari stat() does pretty much the same thing. we set x_bit_set_in_stat * too so it will actually look into the files for magic numbers */ return (bit & statbufp->st_mode) ? TRUE : FALSE;#else /* ! MSDOS */ if ((effective ? euid : uid) == 0) { /* root is special */ if (bit == S_IXUSR) { if (statbufp->st_mode & 0111 || S_ISDIR(statbufp->st_mode)) return TRUE; } else return TRUE; /* root reads and writes anything */ return FALSE; } if (statbufp->st_uid == (effective ? euid : uid) ) { if (statbufp->st_mode & bit) return TRUE; /* ok as "user" */ } else if (ingroup((int)statbufp->st_gid,effective)) { if (statbufp->st_mode & bit >> 3) return TRUE; /* ok as "group" */ } else if (statbufp->st_mode & bit >> 6) return TRUE; /* ok as "other" */ return FALSE;#endif /* ! MSDOS */}intingroup(testgid,effective)int testgid;int effective;{ if (testgid == (effective ? egid : gid)) return TRUE;#ifdef HAS_GETGROUPS#ifndef NGROUPS#define NGROUPS 32#endif { GROUPSTYPE gary[NGROUPS]; int anum; anum = getgroups(NGROUPS,gary); while (--anum >= 0) if (gary[anum] == testgid) return TRUE; }#endif return FALSE;}#if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)intdo_ipcget(optype, arglast)int optype;int *arglast;{ register STR **st = stack->ary_array; register int sp = arglast[0]; key_t key; int n, flags; key = (key_t)str_gnum(st[++sp]); n = (optype == O_MSGGET) ? 0 : (int)str_gnum(st[++sp]); flags = (int)str_gnum(st[++sp]); errno = 0; switch (optype) {#ifdef HAS_MSG case O_MSGGET: return msgget(key, flags);#endif#ifdef HAS_SEM case O_SEMGET: return semget(key, n, flags);#endif#ifdef HAS_SHM case O_SHMGET: return shmget(key, n, flags);#endif#if !defined(HAS_MSG) || !defined(HAS_SEM) || !defined(HAS_SHM) default: fatal("%s not implemented", opname[optype]);#endif } return -1; /* should never happen */}intdo_ipcctl(optype, arglast)int optype;int *arglast;{ register STR **st = stack->ary_array; register int sp = arglast[0]; STR *astr; char *a; int id, n, cmd, infosize, getinfo, ret; id = (int)str_gnum(st[++sp]); n = (optype == O_SEMCTL) ? (int)str_gnum(st[++sp]) : 0; cmd = (int)str_gnum(st[++sp]); astr = st[++sp]; infosize = 0; getinfo = (cmd == IPC_STAT); switch (optype) {#ifdef HAS_MSG case O_MSGCTL: if (cmd == IPC_STAT || cmd == IPC_SET) infosize = sizeof(struct msqid_ds); break;#endif#ifdef HAS_SHM case O_SHMCTL: if (cmd == IPC_STAT || cmd == IPC_SET) infosize = sizeof(struct shmid_ds); break;#endif#ifdef HAS_SEM case O_SEMCTL: if (cmd == IPC_STAT || cmd == IPC_SET) infosize = sizeof(struct semid_ds); else if (cmd == GETALL || cmd == SETALL) { struct semid_ds semds; if (semctl(id, 0, IPC_STAT, &semds) == -1) return -1; getinfo = (cmd == GETALL); infosize = semds.sem_nsems * sizeof(short); /* "short" is technically wrong but much more portable than guessing about u_?short(_t)? */ } break;#endif#if !defined(HAS_MSG) || !defined(HAS_SEM) || !defined(HAS_SHM) default: fatal("%s not implemented", opname[optype]);#endif } if (infosize) { if (getinfo) { STR_GROW(astr, infosize+1); a = str_get(astr); } else { a = str_get(astr); if (astr->str_cur != infosize) { errno = EINVAL; return -1; } } } else { int i = (int)str_gnum(astr); a = (char *)i; /* ouch */ } errno = 0; switch (optype) {#ifdef HAS_MSG case O_MSGCTL: ret = msgctl(id, cmd, (struct msqid_ds *)a); break;#endif#ifdef HAS_SEM case O_SEMCTL: ret = semctl(id, n, cmd, a); break;#endif#ifdef HAS_SHM case O_SHMCTL: ret = shmctl(id, cmd, (struct shmid_ds *)a); break;#endif } if (getinfo && ret >= 0) { astr->str_cur = infosize; astr->str_ptr[infosize] = '\0'; } return ret;}intdo_msgsnd(arglast)int *arglast;{#ifdef HAS_MSG register STR **st = stack->ary_array; register int sp = arglast[0]; STR *mstr; char *mbuf; int id, msize, flags; id = (int)str_gnum(st[++sp]); mstr = st[++sp]; flags = (int)str_gnum(st[++sp]); mbuf = str_get(mstr); if ((msize = mstr->str_cur - sizeof(long)) < 0) { errno = EINVAL; return -1; } errno = 0; return msgsnd(id, (struct msgbuf *)mbuf, msize, flags);#else fatal("msgsnd not implemented");#endif}intdo_msgrcv(arglast)int *arglast;{#ifdef HAS_MSG register STR **st = stack->ary_array; register int sp = arglast[0]; STR *mstr; char *mbuf; long mtype; int id, msize, flags, ret; id = (int)str_gnum(st[++sp]); mstr = st[++sp]; msize = (int)str_gnum(st[++sp]); mtype = (long)str_gnum(st[++sp]); flags = (int)str_gnum(st[++sp]); mbuf = str_get(mstr); if (mstr->str_cur < sizeof(long)+msize+1) { STR_GROW(mstr, sizeof(long)+msize+1); mbuf = str_get(mstr); } errno = 0; ret = msgrcv(id, (struct msgbuf *)mbuf, msize, mtype, flags); if (ret >= 0) { mstr->str_cur = sizeof(long)+ret; mstr->str_ptr[sizeof(long)+ret] = '\0'; } return ret;#else fatal("msgrcv not implemented");#endif}intdo_semop(arglast)int *arglast;{#ifdef HAS_SEM register STR **st = stack->ary_array; register int sp = arglast[0]; STR *opstr; char *opbuf; int id, opsize; id = (int)str_gnum(st[++sp]); opstr = st[++sp]; opbuf = str_get(opstr); opsize = opstr->str_cur; if (opsize < sizeof(struct sembuf) || (opsize % sizeof(struct sembuf)) != 0) { errno = EINVAL; return -1; } errno = 0; return semop(id, (struct sembuf *)opbuf, opsize/sizeof(struct sembuf));#else fatal("semop not implemented");#endif}intdo_shmio(optype, arglast)int optype;int *arglast;{#ifdef HAS_SHM register STR **st = stack->ary_array; register int sp = arglast[0]; STR *mstr; char *mbuf, *shm; int id, mpos, msize; struct shmid_ds shmds;#ifndef VOIDSHMAT extern char *shmat();#endif id = (int)str_gnum(st[++sp]); mstr = st[++sp]; mpos = (int)str_gnum(st[++sp]); msize = (int)str_gnum(st[++sp]); errno = 0; if (shmctl(id, IPC_STAT, &shmds) == -1) return -1; if (mpos < 0 || msize < 0 || mpos + msize > shmds.shm_segsz) { errno = EFAULT; /* can't do as caller requested */ return -1; } shm = (char*)shmat(id, (char*)NULL, (optype == O_SHMREAD) ? SHM_RDONLY : 0); if (shm == (char *)-1) /* I hate System V IPC, I really do */ return -1; mbuf = str_get(mstr); if (optype == O_SHMREAD) { if (mstr->str_cur < msize) { STR_GROW(mstr, msize+1); mbuf = str_get(mstr); } Copy(shm + mpos, mbuf, msize, char); mstr->str_cur = msize; mstr->str_ptr[msize] = '\0'; } else { int n; if ((n = mstr->str_cur) > msize) n = msize; Copy(mbuf, shm + mpos, n, char); if (n < msize) memzero(shm + mpos + n, msize - n); } return shmdt(shm);#else fatal("shm I/O not implemented");#endif}#endif /* SYSV IPC */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -