PageRenderTime 14ms CodeModel.GetById 7ms app.highlight 5ms RepoModel.GetById 0ms app.codeStats 0ms

/arch/um/os-Linux/execvp.c

https://bitbucket.org/ndreys/linux-sunxi
C | 149 lines | 81 code | 14 blank | 54 comment | 16 complexity | bf064d80a96e1f3dc75266ae358e3fdb MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
  1/* Copyright (C) 2006 by Paolo Giarrusso - modified from glibc' execvp.c.
  2   Original copyright notice follows:
  3
  4   Copyright (C) 1991,92,1995-99,2002,2004 Free Software Foundation, Inc.
  5   This file is part of the GNU C Library.
  6
  7   The GNU C Library is free software; you can redistribute it and/or
  8   modify it under the terms of the GNU Lesser General Public
  9   License as published by the Free Software Foundation; either
 10   version 2.1 of the License, or (at your option) any later version.
 11
 12   The GNU C Library is distributed in the hope that it will be useful,
 13   but WITHOUT ANY WARRANTY; without even the implied warranty of
 14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 15   Lesser General Public License for more details.
 16
 17   You should have received a copy of the GNU Lesser General Public
 18   License along with the GNU C Library; if not, write to the Free
 19   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 20   02111-1307 USA.  */
 21#include <unistd.h>
 22
 23#include <stdbool.h>
 24#include <stdlib.h>
 25#include <string.h>
 26#include <errno.h>
 27#include <limits.h>
 28
 29#ifndef TEST
 30#include "um_malloc.h"
 31#else
 32#include <stdio.h>
 33#define um_kmalloc malloc
 34#endif
 35#include "os.h"
 36
 37/* Execute FILE, searching in the `PATH' environment variable if it contains
 38   no slashes, with arguments ARGV and environment from `environ'.  */
 39int execvp_noalloc(char *buf, const char *file, char *const argv[])
 40{
 41	if (*file == '\0') {
 42		return -ENOENT;
 43	}
 44
 45	if (strchr (file, '/') != NULL) {
 46		/* Don't search when it contains a slash.  */
 47		execv(file, argv);
 48	} else {
 49		int got_eacces;
 50		size_t len, pathlen;
 51		char *name, *p;
 52		char *path = getenv("PATH");
 53		if (path == NULL)
 54			path = ":/bin:/usr/bin";
 55
 56		len = strlen(file) + 1;
 57		pathlen = strlen(path);
 58		/* Copy the file name at the top.  */
 59		name = memcpy(buf + pathlen + 1, file, len);
 60		/* And add the slash.  */
 61		*--name = '/';
 62
 63		got_eacces = 0;
 64		p = path;
 65		do {
 66			char *startp;
 67
 68			path = p;
 69			//Let's avoid this GNU extension.
 70			//p = strchrnul (path, ':');
 71			p = strchr(path, ':');
 72			if (!p)
 73				p = strchr(path, '\0');
 74
 75			if (p == path)
 76				/* Two adjacent colons, or a colon at the beginning or the end
 77				   of `PATH' means to search the current directory.  */
 78				startp = name + 1;
 79			else
 80				startp = memcpy(name - (p - path), path, p - path);
 81
 82			/* Try to execute this name.  If it works, execv will not return.  */
 83			execv(startp, argv);
 84
 85			/*
 86			if (errno == ENOEXEC) {
 87			}
 88			*/
 89
 90			switch (errno) {
 91				case EACCES:
 92					/* Record the we got a `Permission denied' error.  If we end
 93					   up finding no executable we can use, we want to diagnose
 94					   that we did find one but were denied access.  */
 95					got_eacces = 1;
 96				case ENOENT:
 97				case ESTALE:
 98				case ENOTDIR:
 99					/* Those errors indicate the file is missing or not executable
100					   by us, in which case we want to just try the next path
101					   directory.  */
102				case ENODEV:
103				case ETIMEDOUT:
104					/* Some strange filesystems like AFS return even
105					   stranger error numbers.  They cannot reasonably mean
106					   anything else so ignore those, too.  */
107				case ENOEXEC:
108					/* We won't go searching for the shell
109					 * if it is not executable - the Linux
110					 * kernel already handles this enough,
111					 * for us. */
112					break;
113
114				default:
115					/* Some other error means we found an executable file, but
116					   something went wrong executing it; return the error to our
117					   caller.  */
118					return -errno;
119			}
120		} while (*p++ != '\0');
121
122		/* We tried every element and none of them worked.  */
123		if (got_eacces)
124			/* At least one failure was due to permissions, so report that
125			   error.  */
126			return -EACCES;
127	}
128
129	/* Return the error from the last attempt (probably ENOENT).  */
130	return -errno;
131}
132#ifdef TEST
133int main(int argc, char**argv)
134{
135	char buf[PATH_MAX];
136	int ret;
137	argc--;
138	if (!argc) {
139		fprintf(stderr, "Not enough arguments\n");
140		return 1;
141	}
142	argv++;
143	if (ret = execvp_noalloc(buf, argv[0], argv)) {
144		errno = -ret;
145		perror("execvp_noalloc");
146	}
147	return 0;
148}
149#endif