[project @ 2004-10-07 13:13:22 by stolz]
[packages/old-time.git] / cbits / execvpe.c
1 /* -----------------------------------------------------------------------------
2 (c) The University of Glasgow 1995-2004
3
4 Our low-level exec() variant.
5 -------------------------------------------------------------------------- */
6 #include "HsBase.h"
7
8 #if !defined(mingw32_TARGET_OS) /* to the end */
9
10 /* Evidently non-Posix. */
11 /* #include "PosixSource.h" */
12
13 #include <unistd.h>
14 #include <sys/time.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <errno.h>
18
19 /*
20 * We want the search semantics of execvp, but we want to provide our
21 * own environment, like execve. The following copyright applies to
22 * this code, as it is a derivative of execvp:
23 *-
24 * Copyright (c) 1991 The Regents of the University of California.
25 * All rights reserved.
26 *
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions
29 * are met:
30 * 1. Redistributions of source code must retain the above copyright
31 * notice, this list of conditions and the following disclaimer.
32 * 2. Redistributions in binary form must reproduce the above copyright
33 * notice, this list of conditions and the following disclaimer in the
34 * documentation and/or other materials provided with the distribution.
35 * 3. All advertising materials mentioning features or use of this software
36 * must display the following acknowledgement:
37 * This product includes software developed by the University of
38 * California, Berkeley and its contributors.
39 * 4. Neither the name of the University nor the names of its contributors
40 * may be used to endorse or promote products derived from this software
41 * without specific prior written permission.
42 *
43 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
44 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
47 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53 * SUCH DAMAGE.
54 */
55
56 int
57 execvpe(char *name, char *const argv[], char **envp)
58 {
59 register int lp, ln;
60 register char *p;
61 int eacces=0, etxtbsy=0;
62 char *bp, *cur, *path, *buf = 0;
63
64 /* If it's an absolute or relative path name, it's easy. */
65 if (strchr(name, '/')) {
66 bp = (char *) name;
67 cur = path = buf = NULL;
68 goto retry;
69 }
70
71 /* Get the path we're searching. */
72 if (!(path = getenv("PATH"))) {
73 #ifdef HAVE_CONFSTR
74 ln = confstr(_CS_PATH, NULL, 0);
75 if ((cur = path = malloc(ln + 1)) != NULL) {
76 path[0] = ':';
77 (void) confstr (_CS_PATH, path + 1, ln);
78 }
79 #else
80 if ((cur = path = malloc(1 + 1)) != NULL) {
81 path[0] = ':';
82 path[1] = '\0';
83 }
84 #endif
85 } else
86 cur = path = strdup(path);
87
88 if (path == NULL || (bp = buf = malloc(strlen(path)+strlen(name)+2)) == NULL)
89 goto done;
90
91 while (cur != NULL) {
92 p = cur;
93 if ((cur = strchr(cur, ':')) != NULL)
94 *cur++ = '\0';
95
96 /*
97 * It's a SHELL path -- double, leading and trailing colons mean the current
98 * directory.
99 */
100 if (!*p) {
101 p = ".";
102 lp = 1;
103 } else
104 lp = strlen(p);
105 ln = strlen(name);
106
107 memcpy(buf, p, lp);
108 buf[lp] = '/';
109 memcpy(buf + lp + 1, name, ln);
110 buf[lp + ln + 1] = '\0';
111
112 retry:
113 (void) execve(bp, argv, envp);
114 switch (errno) {
115 case EACCES:
116 eacces = 1;
117 break;
118 case ENOENT:
119 break;
120 case ENOEXEC:
121 {
122 register size_t cnt;
123 register char **ap;
124
125 for (cnt = 0, ap = (char **) argv; *ap; ++ap, ++cnt)
126 ;
127 if ((ap = malloc((cnt + 2) * sizeof(char *))) != NULL) {
128 memcpy(ap + 2, argv + 1, cnt * sizeof(char *));
129
130 ap[0] = "sh";
131 ap[1] = bp;
132 (void) execve("/bin/sh", ap, envp);
133 free(ap);
134 }
135 goto done;
136 }
137 case ETXTBSY:
138 if (etxtbsy < 3)
139 (void) sleep(++etxtbsy);
140 goto retry;
141 default:
142 goto done;
143 }
144 }
145 if (eacces)
146 errno = EACCES;
147 else if (!errno)
148 errno = ENOENT;
149 done:
150 if (path)
151 free(path);
152 if (buf)
153 free(buf);
154 return (-1);
155 }
156
157
158 /* Copied verbatim from ghc/lib/std/cbits/system.c. */
159 void pPrPr_disableITimers (void)
160 {
161 # ifdef HAVE_SETITIMER
162 /* Reset the itimers in the child, so it doesn't get plagued
163 * by SIGVTALRM interrupts.
164 */
165 struct timeval tv_null = { 0, 0 };
166 struct itimerval itv;
167 itv.it_interval = tv_null;
168 itv.it_value = tv_null;
169 setitimer(ITIMER_REAL, &itv, NULL);
170 setitimer(ITIMER_VIRTUAL, &itv, NULL);
171 setitimer(ITIMER_PROF, &itv, NULL);
172 # endif
173 }
174
175 #endif