15c51f124SMoriah Waterland /*
25c51f124SMoriah Waterland * CDDL HEADER START
35c51f124SMoriah Waterland *
45c51f124SMoriah Waterland * The contents of this file are subject to the terms of the
55c51f124SMoriah Waterland * Common Development and Distribution License (the "License").
65c51f124SMoriah Waterland * You may not use this file except in compliance with the License.
75c51f124SMoriah Waterland *
85c51f124SMoriah Waterland * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95c51f124SMoriah Waterland * or http://www.opensolaris.org/os/licensing.
105c51f124SMoriah Waterland * See the License for the specific language governing permissions
115c51f124SMoriah Waterland * and limitations under the License.
125c51f124SMoriah Waterland *
135c51f124SMoriah Waterland * When distributing Covered Code, include this CDDL HEADER in each
145c51f124SMoriah Waterland * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155c51f124SMoriah Waterland * If applicable, add the following below this CDDL HEADER, with the
165c51f124SMoriah Waterland * fields enclosed by brackets "[]" replaced with your own identifying
175c51f124SMoriah Waterland * information: Portions Copyright [yyyy] [name of copyright owner]
185c51f124SMoriah Waterland *
195c51f124SMoriah Waterland * CDDL HEADER END
205c51f124SMoriah Waterland */
215c51f124SMoriah Waterland
225c51f124SMoriah Waterland /*
235c51f124SMoriah Waterland * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
245c51f124SMoriah Waterland * Use is subject to license terms.
255c51f124SMoriah Waterland */
265c51f124SMoriah Waterland
275c51f124SMoriah Waterland /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
285c51f124SMoriah Waterland /* All Rights Reserved */
295c51f124SMoriah Waterland
305c51f124SMoriah Waterland
315c51f124SMoriah Waterland #include <stdio.h>
325c51f124SMoriah Waterland #include <errno.h>
335c51f124SMoriah Waterland #include <string.h>
345c51f124SMoriah Waterland #include <stdlib.h>
355c51f124SMoriah Waterland #include <unistd.h>
365c51f124SMoriah Waterland #include <signal.h>
375c51f124SMoriah Waterland #include <wait.h>
385c51f124SMoriah Waterland #include <sys/types.h>
395c51f124SMoriah Waterland #include <sys/stat.h>
405c51f124SMoriah Waterland #include <fcntl.h>
415c51f124SMoriah Waterland #include <pwd.h>
425c51f124SMoriah Waterland #include <grp.h>
43*4656d474SGarrett D'Amore #include <note.h>
445c51f124SMoriah Waterland #include "pkglib.h"
455c51f124SMoriah Waterland #include "pkglibmsgs.h"
465c51f124SMoriah Waterland #include "pkglocale.h"
475c51f124SMoriah Waterland
485c51f124SMoriah Waterland /* global environment inherited by this process */
495c51f124SMoriah Waterland extern char **environ;
505c51f124SMoriah Waterland
515c51f124SMoriah Waterland /* dstream.c */
525c51f124SMoriah Waterland extern int ds_curpartcnt;
535c51f124SMoriah Waterland extern int ds_close(int pkgendflg);
545c51f124SMoriah Waterland
555c51f124SMoriah Waterland /*
565c51f124SMoriah Waterland * global internal (private) variables
575c51f124SMoriah Waterland */
585c51f124SMoriah Waterland
595c51f124SMoriah Waterland /* received signal count - bumped with hooked signals are caught */
605c51f124SMoriah Waterland
615c51f124SMoriah Waterland static int sig_received = 0;
625c51f124SMoriah Waterland
635c51f124SMoriah Waterland /*
645c51f124SMoriah Waterland * Name: sig_trap
655c51f124SMoriah Waterland * Description: hooked up to signal counts number of signals received
665c51f124SMoriah Waterland * Arguments: a_signo - [RO, *RO] - (int)
675c51f124SMoriah Waterland * Integer representing the signal received; see signal(3c)
685c51f124SMoriah Waterland * Returns: <void>
695c51f124SMoriah Waterland */
705c51f124SMoriah Waterland
715c51f124SMoriah Waterland static void
sig_trap(int a_signo)725c51f124SMoriah Waterland sig_trap(int a_signo)
735c51f124SMoriah Waterland {
74*4656d474SGarrett D'Amore _NOTE(ARGUNUSED(a_signo));
755c51f124SMoriah Waterland sig_received++;
765c51f124SMoriah Waterland }
775c51f124SMoriah Waterland
785c51f124SMoriah Waterland /*
795c51f124SMoriah Waterland * Name: pkgexecv
805c51f124SMoriah Waterland * Description: Asynchronously execute a package command in a separate process
815c51f124SMoriah Waterland * and return results - the subprocess MUST arm it's own SIGINT
825c51f124SMoriah Waterland * and SIGHUP signals and must return a standard package command
835c51f124SMoriah Waterland * exit code (see returns below)
845c51f124SMoriah Waterland * Only another package command (such as pkginstall, pkgremove,
855c51f124SMoriah Waterland * etc.) may be called via this interface. No files are closed
865c51f124SMoriah Waterland * because open files are passed across to certain commands using
875c51f124SMoriah Waterland * either implicit agreements between the two (yuk!) or by using
885c51f124SMoriah Waterland * the '-p' option which passes a string of digits, some of which
895c51f124SMoriah Waterland * represent open file descriptors passed through this interface!
905c51f124SMoriah Waterland * Arguments: filein - [RO, *RO] - (char *)
915c51f124SMoriah Waterland * Pointer to string representing the name of the file to
925c51f124SMoriah Waterland * use for the package commands's stdin
935c51f124SMoriah Waterland * == (char *)NULL or == "" - the current stdin
945c51f124SMoriah Waterland * is used for the new package command process
955c51f124SMoriah Waterland * fileout - [RO, *RO] - (char *)
965c51f124SMoriah Waterland * Pointer to string representing the name of the file to
975c51f124SMoriah Waterland * use for the package commands's stdout and stderr
985c51f124SMoriah Waterland * == (char *)NULL or == "" - the current stdout/stderr
995c51f124SMoriah Waterland * is used for the new package command process
1005c51f124SMoriah Waterland * uname - [RO, *RO] - (char *)
1015c51f124SMoriah Waterland * Pointer to string representing the user name to execute
1025c51f124SMoriah Waterland * the package command as - the user name is looked up
1035c51f124SMoriah Waterland * using the ncgrpw:cpwnam() interface
1045c51f124SMoriah Waterland * == (char *)NULL or == "" - the user name of the current
1055c51f124SMoriah Waterland * process is used for the new package command process
1065c51f124SMoriah Waterland * gname - [RO, *RO] - (char *)
1075c51f124SMoriah Waterland * Pointer to string representing the group name to execute
1085c51f124SMoriah Waterland * the package command as - the group name is looked up
1095c51f124SMoriah Waterland * using the ncgrpw:cgrnam() interface
1105c51f124SMoriah Waterland * == (char *)NULL or == "" - the group name of the current
1115c51f124SMoriah Waterland * process is used for the new package command process
1125c51f124SMoriah Waterland * arg - [RO, *RO] - (char **)
1135c51f124SMoriah Waterland * Pointer to array of character pointers representing the
1145c51f124SMoriah Waterland * arguments to pass to the package command - the array is
1155c51f124SMoriah Waterland * terminated with a pointer to (char *)NULL
1165c51f124SMoriah Waterland * Returns: int
1175c51f124SMoriah Waterland * == 99 - exec() of package command failed
1185c51f124SMoriah Waterland * == -1 - fork failed or other fatal error during
1195c51f124SMoriah Waterland * execution of the package command
1205c51f124SMoriah Waterland * otherwise - exit code from package command:
1215c51f124SMoriah Waterland * 0 - successful
1225c51f124SMoriah Waterland * 1 - package operation failed (fatal error)
1235c51f124SMoriah Waterland * 2 - non-fatal error (warning)
1245c51f124SMoriah Waterland * 3 - operation interrupted (including SIGINT/SIGHUP)
1255c51f124SMoriah Waterland * 4 - admin settings prevented operation
1265c51f124SMoriah Waterland * 5 - administration required and -n was specified
1275c51f124SMoriah Waterland * IN addition:
1285c51f124SMoriah Waterland * 10 is added to the return code if reboot after the
1295c51f124SMoriah Waterland * installation of all packages is required
1305c51f124SMoriah Waterland * 20 is added to the return code if immediate reboot
1315c51f124SMoriah Waterland * after installation of this package is required
1325c51f124SMoriah Waterland */
1335c51f124SMoriah Waterland
1345c51f124SMoriah Waterland int
pkgexecv(char * filein,char * fileout,char * uname,char * gname,char * arg[])1355c51f124SMoriah Waterland pkgexecv(char *filein, char *fileout, char *uname, char *gname, char *arg[])
1365c51f124SMoriah Waterland {
1375c51f124SMoriah Waterland int exit_no;
1385c51f124SMoriah Waterland int n;
1395c51f124SMoriah Waterland int status;
1405c51f124SMoriah Waterland pid_t pid;
1415c51f124SMoriah Waterland pid_t waitstat;
1425c51f124SMoriah Waterland struct group *grp;
1435c51f124SMoriah Waterland struct passwd *pwp;
1445c51f124SMoriah Waterland struct sigaction nact;
1455c51f124SMoriah Waterland struct sigaction oact;
1465c51f124SMoriah Waterland void (*funcSighup)();
1475c51f124SMoriah Waterland void (*funcSigint)();
1485c51f124SMoriah Waterland
1495c51f124SMoriah Waterland /* flush standard i/o before creating new process */
1505c51f124SMoriah Waterland
1515c51f124SMoriah Waterland (void) fflush(stdout);
1525c51f124SMoriah Waterland (void) fflush(stderr);
1535c51f124SMoriah Waterland
1545c51f124SMoriah Waterland /*
1555c51f124SMoriah Waterland * hold SIGINT/SIGHUP signals and reset signal received counter;
1565c51f124SMoriah Waterland * after the vfork() the parent and child need to setup their respective
1575c51f124SMoriah Waterland * interrupt handling and release the hold on the signals
1585c51f124SMoriah Waterland */
1595c51f124SMoriah Waterland
1605c51f124SMoriah Waterland (void) sighold(SIGINT);
1615c51f124SMoriah Waterland (void) sighold(SIGHUP);
1625c51f124SMoriah Waterland
1635c51f124SMoriah Waterland sig_received = 0;
1645c51f124SMoriah Waterland
1655c51f124SMoriah Waterland /*
1665c51f124SMoriah Waterland * create new process to execute command in;
1675c51f124SMoriah Waterland * vfork() is being used to avoid duplicating the parents
1685c51f124SMoriah Waterland * memory space - this means that the child process may
1695c51f124SMoriah Waterland * not modify any of the parents memory including the
1705c51f124SMoriah Waterland * standard i/o descriptors - all the child can do is
1715c51f124SMoriah Waterland * adjust interrupts and open files as a prelude to a
1725c51f124SMoriah Waterland * call to exec().
1735c51f124SMoriah Waterland */
1745c51f124SMoriah Waterland
1755c51f124SMoriah Waterland pid = vfork();
1765c51f124SMoriah Waterland
1775c51f124SMoriah Waterland if (pid < 0) {
1785c51f124SMoriah Waterland /*
1795c51f124SMoriah Waterland * *************************************************************
1805c51f124SMoriah Waterland * fork failed!
1815c51f124SMoriah Waterland * *************************************************************
1825c51f124SMoriah Waterland */
1835c51f124SMoriah Waterland
1845c51f124SMoriah Waterland progerr(pkg_gt(ERR_FORK_FAILED), errno, strerror(errno));
1855c51f124SMoriah Waterland
1865c51f124SMoriah Waterland /* release hold on signals */
1875c51f124SMoriah Waterland
1885c51f124SMoriah Waterland (void) sigrelse(SIGHUP);
1895c51f124SMoriah Waterland (void) sigrelse(SIGINT);
1905c51f124SMoriah Waterland
1915c51f124SMoriah Waterland return (-1);
1925c51f124SMoriah Waterland }
1935c51f124SMoriah Waterland
1945c51f124SMoriah Waterland if (pid > 0) {
1955c51f124SMoriah Waterland /*
1965c51f124SMoriah Waterland * *************************************************************
1975c51f124SMoriah Waterland * This is the forking (parent) process
1985c51f124SMoriah Waterland * *************************************************************
1995c51f124SMoriah Waterland */
2005c51f124SMoriah Waterland
2015c51f124SMoriah Waterland /* close datastream if any portion read */
2025c51f124SMoriah Waterland
2035c51f124SMoriah Waterland if (ds_curpartcnt >= 0) {
2045c51f124SMoriah Waterland if (ds_close(0) != 0) {
2055c51f124SMoriah Waterland /* kill child process */
2065c51f124SMoriah Waterland
2075c51f124SMoriah Waterland (void) sigsend(P_PID, pid, SIGKILL);
2085c51f124SMoriah Waterland
2095c51f124SMoriah Waterland /* release hold on signals */
2105c51f124SMoriah Waterland
2115c51f124SMoriah Waterland (void) sigrelse(SIGHUP);
2125c51f124SMoriah Waterland (void) sigrelse(SIGINT);
2135c51f124SMoriah Waterland
2145c51f124SMoriah Waterland return (-1);
2155c51f124SMoriah Waterland }
2165c51f124SMoriah Waterland }
2175c51f124SMoriah Waterland
2185c51f124SMoriah Waterland /*
2195c51f124SMoriah Waterland * setup signal handlers for SIGINT and SIGHUP and release hold
2205c51f124SMoriah Waterland */
2215c51f124SMoriah Waterland
2225c51f124SMoriah Waterland /* hook SIGINT to sig_trap() */
2235c51f124SMoriah Waterland
2245c51f124SMoriah Waterland nact.sa_handler = sig_trap;
2255c51f124SMoriah Waterland nact.sa_flags = SA_RESTART;
2265c51f124SMoriah Waterland (void) sigemptyset(&nact.sa_mask);
2275c51f124SMoriah Waterland
2285c51f124SMoriah Waterland if (sigaction(SIGINT, &nact, &oact) < 0) {
2295c51f124SMoriah Waterland funcSigint = SIG_DFL;
2305c51f124SMoriah Waterland } else {
2315c51f124SMoriah Waterland funcSigint = oact.sa_handler;
2325c51f124SMoriah Waterland }
2335c51f124SMoriah Waterland
2345c51f124SMoriah Waterland /* hook SIGHUP to sig_trap() */
2355c51f124SMoriah Waterland
2365c51f124SMoriah Waterland nact.sa_handler = sig_trap;
2375c51f124SMoriah Waterland nact.sa_flags = SA_RESTART;
2385c51f124SMoriah Waterland (void) sigemptyset(&nact.sa_mask);
2395c51f124SMoriah Waterland
2405c51f124SMoriah Waterland if (sigaction(SIGHUP, &nact, &oact) < 0) {
2415c51f124SMoriah Waterland funcSighup = SIG_DFL;
2425c51f124SMoriah Waterland } else {
2435c51f124SMoriah Waterland funcSighup = oact.sa_handler;
2445c51f124SMoriah Waterland }
2455c51f124SMoriah Waterland
2465c51f124SMoriah Waterland /* release hold on signals */
2475c51f124SMoriah Waterland
2485c51f124SMoriah Waterland (void) sigrelse(SIGHUP);
2495c51f124SMoriah Waterland (void) sigrelse(SIGINT);
2505c51f124SMoriah Waterland
2515c51f124SMoriah Waterland /*
2525c51f124SMoriah Waterland * wait for the process to exit, reap child exit status
2535c51f124SMoriah Waterland */
2545c51f124SMoriah Waterland
2555c51f124SMoriah Waterland for (;;) {
2565c51f124SMoriah Waterland status = 0;
257*4656d474SGarrett D'Amore waitstat = waitpid(pid, &status, 0);
2585c51f124SMoriah Waterland if (waitstat < 0) {
2595c51f124SMoriah Waterland /* waitpid returned error */
2605c51f124SMoriah Waterland if (errno == EAGAIN) {
2615c51f124SMoriah Waterland /* try again */
2625c51f124SMoriah Waterland continue;
2635c51f124SMoriah Waterland }
2645c51f124SMoriah Waterland if (errno == EINTR) {
2655c51f124SMoriah Waterland continue;
2665c51f124SMoriah Waterland }
2675c51f124SMoriah Waterland /* error from waitpid: bail */
2685c51f124SMoriah Waterland break;
2695c51f124SMoriah Waterland } else if (waitstat == pid) {
2705c51f124SMoriah Waterland /* child exit status available */
2715c51f124SMoriah Waterland break;
2725c51f124SMoriah Waterland }
2735c51f124SMoriah Waterland }
2745c51f124SMoriah Waterland
2755c51f124SMoriah Waterland /*
2765c51f124SMoriah Waterland * reset signal handlers
2775c51f124SMoriah Waterland */
2785c51f124SMoriah Waterland
2795c51f124SMoriah Waterland /* reset SIGINT */
2805c51f124SMoriah Waterland
2815c51f124SMoriah Waterland nact.sa_handler = funcSigint;
2825c51f124SMoriah Waterland nact.sa_flags = SA_RESTART;
2835c51f124SMoriah Waterland (void) sigemptyset(&nact.sa_mask);
2845c51f124SMoriah Waterland
2855c51f124SMoriah Waterland (void) sigaction(SIGINT, &nact, (struct sigaction *)NULL);
2865c51f124SMoriah Waterland
2875c51f124SMoriah Waterland /* reset SIGHUP */
2885c51f124SMoriah Waterland
2895c51f124SMoriah Waterland nact.sa_handler = funcSighup;
2905c51f124SMoriah Waterland nact.sa_flags = SA_RESTART;
2915c51f124SMoriah Waterland (void) sigemptyset(&nact.sa_mask);
2925c51f124SMoriah Waterland
2935c51f124SMoriah Waterland (void) sigaction(SIGHUP, &nact, (struct sigaction *)NULL);
2945c51f124SMoriah Waterland
2955c51f124SMoriah Waterland /* error if child process does not match */
2965c51f124SMoriah Waterland
2975c51f124SMoriah Waterland if (waitstat != pid) {
298*4656d474SGarrett D'Amore progerr(pkg_gt(ERR_WAIT_FAILED), pid, status,
299*4656d474SGarrett D'Amore errno, strerror(errno));
3005c51f124SMoriah Waterland return (-1);
3015c51f124SMoriah Waterland }
3025c51f124SMoriah Waterland
3035c51f124SMoriah Waterland /*
3045c51f124SMoriah Waterland * determine final exit code:
3055c51f124SMoriah Waterland * - if signal received, then return interrupted (3)
3065c51f124SMoriah Waterland * - if child exit status is available, return exit child status
3075c51f124SMoriah Waterland * - otherwise return error (-1)
3085c51f124SMoriah Waterland */
3095c51f124SMoriah Waterland
3105c51f124SMoriah Waterland if (sig_received != 0) {
3115c51f124SMoriah Waterland exit_no = 3; /* interrupted */
3125c51f124SMoriah Waterland } else if (WIFEXITED(status)) {
3135c51f124SMoriah Waterland exit_no = WEXITSTATUS(status);
3145c51f124SMoriah Waterland } else {
3155c51f124SMoriah Waterland exit_no = -1; /* exec() or other process error */
3165c51f124SMoriah Waterland }
3175c51f124SMoriah Waterland
3185c51f124SMoriah Waterland return (exit_no);
3195c51f124SMoriah Waterland }
3205c51f124SMoriah Waterland
3215c51f124SMoriah Waterland /*
3225c51f124SMoriah Waterland * *********************************************************************
3235c51f124SMoriah Waterland * This is the forked (child) process
3245c51f124SMoriah Waterland * *********************************************************************
3255c51f124SMoriah Waterland */
3265c51f124SMoriah Waterland
3275c51f124SMoriah Waterland /* reset all signals to default */
3285c51f124SMoriah Waterland
3295c51f124SMoriah Waterland for (n = 0; n < NSIG; n++) {
3305c51f124SMoriah Waterland (void) sigset(n, SIG_DFL);
3315c51f124SMoriah Waterland }
3325c51f124SMoriah Waterland
3335c51f124SMoriah Waterland /* release hold on signals held by parent before fork() */
3345c51f124SMoriah Waterland
3355c51f124SMoriah Waterland (void) sigrelse(SIGHUP);
3365c51f124SMoriah Waterland (void) sigrelse(SIGINT);
3375c51f124SMoriah Waterland
3385c51f124SMoriah Waterland /*
3395c51f124SMoriah Waterland * The caller wants to have stdin connected to filein.
3405c51f124SMoriah Waterland */
3415c51f124SMoriah Waterland
3425c51f124SMoriah Waterland if (filein && *filein) {
3435c51f124SMoriah Waterland /*
3445c51f124SMoriah Waterland * If input is supposed to be connected to /dev/tty
3455c51f124SMoriah Waterland */
3465c51f124SMoriah Waterland if (strncmp(filein, "/dev/tty", 8) == 0) {
3475c51f124SMoriah Waterland /*
3485c51f124SMoriah Waterland * If stdin is connected to a tty device.
3495c51f124SMoriah Waterland */
3505c51f124SMoriah Waterland if (isatty(STDIN_FILENO)) {
3515c51f124SMoriah Waterland /*
3525c51f124SMoriah Waterland * Reopen it to /dev/tty.
3535c51f124SMoriah Waterland */
3545c51f124SMoriah Waterland n = open(filein, O_RDONLY);
3555c51f124SMoriah Waterland if (n >= 0) {
3565c51f124SMoriah Waterland (void) dup2(n, STDIN_FILENO);
3575c51f124SMoriah Waterland }
3585c51f124SMoriah Waterland }
3595c51f124SMoriah Waterland } else {
3605c51f124SMoriah Waterland /*
3615c51f124SMoriah Waterland * If we did not want to be connected to /dev/tty, we
3625c51f124SMoriah Waterland * connect input to the requested file no questions.
3635c51f124SMoriah Waterland */
3645c51f124SMoriah Waterland n = open(filein, O_RDONLY);
3655c51f124SMoriah Waterland if (n >= 0) {
3665c51f124SMoriah Waterland (void) dup2(n, STDIN_FILENO);
3675c51f124SMoriah Waterland }
3685c51f124SMoriah Waterland }
3695c51f124SMoriah Waterland }
3705c51f124SMoriah Waterland
3715c51f124SMoriah Waterland /*
3725c51f124SMoriah Waterland * The caller wants to have stdout and stderr connected to fileout.
3735c51f124SMoriah Waterland * If "fileout" is "/dev/tty" then reconnect stdout to "/dev/tty"
3745c51f124SMoriah Waterland * only if /dev/tty is not already associated with "a tty".
3755c51f124SMoriah Waterland */
3765c51f124SMoriah Waterland
3775c51f124SMoriah Waterland if (fileout && *fileout) {
3785c51f124SMoriah Waterland /*
3795c51f124SMoriah Waterland * If output is supposed to be connected to /dev/tty
3805c51f124SMoriah Waterland */
3815c51f124SMoriah Waterland if (strncmp(fileout, "/dev/tty", 8) == 0) {
3825c51f124SMoriah Waterland /*
3835c51f124SMoriah Waterland * If stdout is connected to a tty device.
3845c51f124SMoriah Waterland */
3855c51f124SMoriah Waterland if (isatty(STDOUT_FILENO)) {
3865c51f124SMoriah Waterland /*
3875c51f124SMoriah Waterland * Reopen it to /dev/tty if /dev/tty available.
3885c51f124SMoriah Waterland */
3895c51f124SMoriah Waterland n = open(fileout, O_WRONLY);
3905c51f124SMoriah Waterland if (n >= 0) {
3915c51f124SMoriah Waterland /*
3925c51f124SMoriah Waterland * /dev/tty is available - close the
3935c51f124SMoriah Waterland * current standard output stream, and
3945c51f124SMoriah Waterland * reopen it on /dev/tty
3955c51f124SMoriah Waterland */
3965c51f124SMoriah Waterland (void) dup2(n, STDOUT_FILENO);
3975c51f124SMoriah Waterland }
3985c51f124SMoriah Waterland }
3995c51f124SMoriah Waterland /*
4005c51f124SMoriah Waterland * not connected to tty device - probably redirect to
4015c51f124SMoriah Waterland * file - preserve existing output device
4025c51f124SMoriah Waterland */
4035c51f124SMoriah Waterland } else {
4045c51f124SMoriah Waterland /*
4055c51f124SMoriah Waterland * If we did not want to be connected to /dev/tty, we
4065c51f124SMoriah Waterland * connect output to the requested file no questions.
4075c51f124SMoriah Waterland */
4085c51f124SMoriah Waterland /* LINTED O_CREAT without O_EXCL specified in call to */
4095c51f124SMoriah Waterland n = open(fileout, O_WRONLY|O_CREAT|O_APPEND, 0666);
4105c51f124SMoriah Waterland if (n >= 0) {
4115c51f124SMoriah Waterland (void) dup2(n, STDOUT_FILENO);
4125c51f124SMoriah Waterland }
4135c51f124SMoriah Waterland }
4145c51f124SMoriah Waterland
4155c51f124SMoriah Waterland /*
4165c51f124SMoriah Waterland * Dup stderr from stdout.
4175c51f124SMoriah Waterland */
4185c51f124SMoriah Waterland
4195c51f124SMoriah Waterland (void) dup2(STDOUT_FILENO, STDERR_FILENO);
4205c51f124SMoriah Waterland }
4215c51f124SMoriah Waterland
4225c51f124SMoriah Waterland /*
4235c51f124SMoriah Waterland * do NOT close all file descriptors except stdio
4245c51f124SMoriah Waterland * file descriptors are passed in to some subcommands
4255c51f124SMoriah Waterland * (see dstream:ds_getinfo() and dstream:ds_putinfo())
4265c51f124SMoriah Waterland */
4275c51f124SMoriah Waterland
4285c51f124SMoriah Waterland /* set group/user i.d. if requested */
4295c51f124SMoriah Waterland
4305c51f124SMoriah Waterland if (gname && *gname && (grp = cgrnam(gname)) != NULL) {
4315c51f124SMoriah Waterland if (setgid(grp->gr_gid) == -1) {
4325c51f124SMoriah Waterland progerr(pkg_gt(ERR_SETGID), grp->gr_gid);
4335c51f124SMoriah Waterland }
4345c51f124SMoriah Waterland }
4355c51f124SMoriah Waterland if (uname && *uname && (pwp = cpwnam(uname)) != NULL) {
4365c51f124SMoriah Waterland if (setuid(pwp->pw_uid) == -1) {
4375c51f124SMoriah Waterland progerr(pkg_gt(ERR_SETUID), pwp->pw_uid);
4385c51f124SMoriah Waterland }
4395c51f124SMoriah Waterland }
4405c51f124SMoriah Waterland
4415c51f124SMoriah Waterland /* execute target executable */
4425c51f124SMoriah Waterland
4435c51f124SMoriah Waterland (void) execve(arg[0], arg, environ);
4445c51f124SMoriah Waterland progerr(pkg_gt(ERR_EX_FAIL), arg[0], errno);
4455c51f124SMoriah Waterland _exit(99);
4465c51f124SMoriah Waterland /*NOTREACHED*/
4475c51f124SMoriah Waterland }
448