1*5c51f124SMoriah Waterland /* 2*5c51f124SMoriah Waterland * CDDL HEADER START 3*5c51f124SMoriah Waterland * 4*5c51f124SMoriah Waterland * The contents of this file are subject to the terms of the 5*5c51f124SMoriah Waterland * Common Development and Distribution License (the "License"). 6*5c51f124SMoriah Waterland * You may not use this file except in compliance with the License. 7*5c51f124SMoriah Waterland * 8*5c51f124SMoriah Waterland * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*5c51f124SMoriah Waterland * or http://www.opensolaris.org/os/licensing. 10*5c51f124SMoriah Waterland * See the License for the specific language governing permissions 11*5c51f124SMoriah Waterland * and limitations under the License. 12*5c51f124SMoriah Waterland * 13*5c51f124SMoriah Waterland * When distributing Covered Code, include this CDDL HEADER in each 14*5c51f124SMoriah Waterland * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*5c51f124SMoriah Waterland * If applicable, add the following below this CDDL HEADER, with the 16*5c51f124SMoriah Waterland * fields enclosed by brackets "[]" replaced with your own identifying 17*5c51f124SMoriah Waterland * information: Portions Copyright [yyyy] [name of copyright owner] 18*5c51f124SMoriah Waterland * 19*5c51f124SMoriah Waterland * CDDL HEADER END 20*5c51f124SMoriah Waterland */ 21*5c51f124SMoriah Waterland 22*5c51f124SMoriah Waterland /* 23*5c51f124SMoriah Waterland * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*5c51f124SMoriah Waterland * Use is subject to license terms. 25*5c51f124SMoriah Waterland */ 26*5c51f124SMoriah Waterland 27*5c51f124SMoriah Waterland /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*5c51f124SMoriah Waterland /* All Rights Reserved */ 29*5c51f124SMoriah Waterland 30*5c51f124SMoriah Waterland 31*5c51f124SMoriah Waterland #include <stdio.h> 32*5c51f124SMoriah Waterland #include <errno.h> 33*5c51f124SMoriah Waterland #include <string.h> 34*5c51f124SMoriah Waterland #include <stdlib.h> 35*5c51f124SMoriah Waterland #include <unistd.h> 36*5c51f124SMoriah Waterland #include <signal.h> 37*5c51f124SMoriah Waterland #include <wait.h> 38*5c51f124SMoriah Waterland #include <sys/types.h> 39*5c51f124SMoriah Waterland #include <sys/stat.h> 40*5c51f124SMoriah Waterland #include <fcntl.h> 41*5c51f124SMoriah Waterland #include <pwd.h> 42*5c51f124SMoriah Waterland #include <grp.h> 43*5c51f124SMoriah Waterland #include "pkglib.h" 44*5c51f124SMoriah Waterland #include "pkglibmsgs.h" 45*5c51f124SMoriah Waterland #include "pkglocale.h" 46*5c51f124SMoriah Waterland 47*5c51f124SMoriah Waterland /* global environment inherited by this process */ 48*5c51f124SMoriah Waterland extern char **environ; 49*5c51f124SMoriah Waterland 50*5c51f124SMoriah Waterland /* dstream.c */ 51*5c51f124SMoriah Waterland extern int ds_curpartcnt; 52*5c51f124SMoriah Waterland extern int ds_close(int pkgendflg); 53*5c51f124SMoriah Waterland 54*5c51f124SMoriah Waterland /* 55*5c51f124SMoriah Waterland * global internal (private) variables 56*5c51f124SMoriah Waterland */ 57*5c51f124SMoriah Waterland 58*5c51f124SMoriah Waterland /* received signal count - bumped with hooked signals are caught */ 59*5c51f124SMoriah Waterland 60*5c51f124SMoriah Waterland static int sig_received = 0; 61*5c51f124SMoriah Waterland 62*5c51f124SMoriah Waterland /* 63*5c51f124SMoriah Waterland * Name: sig_trap 64*5c51f124SMoriah Waterland * Description: hooked up to signal counts number of signals received 65*5c51f124SMoriah Waterland * Arguments: a_signo - [RO, *RO] - (int) 66*5c51f124SMoriah Waterland * Integer representing the signal received; see signal(3c) 67*5c51f124SMoriah Waterland * Returns: <void> 68*5c51f124SMoriah Waterland */ 69*5c51f124SMoriah Waterland 70*5c51f124SMoriah Waterland static void 71*5c51f124SMoriah Waterland sig_trap(int a_signo) 72*5c51f124SMoriah Waterland { 73*5c51f124SMoriah Waterland sig_received++; 74*5c51f124SMoriah Waterland } 75*5c51f124SMoriah Waterland 76*5c51f124SMoriah Waterland /* 77*5c51f124SMoriah Waterland * Name: pkgexecv 78*5c51f124SMoriah Waterland * Description: Asynchronously execute a package command in a separate process 79*5c51f124SMoriah Waterland * and return results - the subprocess MUST arm it's own SIGINT 80*5c51f124SMoriah Waterland * and SIGHUP signals and must return a standard package command 81*5c51f124SMoriah Waterland * exit code (see returns below) 82*5c51f124SMoriah Waterland * Only another package command (such as pkginstall, pkgremove, 83*5c51f124SMoriah Waterland * etc.) may be called via this interface. No files are closed 84*5c51f124SMoriah Waterland * because open files are passed across to certain commands using 85*5c51f124SMoriah Waterland * either implicit agreements between the two (yuk!) or by using 86*5c51f124SMoriah Waterland * the '-p' option which passes a string of digits, some of which 87*5c51f124SMoriah Waterland * represent open file descriptors passed through this interface! 88*5c51f124SMoriah Waterland * Arguments: filein - [RO, *RO] - (char *) 89*5c51f124SMoriah Waterland * Pointer to string representing the name of the file to 90*5c51f124SMoriah Waterland * use for the package commands's stdin 91*5c51f124SMoriah Waterland * == (char *)NULL or == "" - the current stdin 92*5c51f124SMoriah Waterland * is used for the new package command process 93*5c51f124SMoriah Waterland * fileout - [RO, *RO] - (char *) 94*5c51f124SMoriah Waterland * Pointer to string representing the name of the file to 95*5c51f124SMoriah Waterland * use for the package commands's stdout and stderr 96*5c51f124SMoriah Waterland * == (char *)NULL or == "" - the current stdout/stderr 97*5c51f124SMoriah Waterland * is used for the new package command process 98*5c51f124SMoriah Waterland * uname - [RO, *RO] - (char *) 99*5c51f124SMoriah Waterland * Pointer to string representing the user name to execute 100*5c51f124SMoriah Waterland * the package command as - the user name is looked up 101*5c51f124SMoriah Waterland * using the ncgrpw:cpwnam() interface 102*5c51f124SMoriah Waterland * == (char *)NULL or == "" - the user name of the current 103*5c51f124SMoriah Waterland * process is used for the new package command process 104*5c51f124SMoriah Waterland * gname - [RO, *RO] - (char *) 105*5c51f124SMoriah Waterland * Pointer to string representing the group name to execute 106*5c51f124SMoriah Waterland * the package command as - the group name is looked up 107*5c51f124SMoriah Waterland * using the ncgrpw:cgrnam() interface 108*5c51f124SMoriah Waterland * == (char *)NULL or == "" - the group name of the current 109*5c51f124SMoriah Waterland * process is used for the new package command process 110*5c51f124SMoriah Waterland * arg - [RO, *RO] - (char **) 111*5c51f124SMoriah Waterland * Pointer to array of character pointers representing the 112*5c51f124SMoriah Waterland * arguments to pass to the package command - the array is 113*5c51f124SMoriah Waterland * terminated with a pointer to (char *)NULL 114*5c51f124SMoriah Waterland * Returns: int 115*5c51f124SMoriah Waterland * == 99 - exec() of package command failed 116*5c51f124SMoriah Waterland * == -1 - fork failed or other fatal error during 117*5c51f124SMoriah Waterland * execution of the package command 118*5c51f124SMoriah Waterland * otherwise - exit code from package command: 119*5c51f124SMoriah Waterland * 0 - successful 120*5c51f124SMoriah Waterland * 1 - package operation failed (fatal error) 121*5c51f124SMoriah Waterland * 2 - non-fatal error (warning) 122*5c51f124SMoriah Waterland * 3 - operation interrupted (including SIGINT/SIGHUP) 123*5c51f124SMoriah Waterland * 4 - admin settings prevented operation 124*5c51f124SMoriah Waterland * 5 - administration required and -n was specified 125*5c51f124SMoriah Waterland * IN addition: 126*5c51f124SMoriah Waterland * 10 is added to the return code if reboot after the 127*5c51f124SMoriah Waterland * installation of all packages is required 128*5c51f124SMoriah Waterland * 20 is added to the return code if immediate reboot 129*5c51f124SMoriah Waterland * after installation of this package is required 130*5c51f124SMoriah Waterland */ 131*5c51f124SMoriah Waterland 132*5c51f124SMoriah Waterland int 133*5c51f124SMoriah Waterland pkgexecv(char *filein, char *fileout, char *uname, char *gname, char *arg[]) 134*5c51f124SMoriah Waterland { 135*5c51f124SMoriah Waterland int exit_no; 136*5c51f124SMoriah Waterland int n; 137*5c51f124SMoriah Waterland int status; 138*5c51f124SMoriah Waterland pid_t pid; 139*5c51f124SMoriah Waterland pid_t waitstat; 140*5c51f124SMoriah Waterland struct group *grp; 141*5c51f124SMoriah Waterland struct passwd *pwp; 142*5c51f124SMoriah Waterland struct sigaction nact; 143*5c51f124SMoriah Waterland struct sigaction oact; 144*5c51f124SMoriah Waterland void (*funcSighup)(); 145*5c51f124SMoriah Waterland void (*funcSigint)(); 146*5c51f124SMoriah Waterland 147*5c51f124SMoriah Waterland /* flush standard i/o before creating new process */ 148*5c51f124SMoriah Waterland 149*5c51f124SMoriah Waterland (void) fflush(stdout); 150*5c51f124SMoriah Waterland (void) fflush(stderr); 151*5c51f124SMoriah Waterland 152*5c51f124SMoriah Waterland /* 153*5c51f124SMoriah Waterland * hold SIGINT/SIGHUP signals and reset signal received counter; 154*5c51f124SMoriah Waterland * after the vfork() the parent and child need to setup their respective 155*5c51f124SMoriah Waterland * interrupt handling and release the hold on the signals 156*5c51f124SMoriah Waterland */ 157*5c51f124SMoriah Waterland 158*5c51f124SMoriah Waterland (void) sighold(SIGINT); 159*5c51f124SMoriah Waterland (void) sighold(SIGHUP); 160*5c51f124SMoriah Waterland 161*5c51f124SMoriah Waterland sig_received = 0; 162*5c51f124SMoriah Waterland 163*5c51f124SMoriah Waterland /* 164*5c51f124SMoriah Waterland * create new process to execute command in; 165*5c51f124SMoriah Waterland * vfork() is being used to avoid duplicating the parents 166*5c51f124SMoriah Waterland * memory space - this means that the child process may 167*5c51f124SMoriah Waterland * not modify any of the parents memory including the 168*5c51f124SMoriah Waterland * standard i/o descriptors - all the child can do is 169*5c51f124SMoriah Waterland * adjust interrupts and open files as a prelude to a 170*5c51f124SMoriah Waterland * call to exec(). 171*5c51f124SMoriah Waterland */ 172*5c51f124SMoriah Waterland 173*5c51f124SMoriah Waterland pid = vfork(); 174*5c51f124SMoriah Waterland 175*5c51f124SMoriah Waterland if (pid < 0) { 176*5c51f124SMoriah Waterland /* 177*5c51f124SMoriah Waterland * ************************************************************* 178*5c51f124SMoriah Waterland * fork failed! 179*5c51f124SMoriah Waterland * ************************************************************* 180*5c51f124SMoriah Waterland */ 181*5c51f124SMoriah Waterland 182*5c51f124SMoriah Waterland progerr(pkg_gt(ERR_FORK_FAILED), errno, strerror(errno)); 183*5c51f124SMoriah Waterland 184*5c51f124SMoriah Waterland /* release hold on signals */ 185*5c51f124SMoriah Waterland 186*5c51f124SMoriah Waterland (void) sigrelse(SIGHUP); 187*5c51f124SMoriah Waterland (void) sigrelse(SIGINT); 188*5c51f124SMoriah Waterland 189*5c51f124SMoriah Waterland return (-1); 190*5c51f124SMoriah Waterland } 191*5c51f124SMoriah Waterland 192*5c51f124SMoriah Waterland if (pid > 0) { 193*5c51f124SMoriah Waterland /* 194*5c51f124SMoriah Waterland * ************************************************************* 195*5c51f124SMoriah Waterland * This is the forking (parent) process 196*5c51f124SMoriah Waterland * ************************************************************* 197*5c51f124SMoriah Waterland */ 198*5c51f124SMoriah Waterland 199*5c51f124SMoriah Waterland /* close datastream if any portion read */ 200*5c51f124SMoriah Waterland 201*5c51f124SMoriah Waterland if (ds_curpartcnt >= 0) { 202*5c51f124SMoriah Waterland if (ds_close(0) != 0) { 203*5c51f124SMoriah Waterland /* kill child process */ 204*5c51f124SMoriah Waterland 205*5c51f124SMoriah Waterland (void) sigsend(P_PID, pid, SIGKILL); 206*5c51f124SMoriah Waterland 207*5c51f124SMoriah Waterland /* release hold on signals */ 208*5c51f124SMoriah Waterland 209*5c51f124SMoriah Waterland (void) sigrelse(SIGHUP); 210*5c51f124SMoriah Waterland (void) sigrelse(SIGINT); 211*5c51f124SMoriah Waterland 212*5c51f124SMoriah Waterland return (-1); 213*5c51f124SMoriah Waterland } 214*5c51f124SMoriah Waterland } 215*5c51f124SMoriah Waterland 216*5c51f124SMoriah Waterland /* 217*5c51f124SMoriah Waterland * setup signal handlers for SIGINT and SIGHUP and release hold 218*5c51f124SMoriah Waterland */ 219*5c51f124SMoriah Waterland 220*5c51f124SMoriah Waterland /* hook SIGINT to sig_trap() */ 221*5c51f124SMoriah Waterland 222*5c51f124SMoriah Waterland nact.sa_handler = sig_trap; 223*5c51f124SMoriah Waterland nact.sa_flags = SA_RESTART; 224*5c51f124SMoriah Waterland (void) sigemptyset(&nact.sa_mask); 225*5c51f124SMoriah Waterland 226*5c51f124SMoriah Waterland if (sigaction(SIGINT, &nact, &oact) < 0) { 227*5c51f124SMoriah Waterland funcSigint = SIG_DFL; 228*5c51f124SMoriah Waterland } else { 229*5c51f124SMoriah Waterland funcSigint = oact.sa_handler; 230*5c51f124SMoriah Waterland } 231*5c51f124SMoriah Waterland 232*5c51f124SMoriah Waterland /* hook SIGHUP to sig_trap() */ 233*5c51f124SMoriah Waterland 234*5c51f124SMoriah Waterland nact.sa_handler = sig_trap; 235*5c51f124SMoriah Waterland nact.sa_flags = SA_RESTART; 236*5c51f124SMoriah Waterland (void) sigemptyset(&nact.sa_mask); 237*5c51f124SMoriah Waterland 238*5c51f124SMoriah Waterland if (sigaction(SIGHUP, &nact, &oact) < 0) { 239*5c51f124SMoriah Waterland funcSighup = SIG_DFL; 240*5c51f124SMoriah Waterland } else { 241*5c51f124SMoriah Waterland funcSighup = oact.sa_handler; 242*5c51f124SMoriah Waterland } 243*5c51f124SMoriah Waterland 244*5c51f124SMoriah Waterland /* release hold on signals */ 245*5c51f124SMoriah Waterland 246*5c51f124SMoriah Waterland (void) sigrelse(SIGHUP); 247*5c51f124SMoriah Waterland (void) sigrelse(SIGINT); 248*5c51f124SMoriah Waterland 249*5c51f124SMoriah Waterland /* 250*5c51f124SMoriah Waterland * wait for the process to exit, reap child exit status 251*5c51f124SMoriah Waterland */ 252*5c51f124SMoriah Waterland 253*5c51f124SMoriah Waterland for (;;) { 254*5c51f124SMoriah Waterland status = 0; 255*5c51f124SMoriah Waterland waitstat = waitpid(pid, (int *)&status, 0); 256*5c51f124SMoriah Waterland if (waitstat < 0) { 257*5c51f124SMoriah Waterland /* waitpid returned error */ 258*5c51f124SMoriah Waterland if (errno == EAGAIN) { 259*5c51f124SMoriah Waterland /* try again */ 260*5c51f124SMoriah Waterland continue; 261*5c51f124SMoriah Waterland } 262*5c51f124SMoriah Waterland if (errno == EINTR) { 263*5c51f124SMoriah Waterland continue; 264*5c51f124SMoriah Waterland } 265*5c51f124SMoriah Waterland /* error from waitpid: bail */ 266*5c51f124SMoriah Waterland break; 267*5c51f124SMoriah Waterland } else if (waitstat == pid) { 268*5c51f124SMoriah Waterland /* child exit status available */ 269*5c51f124SMoriah Waterland break; 270*5c51f124SMoriah Waterland } 271*5c51f124SMoriah Waterland } 272*5c51f124SMoriah Waterland 273*5c51f124SMoriah Waterland /* 274*5c51f124SMoriah Waterland * reset signal handlers 275*5c51f124SMoriah Waterland */ 276*5c51f124SMoriah Waterland 277*5c51f124SMoriah Waterland /* reset SIGINT */ 278*5c51f124SMoriah Waterland 279*5c51f124SMoriah Waterland nact.sa_handler = funcSigint; 280*5c51f124SMoriah Waterland nact.sa_flags = SA_RESTART; 281*5c51f124SMoriah Waterland (void) sigemptyset(&nact.sa_mask); 282*5c51f124SMoriah Waterland 283*5c51f124SMoriah Waterland (void) sigaction(SIGINT, &nact, (struct sigaction *)NULL); 284*5c51f124SMoriah Waterland 285*5c51f124SMoriah Waterland /* reset SIGHUP */ 286*5c51f124SMoriah Waterland 287*5c51f124SMoriah Waterland nact.sa_handler = funcSighup; 288*5c51f124SMoriah Waterland nact.sa_flags = SA_RESTART; 289*5c51f124SMoriah Waterland (void) sigemptyset(&nact.sa_mask); 290*5c51f124SMoriah Waterland 291*5c51f124SMoriah Waterland (void) sigaction(SIGHUP, &nact, (struct sigaction *)NULL); 292*5c51f124SMoriah Waterland 293*5c51f124SMoriah Waterland /* error if child process does not match */ 294*5c51f124SMoriah Waterland 295*5c51f124SMoriah Waterland if (waitstat != pid) { 296*5c51f124SMoriah Waterland progerr(pkg_gt(ERR_WAIT_FAILED), pid, waitstat, status, 297*5c51f124SMoriah Waterland errno, strerror(errno)); 298*5c51f124SMoriah Waterland return (-1); 299*5c51f124SMoriah Waterland } 300*5c51f124SMoriah Waterland 301*5c51f124SMoriah Waterland /* 302*5c51f124SMoriah Waterland * determine final exit code: 303*5c51f124SMoriah Waterland * - if signal received, then return interrupted (3) 304*5c51f124SMoriah Waterland * - if child exit status is available, return exit child status 305*5c51f124SMoriah Waterland * - otherwise return error (-1) 306*5c51f124SMoriah Waterland */ 307*5c51f124SMoriah Waterland 308*5c51f124SMoriah Waterland if (sig_received != 0) { 309*5c51f124SMoriah Waterland exit_no = 3; /* interrupted */ 310*5c51f124SMoriah Waterland } else if (WIFEXITED(status)) { 311*5c51f124SMoriah Waterland exit_no = WEXITSTATUS(status); 312*5c51f124SMoriah Waterland } else { 313*5c51f124SMoriah Waterland exit_no = -1; /* exec() or other process error */ 314*5c51f124SMoriah Waterland } 315*5c51f124SMoriah Waterland 316*5c51f124SMoriah Waterland return (exit_no); 317*5c51f124SMoriah Waterland } 318*5c51f124SMoriah Waterland 319*5c51f124SMoriah Waterland /* 320*5c51f124SMoriah Waterland * ********************************************************************* 321*5c51f124SMoriah Waterland * This is the forked (child) process 322*5c51f124SMoriah Waterland * ********************************************************************* 323*5c51f124SMoriah Waterland */ 324*5c51f124SMoriah Waterland 325*5c51f124SMoriah Waterland /* reset all signals to default */ 326*5c51f124SMoriah Waterland 327*5c51f124SMoriah Waterland for (n = 0; n < NSIG; n++) { 328*5c51f124SMoriah Waterland (void) sigset(n, SIG_DFL); 329*5c51f124SMoriah Waterland } 330*5c51f124SMoriah Waterland 331*5c51f124SMoriah Waterland /* release hold on signals held by parent before fork() */ 332*5c51f124SMoriah Waterland 333*5c51f124SMoriah Waterland (void) sigrelse(SIGHUP); 334*5c51f124SMoriah Waterland (void) sigrelse(SIGINT); 335*5c51f124SMoriah Waterland 336*5c51f124SMoriah Waterland /* 337*5c51f124SMoriah Waterland * The caller wants to have stdin connected to filein. 338*5c51f124SMoriah Waterland */ 339*5c51f124SMoriah Waterland 340*5c51f124SMoriah Waterland if (filein && *filein) { 341*5c51f124SMoriah Waterland /* 342*5c51f124SMoriah Waterland * If input is supposed to be connected to /dev/tty 343*5c51f124SMoriah Waterland */ 344*5c51f124SMoriah Waterland if (strncmp(filein, "/dev/tty", 8) == 0) { 345*5c51f124SMoriah Waterland /* 346*5c51f124SMoriah Waterland * If stdin is connected to a tty device. 347*5c51f124SMoriah Waterland */ 348*5c51f124SMoriah Waterland if (isatty(STDIN_FILENO)) { 349*5c51f124SMoriah Waterland /* 350*5c51f124SMoriah Waterland * Reopen it to /dev/tty. 351*5c51f124SMoriah Waterland */ 352*5c51f124SMoriah Waterland n = open(filein, O_RDONLY); 353*5c51f124SMoriah Waterland if (n >= 0) { 354*5c51f124SMoriah Waterland (void) dup2(n, STDIN_FILENO); 355*5c51f124SMoriah Waterland } 356*5c51f124SMoriah Waterland } 357*5c51f124SMoriah Waterland } else { 358*5c51f124SMoriah Waterland /* 359*5c51f124SMoriah Waterland * If we did not want to be connected to /dev/tty, we 360*5c51f124SMoriah Waterland * connect input to the requested file no questions. 361*5c51f124SMoriah Waterland */ 362*5c51f124SMoriah Waterland n = open(filein, O_RDONLY); 363*5c51f124SMoriah Waterland if (n >= 0) { 364*5c51f124SMoriah Waterland (void) dup2(n, STDIN_FILENO); 365*5c51f124SMoriah Waterland } 366*5c51f124SMoriah Waterland } 367*5c51f124SMoriah Waterland } 368*5c51f124SMoriah Waterland 369*5c51f124SMoriah Waterland /* 370*5c51f124SMoriah Waterland * The caller wants to have stdout and stderr connected to fileout. 371*5c51f124SMoriah Waterland * If "fileout" is "/dev/tty" then reconnect stdout to "/dev/tty" 372*5c51f124SMoriah Waterland * only if /dev/tty is not already associated with "a tty". 373*5c51f124SMoriah Waterland */ 374*5c51f124SMoriah Waterland 375*5c51f124SMoriah Waterland if (fileout && *fileout) { 376*5c51f124SMoriah Waterland /* 377*5c51f124SMoriah Waterland * If output is supposed to be connected to /dev/tty 378*5c51f124SMoriah Waterland */ 379*5c51f124SMoriah Waterland if (strncmp(fileout, "/dev/tty", 8) == 0) { 380*5c51f124SMoriah Waterland /* 381*5c51f124SMoriah Waterland * If stdout is connected to a tty device. 382*5c51f124SMoriah Waterland */ 383*5c51f124SMoriah Waterland if (isatty(STDOUT_FILENO)) { 384*5c51f124SMoriah Waterland /* 385*5c51f124SMoriah Waterland * Reopen it to /dev/tty if /dev/tty available. 386*5c51f124SMoriah Waterland */ 387*5c51f124SMoriah Waterland n = open(fileout, O_WRONLY); 388*5c51f124SMoriah Waterland if (n >= 0) { 389*5c51f124SMoriah Waterland /* 390*5c51f124SMoriah Waterland * /dev/tty is available - close the 391*5c51f124SMoriah Waterland * current standard output stream, and 392*5c51f124SMoriah Waterland * reopen it on /dev/tty 393*5c51f124SMoriah Waterland */ 394*5c51f124SMoriah Waterland (void) dup2(n, STDOUT_FILENO); 395*5c51f124SMoriah Waterland } 396*5c51f124SMoriah Waterland } 397*5c51f124SMoriah Waterland /* 398*5c51f124SMoriah Waterland * not connected to tty device - probably redirect to 399*5c51f124SMoriah Waterland * file - preserve existing output device 400*5c51f124SMoriah Waterland */ 401*5c51f124SMoriah Waterland } else { 402*5c51f124SMoriah Waterland /* 403*5c51f124SMoriah Waterland * If we did not want to be connected to /dev/tty, we 404*5c51f124SMoriah Waterland * connect output to the requested file no questions. 405*5c51f124SMoriah Waterland */ 406*5c51f124SMoriah Waterland /* LINTED O_CREAT without O_EXCL specified in call to */ 407*5c51f124SMoriah Waterland n = open(fileout, O_WRONLY|O_CREAT|O_APPEND, 0666); 408*5c51f124SMoriah Waterland if (n >= 0) { 409*5c51f124SMoriah Waterland (void) dup2(n, STDOUT_FILENO); 410*5c51f124SMoriah Waterland } 411*5c51f124SMoriah Waterland } 412*5c51f124SMoriah Waterland 413*5c51f124SMoriah Waterland /* 414*5c51f124SMoriah Waterland * Dup stderr from stdout. 415*5c51f124SMoriah Waterland */ 416*5c51f124SMoriah Waterland 417*5c51f124SMoriah Waterland (void) dup2(STDOUT_FILENO, STDERR_FILENO); 418*5c51f124SMoriah Waterland } 419*5c51f124SMoriah Waterland 420*5c51f124SMoriah Waterland /* 421*5c51f124SMoriah Waterland * do NOT close all file descriptors except stdio 422*5c51f124SMoriah Waterland * file descriptors are passed in to some subcommands 423*5c51f124SMoriah Waterland * (see dstream:ds_getinfo() and dstream:ds_putinfo()) 424*5c51f124SMoriah Waterland */ 425*5c51f124SMoriah Waterland 426*5c51f124SMoriah Waterland /* set group/user i.d. if requested */ 427*5c51f124SMoriah Waterland 428*5c51f124SMoriah Waterland if (gname && *gname && (grp = cgrnam(gname)) != NULL) { 429*5c51f124SMoriah Waterland if (setgid(grp->gr_gid) == -1) { 430*5c51f124SMoriah Waterland progerr(pkg_gt(ERR_SETGID), grp->gr_gid); 431*5c51f124SMoriah Waterland } 432*5c51f124SMoriah Waterland } 433*5c51f124SMoriah Waterland if (uname && *uname && (pwp = cpwnam(uname)) != NULL) { 434*5c51f124SMoriah Waterland if (setuid(pwp->pw_uid) == -1) { 435*5c51f124SMoriah Waterland progerr(pkg_gt(ERR_SETUID), pwp->pw_uid); 436*5c51f124SMoriah Waterland } 437*5c51f124SMoriah Waterland } 438*5c51f124SMoriah Waterland 439*5c51f124SMoriah Waterland /* execute target executable */ 440*5c51f124SMoriah Waterland 441*5c51f124SMoriah Waterland (void) execve(arg[0], arg, environ); 442*5c51f124SMoriah Waterland progerr(pkg_gt(ERR_EX_FAIL), arg[0], errno); 443*5c51f124SMoriah Waterland _exit(99); 444*5c51f124SMoriah Waterland /*NOTREACHED*/ 445*5c51f124SMoriah Waterland } 446