Esempio n. 1
0
/*
 * set_env - copy command line arguments into the environment
 */
void
set_env(int argc, char * const *argv)
{
	int	noname = 1;
	char	variable[1024];
	char	*cp;

	for ( ; argc > 0; argc--, argv++) {
		if (strlen(*argv) >= sizeof variable)
			continue;	/* ignore long entries */

		if (! (cp = strchr (*argv, '='))) {
			snprintf(variable, sizeof variable, "L%d", noname++);
			addenv(variable, *argv);
		} else {
			const char **p;

			for (p = forbid; *p; p++)
				if (strncmp(*argv, *p, strlen(*p)) == 0)
					break;

			if (*p) {
				strncpy(variable, *argv, cp - *argv);
				variable[cp - *argv] = '\0';
				printf(_("You may not change $%s\n"), variable);
				continue;
			}

			addenv(*argv, NULL);
		}
	}
}
Esempio n. 2
0
/*
 *	change to the user's home directory
 *	set the HOME, SHELL, MAIL, PATH, and LOGNAME or USER environmental
 *	variables.
 */
void setup_env(struct passwd *info)
{
	char	*cp;

	/*
	 * Change the current working directory to be the home directory
	 * of the user.  It is a fatal error for this process to be unable
	 * to change to that directory.  There is no "default" home
	 * directory.
	 *
	 * We no longer do it as root - should work better on NFS-mounted
	 * home directories.
	 */
	if (chdir(info->pw_dir) == -1) {
	    static char temp_pw_dir[] = "/";
	    if (!getdef_bool("DEFAULT_HOME") || chdir("/") == -1) {
		fprintf(stderr, _("Unable to cd to \"%s\"\n"), info->pw_dir);
		syslog(LOG_WARNING, "unable to cd to `%s' for user `%s'\n", info->pw_dir, info->pw_name);
		closelog();
		exit (1);
	    }
	    puts(_("No directory, logging in with HOME=/"));
	    info->pw_dir = temp_pw_dir;
	}

	/*
	 * Create the HOME environmental variable and export it.
	 */
	addenv("HOME", info->pw_dir);

	/*
	 * Create the SHELL environmental variable and export it.
	 */
	if (info->pw_shell == (char *) 0 || ! *info->pw_shell) {
		static char temp_pw_shell[] = "/bin/sh";
		info->pw_shell = temp_pw_shell;
	}

	addenv("SHELL", info->pw_shell);

	/*
	 * Create the PATH environmental variable and export it.
	 */
	cp = getdef_str("ENV_PATH");
	addenv(cp ? cp : "PATH=/bin:/usr/bin", NULL);

	/*
	 * Export the user name.  For BSD derived systems, it's "USER", for
	 * all others it's "LOGNAME".  We set both of them.
	 */

	addenv("USER", info->pw_name);
	addenv("LOGNAME", info->pw_name);
}
Esempio n. 3
0
void
semicolon_arrfixenv(char *s, char **t)
{
    char **ep, *u;
    int len_s;
    Param pm;

    MUSTUSEHEAP("semicolon_arrfixenv");
    if (t == path)
	cmdnamtab->emptytable(cmdnamtab);
    u = zjoin(t, ';');
    len_s = strlen(s);
    pm = (Param) paramtab->getnode(paramtab, s);
    for (ep = environ; *ep; ep++)
	if (!strncmp(*ep, s, len_s) && (*ep)[len_s] == '=') {
	    pm->env = replenv(*ep, u);
//		(void)SetEnvironmentVariable(*ep,u);
	    return;
	}
    if (isset(ALLEXPORT))
	pm->flags |= PM_EXPORTED;
    if (pm->flags & PM_EXPORTED) {
		pm->env = addenv(s, u);
		(void)SetEnvironmentVariable(s,u);
	}
}
Esempio n. 4
0
void
updenvlocal(Var *v)
{
	if(v){
		updenvlocal(v->next);
		addenv(v);
	}
}
Esempio n. 5
0
static void init_env (void)
{
#ifndef USE_PAM
	char *cp;
#endif
	char *tmp;

	tmp = getenv ("LANG");
	if (NULL != tmp) {
		addenv ("LANG", tmp);
	}

	/*
	 * Add the timezone environmental variable so that time functions
	 * work correctly.
	 */
	tmp = getenv ("TZ");
	if (NULL != tmp) {
		addenv ("TZ", tmp);
	}
#ifndef USE_PAM
	else {
		cp = getdef_str ("ENV_TZ");
		if (NULL != cp) {
			addenv (('/' == *cp) ? tz (cp) : cp, NULL);
		}
	}
#endif				/* !USE_PAM */
	/* 
	 * Add the clock frequency so that profiling commands work
	 * correctly.
	 */
	tmp = getenv ("HZ");
	if (NULL != tmp) {
		addenv ("HZ", tmp);
	}
#ifndef USE_PAM
	else {
		cp = getdef_str ("ENV_HZ");
		if (NULL != cp) {
			addenv (cp, NULL);
		}
	}
#endif				/* !USE_PAM */
}
Esempio n. 6
0
File: plan9.c Progetto: aahud/harvey
void
Updenv(void)
{
	var *v, **h;
	for(h = gvar;h!=&gvar[NVAR];h++)
		for(v=*h;v;v = v->next)
			addenv(v);
	if(runq)
		updenvlocal(runq->local);
}
Esempio n. 7
0
/*
 * set_env - copy command line arguments into the environment
 */
void set_env (int argc, char *const *argv)
{
	int noname = 1;
	char variable[1024];
	char *cp;

	for (; argc > 0; argc--, argv++) {
		if (strlen (*argv) >= sizeof variable) {
			continue;	/* ignore long entries */
		}

		cp = strchr (*argv, '=');
		if (NULL == cp) {
			int wlen;
			wlen = snprintf (variable, sizeof variable, "L%d", noname);
			assert (wlen < (int) sizeof(variable));
			noname++;
			addenv (variable, *argv);
		} else {
			const char **p;

			for (p = forbid; NULL != *p; p++) {
				if (strncmp (*argv, *p, strlen (*p)) == 0) {
					break;
				}
			}

			if (NULL != *p) {
				strncpy (variable, *argv, (size_t)(cp - *argv));
				variable[cp - *argv] = '\0';
				printf (_("You may not change $%s\n"),
					variable);
				continue;
			}

			addenv (*argv, NULL);
		}
	}
}
Esempio n. 8
0
/*
 * ttytype - set ttytype from port to terminal type mapping database
 */
void ttytype (const char *line)
{
	FILE *fp;
	char buf[BUFSIZ];
	char *typefile;
	char *cp;
	char type[BUFSIZ];
	char port[BUFSIZ];

	if (getenv ("TERM"))
		return;
	if ((typefile = getdef_str ("TTYTYPE_FILE")) == NULL)
		return;
	if (access (typefile, F_OK))
		return;

	if (!(fp = fopen (typefile, "r"))) {
		perror (typefile);
		return;
	}
	while (fgets (buf, sizeof buf, fp)) {
		if (buf[0] == '#')
			continue;

		if ((cp = strchr (buf, '\n')))
			*cp = '\0';

		if (sscanf (buf, "%s %s", type, port) == 2 &&
		    strcmp (line, port) == 0)
			break;
	}
	if (!feof (fp) && !ferror (fp))
		addenv ("TERM", type);

	fclose (fp);
}
Esempio n. 9
0
int
main(int argc, char **argv)
{
    const char *filename = NULL;

    for (int i = 1; i < argc; i++) {
        if (strstr(argv[i], "-mcpu=") == argv[i]) {
            setenv("SI_FORCE_FAMILY", argv[i] + 6, 1);
        } else if (filename == NULL) {
            filename = argv[i];
        } else {
            if (strcmp(argv[i], "--help") != 0 && strcmp(argv[i], "-h") != 0)
                fprintf(stderr, "Unknown option: %s\n\n", argv[i]);

            fprintf(stderr, "Usage: amdgcn_glslc -mcpu=[chip name] [glsl filename]\n");
            return 1;
        }
    }

    if (filename == NULL) {
        fprintf(stderr, "No filename specified.\n");
        return 1;
    }

    addenv("R600_DEBUG", "precompile,vs,tcs,tes,gs,ps,cs,noir,notgsi");

    create_gl_core_context();

    /* Read the source. */
    char *input = read_file(filename);

    /* Comment out lines beginning with ; (FileCheck prefix). */
    if (input[0] == ';')
        memcpy(input, "//", 2);

    char *s = input;
    while (s = strstr(s, "\n;"))
        memcpy(s + 1, "//", 2);

    s = input;
    while (s && (s = strstr(s, "#shader "))) {
        char type_str[16], name[128];
        GLenum type;

        /* If #shader is not at the beginning of the line. */
        if (s != input && s[-1] != '\n' && s[-1] != 0) {
            s = strstr(s, "\n");
            continue;
        }

        /* Parse the #shader directive. */
        if (sscanf(s + 8, "%s %s", type_str, name) != 2) {
            fprintf(stderr, "Cannot parse #shader directive.\n");
            continue;
        }

        if (!strcmp(type_str, "vs"))
            type = GL_VERTEX_SHADER;
        else if (!strcmp(type_str, "tcs"))
            type = GL_TESS_CONTROL_SHADER;
        else if (!strcmp(type_str, "tes"))
            type = GL_TESS_EVALUATION_SHADER;
        else if (!strcmp(type_str, "gs"))
            type = GL_GEOMETRY_SHADER;
        else if (!strcmp(type_str, "fs"))
            type = GL_FRAGMENT_SHADER;
        else if (!strcmp(type_str, "cs"))
            type = GL_COMPUTE_SHADER;

        /* Go the next line. */
        s = strstr(s, "\n");
        if (!s)
            break;
        s++;

        const char *source = s;

        /* Cut the shader source at the end. */
        s = strstr(s, "#shader");
        if (s && s[-1] == '\n')
            s[-1] = 0;

        /* Compile the shader. */
        printf("@%s:\n", name);

        /* Redirect stderr to stdout for the compiler. */
        FILE *stderr_original = stderr;
        stderr = stdout;
        GLuint prog = glCreateShaderProgramv(type, 1, &source);
        stderr = stderr_original;

        GLint linked;
        glGetProgramiv(prog, GL_LINK_STATUS, &linked);

        if (!linked) {
            char log[4096];
            GLsizei length;

            glGetProgramInfoLog(prog, sizeof(log), &length, log);
            fprintf(stderr, "ERROR: Compile failure:\n\n%s\n%s\n",
                    source, log);
            return 1;
        }

        glDeleteProgram(prog);
    }
    return 0;
}
Esempio n. 10
0
/* 
 * TODO: CLEANUP
 *
 * This function is DEPRECATED and should be removed with the next
 * major release.
 *
 * This function can't be used in multi threaded environments because it
 * might cause a deadlock in the executing qmaster thread.
 * Use sge_peopen_r() instead.
 */
