whereis.c

Go to the documentation of this file.
00001 /*                       W H E R I S . C
00002  * BRL-CAD
00003  *
00004  * Copyright (c) 2005-2006 United States Government as represented by
00005  * the U.S. Army Research Laboratory.
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License
00009  * as published by the Free Software Foundation; either version 2 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful, but
00013  * WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Library General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this file; see the file named COPYING for more
00019  * information.
00020  */
00021 
00022 /** @addtogroup bu_log */
00023 /*@{*/
00024 /** @file whereis.c
00025  *
00026  * Routine to provide BSD "whereis" functionality, locating binaries
00027  * of specified programs from the SYSTEM path (i.e.  not necessarily
00028  * the user PATH).  This is useful to locate system binaries and
00029  * resources at run-time.
00030  *
00031  *  Author -
00032  *      Christopher Sean Morrison
00033  *
00034  *  Source -
00035  *      The U. S. Army Research Laboratory
00036  *      Aberdeen Proving Ground, Maryland  21005-5068  USA
00037  */
00038 #include "common.h"
00039 
00040 #include <stdlib.h>
00041 #include <stdio.h>
00042 #include <string.h>
00043 #ifdef HAVE_SYS_TYPES_H
00044 #  include <sys/types.h>
00045 #endif
00046 #ifdef HAVE_SYS_SYSCTL_H
00047 #  ifdef HAVE_SYS_PARAM_H
00048 #    include <sys/param.h>
00049 #  endif
00050 #  include <sys/sysctl.h>
00051 #endif
00052 
00053 #include "machine.h"
00054 #include "bu.h"
00055 
00056 
00057 /** b u _ w h e r e i s
00058  *
00059  * Sets argv array of path matches to the given executable cmd name
00060  * returning up to lim number of occurances found.  the system
00061  * environment path is obtained via a sysctl call for the
00062  * ``user.cs_path'' string.  In the absense of sysctl, getenv will be
00063  * used for the user PATH instead.
00064  *
00065  * It is the callers responsibility to allocate sufficient memory to
00066  * the argv array itself (lim elements), memory for the array contents
00067  * will be automatically allocated as needed.  It is the callers
00068  * responsibility to free the array contents with bu_free_array() as
00069  * well as the argv array itself.
00070  */
00071 int bu_whereis(char *argv[], int lim, const char *cmd)
00072 {
00073   char *PATH = {0};
00074   int free_path = 0;
00075   char *curr_path;
00076   int max_length;
00077 
00078   char *directory;
00079   char *fullname = {0};
00080 
00081   int found_it;
00082   int found_count = 0;
00083 
00084   int i;
00085 
00086   if (!cmd) {
00087     return 0;
00088   }
00089 
00090   if (lim <= 0) {
00091     return 0;
00092   }
00093 
00094   if (!argv) {
00095     bu_bomb("bu_whereis was given a null array?\n");
00096   }
00097 
00098 
00099   /* otherwise use sysctl() to get the PATH */
00100 #if defined(HAVE_SYSCTL) && defined(CTL_USER) && defined(USER_CS_PATH)
00101 #  define bu_whereis_found_path 1
00102  {
00103    int mib[2];
00104    size_t len;
00105    mib[0] = CTL_USER;
00106    mib[1] = USER_CS_PATH;
00107 
00108    if (sysctl(mib, 2, NULL, &len, NULL, 0) != 0) {
00109      perror("sysctl unable to read user.cs_path");
00110      return 0;
00111    }
00112    if (len > 0) {
00113      PATH = bu_calloc(len, sizeof(char), "bu_whereis PATH");
00114      free_path = 1;
00115    }
00116    if (sysctl(mib, 2, PATH, &len, NULL, 0) != 0) {
00117      perror("sysctl unable to get user.cs_path");
00118      return 0;
00119    }
00120    goto found_path;
00121  }
00122 #endif  /* HAVE_SYSCTL */
00123 
00124   /* use getenv() if it is available to get the PATH */
00125 #ifdef HAVE_GETENV
00126 #  define bu_whereis_found_path 1
00127   PATH = getenv("PATH");
00128   goto found_path;
00129 #endif  /* HAVE_GETENV */
00130 
00131  /* sanity check, make sure we have _some_ means to get a PATH */
00132 #ifndef bu_whereis_found_path
00133 #  error "Do not know how to read the PATH environment variable on this system"
00134 #endif
00135 
00136  found_path:
00137 
00138   if (!PATH) {
00139     /* no path, no match */
00140     bu_log("Unable to read the environment PATH\n");
00141     return 0;
00142   }
00143 
00144 
00145   /* something big enough to hold any path */
00146   max_length = strlen(PATH) + strlen(cmd) + 1;
00147   fullname = (char *)bu_calloc(max_length+1, sizeof(char), "bu_whereis fullname");
00148 
00149   /* search the PATH for the executable */
00150   for (curr_path = PATH; ; *curr_path++ = BU_PATH_SEPARATOR) {
00151     directory = curr_path;
00152 
00153     if ((curr_path = strchr(curr_path, BU_PATH_SEPARATOR)) != NULL) {
00154       *curr_path = '\0';
00155 
00156       /* equal means empty, so use current directory */
00157       if (directory == curr_path) {
00158         directory = ".";
00159       }
00160     } else {
00161       /* did not find a path separator, so this is the last element in the list */
00162       if (strlen(directory) == 0) {
00163         directory = ".";
00164       }
00165     }
00166 
00167     (void)snprintf(fullname, max_length, "%s/%s", directory, cmd);
00168 
00169     if (bu_file_exists(fullname)) {
00170       found_it = 0;
00171 
00172       /* make sure it is a new unique path */
00173       for (i = 0; i < found_count; i++) {
00174         if (strncmp(argv[i], fullname, max_length) == 0) {
00175           found_it = 1;
00176           break;
00177         }
00178       }
00179 
00180       /* add the finding if not previously added result */
00181       if (!found_it) {
00182         argv[found_count] = bu_malloc(max_length+1, "bu_whereis argv entry");
00183         strncpy(argv[found_count], fullname, max_length);
00184         found_count++;
00185       }
00186     }
00187 
00188     if (!curr_path) {
00189       break;
00190     }
00191     if (found_count >= lim) {
00192       break;
00193     }
00194   } /* end loop over PATH directories */
00195 
00196   bu_free(fullname, "bu_whereis fullname");
00197   fullname = NULL;
00198 
00199   /* free up the temporary resources */
00200 #ifdef HAVE_SYSCTL
00201   if (free_path && PATH) {
00202     bu_free(PATH, "bu_whereis PATH");
00203     PATH = NULL;
00204   }
00205 #endif
00206 
00207   return found_count;
00208 }
00209 /*@}*/
00210 
00211 /*
00212  * Local Variables:
00213  * mode: C
00214  * tab-width: 8
00215  * c-basic-offset: 4
00216  * indent-tabs-mode: t
00217  * End:
00218  * ex: shiftwidth=4 tabstop=8
00219  */

Generated on Mon Sep 18 01:24:48 2006 for BRL-CAD by  doxygen 1.4.6