15d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso/* Copyright (C) 2006 by Paolo Giarrusso - modified from glibc' execvp.c. 25d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso Original copyright notice follows: 35d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso 45d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso Copyright (C) 1991,92,1995-99,2002,2004 Free Software Foundation, Inc. 55d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso This file is part of the GNU C Library. 65d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso 75d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso The GNU C Library is free software; you can redistribute it and/or 85d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso modify it under the terms of the GNU Lesser General Public 95d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso License as published by the Free Software Foundation; either 105d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso version 2.1 of the License, or (at your option) any later version. 115d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso 125d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso The GNU C Library is distributed in the hope that it will be useful, 135d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso but WITHOUT ANY WARRANTY; without even the implied warranty of 145d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 155d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso Lesser General Public License for more details. 165d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso 175d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso You should have received a copy of the GNU Lesser General Public 185d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso License along with the GNU C Library; if not, write to the Free 195d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 205d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso 02111-1307 USA. */ 215d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso#include <unistd.h> 225d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso 235d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso#include <stdbool.h> 245d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso#include <stdlib.h> 255d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso#include <string.h> 265d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso#include <errno.h> 275d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso#include <limits.h> 285d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso 295d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso#ifndef TEST 3037185b33240870719b6b5913a46e6a441f1ae96fAl Viro#include <um_malloc.h> 315d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso#else 325d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso#include <stdio.h> 335d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso#define um_kmalloc malloc 345d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso#endif 3537185b33240870719b6b5913a46e6a441f1ae96fAl Viro#include <os.h> 365d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso 375d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso/* Execute FILE, searching in the `PATH' environment variable if it contains 385d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso no slashes, with arguments ARGV and environment from `environ'. */ 395d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrussoint execvp_noalloc(char *buf, const char *file, char *const argv[]) 405d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso{ 415d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso if (*file == '\0') { 425d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso return -ENOENT; 435d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso } 445d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso 455d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso if (strchr (file, '/') != NULL) { 465d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso /* Don't search when it contains a slash. */ 475d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso execv(file, argv); 485d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso } else { 495d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso int got_eacces; 505d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso size_t len, pathlen; 515d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso char *name, *p; 525d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso char *path = getenv("PATH"); 535d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso if (path == NULL) 545d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso path = ":/bin:/usr/bin"; 555d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso 565d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso len = strlen(file) + 1; 575d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso pathlen = strlen(path); 585d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso /* Copy the file name at the top. */ 595d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso name = memcpy(buf + pathlen + 1, file, len); 605d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso /* And add the slash. */ 615d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso *--name = '/'; 625d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso 635d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso got_eacces = 0; 645d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso p = path; 655d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso do { 665d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso char *startp; 675d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso 685d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso path = p; 695d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso //Let's avoid this GNU extension. 705d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso //p = strchrnul (path, ':'); 715d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso p = strchr(path, ':'); 725d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso if (!p) 735d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso p = strchr(path, '\0'); 745d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso 755d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso if (p == path) 765d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso /* Two adjacent colons, or a colon at the beginning or the end 775d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso of `PATH' means to search the current directory. */ 785d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso startp = name + 1; 795d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso else 805d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso startp = memcpy(name - (p - path), path, p - path); 815d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso 825d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso /* Try to execute this name. If it works, execv will not return. */ 835d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso execv(startp, argv); 845d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso 855d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso /* 865d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso if (errno == ENOEXEC) { 875d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso } 885d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso */ 895d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso 905d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso switch (errno) { 915d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso case EACCES: 925d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso /* Record the we got a `Permission denied' error. If we end 935d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso up finding no executable we can use, we want to diagnose 945d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso that we did find one but were denied access. */ 955d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso got_eacces = 1; 965d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso case ENOENT: 975d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso case ESTALE: 985d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso case ENOTDIR: 995d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso /* Those errors indicate the file is missing or not executable 1005d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso by us, in which case we want to just try the next path 1015d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso directory. */ 1025d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso case ENODEV: 1035d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso case ETIMEDOUT: 1045d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso /* Some strange filesystems like AFS return even 1055d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso stranger error numbers. They cannot reasonably mean 1065d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso anything else so ignore those, too. */ 1075d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso case ENOEXEC: 1085d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso /* We won't go searching for the shell 1095d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso * if it is not executable - the Linux 1105d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso * kernel already handles this enough, 1115d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso * for us. */ 1125d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso break; 1135d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso 1145d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso default: 1155d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso /* Some other error means we found an executable file, but 1165d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso something went wrong executing it; return the error to our 1175d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso caller. */ 1185d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso return -errno; 1195d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso } 1205d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso } while (*p++ != '\0'); 1215d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso 1225d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso /* We tried every element and none of them worked. */ 1235d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso if (got_eacces) 1245d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso /* At least one failure was due to permissions, so report that 1255d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso error. */ 1265d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso return -EACCES; 1275d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso } 1285d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso 1295d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso /* Return the error from the last attempt (probably ENOENT). */ 1305d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso return -errno; 1315d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso} 1325d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso#ifdef TEST 1335d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrussoint main(int argc, char**argv) 1345d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso{ 1355d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso char buf[PATH_MAX]; 1365d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso int ret; 1375d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso argc--; 1385d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso if (!argc) { 1395d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso fprintf(stderr, "Not enough arguments\n"); 1405d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso return 1; 1415d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso } 1425d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso argv++; 1435d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso if (ret = execvp_noalloc(buf, argv[0], argv)) { 1445d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso errno = -ret; 1455d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso perror("execvp_noalloc"); 1465d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso } 1475d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso return 0; 1485d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso} 1495d48545e5e88ab7a27ba6a5cb1e8fff617754b61Paolo 'Blaisorblade' Giarrusso#endif 150