pid_t sge_peopen(const char *shell, int login_shell, const char *command,
                 const char *user, char **env,  FILE **fp_in, FILE **fp_out,
                 FILE **fp_err, bool null_stderr)
{
   pid_t pid;
   int pipefds[3][2];
   const char *could_not = MSG_SYSTEM_EXECBINSHFAILED;
   const char *not_root = MSG_SYSTEM_NOROOTRIGHTSTOSWITCHUSER;
   int i;
   char arg0[256];
   char err_str[256];
#if !(defined(WIN32) || defined(INTERIX)) /* var not needed */
   int res;
#endif /* WIN32 */
   uid_t myuid;
 
   DENTER(TOP_LAYER, "sge_peopen");
 
   /* open pipes - close on failure */
   for (i=0; i<3; i++) {
      if (pipe(pipefds[i]) != 0) {
         while (--i >= 0) {
            close(pipefds[i][0]);
            close(pipefds[i][1]);
         }
         ERROR((SGE_EVENT, MSG_SYSTEM_FAILOPENPIPES_SS,
                command, strerror(errno)));
         DEXIT;
         return -1;
      }
   }

#if defined(SOLARIS)
   pid = sge_smf_contract_fork(err_str, 256);
#else
   pid = fork();
#endif
   if (pid == 0) {  /* child */
      int keep_open[6];
      keep_open[0] = 0;
      keep_open[1] = 1;
      keep_open[2] = 2;
      keep_open[3] = pipefds[0][0];
      keep_open[4] = pipefds[1][1];
      keep_open[5] = pipefds[2][1];
      sge_close_all_fds(keep_open, 6);
      /* shall we redirect stderr to /dev/null? */
      if (null_stderr) {
         /* open /dev/null */
         int fd = open("/dev/null", O_WRONLY);
         if (fd == -1) {
            sprintf(err_str, MSG_ERROROPENINGFILEFORWRITING_SS, "/dev/null", 
                    strerror(errno));
            sprintf(err_str, "\n");
            write(2, err_str, strlen(err_str));
            SGE_EXIT(NULL, 1);
         }

         /* set stderr to /dev/null */
         close(2);
         dup(fd);

         /* we don't need the stderr the pipe - close it */
         close(pipefds[2][1]);
      } else {
         /* redirect stderr to the pipe */
         close(2);
         dup(pipefds[2][1]);
      }

      /* redirect stdin and stdout to the pipes */
      close(0);
      close(1);
      dup(pipefds[0][0]);
      dup(pipefds[1][1]);
 
      if (user) {
         struct passwd *pw;
         struct passwd pw_struct;
         char *buffer;
         int size;

         size = get_pw_buffer_size();
         buffer = sge_malloc(size);
         if (!(pw=sge_getpwnam_r(user, &pw_struct, buffer, size))) {
            sprintf(err_str, MSG_SYSTEM_NOUSERFOUND_SS , user, strerror(errno));            
            sprintf(err_str, "\n");
            write(2, err_str, strlen(err_str));
            FREE(buffer);
            SGE_EXIT(NULL, 1);
         }
 
         myuid = geteuid();
 
         if (myuid != pw->pw_uid) {
 
            /* Only change user if we differ from the wanted user */
            if(myuid != SGE_SUPERUSER_UID) {
               write(2, not_root, sizeof(not_root));
               FREE(buffer);
               SGE_EXIT(NULL, 1);
            }                             
            sprintf(err_str, "%s %d\n", pw->pw_name, (int)pw->pw_gid);
            write(2, err_str, strlen(err_str));
#if !(defined(WIN32) || defined(INTERIX))  /* initgroups not called */
            res = initgroups(pw->pw_name,pw->pw_gid);
#  if defined(SVR3) || defined(sun)
            if (res < 0)
#  else
            if (res)
#  endif
            {
               sprintf(err_str, MSG_SYSTEM_INITGROUPSFORUSERFAILED_ISS ,
                     res, user, strerror(errno));
               sprintf(err_str, "\n");
               write(2, err_str, strlen(err_str));
               FREE(buffer);
               SGE_EXIT(NULL, 1);
            }
#endif /* WIN32 */
 
            if (setuid(pw->pw_uid)) {
               sprintf(err_str, MSG_SYSTEM_SWITCHTOUSERFAILED_SS , user,
                     strerror(errno));
               sprintf(err_str, "\n");
               write(2, err_str, strlen(err_str));
               FREE(buffer);
               SGE_EXIT(NULL, 1);
            }
         }
 
         addenv("HOME", pw->pw_dir);
         addenv("SHELL", pw->pw_shell);
         addenv("USER", pw->pw_name);
         addenv("LOGNAME", pw->pw_name);
         addenv("PATH", SGE_DEFAULT_PATH);

         FREE(buffer);
      }
 
      if (login_shell)
         strcpy(arg0, "-");
      else
         strcpy(arg0, "");
      strcat(arg0, shell);
 
      if (env)
         for(; *env; env++)
            putenv(*env);
 
      execlp(shell, arg0, "-c", command, NULL);
 
      write(2, could_not, sizeof(could_not));
      SGE_EXIT(NULL, 1);
   }
 
   if (pid < 0) {
      for (i=0; i<3; i++) {
         close(pipefds[i][0]);
         close(pipefds[i][1]);
      }
#if defined(SOLARIS)
      if (pid < -1 && err_str) {
          ERROR((SGE_EVENT, MSG_SMF_FORK_FAILED_SS, "sge_peopen()", err_str));
      }
#endif
      /* fork could have failed, report it */
      ERROR((SGE_EVENT, MSG_SMF_FORK_FAILED_SS, "sge_peopen()", strerror(errno)));
      DEXIT;
      return -1;
   }
 
   /* close the childs ends of the pipes */
   close(pipefds[0][0]);
   close(pipefds[1][1]);
   close(pipefds[2][1]);
  
   /* return filehandles for stdin and stdout */
   *fp_in  = fdopen(pipefds[0][1], "a");
   *fp_out = fdopen(pipefds[1][0], "r");

   /* is stderr redirected to /dev/null? */
   if (null_stderr) {
      /* close the pipe and return NULL as filehandle */
      close(pipefds[2][0]);
      *fp_err = NULL;
   } else {
      /* return filehandle for stderr */
      *fp_err = fdopen(pipefds[2][0], "r");
   }

   DEXIT;
   return pid;
}
Esempio n. 11
0
/****** uti/stdio/sge_peopen() ************************************************
*  NAME
*     sge_peopen_r() -- Advanced popen()
*
*  SYNOPSIS
*     pid_t sge_peopen_r(const char *shell, int login_shell,
*                        const char *command, const char *user,
*                        char **env, FILE **fp_in, FILE **fp_out,
*                        FILE **fp_err)
*
*  FUNCTION
*     Advanced popen() with additional parameters:
*        - free shell usage
*        - login shell if wanted
*        - user under which to start (for root only)
*        - stdin and stderr file pointers
*        - wait for exactly the process we started
*     File descriptors have to be closed with sge_peclose().
*
*     This function is reentrant as long as env is not provided to
*     this function. This means that the function can be used in 
*     multi thread processed as long as env is not used. 
*
*  INPUTS
*     const char *shell   - which shell to use
*     int login_shell     - make it a login shell?
*     const char *command - name of the program
*     const char *user    - user under which to start (for root only)
*     char **env          - env variables to add to child
*     FILE **fp_in        - file input stream
*     FILE **fp_out       - file output stream
*     FILE **fp_err       - file error stream
*
*  RESULT
*     pid_t - process id
*
*  NOTES
*     MT-NOTE: sge_peopen() is MT safe 
*
*     DO NOT ADD ASYNC SIGNAL UNSAFE FUNCTIONS BETWEEN FORK AND EXEC
*     DUE TO THE FACT THAT THIS FUNCTION WILL BE USED IN QMASTER
*     (MULTITHREADED ENVIRONMENT) THIS MIGHT CAUSE A DEADLOCK 
*     IN A MASTER THREAD. 
*
*  SEE ALSO
*     uti/stdio/sge_peclose()
******************************************************************************/ 
pid_t sge_peopen_r(const char *shell, int login_shell, const char *command,
                   const char *user, char **env,  FILE **fp_in, FILE **fp_out,
                   FILE **fp_err, bool null_stderr)
{
   pid_t pid;
   int pipefds[3][2];
   int i;
   char arg0[256];
#if defined(SOLARIS)
   char err_str[256];
#endif
   struct passwd *pw = NULL;
   uid_t myuid;
   uid_t tuid;
 
   DENTER(TOP_LAYER, "sge_peopen_r");

   if (sge_has_admin_user()) {
      sge_switch2start_user();
   }
   myuid = geteuid();
   tuid = myuid;

   /* 
    * open pipes - close on failure 
    */
   for (i = 0; i < 3; i++) {
      if (pipe(pipefds[i]) != 0) {
         while (--i >= 0) {
            close(pipefds[i][0]);
            close(pipefds[i][1]);
         }
         ERROR((SGE_EVENT, MSG_SYSTEM_FAILOPENPIPES_SS, command, strerror(errno)));
         if (sge_has_admin_user()) {
            sge_switch2admin_user();
         }
         DRETURN(-1);
      }
   }

   /*
    * set arg0 for exec call correctly to that
    * either a normal shell or a login shell will be started
    */
   if (login_shell) {
      strcpy(arg0, "-");
   } else {
      strcpy(arg0, "");
   }
   strcat(arg0, shell);
   DPRINTF(("arg0 = %s\n", arg0));
   DPRINTF(("arg1 = -c\n"));
   DPRINTF(("arg2 = %s\n", command));


   /*
    * prepare the change of the user which might be done after fork()
    * if a user name is provided.
    *
    * this has to be done before the fork() afterwards it might cause
    * a deadlock of the child because getpwnam() is not async-thread safe.
    */
   if (user) {
      struct passwd pw_struct;
      int size = get_pw_buffer_size();
      char *buffer = sge_malloc(size);

      /*
       * get information about the target user
       */
      if (buffer != NULL) {
         pw = sge_getpwnam_r(user, &pw_struct, buffer, size);
         if (pw == NULL) {
            ERROR((SGE_EVENT, MSG_SYSTEM_NOUSERFOUND_SS, user, strerror(errno)));
            FREE(buffer);
            if (sge_has_admin_user()) {
               sge_switch2admin_user();
            }
            DRETURN(-1);
         }
      } else {
         ERROR((SGE_EVENT, MSG_UTI_MEMPWNAM));
         FREE(buffer);
         if (sge_has_admin_user()) {
            sge_switch2admin_user();
         }
         DRETURN(-1);
      }

      DPRINTF(("was able to resolve user\n"));

      /* 
       * only prepare change of user if target user is different from current one
       */
      if (myuid != pw->pw_uid) {
#if !(defined(WIN32) || defined(INTERIX)) /* var not needed */
         int res;
#endif 

         if (myuid != SGE_SUPERUSER_UID) {
            DPRINTF(("only root is allowed to switch to a different user\n"));
            ERROR((SGE_EVENT, MSG_SYSTEM_NOROOTRIGHTSTOSWITCHUSER));
            FREE(buffer);
            DRETURN(-2);
         }                             

         DPRINTF(("Before initgroups\n"));

#if !(defined(WIN32) || defined(INTERIX))  /* initgroups not called */
         res = initgroups(pw->pw_name, pw->pw_gid);
#  if defined(SVR3) || defined(sun)
         if (res < 0)
#  else
         if (res)
#  endif
         {
            ERROR((SGE_EVENT, MSG_SYSTEM_INITGROUPSFORUSERFAILED_ISS, res, user, strerror(errno)));
            FREE(buffer);
            SGE_EXIT(NULL, 1);
         }

         DPRINTF(("Initgroups was successful\n"));

#endif /* WIN32 */
      }
      DPRINTF(("user = %s\n", user));
      DPRINTF(("myuid = %d\n", (int)myuid));
      if (pw != NULL) {
         tuid = pw->pw_uid;
         DPRINTF(("target uid = %d\n", (int)tuid));
      }

      FREE(buffer);
   }

   DPRINTF(("Now process will fork\n"));

#if defined(SOLARIS)
   pid = sge_smf_contract_fork(err_str, 256);
#else
   pid = fork();
#endif

   /* 
    * in the child pid is 0 
    */
   if (pid == 0) {  
      /*
       * close all fd's except that ones mentioned in keep_open 
       */
      int keep_open[6];
      keep_open[0] = 0;
      keep_open[1] = 1;
      keep_open[2] = 2;
      keep_open[3] = pipefds[0][0];
      keep_open[4] = pipefds[1][1];
      keep_open[5] = pipefds[2][1];
      sge_close_all_fds(keep_open, 6);

      /* 
       * shall we redirect stderr to /dev/null? Then
       *    - open "/dev/null"
       *    - set stderr to "dev/null"
       *    - close the stderr-pipe
       * otherwise
       *    - redirect stderr to the pipe
       */
      if (null_stderr) {
         int fd = open("/dev/null", O_WRONLY);

         if (fd != -1) {
            close(2);
            dup(fd);
            close(pipefds[2][1]);
         } else {
            SGE_EXIT(NULL, 1);
         }
      } else {
         close(2);
         dup(pipefds[2][1]);
      }

      /* 
       * redirect stdin and stdout to the pipes 
       */
      close(0);
      close(1);
      dup(pipefds[0][0]);
      dup(pipefds[1][1]);

      if (pw != NULL) {
         int lret = setuid(tuid);
         if (lret) {
            SGE_EXIT(NULL, 1);
         }
      }

      /*
       * set the environment if we got one as argument
       */
      if (env != NULL) {
         if (pw != NULL) {
            addenv("HOME", pw->pw_dir);
            addenv("SHELL", pw->pw_shell);
            addenv("USER", pw->pw_name);
            addenv("LOGNAME", pw->pw_name);
         }
         addenv("PATH", SGE_DEFAULT_PATH);
         for(; *env; env++) {
            putenv(*env);
         }
      }
      execlp(shell, arg0, "-c", command, NULL);
   }
 
   if (pid < 0) {
      for (i=0; i<3; i++) {
         close(pipefds[i][0]);
         close(pipefds[i][1]);
      }
#if defined(SOLARIS)
      if (pid < -1 && err_str) {
          ERROR((SGE_EVENT, MSG_SMF_FORK_FAILED_SS, "sge_peopen()", err_str));
      }
#endif
      if (sge_has_admin_user()) {
         sge_switch2admin_user();
      }
      DRETURN(-1);
   }
 
   /* close the childs ends of the pipes */
   close(pipefds[0][0]);
   close(pipefds[1][1]);
   close(pipefds[2][1]);
  
   /* return filehandles for stdin and stdout */
   *fp_in  = fdopen(pipefds[0][1], "a");
   *fp_out = fdopen(pipefds[1][0], "r");

   /* is stderr redirected to /dev/null? */
   if (null_stderr) {
      /* close the pipe and return NULL as filehandle */
      close(pipefds[2][0]);
      *fp_err = NULL;
   } else {
      /* return filehandle for stderr */
      *fp_err = fdopen(pipefds[2][0], "r");
   }

   if (sge_has_admin_user()) {
      sge_switch2admin_user();
   }
   DRETURN(pid);
}
Esempio n. 12
0
 /*ARGSUSED*/ int main (int argc, char **argv)
{
#ifndef USE_PAM
	const char *env;
#endif				/* !USE_PAM */
	char **envp = environ;
	TERMIO termio;
	int err = 0;

#ifdef	USE_TERMIO
	ioctl (0, TCGETA, &termio);
	termio.c_iflag |= (ICRNL | IXON);
	termio.c_oflag |= (OPOST | ONLCR);
	termio.c_cflag |= (CREAD);
	termio.c_lflag |= (ISIG | ICANON | ECHO | ECHOE | ECHOK);
	ioctl (0, TCSETAF, &termio);
#endif
#ifdef	USE_TERMIOS
	tcgetattr (0, &termio);
	termio.c_iflag |= (ICRNL | IXON);
	termio.c_oflag |= (CREAD);
	termio.c_lflag |= (ECHO | ECHOE | ECHOK | ICANON | ISIG);
	tcsetattr (0, TCSANOW, &termio);
#endif

	Prog = Basename (argv[0]);
	(void) setlocale (LC_ALL, "");
	(void) bindtextdomain (PACKAGE, LOCALEDIR);
	(void) textdomain (PACKAGE);

#ifdef	USE_SYSLOG
	OPENLOG ("sulogin");
#endif
	initenv ();
	if (argc > 1) {
		close (0);
		close (1);
		close (2);

		if (open (argv[1], O_RDWR) >= 0) {
			dup (0);
			dup (0);
		} else {
#ifdef	USE_SYSLOG
			SYSLOG (LOG_WARN, "cannot open %s\n", argv[1]);
			closelog ();
#endif
			exit (1);
		}
	}
	if (access (PASSWD_FILE, F_OK) == -1) {	/* must be a password file! */
		(void) puts (_("No password file"));
#ifdef	USE_SYSLOG
		SYSLOG (LOG_WARN, "No password file\n");
		closelog ();
#endif
		exit (1);
	}
#if !defined(DEBUG) && defined(SULOGIN_ONLY_INIT)
	if (getppid () != 1) {	/* parent must be INIT */
#ifdef	USE_SYSLOG
		SYSLOG (LOG_WARN, "Pid == %d, not 1\n", getppid ());
		closelog ();
#endif
		exit (1);
	}
#endif
	if ((isatty (0) == 0) || (isatty (1) == 0) || (isatty (2) == 0)) {
#ifdef	USE_SYSLOG
		closelog ();
#endif
		exit (1);	/* must be a terminal */
	}
	/* If we were init, we need to start a new session */
	if (getppid() == 1) {
		setsid();
		if (ioctl(0, TIOCSCTTY, 1) != 0) {
			(void) fputs (_("TIOCSCTTY failed"), stderr);
		}
	}
	while (NULL != *envp) {		/* add inherited environment, */
		addenv (*envp, NULL);	/* some variables change later */
		envp++;
	}

#ifndef USE_PAM
	env = getdef_str ("ENV_TZ");
	if (NULL != env) {
		addenv (('/' == *env) ? tz (env) : env, NULL);
	}
	env = getdef_str ("ENV_HZ");
	if (NULL != env) {
		addenv (env, NULL);	/* set the default $HZ, if one */
	}
#endif				/* !USE_PAM */

	(void) strcpy (name, "root");	/* KLUDGE!!! */

	(void) signal (SIGALRM, catch_signals);	/* exit if the timer expires */
	(void) alarm (ALARM);		/* only wait so long ... */

	while (true) {		/* repeatedly get login/password pairs */
		char *cp;
		pw_entry (name, &pwent);	/* get entry from password file */
		if (pwent.pw_name == (char *) 0) {
			/*
			 * Fail secure
			 */
			(void) puts (_("No password entry for 'root'"));
#ifdef	USE_SYSLOG
			SYSLOG (LOG_WARN, "No password entry for 'root'\n");
			closelog ();
#endif
			exit (1);
		}

		/*
		 * Here we prompt for the root password, or if no password
		 * is given we just exit.
		 */

		/* get a password for root */
		cp = getpass (_(
"\n"
"Type control-d to proceed with normal startup,\n"
"(or give root password for system maintenance):"));
		/*
		 * XXX - can't enter single user mode if root password is
		 * empty.  I think this doesn't happen very often :-). But
		 * it will work with standard getpass() (no NULL on EOF). 
		 * --marekm
		 */
		if ((NULL == cp) || ('\0' == *cp)) {
#ifdef	USE_SYSLOG
			SYSLOG (LOG_INFO, "Normal startup\n");
			closelog ();
#endif
			(void) puts ("");
#ifdef	TELINIT
			execl (PATH_TELINIT, "telinit", RUNLEVEL, (char *) 0);
#endif
			exit (0);
		} else {
			STRFCPY (pass, cp);
			strzero (cp);
		}
		if (valid (pass, &pwent)) {	/* check encrypted passwords ... */
			break;	/* ... encrypted passwords matched */
		}

#ifdef	USE_SYSLOG
		SYSLOG (LOG_WARN, "Incorrect root password\n");
#endif
		sleep (2);
		(void) puts (_("Login incorrect"));
	}
	strzero (pass);
	(void) alarm (0);
	(void) signal (SIGALRM, SIG_DFL);
	environ = newenvp;	/* make new environment active */

	(void) puts (_("Entering System Maintenance Mode"));
#ifdef	USE_SYSLOG
	SYSLOG (LOG_INFO, "System Maintenance Mode\n");
#endif

#ifdef	USE_SYSLOG
	closelog ();
#endif
	/* exec the shell finally. */
	err = shell (pwent.pw_shell, (char *) 0, environ);

	return ((err == ENOENT) ? E_CMD_NOTFOUND : E_CMD_NOEXEC);
}
Esempio n. 13
0
/*
 * login - create a new login session for a user
 *
 *	login is typically called by getty as the second step of a
 *	new user session. getty is responsible for setting the line
 *	characteristics to a reasonable set of values and getting
 *	the name of the user to be logged in. login may also be
 *	called to create a new user session on a pty for a variety
 *	of reasons, such as X servers or network logins.
 *
 *	the flags which login supports are
 *	
 *	-p - preserve the environment
 *	-r - perform autologin protocol for rlogin
 *	-f - do not perform authentication, user is preauthenticated
 *	-h - the name of the remote host
 */
