(linenum→info "unix/slp.c:2238")

glibc/2.7/posix/execvp.c

    1: /* Copyright (C) 1991,92, 1995-99, 2002, 2004, 2005, 2007
    2:    Free Software Foundation, Inc.
    3:    This file is part of the GNU C Library.
    4: 
    5:    The GNU C Library is free software; you can redistribute it and/or
    6:    modify it under the terms of the GNU Lesser General Public
    7:    License as published by the Free Software Foundation; either
    8:    version 2.1 of the License, or (at your option) any later version.
    9: 
   10:    The GNU C Library is distributed in the hope that it will be useful,
   11:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   12:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   13:    Lesser General Public License for more details.
   14: 
   15:    You should have received a copy of the GNU Lesser General Public
   16:    License along with the GNU C Library; if not, write to the Free
   17:    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   18:    02111-1307 USA.  */
   19: 
   20: #include <alloca.h>
   21: #include <unistd.h>
   22: #include <stdarg.h>
   23: #include <stdbool.h>
   24: #include <stdlib.h>
   25: #include <string.h>
   26: #include <errno.h>
   27: #include <paths.h>
   28: 
   29: 
   30: /* The file is accessible but it is not an executable file.  Invoke
   31:    the shell to interpret it as a script.  */
   32: static void
   33: internal_function
   34: scripts_argv (const char *file, char *const argv[], int argc, char **new_argv)
   35: {
   36:   /* Construct an argument list for the shell.  */
   37:   new_argv[0] = (char *) _PATH_BSHELL;
   38:   new_argv[1] = (char *) file;
   39:   while (argc > 1)
   40:     {
   41:       new_argv[argc] = argv[argc - 1];
   42:       --argc;
   43:     }
   44: }
   45: 
   46: 
   47: /* Execute FILE, searching in the `PATH' environment variable if it contains
   48:    no slashes, with arguments ARGV and environment from `environ'.  */
   49: int
   50: execvp (file, argv)
   51:      const char *file;
   52:      char *const argv[];
   53: {
   54:   if (*file == '\0')
   55:     {
   56:       /* We check the simple case first. */
   57:       __set_errno (ENOENT);
   58:       return -1;
   59:     }
   60: 
   61:   if (strchr (file, '/') != NULL)
   62:     {
   63:       /* Don't search when it contains a slash.  */
   64:       __execve (file, argv, __environ);
   65: 
   66:       if (errno == ENOEXEC)
   67:         {
   68:           /* Count the arguments.  */
   69:           int argc = 0;
   70:           while (argv[argc++])
   71:             ;
   72:           size_t len = (argc + 1) * sizeof (char *);
   73:           char **script_argv;
   74:           void *ptr = NULL;
   75:           if (__libc_use_alloca (len))
   76:             script_argv = alloca (len);
   77:           else
   78:             script_argv = ptr = malloc (len);
   79: 
   80:           if (script_argv != NULL)
   81:             {
   82:               scripts_argv (file, argv, argc, script_argv);
   83:               __execve (script_argv[0], script_argv, __environ);
   84: 
   85:               free (ptr);
   86:             }
   87:         }
   88:     }
   89:   else
   90:     {
   91:       size_t pathlen;
   92:       size_t alloclen = 0;
   93:       char *path = getenv ("PATH");
   94:       if (path == NULL)
   95:         {
   96:           pathlen = confstr (_CS_PATH, (char *) NULL, 0);
   97:           alloclen = pathlen + 1;
   98:         }
   99:       else
  100:         pathlen = strlen (path);
  101: 
  102:       size_t len = strlen (file) + 1;
  103:       alloclen += pathlen + len + 1;
  104: 
  105:       char *name;
  106:       char *path_malloc = NULL;
  107:       if (__libc_use_alloca (alloclen))
  108:         name = alloca (alloclen);
  109:       else
  110:         {
  111:           path_malloc = name = malloc (alloclen);
  112:           if (name == NULL)
  113:             return -1;
  114:         }
  115: 
  116:       if (path == NULL)
  117:         {
  118:           /* There is no `PATH' in the environment.
  119:              The default search path is the current directory
  120:              followed by the path `confstr' returns for `_CS_PATH'.  */
  121:           path = name + pathlen + len + 1;
  122:           path[0] = ':';
  123:           (void) confstr (_CS_PATH, path + 1, pathlen);
  124:         }
  125: 
  126:       /* Copy the file name at the top.  */
  127:       name = (char *) memcpy (name + pathlen + 1, file, len);
  128:       /* And add the slash.  */
  129:       *--name = '/';
  130: 
  131:       char **script_argv = NULL;
  132:       void *script_argv_malloc = NULL;
  133:       bool got_eacces = false;
  134:       char *p = path;
  135:       do
  136:         {
  137:           char *startp;
  138: 
  139:           path = p;
  140:           p = __strchrnul (path, ':');
  141: 
  142:           if (p == path)
  143:             /* Two adjacent colons, or a colon at the beginning or the end
  144:                of `PATH' means to search the current directory.  */
  145:             startp = name + 1;
  146:           else
  147:             startp = (char *) memcpy (name - (p - path), path, p - path);
  148: 
  149:           /* Try to execute this name.  If it works, execve will not return. */
  150:           __execve (startp, argv, __environ);
  151: 
  152:           if (errno == ENOEXEC)
  153:             {
  154:               if (script_argv == NULL)
  155:                 {
  156:                   /* Count the arguments.  */
  157:                   int argc = 0;
  158:                   while (argv[argc++])
  159:                     ;
  160:                   size_t arglen = (argc + 1) * sizeof (char *);
  161:                   if (__libc_use_alloca (alloclen + arglen))
  162:                     script_argv = alloca (arglen);
  163:                   else
  164:                     script_argv = script_argv_malloc = malloc (arglen);
  165:                   if (script_argv == NULL)
  166:                     {
  167:                       /* A possible EACCES error is not as important as
  168:                          the ENOMEM.  */
  169:                       got_eacces = false;
  170:                       break;
  171:                     }
  172:                   scripts_argv (startp, argv, argc, script_argv);
  173:                 }
  174: 
  175:               __execve (script_argv[0], script_argv, __environ);
  176:             }
  177: 
  178:           switch (errno)
  179:             {
  180:             case EACCES:
  181:               /* Record the we got a `Permission denied' error.  If we end
  182:                  up finding no executable we can use, we want to diagnose
  183:                  that we did find one but were denied access.  */
  184:               got_eacces = true;
  185:             case ENOENT:
  186:             case ESTALE:
  187:             case ENOTDIR:
  188:               /* Those errors indicate the file is missing or not executable
  189:                  by us, in which case we want to just try the next path
  190:                  directory.  */
  191:             case ENODEV:
  192:             case ETIMEDOUT:
  193:               /* Some strange filesystems like AFS return even
  194:                  stranger error numbers.  They cannot reasonably mean
  195:                  anything else so ignore those, too.  */
  196:               break;
  197: 
  198:             default:
  199:               /* Some other error means we found an executable file, but
  200:                  something went wrong executing it; return the error to our
  201:                  caller.  */
  202:               return -1;
  203:             }
  204:         }
  205:       while (*p++ != '\0');
  206: 
  207:       /* We tried every element and none of them worked.  */
  208:       if (got_eacces)
  209:         /* At least one failure was due to permissions, so report that
  210:            error.  */
  211:         __set_errno (EACCES);
  212: 
  213:       free (script_argv_malloc);
  214:       free (path_malloc);
  215:     }
  216: 
  217:   /* Return the error from the last attempt (probably ENOENT).  */
  218:   return -1;
  219: }
  220: libc_hidden_def (execvp)
Syntax (Markdown)