root/maint/gnulib/lib/findprog.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. find_in_path

   1 /* Locating a program in PATH.
   2    Copyright (C) 2001-2004, 2006-2021 Free Software Foundation, Inc.
   3    Written by Bruno Haible <haible@clisp.cons.org>, 2001.
   4 
   5    This file is free software: you can redistribute it and/or modify
   6    it under the terms of the GNU Lesser General Public License as
   7    published by the Free Software Foundation; either version 2.1 of the
   8    License, or (at your option) any later version.
   9 
  10    This file 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
  13    GNU Lesser General Public License for more details.
  14 
  15    You should have received a copy of the GNU Lesser General Public License
  16    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
  17 
  18 
  19 #include <config.h>
  20 
  21 /* Specification.  */
  22 #include "findprog.h"
  23 
  24 #include <stdbool.h>
  25 #include <stdlib.h>
  26 #include <string.h>
  27 #include <unistd.h>
  28 #if !(defined _WIN32 || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__)
  29 # include <sys/stat.h>
  30 #endif
  31 
  32 /* Avoid collision between findprog.c and findprog-lgpl.c.  */
  33 #if IN_FINDPROG_LGPL || ! GNULIB_FINDPROG_LGPL
  34 
  35 #if !IN_FINDPROG_LGPL
  36 # include "xalloc.h"
  37 #endif
  38 #include "concat-filename.h"
  39 
  40 
  41 const char *
  42 find_in_path (const char *progname)
     /* [previous][next][first][last][top][bottom][index][help] */
  43 {
  44 #if defined _WIN32 || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
  45   /* Native Windows, Cygwin, OS/2, DOS */
  46   /* The searching rules with .COM, .EXE, .BAT, .CMD etc. suffixes are
  47      too complicated.  Leave it to the OS.  */
  48   return progname;
  49 #else
  50   /* Unix */
  51   char *path;
  52   char *path_rest;
  53   char *cp;
  54 
  55   if (strchr (progname, '/') != NULL)
  56     /* If progname contains a slash, it is either absolute or relative to
  57        the current directory.  PATH is not used.  */
  58     return progname;
  59 
  60   path = getenv ("PATH");
  61   if (path == NULL || *path == '\0')
  62     /* If PATH is not set, the default search path is implementation
  63        dependent.  */
  64     return progname;
  65 
  66   /* Make a copy, to prepare for destructive modifications.  */
  67 # if !IN_FINDPROG_LGPL
  68   path = xstrdup (path);
  69 # else
  70   path = strdup (path);
  71   if (path == NULL)
  72     /* Out of memory.  */
  73     return progname;
  74 # endif
  75   for (path_rest = path; ; path_rest = cp + 1)
  76     {
  77       const char *dir;
  78       bool last;
  79       char *progpathname;
  80 
  81       /* Extract next directory in PATH.  */
  82       dir = path_rest;
  83       for (cp = path_rest; *cp != '\0' && *cp != ':'; cp++)
  84         ;
  85       last = (*cp == '\0');
  86       *cp = '\0';
  87 
  88       /* Empty PATH components designate the current directory.  */
  89       if (dir == cp)
  90         dir = ".";
  91 
  92       /* Concatenate dir and progname.  */
  93 # if !IN_FINDPROG_LGPL
  94       progpathname = xconcatenated_filename (dir, progname, NULL);
  95 # else
  96       progpathname = concatenated_filename (dir, progname, NULL);
  97       if (progpathname == NULL)
  98         {
  99           /* Out of memory.  */
 100           free (path);
 101           return progname;
 102         }
 103 # endif
 104 
 105       /* On systems which have the eaccess() system call, let's use it.
 106          On other systems, let's hope that this program is not installed
 107          setuid or setgid, so that it is ok to call access() despite its
 108          design flaw.  */
 109       if (eaccess (progpathname, X_OK) == 0)
 110         {
 111           /* Check that the progpathname does not point to a directory.  */
 112           struct stat statbuf;
 113 
 114           if (stat (progpathname, &statbuf) >= 0
 115               && ! S_ISDIR (statbuf.st_mode))
 116             {
 117               /* Found!  */
 118               if (strcmp (progpathname, progname) == 0)
 119                 {
 120                   free (progpathname);
 121 
 122                   /* Add the "./" prefix for real, that xconcatenated_filename()
 123                      optimized away.  This avoids a second PATH search when the
 124                      caller uses execlp/execvp.  */
 125 # if !IN_FINDPROG_LGPL
 126                   progpathname = XNMALLOC (2 + strlen (progname) + 1, char);
 127 # else
 128                   progpathname = (char *) malloc (2 + strlen (progname) + 1);
 129                   if (progpathname == NULL)
 130                     {
 131                       /* Out of memory.  */
 132                       free (path);
 133                       return progname;
 134                     }
 135 # endif
 136                   progpathname[0] = '.';
 137                   progpathname[1] = '/';
 138                   memcpy (progpathname + 2, progname, strlen (progname) + 1);
 139                 }
 140 
 141               free (path);
 142               return progpathname;
 143             }
 144         }
 145 
 146       free (progpathname);
 147 
 148       if (last)
 149         break;
 150     }
 151 
 152   /* Not found in PATH.  An error will be signalled at the first call.  */
 153   free (path);
 154   return progname;
 155 #endif
 156 }
 157 
 158 #endif

/* [previous][next][first][last][top][bottom][index][help] */