static char rcsid[] = "@(#)$Id: can_access.c,v 1.11 2006/04/09 07:37:05 hurtta Exp $";

/******************************************************************************
 *  The Elm (ME+) Mail System  -  $Revision: 1.11 $   $State: Exp $
 *
 *  Modified by: Kari Hurtta <hurtta+elm@posti.FMI.FI>
 *                           (was hurtta+elm@ozone.FMI.FI)
 ******************************************************************************
 *  The Elm Mail System 
 *
 *			Copyright (c) 1988-1992 USENET Community Trust
 *			Copyright (c) 1986,1987 Dave Taylor
 *****************************************************************************/

/** can_access - can this user access this file using their normal uid/gid

**/

/* WHAT HELL THIS IS!
 *
 * access -system call uses real uid / gid anyway !!!!!
 *
 *                              - K E H <hurtta@ozone.FMI.FI>
 */

#include "headers.h"
#include <errno.h>
#ifndef ANSI_C
extern int errno;		/* system error number */
#endif

#ifndef I_UNISTD
void _exit();
#endif



int can_access(file, mode)
     char *file; 
     int   mode;
{
	/** returns ZERO iff user can access file or "errno" otherwise **/

	int the_stat = 0, pid, w; 
	struct stat stat_buf;
#if defined(BSD_TYPE) && !defined(WEXITSTATUS)
	union wait status;
#else
	int status;
#endif
	
#ifdef VFORK
	if ((pid = vfork()) == 0) {
#else
	if ((pid = fork()) == 0) {
#endif

	  /* Why we are returning to real gid/uid -- 
	     access() uses them anyway!
	  */

	  if (-1 == setgid(groupid)) {
	    int err = errno;
	    fprintf(stderr,"can_access: setgid(%d) FAILED: %s\n",
		    groupid,error_description(err));
	    fflush(stderr);
	    _exit(err != 0? err : 1);	/* never return zero! */
	  }
	  if (-1 == setuid(userid)) {		/** back to normal userid **/
	    int err = errno;
	    fprintf(stderr,"can_access: setuid(%d) FAILED: %s\n",
		    userid,error_description(err));
	    fflush(stderr);
	    _exit(err != 0? err : 1);	/* never return zero! */
	  }

	  errno = 0;

	  if (access(file, mode) == 0) 
	    _exit(0);
	  else 
	    _exit(errno != 0? errno : 1);	/* never return zero! */
	  _exit(127);
	}

	errno = 0;
	while (((w = my_wait(pid,&status)) != pid && w != -1) || 
	       EINTR == errno)
	  ;


	if (w == -1) {
	  the_stat = errno;
	  if (!the_stat)
	    the_stat = 1;
	} else {
	  int sig = convert_status(status,&the_stat);
	  if (sig)
	    the_stat = 1;
	}

	if (the_stat == 0) {
	  if (stat(file, &stat_buf) == 0) {
#ifndef _POSIX_SOURCE
	    w = stat_buf.st_mode & S_IFMT;
	    if (w != S_IFREG)
	      the_stat = 1;
#else /* _POSIX_SOURCE */
	    w = stat_buf.st_mode;

	    if (! S_ISREG(w))
	      the_stat = 1;
#endif
	  }
	}

	return(the_stat);
}

/*
 * Local Variables:
 *  mode:c
 *  c-basic-offset:4
 *  buffer-file-coding-system: iso-8859-1
 * End:
 */


syntax highlighted by Code2HTML, v. 0.9.1