1/*- 2 * Copyright (C) 2005 Max Okumoto. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD$"); 29 30#include <unistd.h> 31#include <errno.h> 32#include <stdlib.h> 33#include <string.h> 34#include <fcntl.h> 35 36#include "proc.h" 37#include "shell.h" 38#include "util.h" 39 40/** 41 * Replace the current process. 42 */ 43void 44Proc_Exec(const ProcStuff *ps) 45{ 46 47 if (ps->in != STDIN_FILENO) { 48 /* 49 * Redirect the child's stdin to the input fd 50 * and reset it to the beginning (again). 51 */ 52 if (dup2(ps->in, STDIN_FILENO) == -1) 53 Punt("Cannot dup2: %s", strerror(errno)); 54 lseek(STDIN_FILENO, (off_t)0, SEEK_SET); 55 } 56 57 if (ps->out != STDOUT_FILENO) { 58 /* 59 * Redirect the child's stdout to the output fd. 60 */ 61 if (dup2(ps->out, STDOUT_FILENO) == -1) 62 Punt("Cannot dup2: %s", strerror(errno)); 63 close(ps->out); 64 } 65 66 if (ps->err != STDERR_FILENO) { 67 /* 68 * Redirect the child's stderr to the err fd. 69 */ 70 if (dup2(ps->err, STDERR_FILENO) == -1) 71 Punt("Cannot dup2: %s", strerror(errno)); 72 close(ps->err); 73 } 74 75 if (ps->merge_errors) { 76 /* 77 * Send stderr to parent process too. 78 */ 79 if (dup2(STDOUT_FILENO, STDERR_FILENO) == -1) 80 Punt("Cannot dup2: %s", strerror(errno)); 81 } 82 83 if (commandShell->unsetenv) { 84 /* for the benfit of ksh */ 85 unsetenv("ENV"); 86 } 87 88 /* 89 * The file descriptors for stdin, stdout, or stderr might 90 * have been marked close-on-exec. Clear the flag on all 91 * of them. 92 */ 93 fcntl(STDIN_FILENO, F_SETFD, 94 fcntl(STDIN_FILENO, F_GETFD) & (~FD_CLOEXEC)); 95 fcntl(STDOUT_FILENO, F_SETFD, 96 fcntl(STDOUT_FILENO, F_GETFD) & (~FD_CLOEXEC)); 97 fcntl(STDERR_FILENO, F_SETFD, 98 fcntl(STDERR_FILENO, F_GETFD) & (~FD_CLOEXEC)); 99 100 if (ps->pgroup) { 101#ifdef USE_PGRP 102 /* 103 * Become a process group leader, so we can kill it and all 104 * its descendants in one fell swoop, by killing its process 105 * family, but not commit suicide. 106 */ 107#if defined(SYSV) 108 setsid(); 109#else 110 setpgid(0, getpid()); 111#endif 112#endif /* USE_PGRP */ 113 } 114 115 if (ps->searchpath) { 116 execvp(ps->argv[0], ps->argv); 117 118 write(STDERR_FILENO, ps->argv[0], strlen(ps->argv[0])); 119 write(STDERR_FILENO, ": ", 2); 120 write(STDERR_FILENO, strerror(errno), strlen(strerror(errno))); 121 write(STDERR_FILENO, "\n", 1); 122 } else { 123 execv(commandShell->path, ps->argv); 124 125 write(STDERR_FILENO, 126 "Could not execute shell\n", 127 sizeof("Could not execute shell")); 128 } 129 130 /* 131 * Since we are the child process, exit without flushing buffers. 132 */ 133 _exit(1); 134} 135