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

/******************************************************************************
 *  The Elm (ME+) Mail System  -  $Revision: 1.13 $   $State: Exp $
 *
 *  Modified by: Kari Hurtta <hurtta+elm@poasti.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_open - can this user open this file using their normal uid/gid

**/

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

DEBUG_VAR(Debug,__FILE__,"file");

#ifndef I_UNISTD
void _exit();
#endif



int can_open(file, mode)
     CONST char *file, *mode;
{
	/** Returns 0 iff user can open the file.  This is not
	    the same as can_access - it's used for when the file might
	    not exist... **/

	FILE *fd;
	int the_stat = 0, pid, w, sig;
	VOLATILE int preexisted = 0;
	S__ status;
	
#ifdef VFORK
	if ((pid = vfork()) == 0) {
#else
	if ((pid = fork()) == 0) {
#endif
	  if (-1 == setgid(groupid)) {
	    int err = errno;
	    fprintf(stderr,"can_open: 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_open: setuid(%d) FAILED: %s\n",
		    userid,error_description(err));
	    fflush(stderr);
	    _exit(err != 0? err : 1);	/* never return zero! */
	  }
	  errno = 0;
	  if (mode[0] == 's' && mode[1] == 'w' && ! mode[2]) {
	      int filedes = open(file, O_WRONLY | O_CREAT | O_EXCL, 0600);
	      if (filedes < 0 &&
		  (unlink(file) ||
		   (filedes = open(file, O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0))
		  _exit(errno);
	      else {
		  close(filedes);
		  _exit(0);
	      }
	  }
	  if (access(file, ACCESS_EXISTS) == 0)
	    preexisted = 1;
	  if ((fd = fopen(file, mode)) == NULL)
	    _exit(errno != 0 ? errno : 1);
	  else {
	    fclose(fd);		/* don't just leave it open! */
	    if(!preexisted)	/* don't leave it if this test created it! */
	      unlink(file);
	    _exit(0);
	  }
	  _exit(127);
	}

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

	sig = convert_status(status,&the_stat);
	if (sig)
	  the_stat = 1;
	DPRINT(Debug,1,(&Debug, 
			"can_open(%s,%s) = %d\n",file,mode,the_stat));
	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