2 * This file has been modified for the cdrkit suite.
4 * The behaviour and appearence of the program code below can differ to a major
5 * extent from the version distributed by the original author(s).
7 * For details, see Changelog file distributed with the cdrkit package. If you
8 * received this file from another source then ask the distributing person for
9 * a log of modifications.
13 /* @(#)fexec.c 1.24 04/06/06 Copyright 1985, 1995-2004 J. Schilling */
15 * Execute a program with stdio redirection
17 * Copyright (c) 1985, 1995-2004 J. Schilling
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License version 2
22 * as published by the Free Software Foundation.
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
29 * You should have received a copy of the GNU General Public License along with
30 * this program; see the file COPYING. If not, write to the Free Software
31 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
37 #define rols_fexecl __nothing_1_ /* prototype in schily.h is wrong */
38 #define rols_fexecle __nothing_2_ /* prototype in schily.h is wrong */
42 int rols_fexecl __PR((const char *, FILE *, FILE *, FILE *, ...));
43 int rols_fexecle __PR((const char *, FILE *, FILE *, FILE *, ...));
60 extern char **environ;
62 LOCAL void fdcopy __PR((int, int));
63 LOCAL void fdmove __PR((int, int));
64 LOCAL const char *chkname __PR((const char *, const char *));
65 LOCAL const char *getpath __PR((char * const *));
69 rols_fexecl(const char *name, FILE *in, FILE *out, FILE *err, ...)
72 rols_fexecl(name, in, out, err, va_alist)
82 char *xav[MAX_F_ARGS];
93 while (va_arg(args, char *) != NULL)
97 if (ac < MAX_F_ARGS) {
100 pav = av = (char **)malloc((ac+1)*sizeof (char *));
111 p = va_arg(args, char *);
116 ret = rols_fexecv(name, in, out, err, ac, av);
124 rols_fexecle(const char *name, FILE *in, FILE *out, FILE *err, ...)
127 rols_fexecle(name, in, out, err, va_alist)
137 char *xav[MAX_F_ARGS];
149 while (va_arg(args, char *) != NULL)
151 env = va_arg(args, char **);
154 if (ac < MAX_F_ARGS) {
157 pav = av = (char **)malloc((ac+1)*sizeof (char *));
168 p = va_arg(args, char *);
173 ret = rols_fexecve(name, in, out, err, av, env);
180 rols_fexecv(name, in, out, err, ac, av)
182 FILE *in, *out, *err;
186 av[ac] = NULL; /* force list to be null terminated */
187 return (rols_fexecve(name, in, out, err, av, environ));
191 rols_fexecve(name, in, out, err, av, env)
193 FILE *in, *out, *err;
194 char * const av[], * const env[];
196 char nbuf[MAXPATHNAME+1];
208 o[0] = o[1] = o[2] = f[0] = f[1] = f[2] = 0;
219 * If name contains a pathdelimiter ('/' on unix)
220 * or name is too long ...
221 * try exec without path search.
223 if (find('/', name) || strlen(name) > MAXFILENAME) {
224 ret = exec_env(name, fin, fout, ferr, av, env);
226 } else if ((path = getpath(env)) == NULL) {
227 ret = exec_env(name, fin, fout, ferr, av, env);
228 if ((ret == ENOFILE) && strlen(name) <= (sizeof (nbuf) - 6)) {
229 strcatl(nbuf, "/bin/", name, (char *)NULL);
230 ret = exec_env(nbuf, fin, fout, ferr, av, env);
235 int nlen = strlen(name);
240 * JOS always uses ':' as PATH Environ separator
242 while (*path != ':' && *path != '\0' &&
243 np < &nbuf[MAXPATHNAME-nlen-2]) {
249 strcatl(nbuf, name, (char *)NULL);
251 strcatl(nbuf, nbuf, "/", name, (char *)NULL);
252 ret = exec_env(nbuf, fin, fout, ferr, av, env);
255 if (ret != ENOFILE || *path == '\0')
265 f[0] = fcntl(0, F_GETFD, 0);
267 fcntl(o[0], F_SETFD, 1);
271 f[1] = fcntl(1, F_GETFD, 0);
273 fcntl(o[1], F_SETFD, 1);
277 f[2] = fcntl(2, F_GETFD, 0);
279 fcntl(o[2], F_SETFD, 1);
290 * If name contains a pathdelimiter ('/' on unix)
291 * or name is too long ...
292 * try exec without path search.
294 #ifdef FOUND_MAXFILENAME
295 if (strchr(name, '/') || strlen(name) > (unsigned)MAXFILENAME) {
297 if (strchr(name, '/')) {
299 ret = execve(name, av, env);
301 } else if ((path = getpath(env)) == NULL) {
302 ret = execve(name, av, env);
303 if ((geterrno() == ENOENT) && strlen(name) <= (sizeof (nbuf) - 6)) {
304 strcatl(nbuf, "/bin/", name, (char *)NULL);
305 ret = execve(nbuf, av, env);
308 int nlen = strlen(name);
312 while (*path != PATH_ENV_DELIM && *path != '\0' &&
313 np < &nbuf[MAXPATHNAME-nlen-2]) {
319 strcatl(nbuf, name, (char *)NULL);
321 strcatl(nbuf, nbuf, "/", name, (char *)NULL);
322 ret = execve(nbuf, av, env);
323 if (geterrno() != ENOENT || *path == '\0')
329 /* reestablish old files */
334 fcntl(2, F_SETFD, 0);
340 fcntl(1, F_SETFD, 0);
346 fcntl(0, F_SETFD, 0);
362 fcntl(fd1, F_DUPFD, fd2);
376 /*----------------------------------------------------------------------------
380 +----------------------------------------------------------------------------*/
386 char * const *p = env;
391 if ((p2 = chkname("PATH", *p)) != NULL)
400 /*----------------------------------------------------------------------------
402 | Check if name is in environment.
403 | Return pointer to value name is found.
405 +----------------------------------------------------------------------------*/
414 if (*ev == '=' && *name == '\0')