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 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 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, 2995c51f124SMoriah Waterland 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