Pass commandShell is a paramter to Proc_Exec() instead of
[dragonfly.git] / usr.bin / make / proc.c
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  * $DragonFly: src/usr.bin/make/proc.c,v 1.5 2005/07/02 10:46:01 okumoto Exp $
27  */
28
29 #include <unistd.h>
30 #include <errno.h>
31 #include <string.h>
32 #include <fcntl.h>
33 #include <stdlib.h>
34
35 #include "proc.h"
36 #include "shell.h"
37 #include "util.h"
38
39 /**
40  * Replace the current process.
41  */
42 void
43 Proc_Exec(const ProcStuff *ps, struct Shell *shell)
44 {
45
46         if (ps->in != STDIN_FILENO) {
47                 /*
48                  * Redirect the child's stdin to the input fd
49                  * and reset it to the beginning (again).
50                  */
51                 if (dup2(ps->in, STDIN_FILENO) == -1)
52                         Punt("Cannot dup2: %s", strerror(errno));
53                 lseek(STDIN_FILENO, (off_t)0, SEEK_SET);
54         }
55
56         if (ps->out != STDOUT_FILENO) {
57                 /*
58                  * Redirect the child's stdout to the output fd.
59                  */
60                 if (dup2(ps->out, STDOUT_FILENO) == -1)
61                         Punt("Cannot dup2: %s", strerror(errno));
62                 close(ps->out);
63         }
64
65         if (ps->err != STDERR_FILENO) {
66                 /*
67                  * Redirect the child's stderr to the err fd.
68                  */
69                 if (dup2(ps->err, STDERR_FILENO) == -1)
70                         Punt("Cannot dup2: %s", strerror(errno));
71                 close(ps->err);
72         }
73
74         if (ps->merge_errors) {
75                 /*
76                  * Send stderr to parent process too.
77                  */
78                 if (dup2(STDOUT_FILENO, STDERR_FILENO) == -1)
79                         Punt("Cannot dup2: %s", strerror(errno));
80         }
81
82         if (shell->unsetenv) {
83                 /* for the benfit of ksh */
84                 unsetenv("ENV");
85         }
86
87         /*
88          * The file descriptors for stdin, stdout, or stderr might
89          * have been marked close-on-exec.  Clear the flag on all
90          * of them.
91          */
92         fcntl(STDIN_FILENO, F_SETFD,
93             fcntl(STDIN_FILENO, F_GETFD) & (~FD_CLOEXEC));
94         fcntl(STDOUT_FILENO, F_SETFD,
95             fcntl(STDOUT_FILENO, F_GETFD) & (~FD_CLOEXEC));
96         fcntl(STDERR_FILENO, F_SETFD,
97             fcntl(STDERR_FILENO, F_GETFD) & (~FD_CLOEXEC));
98
99         if (ps->pgroup) {
100 #ifdef USE_PGRP
101                 /*
102                  * Become a process group leader, so we can kill it and all
103                  * its descendants in one fell swoop, by killing its process
104                  * family, but not commit suicide.
105                  */
106 #if defined(SYSV)
107                 setsid();
108 #else
109                 setpgid(0, getpid());
110 #endif
111 #endif /* USE_PGRP */
112         }
113
114         if (ps->searchpath) {
115                 execvp(ps->argv[0], ps->argv);
116
117                 write(STDERR_FILENO, ps->argv[0], strlen(ps->argv[0]));
118                 write(STDERR_FILENO, ":", 1);
119                 write(STDERR_FILENO, strerror(errno), strlen(strerror(errno)));
120                 write(STDERR_FILENO, "\n", 1);
121         } else {
122                 execv(shell->path, ps->argv);
123
124                 write(STDERR_FILENO,
125                     "Could not execute shell\n",
126                     sizeof("Could not execute shell"));
127         }
128
129         /*
130          * Since we are the child process, exit without flushing buffers.
131          */
132         _exit(1);
133 }