1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
|
/* Provide an execlp replacement for Minix.
Copyright (C) 1988, 1994, 1995, 1997 Free Software Foundation, Inc.
This file is part of GNU Tar.
GNU Tar is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Tar is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Tar; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA. */
#if HAVE_CONFIG_H
# include <config.h>
#endif
/* For defining NULL. */
#include <stdio.h>
#if STDC_HEADERS
# include <stdlib.h>
#else
char *getenv ();
char *malloc ();
#endif
#include <errno.h>
#ifndef errno
extern int errno;
#endif
#include <sys/types.h>
#include <sys/stat.h>
#if STDC_HEADERS || HAVE_STRING_H
# include <string.h>
#else
# include <strings.h>
# ifndef strchr
# define strchr index
# endif
#endif
/* Synopsis: execlp (file, arg0, arg1... argN, (char *) NULL)
Exec a program, automatically searching for the program through all the
directories on the PATH.
This version is naive about variable argument lists and assumes a quite
straightforward C calling sequence. It will not work on systems having
odd stacks. */
int
execlp (filename, arg0)
char *filename;
char *arg0;
{
register char *p, *path;
register char *fnbuffer;
char **argstart = &arg0;
struct stat statbuf;
extern char **environ;
if (p = getenv ("PATH"), p == NULL)
{
/* Could not find path variable -- try to exec given filename. */
return execve (filename, argstart, environ);
}
/* Make a place to build the filename. We malloc larger than we need,
but we know it will fit in this. */
fnbuffer = malloc (strlen (p) + 1 + strlen (filename));
if (fnbuffer == NULL)
{
errno = ENOMEM;
return -1;
}
/* Try each component of the path to see if the file's there and
executable. */
for (path = p; path; path = p)
{
/* Construct full path name to try. */
if (p = strchr (path, ':'), !p)
strcpy (fnbuffer, path);
else
{
strncpy (fnbuffer, path, p - path);
fnbuffer[p - path] = '\0';
p++; /* skip : for next time */
}
if (strlen (fnbuffer) != 0)
strcat (fnbuffer, "/");
strcat (fnbuffer, filename);
/* Check to see if file is there and is a normal file. */
if (stat (fnbuffer, &statbuf) < 0)
{
if (errno == ENOENT)
continue; /* file not there,keep on looking */
else
goto fail; /* failed for some reason, return */
}
if (!S_ISREG (statbuf.st_mode))
continue;
if (execve (fnbuffer, argstart, environ) < 0
&& errno != ENOENT
&& errno != ENOEXEC)
{
/* Failed, for some other reason besides "file. */
goto fail;
}
/* If we got error ENOEXEC, the file is executable but is not an
object file. Try to execute it as a shell script, returning
error if we can't execute /bin/sh.
FIXME, this code is broken in several ways. Shell scripts
should not in general be executed by the user's SHELL variable
program. On more mature systems, the script can specify with
#!/bin/whatever. Also, this code clobbers argstart[-1] if the
exec of the shell fails. */
if (errno == ENOEXEC)
{
char *shell;
/* Try to execute command "sh arg0 arg1 ...". */
if (shell = getenv ("SHELL"), shell == NULL)
shell = "/bin/sh";
argstart[-1] = shell;
argstart[0] = fnbuffer;
execve (shell, &argstart[-1], environ);
goto fail; /* exec didn't work */
}
/* If we succeeded, the execve() doesn't return, so we can only be
here is if the file hasn't been found yet. Try the next place
on the path. */
}
/* All attempts failed to locate the file. Give up. */
errno = ENOENT;
fail:
free (fnbuffer);
return -1;
}
|