static char rcsid[] = "@(#)$Id: can_access.c,v 1.3 1999/03/24 14:03:50 wfp5p Exp $";
/*******************************************************************************
* The Elm Mail System - $Revision: 1.3 $ $State: Exp $
*
* Copyright (c) 1988-1995 USENET Community Trust
* Copyright (c) 1986,1987 Dave Taylor
*******************************************************************************
* Bug reports, patches, comments, suggestions should be sent to:
*
* Bill Pemberton, Elm Coordinator
* flash@virginia.edu
*
*******************************************************************************
* $Log: can_access.c,v $
* Revision 1.3 1999/03/24 14:03:50 wfp5p
* elm 2.5PL0
*
* Revision 1.2 1995/09/29 17:41:04 wfp5p
* Alpha 8 (Chip's big changes)
*
* Revision 1.1.1.1 1995/04/19 20:38:31 wfp5p
* Initial import of elm 2.4 PL0 as base for elm 2.5.
*
******************************************************************************/
/*
* can_access() - Verify that a user can access a filesystem entry
* as their normal uid/gid, and also that the entry is a regular file.
* Returns 0 on success. Returns -1 and sets errno on failure.
*/
#include "elm_defs.h"
#include <errno.h>
#include "port_stat.h"
#include "port_wait.h"
#ifndef VFORK
# ifndef vfork
# define vfork fork
# endif
#endif
static int painful_access_check P_((const char *, int));
int
can_access(fname, mode)
const char *fname;
int mode;
{
struct stat stat_buf;
int rc;
if (mode == F_OK || (getuid() == geteuid() && getgid() == getegid()))
rc = access(fname, mode);
else
rc = painful_access_check(fname, mode);
if ( (rc == 0) &&
(stat(fname, &stat_buf) == 0) &&
( !S_ISREG(stat_buf.st_mode) && !S_ISCHR(stat_buf.st_mode) ) )
{
errno = EISDIR; /* well...at least it is not a file */
rc = -1;
}
return rc;
}
#ifndef I_UNISTD
void _exit();
#endif
static int
painful_access_check(file, mode)
const char *file;
int mode;
{
int pid, w, err;
waitstatus_t status;
register SIGHAND_TYPE (*istat)(), (*qstat)();
if ((pid = vfork()) < 0) {
errno = EAGAIN;
return -1;
}
if (pid == 0) {
SETGID(getgid());
setuid(getuid());
_exit(access(file, mode) == 0 ? 0 : errno);
}
istat = signal(SIGINT, SIG_IGN);
qstat = signal(SIGQUIT, SIG_IGN);
while ((w = wait(&status)) != pid) {
if (w < 0 && errno != EINTR)
break;
}
err = errno;
signal(SIGINT, istat);
signal(SIGQUIT, qstat);
/* wait() failed?? */
if (w < 0) {
errno = err;
return -1;
}
/* subprocess stopped?? */
if (!WIFEXITED(status)) {
errno = EINTR; /* ehhh...pick one...shouldn't really happen */
return -1;
}
/* exit status is errno from access check */
if ((err = WEXITSTATUS(status)) != 0) {
errno = err;
return -1;
}
errno = 0;
return 0;
}
#ifdef _TEST /*{*/
static char *mstr[] = {
"F_OK", /* 00 --- */
"X_OK", /* 01 --x */
"W_OK", /* 02 -w- */
"W_OK X_OK", /* 03 -wx */
"R_OK", /* 04 r-- */
"R_OK X_OK", /* 05 r-x */
"R_OK W_OK", /* 06 rw- */
"R_OK W_OK X_OK", /* 07 rwx */
};
main()
{
char path[512], buf[512], *pstr;
int mode, rc, err;
(void) strcpy(path, "/blurfl/grimmitz");
mode = 0;
for (;;) {
printf("path [%s] : ", path);
if (gets(buf) == NULL)
break;
if (buf[0] != '\0')
(void) strcpy(path, buf);
printf("mode [%d] : ", mode);
if (gets(buf) == NULL)
break;
if (buf[0] != '\0')
mode = atoi(buf);
rc = can_access(path, mode);
err = errno;
switch (rc) {
case 0:
printf("can_access(\"%s\", \"%s\") succeeded\n",
path, mstr[mode&07]);
break;
case -1:
printf("can_access(\"%s\", \"%s\") failed [%s]\n",
path, mstr[mode&07], strerror(err));
break;
default:
printf("can_access(\"%s\", \"%s\") ???rc=%d??? [%s]\n",
path, mstr[mode&07], rc, strerror(err));
break;
}
putchar('\n');
}
putchar('\n');
exit(0);
}
#endif /*}_TEST*/
syntax highlighted by Code2HTML, v. 0.9.1