Return to BSD News archive
Newsgroups: comp.os.386bsd.development Path: sserve!newshost.anu.edu.au!munnari.oz.au!news.Hawaii.Edu!ames!haven.umd.edu!darwin.sura.net!sgiblab!majipoor.cygnus.com!kithrup.com!sef From: sef@kithrup.com (Sean Eric Fagan) Subject: eaccess() system call Organization: Kithrup Enterprises, Ltd. Message-ID: <CA9zvs.82J@kithrup.com> Date: Fri, 16 Jul 1993 21:04:25 GMT Lines: 216 I saw a discussion about making ash handle multiple groups correctly (in determining whether a file could be executed or not), and was appalled, since it was, basicly, replicating code that was already in the kernel -- sorta, since access() uses real user and group id's, but a shell only needs to care about the effective id's. So, I decided to write eaccess(), which is exactly like access(), only it uses the effective id's. When I did so, I found three more files that were missing from the 386BSD distribution, al in /sys/kern: syscalls.master, makesyscalls.sh, and Makefile. I've let both the NetBSD and interim groups know about this, so the missing files should be in the next release. In the meanwhile, you can get them from any archive site that has net/2. Anyway, for anyone who really cares, here's eaccess(), and some patches to /bin/sh to make it use it. The NetBSD folks don't want it, I haven't heard back from the 4.4 folks, and I have offered it to the interim folks :). But, if nothing else, it can serve as an example of how to add a system call to *bsd. Enjoy. *** sys.386bsd/kern/vfs_syscalls.c.~1~ Sat May 16 20:22:16 1992 --- sys.386bsd/kern/vfs_syscalls.c Wed Jul 14 21:41:20 1993 *************** *** 969,975 **** /* * Check access permissions. */ ! /* ARGSUSED */ saccess(p, uap, retval) struct proc *p; register struct args { --- 969,989 ---- /* * Check access permissions. */ ! ! eaccess(p, uap, retval) ! struct proc *p; ! register struct args { ! char *fname; ! int fmode; ! } *uap; ! int *retval; ! { ! int error; ! ! error = saccess1(p, uap, retval); ! return error; ! } ! saccess(p, uap, retval) struct proc *p; register struct args { *************** *** 978,994 **** } *uap; int *retval; { register struct nameidata *ndp; register struct ucred *cred = p->p_ucred; register struct vnode *vp; ! int error, mode, svuid, svgid; struct nameidata nd; ndp = &nd; - svuid = cred->cr_uid; - svgid = cred->cr_groups[0]; - cred->cr_uid = p->p_cred->p_ruid; - cred->cr_groups[0] = p->p_cred->p_rgid; ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; ndp->ni_segflg = UIO_USERSPACE; ndp->ni_dirp = uap->fname; --- 992,1025 ---- } *uap; int *retval; { + int error; + int svuid = p->p_ucred->cr_uid; + int svgid = p->p_ucred->cr_groups[0]; + + p->p_ucred->cr_uid = p->p_cred->p_ruid; + p->p_ucred->cr_groups[0] = p->p_cred->p_rgid; + error = saccess1(p, uap, retval); + p->p_ucred->cr_uid = svuid; + p->p_ucred->cr_groups[0] = svgid; + return error; + } + + /* ARGSUSED */ + saccess1(p, uap, retval) + struct proc *p; + register struct args { + char *fname; + int fmode; + } *uap; + int *retval; + { register struct nameidata *ndp; register struct ucred *cred = p->p_ucred; register struct vnode *vp; ! int error, mode; struct nameidata nd; ndp = &nd; ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; ndp->ni_segflg = UIO_USERSPACE; ndp->ni_dirp = uap->fname; *************** *** 1011,1018 **** } vput(vp); out1: - cred->cr_uid = svuid; - cred->cr_groups[0] = svgid; return (error); } --- 1042,1047 ---- *** sys.386bsd/kern/syscalls.master.~1~ Tue Jul 13 19:48:26 1993 --- sys.386bsd/kern/syscalls.master Wed Jul 14 14:49:21 1993 *************** *** 114,120 **** 78 STD 3 mincore 79 STD 2 getgroups 80 STD 2 setgroups ! 81 STD 0 getpgrp 82 STD 2 setpgid 83 STD 3 setitimer 84 COMPAT 0 wait --- 114,120 ---- 78 STD 3 mincore 79 STD 2 getgroups 80 STD 2 setgroups ! 81 STD 1 getpgrp 82 STD 2 setpgid 83 STD 3 setitimer 84 COMPAT 0 wait *** lib/libc/sys/Makefile.inc.~1~ Wed Feb 12 23:42:44 1992 --- lib/libc/sys/Makefile.inc Wed Jul 14 17:29:42 1993 *************** *** 11,17 **** # modules with default implementations on all architectures: ASM= accept.o access.o acct.o adjtime.o async_daemon.o bind.o chdir.o \ chflags.o chmod.o chown.o chroot.o close.o connect.o dup.o dup2.o \ ! execve.o fchdir.o fchflags.o fchmod.o fchown.o fcntl.o flock.o \ fstat.o fstatfs.o fsync.o ftruncate.o getdirentries.o \ getdtablesize.o getegid.o geteuid.o getfh.o getfsstat.o getgid.o \ getgroups.o gethostid.o gethostname.o getitimer.o getkerninfo.o \ --- 11,17 ---- # modules with default implementations on all architectures: ASM= accept.o access.o acct.o adjtime.o async_daemon.o bind.o chdir.o \ chflags.o chmod.o chown.o chroot.o close.o connect.o dup.o dup2.o \ ! eaccess.o execve.o fchdir.o fchflags.o fchmod.o fchown.o fcntl.o flock.o \ fstat.o fstatfs.o fsync.o ftruncate.o getdirentries.o \ getdtablesize.o getegid.o geteuid.o getfh.o getfsstat.o getgid.o \ getgroups.o gethostid.o gethostname.o getitimer.o getkerninfo.o \ *** bin/sh/exec.c.~1~ Mon Apr 15 17:22:50 1991 --- bin/sh/exec.c Wed Jul 14 22:52:49 1993 *************** *** 66,71 **** --- 66,72 ---- #include "mystring.h" #include <sys/types.h> #include <sys/stat.h> + #include <unistd.h> #include <fcntl.h> #include <errno.h> *************** *** 459,464 **** --- 460,473 ---- TRACE(("searchexec \"%s\": no change\n", name)); goto success; } + #if 1 + while (eaccess(fullname, X_OK) < 0) { + if (errno != ENOENT && errno != ENOTDIR) + e = errno; + goto loop; + } + e = EACCES; + #else while (stat(fullname, &statb) < 0) { #ifdef SYSV if (errno == EINTR) *************** *** 471,476 **** --- 480,486 ---- e = EACCES; /* if we fail, this will be the error */ if ((statb.st_mode & S_IFMT) != S_IFREG) goto loop; + #endif if (pathopt) { /* this is a %func directory */ stalloc(strlen(fullname) + 1); readcmdfile(fullname); *************** *** 479,484 **** --- 489,495 ---- stunalloc(fullname); goto success; } + #if 0 if (statb.st_uid == geteuid()) { if ((statb.st_mode & 0100) == 0) goto loop; *************** *** 489,494 **** --- 500,506 ---- if ((statb.st_mode & 01) == 0) goto loop; } + #endif TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname)); INTOFF; cmdp = cmdlookup(name, 1);