int main (int argc, char **argv)
{
	const char *tmptty;
	char tty[BUFSIZ];

#ifdef RLOGIN
	char term[128] = "";
#endif				/* RLOGIN */
#if defined(HAVE_STRFTIME) && !defined(USE_PAM)
	char ptime[80];
#endif
	unsigned int delay;
	unsigned int retries;
	bool failed;
	bool subroot = false;
#ifndef USE_PAM
	bool is_console;
#endif
	int err;
	const char *cp;
	char *tmp;
	char fromhost[512];
	struct passwd *pwd = NULL;
	char **envp = environ;
	const char *failent_user;
	/*@null@*/struct utmp *utent;

#ifdef USE_PAM
	int retcode;
	pid_t child;
	char *pam_user = NULL;
#else
	struct spwd *spwd = NULL;
#endif
	/*
	 * Some quick initialization.
	 */

	sanitize_env ();

	(void) setlocale (LC_ALL, "");
	(void) bindtextdomain (PACKAGE, LOCALEDIR);
	(void) textdomain (PACKAGE);

	initenv ();

	amroot = (getuid () == 0);
	Prog = Basename (argv[0]);

	if (geteuid() != 0) {
		fprintf (stderr, _("%s: Cannot possibly work without effective root\n"), Prog);
		exit (1);
	}

	process_flags (argc, argv);

	if ((isatty (0) == 0) || (isatty (1) == 0) || (isatty (2) == 0)) {
		exit (1);	/* must be a terminal */
	}

	utent = get_current_utmp ();
	/*
	 * Be picky if run by normal users (possible if installed setuid
	 * root), but not if run by root. This way it still allows logins
	 * even if your getty is broken, or if something corrupts utmp,
	 * but users must "exec login" which will use the existing utmp
	 * entry (will not overwrite remote hostname).  --marekm
	 */
	if (!amroot && (NULL == utent)) {
		(void) puts (_("No utmp entry.  You must exec \"login\" from the lowest level \"sh\""));
		exit (1);
	}
	/* NOTE: utent might be NULL afterwards */

	tmptty = ttyname (0);
	if (NULL == tmptty) {
		tmptty = "UNKNOWN";
	}
	STRFCPY (tty, tmptty);

#ifndef USE_PAM
	is_console = console (tty);
#endif

	if (rflg || hflg) {
		/*
		 * Add remote hostname to the environment. I think
		 * (not sure) I saw it once on Irix.  --marekm
		 */
		addenv ("REMOTEHOST", hostname);
	}
	if (fflg) {
		preauth_flag = true;
	}
	if (hflg) {
		reason = PW_RLOGIN;
	}
#ifdef RLOGIN
	if (rflg) {
		assert (NULL == username);
		username = xmalloc (USER_NAME_MAX_LENGTH + 1);
		username[USER_NAME_MAX_LENGTH] = '\0';
		if (do_rlogin (hostname, username, USER_NAME_MAX_LENGTH, term, sizeof term)) {
			preauth_flag = true;
		} else {
			free (username);
			username = NULL;
		}
	}
#endif				/* RLOGIN */

	OPENLOG ("login");

	setup_tty ();

#ifndef USE_PAM
	(void) umask (getdef_num ("UMASK", GETDEF_DEFAULT_UMASK));

	{
		/* 
		 * Use the ULIMIT in the login.defs file, and if
		 * there isn't one, use the default value. The
		 * user may have one for themselves, but otherwise,
		 * just take what you get.
		 */
		long limit = getdef_long ("ULIMIT", -1L);

		if (limit != -1) {
			set_filesize_limit (limit);
		}
	}

#endif
	/*
	 * The entire environment will be preserved if the -p flag
	 * is used.
	 */
	if (pflg) {
		while (NULL != *envp) {	/* add inherited environment, */
			addenv (*envp, NULL); /* some variables change later */
			envp++;
		}
	}

#ifdef RLOGIN
	if (term[0] != '\0') {
		addenv ("TERM", term);
	} else
#endif				/* RLOGIN */
	{
		/* preserve TERM from getty */
		if (!pflg) {
			tmp = getenv ("TERM");
			if (NULL != tmp) {
				addenv ("TERM", tmp);
			}
		}
	}

	init_env ();

	if (optind < argc) {	/* now set command line variables */
		set_env (argc - optind, &argv[optind]);
	}

	if (rflg || hflg) {
		cp = hostname;
#ifdef	HAVE_STRUCT_UTMP_UT_HOST
	} else if ((NULL != utent) && ('\0' != utent->ut_host[0])) {
		cp = utent->ut_host;
#endif				/* HAVE_STRUCT_UTMP_UT_HOST */
	} else {
		cp = "";
	}

	if ('\0' != *cp) {
		snprintf (fromhost, sizeof fromhost,
		          " on '%.100s' from '%.200s'", tty, cp);
	} else {
		snprintf (fromhost, sizeof fromhost,
		          " on '%.100s'", tty);
	}

      top:
	/* only allow ALARM sec. for login */
	(void) signal (SIGALRM, alarm_handler);
	timeout = getdef_unum ("LOGIN_TIMEOUT", ALARM);
	if (timeout > 0) {
		(void) alarm (timeout);
	}

	environ = newenvp;	/* make new environment active */
	delay   = getdef_unum ("FAIL_DELAY", 1);
	retries = getdef_unum ("LOGIN_RETRIES", RETRIES);

#ifdef USE_PAM
	retcode = pam_start ("login", username, &conv, &pamh);
	if (retcode != PAM_SUCCESS) {
		fprintf (stderr,
		         _("login: PAM Failure, aborting: %s\n"),
		         pam_strerror (pamh, retcode));
		SYSLOG ((LOG_ERR, "Couldn't initialize PAM: %s",
		         pam_strerror (pamh, retcode)));
		exit (99);
	}

	/*
	 * hostname & tty are either set to NULL or their correct values,
	 * depending on how much we know. We also set PAM's fail delay to
	 * ours.
	 *
	 * PAM_RHOST and PAM_TTY are used for authentication, only use
	 * information coming from login or from the caller (e.g. no utmp)
	 */
	retcode = pam_set_item (pamh, PAM_RHOST, hostname);
	PAM_FAIL_CHECK;
	retcode = pam_set_item (pamh, PAM_TTY, tty);
	PAM_FAIL_CHECK;
#ifdef HAS_PAM_FAIL_DELAY
	retcode = pam_fail_delay (pamh, 1000000 * delay);
	PAM_FAIL_CHECK;
#endif
	/* if fflg, then the user has already been authenticated */
	if (!fflg) {
		unsigned int failcount = 0;
		char hostn[256];
		char loginprompt[256];	/* That's one hell of a prompt :) */

		/* Make the login prompt look like we want it */
		if (gethostname (hostn, sizeof (hostn)) == 0) {
			snprintf (loginprompt,
			          sizeof (loginprompt),
			          _("%s login: "******"login: "******"TOO MANY LOGIN TRIES (%u)%s FOR '%s'",
				         failcount, fromhost, failent_user));
				fprintf(stderr,
				        _("Maximum number of tries exceeded (%u)\n"),
				        failcount);
				PAM_END;
				exit(0);
			} else if (retcode == PAM_ABORT) {
				/* Serious problems, quit now */
				(void) fputs (_("login: abort requested by PAM\n"), stderr);
				SYSLOG ((LOG_ERR,"PAM_ABORT returned from pam_authenticate()"));
				PAM_END;
				exit(99);
			} else if (retcode != PAM_SUCCESS) {
				SYSLOG ((LOG_NOTICE,"FAILED LOGIN (%u)%s FOR '%s', %s",
				         failcount, fromhost, failent_user,
				         pam_strerror (pamh, retcode)));
				failed = true;
			}

			if (!failed) {
				break;
			}

#ifdef WITH_AUDIT
			audit_fd = audit_open ();
			audit_log_acct_message (audit_fd,
			                        AUDIT_USER_LOGIN,
			                        NULL,    /* Prog. name */
			                        "login",
			                        failent_user,
			                        AUDIT_NO_ID,
			                        hostname,
			                        NULL,    /* addr */
			                        tty,
			                        0);      /* result */
			close (audit_fd);
#endif				/* WITH_AUDIT */

			(void) puts ("");
			(void) puts (_("Login incorrect"));

			if (failcount >= retries) {
				SYSLOG ((LOG_NOTICE,
				         "TOO MANY LOGIN TRIES (%u)%s FOR '%s'",
				         failcount, fromhost, failent_user));
				fprintf(stderr,
				        _("Maximum number of tries exceeded (%u)\n"),
				        failcount);
				PAM_END;
				exit(0);
			}

			/*
			 * Let's give it another go around.
			 * Even if a username was given on the command
			 * line, prompt again for the username.
			 */
			retcode = pam_set_item (pamh, PAM_USER, NULL);
			PAM_FAIL_CHECK;
		}

		/* We don't get here unless they were authenticated above */
		(void) alarm (0);
	}

	/* Check the account validity */
	retcode = pam_acct_mgmt (pamh, 0);
	if (retcode == PAM_NEW_AUTHTOK_REQD) {
		retcode = pam_chauthtok (pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
	}
	PAM_FAIL_CHECK;

	/* Open the PAM session */
	get_pam_user (&pam_user);
	retcode = pam_open_session (pamh, hushed (pam_user) ? PAM_SILENT : 0);
	PAM_FAIL_CHECK;

	/* Grab the user information out of the password file for future usage
	 * First get the username that we are actually using, though.
	 *
	 * From now on, we will discard changes of the user (PAM_USER) by
	 * PAM APIs.
	 */
	get_pam_user (&pam_user);
	if (NULL != username) {
		free (username);
	}
	username = pam_user;
	failent_user = get_failent_user (username);

	pwd = xgetpwnam (username);
	if (NULL == pwd) {
		SYSLOG ((LOG_ERR, "cannot find user %s", failent_user));
		exit (1);
	}

	/* This set up the process credential (group) and initialize the
	 * supplementary group access list.
	 * This has to be done before pam_setcred
	 */
	if (setup_groups (pwd) != 0) {
		exit (1);
	}

	retcode = pam_setcred (pamh, PAM_ESTABLISH_CRED);
	PAM_FAIL_CHECK;
	/* NOTE: If pam_setcred changes PAM_USER, this will not be taken
	 * into account.
	 */

#else				/* ! USE_PAM */
	while (true) {	/* repeatedly get login/password pairs */
		/* user_passwd is always a pointer to this constant string
		 * or a passwd or shadow password that will be memzero by
		 * pw_free / spw_free.
		 * Do not free() user_passwd. */
		const char *user_passwd = "!";

		/* Do some cleanup to avoid keeping entries we do not need
		 * anymore. */
		if (NULL != pwd) {
			pw_free (pwd);
			pwd = NULL;
		}
		if (NULL != spwd) {
			spw_free (spwd);
			spwd = NULL;
		}

		failed = false;	/* haven't failed authentication yet */
		if (NULL == username) {	/* need to get a login id */
			if (subroot) {
				closelog ();
				exit (1);
			}
			preauth_flag = false;
			username = xmalloc (USER_NAME_MAX_LENGTH + 1);
			username[USER_NAME_MAX_LENGTH] = '\0';
			login_prompt (_("\n%s login: "******"!",
			 * the account is locked and the user cannot
			 * login, even if they have been
			 * "pre-authenticated."
			 */
			if (   ('!' == user_passwd[0])
			    || ('*' == user_passwd[0])) {
				failed = true;
			}
		}

		if (strcmp (user_passwd, SHADOW_PASSWD_STRING) == 0) {
			spwd = xgetspnam (username);
			if (NULL != spwd) {
				user_passwd = spwd->sp_pwdp;
			} else {
				/* The user exists in passwd, but not in
				 * shadow. SHADOW_PASSWD_STRING indicates
				 * that the password shall be in shadow.
				 */
				SYSLOG ((LOG_WARN,
				         "no shadow password for '%s'%s",
				         username, fromhost));
			}
		}

		/*
		 * The -r and -f flags provide a name which has already
		 * been authenticated by some server.
		 */
		if (preauth_flag) {
			goto auth_ok;
		}

		if (pw_auth (user_passwd, username, reason, (char *) 0) == 0) {
			goto auth_ok;
		}

		SYSLOG ((LOG_WARN, "invalid password for '%s' %s",
		         failent_user, fromhost));
		failed = true;

	      auth_ok:
		/*
		 * This is the point where all authenticated users wind up.
		 * If you reach this far, your password has been
		 * authenticated and so on.
		 */
		if (   !failed
		    && (NULL != pwd)
		    && (0 == pwd->pw_uid)
		    && !is_console) {
			SYSLOG ((LOG_CRIT, "ILLEGAL ROOT LOGIN %s", fromhost));
			failed = true;
		}
		if (   !failed
		    && !login_access (username, ('\0' != *hostname) ? hostname : tty)) {
			SYSLOG ((LOG_WARN, "LOGIN '%s' REFUSED %s",
			         username, fromhost));
			failed = true;
		}
		if (   (NULL != pwd)
		    && getdef_bool ("FAILLOG_ENAB")
		    && !failcheck (pwd->pw_uid, &faillog, failed)) {
			SYSLOG ((LOG_CRIT,
			         "exceeded failure limit for '%s' %s",
			         username, fromhost));
			failed = true;
		}
		if (!failed) {
			break;
		}

		/* don't log non-existent users */
		if ((NULL != pwd) && getdef_bool ("FAILLOG_ENAB")) {
			failure (pwd->pw_uid, tty, &faillog);
		}
		if (getdef_str ("FTMP_FILE") != NULL) {
#ifdef USE_UTMPX
			struct utmpx *failent =
				prepare_utmpx (failent_user,
				               tty,
			/* FIXME: or fromhost? */hostname,
				               utent);
#else				/* !USE_UTMPX */
			struct utmp *failent =
				prepare_utmp (failent_user,
				              tty,
				              hostname,
				              utent);
#endif				/* !USE_UTMPX */
			failtmp (failent_user, failent);
			free (failent);
		}

		retries--;
		if (retries <= 0) {
			SYSLOG ((LOG_CRIT, "REPEATED login failures%s",
			         fromhost));
		}

		/*
		 * If this was a passwordless account and we get here, login
		 * was denied (securetty, faillog, etc.). There was no
		 * password prompt, so do it now (will always fail - the bad
		 * guys won't see that the passwordless account exists at
		 * all).  --marekm
		 */
		if (user_passwd[0] == '\0') {
			pw_auth ("!", username, reason, (char *) 0);
		}

		/*
		 * Authentication of this user failed.
		 * The username must be confirmed in the next try.
		 */
		free (username);
		username = NULL;

		/*
		 * Wait a while (a la SVR4 /usr/bin/login) before attempting
		 * to login the user again. If the earlier alarm occurs
		 * before the sleep() below completes, login will exit.
		 */
		if (delay > 0) {
			(void) sleep (delay);
		}

		(void) puts (_("Login incorrect"));

		/* allow only one attempt with -r or -f */
		if (rflg || fflg || (retries <= 0)) {
			closelog ();
			exit (1);
		}
	}			/* while (true) */
#endif				/* ! USE_PAM */
	assert (NULL != username);
	assert (NULL != pwd);

	(void) alarm (0);		/* turn off alarm clock */

#ifndef USE_PAM			/* PAM does this */
	/*
	 * porttime checks moved here, after the user has been
	 * authenticated. now prints a message, as suggested
	 * by Ivan Nejgebauer <*****@*****.**>.  --marekm
	 */
	if (   getdef_bool ("PORTTIME_CHECKS_ENAB")
	    && !isttytime (username, tty, time ((time_t *) 0))) {
		SYSLOG ((LOG_WARN, "invalid login time for '%s'%s",
		         username, fromhost));
		closelog ();
		bad_time_notify ();
		exit (1);
	}

	check_nologin (pwd->pw_uid == 0);
#endif

	if (getenv ("IFS")) {	/* don't export user IFS ... */
		addenv ("IFS= \t\n", NULL);	/* ... instead, set a safe IFS */
	}

	if (pwd->pw_shell[0] == '*') {	/* subsystem root */
		pwd->pw_shell++;	/* skip the '*' */
		subsystem (pwd);	/* figure out what to execute */
		subroot = true;	/* say I was here again */
		endpwent ();	/* close all of the file which were */
		endgrent ();	/* open in the original rooted file */
		endspent ();	/* system. they will be re-opened */
#ifdef	SHADOWGRP
		endsgent ();	/* in the new rooted file system */
#endif
		goto top;	/* go do all this all over again */
	}

#ifdef WITH_AUDIT
	audit_fd = audit_open ();
	audit_log_acct_message (audit_fd,
	                        AUDIT_USER_LOGIN,
	                        NULL,    /* Prog. name */
	                        "login",
	                        username,
	                        AUDIT_NO_ID,
	                        hostname,
	                        NULL,    /* addr */
	                        tty,
	                        1);      /* result */
	close (audit_fd);
#endif				/* WITH_AUDIT */

#ifndef USE_PAM			/* pam_lastlog handles this */
	if (getdef_bool ("LASTLOG_ENAB")) {	/* give last login and log this one */
		dolastlog (&ll, pwd, tty, hostname);
	}
#endif

#ifndef USE_PAM			/* PAM handles this as well */
	/*
	 * Have to do this while we still have root privileges, otherwise we
	 * don't have access to /etc/shadow.
	 */
	if (NULL != spwd) {		/* check for age of password */
		if (expire (pwd, spwd)) {
			/* The user updated her password, get the new
			 * entries.
			 * Use the x variants because we need to keep the
			 * entry for a long time, and there might be other
			 * getxxyy in between.
			 */
			pw_free (pwd);
			pwd = xgetpwnam (username);
			if (NULL == pwd) {
				SYSLOG ((LOG_ERR,
				         "cannot find user %s after update of expired password",
				         username));
				exit (1);
			}
			spw_free (spwd);
			spwd = xgetspnam (username);
		}
	}
	setup_limits (pwd);	/* nice, ulimit etc. */
#endif				/* ! USE_PAM */
	chown_tty (pwd);

#ifdef USE_PAM
	/*
	 * We must fork before setuid() because we need to call
	 * pam_close_session() as root.
	 */
	(void) signal (SIGINT, SIG_IGN);
	child = fork ();
	if (child < 0) {
		/* error in fork() */
		fprintf (stderr, _("%s: failure forking: %s"),
		         Prog, strerror (errno));
		PAM_END;
		exit (0);
	} else if (child != 0) {
		/*
		 * parent - wait for child to finish, then cleanup
		 * session
		 */
		wait (NULL);
		PAM_END;
		exit (0);
	}
	/* child */
#endif

	/* If we were init, we need to start a new session */
	if (getppid() == 1) {
		setsid();
		if (ioctl(0, TIOCSCTTY, 1) != 0) {
			fprintf (stderr, _("TIOCSCTTY failed on %s"), tty);
		}
	}

	/*
	 * The utmp entry needs to be updated to indicate the new status
	 * of the session, the new PID and SID.
	 */
	update_utmp (username, tty, hostname, utent);

	/* The pwd and spwd entries for the user have been copied.
	 *
	 * Close all the files so that unauthorized access won't occur.
	 */
	endpwent ();		/* stop access to password file */
	endgrent ();		/* stop access to group file */
	endspent ();		/* stop access to shadow passwd file */
#ifdef	SHADOWGRP
	endsgent ();		/* stop access to shadow group file */
#endif

	/* Drop root privileges */
#ifndef USE_PAM
	if (setup_uid_gid (pwd, is_console))
#else
	/* The group privileges were already dropped.
	 * See setup_groups() above.
	 */
	if (change_uid (pwd))
#endif
	{
		exit (1);
	}

	setup_env (pwd);	/* set env vars, cd to the home dir */

#ifdef USE_PAM
	{
		const char *const *env;

		env = (const char *const *) pam_getenvlist (pamh);
		while ((NULL != env) && (NULL != *env)) {
			addenv (*env, NULL);
			env++;
		}
	}
#endif

	(void) setlocale (LC_ALL, "");
	(void) bindtextdomain (PACKAGE, LOCALEDIR);
	(void) textdomain (PACKAGE);

	if (!hushed (username)) {
		addenv ("HUSHLOGIN=FALSE", NULL);
		/*
		 * pam_unix, pam_mail and pam_lastlog should take care of
		 * this
		 */
#ifndef USE_PAM
		motd ();	/* print the message of the day */
		if (   getdef_bool ("FAILLOG_ENAB")
		    && (0 != faillog.fail_cnt)) {
			failprint (&faillog);
			/* Reset the lockout times if logged in */
			if (   (0 != faillog.fail_max)
			    && (faillog.fail_cnt >= faillog.fail_max)) {
				(void) puts (_("Warning: login re-enabled after temporary lockout."));
				SYSLOG ((LOG_WARN,
				         "login '%s' re-enabled after temporary lockout (%d failures)",
				         username, (int) faillog.fail_cnt));
			}
		}
		if (   getdef_bool ("LASTLOG_ENAB")
		    && (ll.ll_time != 0)) {
			time_t ll_time = ll.ll_time;

#ifdef HAVE_STRFTIME
			(void) strftime (ptime, sizeof (ptime),
			                 "%a %b %e %H:%M:%S %z %Y",
			                 localtime (&ll_time));
			printf (_("Last login: %s on %s"),
			        ptime, ll.ll_line);
#else
			printf (_("Last login: %.19s on %s"),
			        ctime (&ll_time), ll.ll_line);
#endif
#ifdef HAVE_LL_HOST		/* __linux__ || SUN4 */
			if ('\0' != ll.ll_host[0]) {
				printf (_(" from %.*s"),
				        (int) sizeof ll.ll_host, ll.ll_host);
			}
#endif
			printf (".\n");
		}
		agecheck (spwd);

		mailcheck ();	/* report on the status of mail */
#endif				/* !USE_PAM */
	} else {
		addenv ("HUSHLOGIN=TRUE", NULL);
	}

	ttytype (tty);

	(void) signal (SIGQUIT, SIG_DFL);	/* default quit signal */
	(void) signal (SIGTERM, SIG_DFL);	/* default terminate signal */
	(void) signal (SIGALRM, SIG_DFL);	/* default alarm signal */
	(void) signal (SIGHUP, SIG_DFL);	/* added this.  --marekm */
	(void) signal (SIGINT, SIG_DFL);	/* default interrupt signal */

	if (0 == pwd->pw_uid) {
		SYSLOG ((LOG_NOTICE, "ROOT LOGIN %s", fromhost));
	} else if (getdef_bool ("LOG_OK_LOGINS")) {
		SYSLOG ((LOG_INFO, "'%s' logged in %s", username, fromhost));
	}
	closelog ();
	tmp = getdef_str ("FAKE_SHELL");
	if (NULL != tmp) {
		err = shell (tmp, pwd->pw_shell, newenvp); /* fake shell */
	} else {
		/* exec the shell finally */
		err = shell (pwd->pw_shell, (char *) 0, newenvp);
	}

	return ((err == ENOENT) ? E_CMD_NOTFOUND : E_CMD_NOEXEC);
}
Esempio n. 14
0
File: cgi.c Progetto: mmocean/shttpd
static void
prepare_environment(const struct conn *c, const char *prog,
		struct env_block *blk)
{
	const struct headers	*h = &c->ch;
	const char		*s;
	size_t			len;

	blk->len = blk->nvars = 0;

	/* Prepare the environment block */
	addenv(blk, "%s", "GATEWAY_INTERFACE=CGI/1.1");
	addenv(blk, "%s", "SERVER_PROTOCOL=HTTP/1.1");
	addenv(blk, "%s", "REDIRECT_STATUS=200");	/* PHP */
	addenv(blk, "SERVER_PORT=%d", c->loc_port);
	addenv(blk, "SERVER_NAME=%s", c->ctx->auth_realm);
	addenv(blk, "SERVER_ROOT=%s", c->ctx->document_root);
	addenv(blk, "DOCUMENT_ROOT=%s", c->ctx->document_root);
	addenv(blk, "REQUEST_METHOD=%s", known_http_methods[c->method].ptr);
	addenv(blk, "REMOTE_ADDR=%s", inet_ntoa(c->sa.u.sin.sin_addr));
	addenv(blk, "REMOTE_PORT=%hu", ntohs(c->sa.u.sin.sin_port));
	addenv(blk, "REQUEST_URI=%s", c->uri);
	addenv(blk, "SCRIPT_NAME=%s", prog + strlen(c->ctx->document_root));
	addenv(blk, "SCRIPT_FILENAME=%s", prog);	/* PHP */
	addenv(blk, "PATH_TRANSLATED=%s", prog);

	if (h->ct.v_vec.len > 0)
		addenv(blk, "CONTENT_TYPE=%.*s", 
		    h->ct.v_vec.len, h->ct.v_vec.ptr);

	if (c->query != NULL)
		addenv(blk, "QUERY_STRING=%s", c->query);

	if (c->path_info != NULL)
		addenv(blk, "PATH_INFO=/%s", c->path_info);

	if (h->cl.v_big_int > 0)
		addenv(blk, "CONTENT_LENGTH=%lu", h->cl.v_big_int);

	if ((s = getenv("PATH")) != NULL)
		addenv(blk, "PATH=%s", s);

#ifdef _WIN32
	if ((s = getenv("COMSPEC")) != NULL)
		addenv(blk, "COMSPEC=%s", s);
	if ((s = getenv("SYSTEMROOT")) != NULL)
		addenv(blk, "SYSTEMROOT=%s", s);
#else
	if ((s = getenv("LD_LIBRARY_PATH")) != NULL)
		addenv(blk, "LD_LIBRARY_PATH=%s", s);
#endif /* _WIN32 */

	if ((s = getenv("PERLLIB")) != NULL)
		addenv(blk, "PERLLIB=%s", s);

	if (h->user.v_vec.len > 0) {
		addenv(blk, "REMOTE_USER=%.*s",
		    h->user.v_vec.len, h->user.v_vec.ptr);
		addenv(blk, "%s", "AUTH_TYPE=Digest");
	}

	/* Add user-specified variables */
	s = c->ctx->cgi_vars;
	FOR_EACH_WORD_IN_LIST(s, len)
		addenv(blk, "%.*s", len, s);

	/* Add all headers as HTTP_* variables */
	add_http_headers_to_env(blk, c->headers,
	    c->rem.headers_len - (c->headers - c->request));

	blk->vars[blk->nvars++] = NULL;
	blk->buf[blk->len++] = '\0';

	assert(blk->nvars < CGI_ENV_VARS);
	assert(blk->len > 0);
	assert(blk->len < (int) sizeof(blk->buf));

	/* Debug stuff to view passed environment */
	DBG(("%s: %d vars, %d env size", prog, blk->nvars, blk->len));
	{
		int i;
		for (i = 0 ; i < blk->nvars; i++)
			DBG(("[%s]", blk->vars[i] ? blk->vars[i] : "null"));
	}
}
Esempio n. 15
0
/*VARARGS1*/
int
exec(int type, ...)
{
	va_list			args;

	int			i;
	int			procuid;
	int			procgid;
	int			ret;
	int			fr_flg;

	char			*cp;
	char			*infile;
	char			*outfile;
	char			*errfile;
	char			*sep;

	char			**listp;
	char			**file_list;
	char			*printerName;
	char			*printerNameToShow;
	static char		nameBuf[100];
	char			*clean_title;

	PSTATUS			*printer;

	RSTATUS			*request;

	FSTATUS			*form;

	EXEC			*ep;

	PWSTATUS		*pwheel;
	time_t			now;
	struct passwd		*pwp;
#ifdef LP_USE_PAPI_ATTR
	struct stat		tmpBuf;
	char 			tmpName[BUFSIZ];
	char			*path = NULL;
#endif
	char *av[ARG_MAX];
	char **envp = NULL;
	int ac = 0;
	char	*mail_zonename = NULL;
	char	*slabel = NULL;

	syslog(LOG_DEBUG, "exec(%s)", _exec_name(type));

	memset(av, 0, sizeof (*av));

	va_start (args, type);

	switch (type) {

	case EX_INTERF:
		printer = va_arg(args, PSTATUS *);
		request = printer->request;
		ep = printer->exec;
		break;
		
	case EX_FAULT_MESSAGE:
		printer = va_arg(args, PSTATUS *);
		request = va_arg(args, RSTATUS *);
		if (! ( printer->status & (PS_FORM_FAULT | PS_SHOW_FAULT))) {
			return(0);
		}
		ep = printer->fault_exec;
		printerName = (printer->printer && printer->printer->name 
				  ? printer->printer->name : "??");
			snprintf(nameBuf, sizeof (nameBuf),
				"%s (on %s)\n", printerName, Local_System);

		printerNameToShow = nameBuf;

		(void) time(&now);
		(void) strftime(time_buf, sizeof (time_buf),
			NULL, localtime(&now));
		break;

	case EX_SLOWF:
		request = va_arg(args, RSTATUS *);
		ep = request->exec;
		break;

	case EX_NOTIFY:
		request = va_arg(args, RSTATUS *);
		if (request->request->actions & ACT_NOTIFY) {
			errno = EINVAL;
			return (-1);
		}
		ep = request->exec;
		break;

	case EX_ALERT:
		printer = va_arg(args, PSTATUS *);
		if (!(printer->printer->fault_alert.shcmd)) {
			errno = EINVAL;
			return(-1);
		}
		ep = printer->alert->exec;
		break;

	case EX_PALERT:
		pwheel = va_arg(args, PWSTATUS *);
		ep = pwheel->alert->exec;
		break;

	case EX_FORM_MESSAGE:
		(void) time(&now);
		(void) strftime(time_buf, sizeof (time_buf),
			NULL, localtime(&now));

		/*FALLTHRU*/
	case EX_FALERT:
		form = va_arg(args, FSTATUS *);
		ep = form->alert->exec;
		break;

	default:
		errno = EINVAL;
		return(-1);

	}
	va_end (args);

	if (!ep || (ep->pid > 0)) {
		errno = EBUSY;
		return(-1);
	}

	ep->flags = 0;

	key = ep->key = getkey();

	switch ((ep->pid = Fork1(ep))) {

	case -1:
		relock ();
		return(-1);

	case 0:
		/*
		 * We want to be able to tell our parent how we died.
		 */
		lp_alloc_fail_handler = child_mallocfail;
		break;

	default:
		switch(type) {

		case EX_INTERF:
			request->request->outcome |= RS_PRINTING;
			break;

		case EX_NOTIFY:
			request->request->outcome |= RS_NOTIFYING;
			break;

		case EX_SLOWF:
			request->request->outcome |= RS_FILTERING;
			request->request->outcome &= ~RS_REFILTER;
			break;

		}
		return(0);

	}

	for (i = 0; i < NSIG; i++)
		(void)signal (i, SIG_DFL);
	(void)signal (SIGALRM, SIG_IGN);
	(void)signal (SIGTERM, sigtrap);

	closelog();
	for (i = 0; i < OpenMax; i++)
		if (i != ChildMd->writefd)
			Close (i);
	openlog("lpsched", LOG_PID|LOG_NDELAY|LOG_NOWAIT, LOG_LPR);

	setpgrp();

	/* Set a default path */
	addenv (&envp, "PATH", "/usr/lib/lp/bin:/usr/bin:/bin:/usr/sbin:/sbin");
	/* copy locale related variables */
	addenv (&envp, "TZ", getenv("TZ"));
	addenv (&envp, "LANG", getenv("LANG"));
	addenv (&envp, "LC_ALL", getenv("LC_ALL"));
	addenv (&envp, "LC_COLLATE", getenv("LC_COLLATE"));
	addenv (&envp, "LC_CTYPE", getenv("LC_CTYPE"));
	addenv (&envp, "LC_MESSAGES", getenv("LC_MESSAGES"));
	addenv (&envp, "LC_MONETARY", getenv("LC_MONETARY"));
	addenv (&envp, "LC_NUMERIC", getenv("LC_NUMERIC"));
	addenv (&envp, "LC_TIME", getenv("LC_TIME"));

	sprintf ((cp = BIGGEST_NUMBER_S), "%ld", key);
	addenv (&envp, "SPOOLER_KEY", cp);

#if	defined(DEBUG)
	addenv (&envp, "LPDEBUG", (debug? "1" : "0"));
#endif

	/*
	 * Open the standard input, standard output, and standard error.
	 */
	switch (type) {
		
	case EX_SLOWF:
	case EX_INTERF:
		/*
		 * stdin:  /dev/null
		 * stdout: /dev/null (EX_SLOWF), printer port (EX_INTERF)
		 * stderr: req#
		 */
		infile = 0;
		outfile = 0;
		errfile = makereqerr(request);
		break;

	case EX_NOTIFY:
		/*
		 * stdin:  req#
		 * stdout: /dev/null
		 * stderr: /dev/null
		 */
		infile = makereqerr(request);
		outfile = 0;
		errfile = 0;

		break;

	case EX_ALERT:
	case EX_FALERT:
	case EX_PALERT:
	case EX_FAULT_MESSAGE:
	case EX_FORM_MESSAGE:
		/*
		 * stdin:  /dev/null
		 * stdout: /dev/null
		 * stderr: /dev/null
		 */
		infile = 0;
		outfile = 0;
		errfile = 0;
		break;

	}

	if (infile) {
		if (Open(infile, O_RDONLY) == -1)
			Done (EXEC_EXIT_NOPEN, errno);
	} else {
		if (Open("/dev/null", O_RDONLY) == -1)
			Done (EXEC_EXIT_NOPEN, errno);
	}

	if (outfile) {
		if (Open(outfile, O_CREAT|O_TRUNC|O_WRONLY, 0600) == -1)
			Done (EXEC_EXIT_NOPEN, errno);
	} else {
		/*
		 * If EX_INTERF, this is still needed to cause the
		 * standard error channel to be #2.
		 */
		if (Open("/dev/null", O_WRONLY) == -1)
			Done (EXEC_EXIT_NOPEN, errno);
	}

	if (errfile) {
		if (Open(errfile, O_CREAT|O_TRUNC|O_WRONLY, 0600) == -1)
			Done (EXEC_EXIT_NOPEN, errno);
	} else {
		if (Open("/dev/null", O_WRONLY) == -1)
			Done (EXEC_EXIT_NOPEN, errno);
	}

	switch (type) {

	case EX_INTERF:
		/*
		 * Opening a ``port'' can be dangerous to our health:
		 *
		 *	- Hangups can occur if the line is dropped.
		 *	- The printer may send an interrupt.
		 *	- A FIFO may be closed, generating SIGPIPE.
		 *
		 * We catch these so we can complain nicely.
		 */
		trap_fault_signals ();

		(void)Close (1);

		if (strchr (request->request->user, '@'))
		{
			procuid = Lp_Uid;
			procgid = Lp_Gid;
		}
		else
		{
			procuid = request->secure->uid;
			procgid = request->secure->gid;
		}
		if (printer->printer->dial_info)
		{
			ret = open_dialup(request->printer_type,
				printer->printer);
			if (ret == 0)
				do_undial = 1;
		}
		else
		{
			ret = open_direct(request->printer_type,
				printer->printer);
			do_undial = 0;
			/* this is a URI */
			if (is_printer_uri(printer->printer->device) == 0)
				addenv(&envp, "DEVICE_URI",
					 printer->printer->device);
		}
				addenv(&envp, "DEVICE_URI",
					 printer->printer->device);
		if (ret != 0)
			Done (ret, errno);
			
		if (!(request->request->outcome & RS_FILTERED))
			file_list = request->request->file_list;

		else {
			register int		count	= 0;
			register char *		num	= BIGGEST_REQID_S;
			register char *		prefix;

			prefix = makestr(
				Lp_Temp,
				"/F",
				getreqno(request->secure->req_id),
				"-",
				(char *)0
			);

			file_list = (char **)Malloc(
				(lenlist(request->request->file_list) + 1)
			      * sizeof(char *)
			);

			for (
				listp = request->request->file_list;
				*listp;
				listp++
			) {
				sprintf (num, "%d", count + 1);
				file_list[count] = makestr(
					prefix,
					num,
					(char *)0
				);
				count++;
			}
			file_list[count] = 0;
		}

#ifdef LP_USE_PAPI_ATTR
		/*
		 * Check if the PAPI job attribute file exists, if it does
		 * pass the file's pathname to the printer interface script
		 * in an environment variable. This file is created when
		 * print jobs are submitted via the PAPI interface.
		 */
		snprintf(tmpName, sizeof (tmpName), "%s-%s",
			getreqno(request->secure->req_id), LP_PAPIATTRNAME);
		path = makepath(Lp_Temp, tmpName, (char *)0);
		if ((path != NULL) && (stat(path, &tmpBuf) == 0))
		{
			/*
			 * IPP job attribute file exists for this job so
			 * set the environment variable
			 */
			addenv(&envp, "ATTRPATH", path);
		}
		Free(path);

		/*
		 * now set environment variable for the printer's PostScript
		 * Printer Description (PPD) file, this is used by the filter
		 * when forming the print data for this printer.
		 */
		if ((request->printer != NULL) &&
		    (request->printer->printer != NULL) &&
		    (request->printer->printer->name != NULL))
		{
			snprintf(tmpName, sizeof (tmpName), "%s.ppd",
				request->printer->printer->name);
			path = makepath(ETCDIR, "ppd", tmpName, (char *)0);
			if ((path != NULL) && (stat(path, &tmpBuf) == 0))
			{
				addenv(&envp, "PPD", path);
			}
			Free(path);
		}
#endif

		if (request->printer_type)
			addenv(&envp, "TERM", request->printer_type);

		if (!(printer->printer->daisy)) {
			register char *	chset = 0;
			register char *	csp;

			if (
				request->form
			     && request->form->form->chset
			     && request->form->form->mandatory
			     && !STREQU(NAME_ANY, request->form->form->chset)
			)
				chset = request->form->form->chset;

			else if (
				request->request->charset
			     && !STREQU(NAME_ANY, request->request->charset)
			)
				chset = request->request->charset;

			if (chset) {
				csp = search_cslist(
					chset,
					printer->printer->char_sets
				);

				/*
				 * The "strtok()" below wrecks the string
				 * for future use, but this is a child
				 * process where it won't be needed again.
				 */
				addenv (&envp, "CHARSET",
					(csp? strtok(csp, "=") : chset)
				);
			}
		}

		if (request->fast)
			addenv(&envp, "FILTER", request->fast);

		/*
		 * Add the sensitivity label to the environment for
		 * banner page and header/footer processing
		 */

		if (is_system_labeled() && request->secure->slabel != NULL)
			addenv(&envp, "SLABEL", request->secure->slabel);

		/*
		 * Add the system name to the user name (ala system!user)
		 * unless it is already there. RFS users may have trouble
		 * here, sorry!
		 */
		cp = strchr(request->secure->user, '@');

		allTraysWithForm(printer, request->form); 

		/*
		 * Fix for 4137389
		 * Remove double quotes from title string.
		 */
		fr_flg = 1;
		clean_title = strdup(NB(request->request->title));
		if (clean_title == NULL) {
			/*
			 * strdup failed. We're probably hosed
			 * but try setting clean_title
			 * to original title and continuing.
			 */
			clean_title = NB(request->request->title);
			fr_flg = 0;
		} else if (strcmp(clean_title, "") != 0) {
			char *ct_p;

			for (ct_p = clean_title; *ct_p != NULL; ct_p++) {
				if (*ct_p == '"')
					*ct_p = ' ';
			}
		}

		av[ac++] = arg_string(TRUSTED, "%s/%s", Lp_A_Interfaces,
					printer->printer->name);
		av[ac++] = arg_string(TRUSTED, "%s", request->secure->req_id);
		av[ac++] = arg_string(UNTRUSTED, "%s", request->request->user);
		av[ac++] = arg_string(TRUSTED, "%s", clean_title);
		av[ac++] = arg_string(TRUSTED, "%d", request->copies);

		if (fr_flg)
			free (clean_title);

		sep = "";

		/*
		 * Do the administrator defined key=value pair options
		 */

		argbuf[0] = '\0';
				
		if (printer->printer->options) {
			char **tmp = printer->printer->options;
			while(*tmp != NULL) {
				STRLCAT(argbuf, sep, sizeof (argbuf));
				sep = " ";
				STRLCAT(argbuf, *tmp++, sizeof (argbuf));
			}
		}

		/*
		 * Do the administrator defined ``stty'' stuff before
		 * the user's -o options, to allow the user to override.
		 */
		if (printer->printer->stty) {
			STRLCAT (argbuf, sep, sizeof (argbuf));
			sep = " ";
			STRLCAT (argbuf, "stty='", sizeof (argbuf));
			STRLCAT (argbuf, printer->printer->stty,
			    sizeof (argbuf));
			STRLCAT (argbuf, "'", sizeof (argbuf));
		}

		/*
		 * Do all of the user's options except the cpi/lpi/etc.
		 * stuff, which is done separately.
		 */
		if (request->request->options) {
			listp = dashos(request->request->options);
			while (*listp) {
				if (
					!STRNEQU(*listp, "cpi=", 4)
				     && !STRNEQU(*listp, "lpi=", 4)
				     && !STRNEQU(*listp, "width=", 6)
				     && !STRNEQU(*listp, "length=", 7)
				) {
					STRLCAT (argbuf, sep, sizeof (argbuf));
					sep = " ";
					STRLCAT (argbuf, *listp,
					    sizeof (argbuf));
				}
				listp++;
			}
		}

		/*
		 * The "pickfilter()" routine (from "validate()")
		 * stored the cpi/lpi/etc. stuff that should be
		 * used for this request. It chose form over user,
		 * and user over printer.
		 */
		if (request->cpi) {
			STRLCAT (argbuf, sep, sizeof (argbuf));
			sep = " ";
			STRLCAT (argbuf, "cpi=", sizeof (argbuf));
			STRLCAT (argbuf, request->cpi, sizeof (argbuf));
		}
		if (request->lpi) {
			STRLCAT (argbuf, sep, sizeof (argbuf));
			sep = " ";
			STRLCAT (argbuf, "lpi=", sizeof (argbuf));
			STRLCAT (argbuf, request->lpi, sizeof (argbuf));
		}
		if (request->pwid) {
			STRLCAT (argbuf, sep, sizeof (argbuf));
			sep = " ";
			STRLCAT (argbuf, "width=", sizeof (argbuf));
			STRLCAT (argbuf, request->pwid, sizeof (argbuf));
		}
		if (request->plen) {
			STRLCAT (argbuf, sep, sizeof (argbuf));
			sep = " ";
			STRLCAT (argbuf, "length=", sizeof (argbuf));
			STRLCAT (argbuf, request->plen, sizeof (argbuf));
		}

		/*
		 * Do the ``raw'' bit last, to ensure it gets
		 * done. If the user doesn't want this, then he or
		 * she can do the correct thing using -o stty=
		 * and leaving out the -r option.
		 */
		if (request->request->actions & ACT_RAW) {
			STRLCAT (argbuf, sep, sizeof (argbuf));
			sep = " ";
			STRLCAT (argbuf, "stty=-opost", sizeof (argbuf));
		}


		/* the "options" */
		av[ac++] = arg_string(UNTRUSTED, "%s", argbuf);

		for (listp = file_list; *listp; listp++)
			av[ac++] = arg_string(TRUSTED, "%s", *listp);

		(void)chfiles (file_list, procuid, procgid);

		break;


	case EX_SLOWF:
		if (request->slow)
			addenv(&envp, "FILTER", request->slow);

		if (strchr (request->request->user, '@'))
		{
			procuid = Lp_Uid;
			procgid = Lp_Gid;
		}
		else
		{
			procuid = request->secure->uid;
			procgid = request->secure->gid;
		}
		cp = _alloc_files(
			lenlist(request->request->file_list),
			getreqno(request->secure->req_id),
			procuid, procgid);

		av[ac++] = arg_string(TRUSTED, "%s", Lp_Slow_Filter);
		av[ac++] = arg_string(TRUSTED, "%s/%s", Lp_Temp, cp);
		for (listp = request->request->file_list; *listp; listp++)
			av[ac++] = arg_string(TRUSTED, "%s", *listp);

		(void)chfiles (request->request->file_list, procuid, procgid);

#ifdef LP_USE_PAPI_ATTR
		/*
		 * Check if the PAPI job attribute file exists, if it does
		 * pass the file's pathname to the slow-filters in an
		 * environment variable. Note: this file is created when
		 * print jobs are submitted via the PAPI interface.
		 */
		snprintf(tmpName, sizeof (tmpName), "%s-%s",
			getreqno(request->secure->req_id), LP_PAPIATTRNAME);
		path = makepath(Lp_Temp, tmpName, (char *)0);
		if ((path != NULL) && (stat(path, &tmpBuf) == 0))
		{
			/*
			 * IPP job attribute file exists for this job so
			 * set the environment variable
			 */
			addenv(&envp, "ATTRPATH", path);
		}
		Free(path);


		/*
		 * now set environment variable for the printer's PostScript
		 * Printer Description (PPD) file, this is used by the filter
		 * when forming the print data for this printer.
		 */
		if ((request->printer != NULL) &&
		    (request->printer->printer != NULL) &&
		    (request->printer->printer->name != NULL))
		{
			snprintf(tmpName, sizeof (tmpName), "%s.ppd",
				request->printer->printer->name);
			path = makepath(ETCDIR, "ppd", tmpName, (char *)0);
			if ((path != NULL) && (stat(path, &tmpBuf) == 0))
			{
				addenv(&envp, "PPD", path);
			}
			Free(path);
		}
#endif
		break;

	case EX_ALERT:
		procuid = Lp_Uid;
		procgid = Lp_Gid;
		(void)Chown (printer->alert->msgfile, procuid, procgid);

		av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_Printers,
				printer->printer->name, ALERTSHFILE);
		av[ac++] = arg_string(TRUSTED, "%s", printer->alert->msgfile);

		break;

	case EX_PALERT:
		procuid = Lp_Uid;
		procgid = Lp_Gid;
		(void)Chown (pwheel->alert->msgfile, procuid, procgid);

		av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_PrintWheels,
				pwheel->pwheel->name, ALERTSHFILE);
		av[ac++] = arg_string(TRUSTED, "%s", printer->alert->msgfile);

		break;

	case EX_FALERT:
		procuid = Lp_Uid;
		procgid = Lp_Gid;
		(void)Chown (form->alert->msgfile, procuid, procgid);

		av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_Forms,
				form->form->name, ALERTSHFILE);
		av[ac++] = arg_string(TRUSTED, "%s", printer->alert->msgfile);

		break;

	case EX_FORM_MESSAGE:
		procuid = Lp_Uid;
		procgid = Lp_Gid;

		av[ac++] = arg_string(TRUSTED, "%s/form", Lp_A_Faults);
		av[ac++] = arg_string(TRUSTED, "%s", form->form->name);
		av[ac++] = arg_string(TRUSTED, "%s", time_buf);
		av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_Forms,
				form->form->name, FORMMESSAGEFILE);

		break;

	case EX_FAULT_MESSAGE:
		procuid = Lp_Uid;
		procgid = Lp_Gid;

		av[ac++] = arg_string(TRUSTED, "%s/printer", Lp_A_Faults);
		av[ac++] = arg_string(TRUSTED, "%s", printerNameToShow);
		av[ac++] = arg_string(TRUSTED, "%s", time_buf);
		av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_Printers,
				printerName, FAULTMESSAGEFILE);

		break;

	case EX_NOTIFY:
		if (request->request->alert) {
			if (strchr(request->request->user, '@')) {
				procuid = Lp_Uid;
				procgid = Lp_Gid;
			} else {
				procuid = request->secure->uid;
				procgid = request->secure->gid;
			}
			av[ac++] = arg_string(TRUSTED, "%s",
					request->request->alert);
		} else {
			char *user = strdup(request->request->user);
			clean_string(user);
			slabel = request->secure->slabel;

			if (request->request->actions & ACT_WRITE) {
				av[ac++] = arg_string(TRUSTED, "%s", BINWRITE);
				snprintf(argbuf, sizeof (argbuf),
					"%s %s || %s %s",
					BINWRITE, user,
					BINMAIL, user
				);
				av[ac++] = arg_string(TRUSTED, "/bin/sh");
				av[ac++] = arg_string(TRUSTED, "-c");
				av[ac++] = arg_string(TRUSTED, "%s", argbuf);
			} else if ((getzoneid() == GLOBAL_ZONEID) &&
				   is_system_labeled() && (slabel != NULL)) {
				/*
				 * If in the global zone and the system is
				 * labeled, mail is handled via a local
				 * labeled zone that is the same label as
				 * the request.
				 */
				if ((mail_zonename =
				    get_labeled_zonename(slabel)) ==
				    (char *)-1) {
					/*
					 * Cannot find labeled zone, just
					 * return 0.
					 */
					return(0);
				}
			}
			if (mail_zonename == NULL) {
				procuid = Lp_Uid;
				procgid = Lp_Gid;
				av[ac++] = arg_string(TRUSTED, "%s", BINMAIL);
				av[ac++] = arg_string(UNTRUSTED, "%s", user);
			} else {
				procuid = getuid();
				procgid = getgid();
				av[ac++] = arg_string(TRUSTED, "%s",
				    "/usr/sbin/zlogin");
				av[ac++] = arg_string(TRUSTED, "%s",
				    mail_zonename);
				av[ac++] = arg_string(TRUSTED, "%s",
				    BINMAIL);
				av[ac++] = arg_string(UNTRUSTED, "%s",
				    user);
				Free(mail_zonename);
			}

			free(user);
		}
		break;
	}

	av[ac++] = NULL;

	Fork2 ();
	/* only the child returns */

	/*
	 * Correctly set up the supplemental group list
	 * for proper file access (before execl the interface program)
	 */

	pwp = getpwuid(procuid);
	if (pwp == NULL) {
		note("getpwuid(%d) call failed\n", procuid);
	} else if (initgroups(pwp->pw_name, procgid) < 0) {
		note("initgroups() call failed %d\n", errno);
	}
	
	setgid (procgid);
	setuid (procuid);

	/*
	 * The shell doesn't allow the "trap" builtin to set a trap
	 * for a signal ignored when the shell is started. Thus, don't
	 * turn off signals in the last child!
	 */

#ifdef DEBUG
	for (i = 0; av[i] != NULL; i++)
		note("exec(%s): av[%d] = %s", _exec_name(type), i, av[i]);
	for (i = 0; envp[i] != NULL; i++)
		note("exec(%s): envp[%d] = %s", _exec_name(type), i, envp[i]);
#endif

	execvpe(av[0], av, envp);
	Done (EXEC_EXIT_NEXEC, errno);
	/*NOTREACHED*/
	return (0);
}