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