BRL-CAD
whereis.c
Go to the documentation of this file.
1 /* W H E R E I S . C
2  * BRL-CAD
3  *
4  * Copyright (c) 2005-2014 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 
21 #include "common.h"
22 
23 /* system headers */
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #ifdef HAVE_SYS_TYPES_H
28 # include <sys/types.h>
29 #endif
30 #ifdef HAVE_SYS_SYSCTL_H
31 # ifdef HAVE_SYS_PARAM_H
32 # include <sys/param.h>
33 # endif
34 # include <sys/sysctl.h>
35 #endif
36 
37 /* common headers */
38 #include "bu/debug.h"
39 #include "bu/file.h"
40 #include "bu/log.h"
41 #include "bu/str.h"
42 
43 
44 /* how big should PATH from getenv ever be */
45 #define MAXPATHENV 32767
46 
47 /* container for path match results */
48 static char bu_whereis_result[MAXPATHLEN] = {0};
49 
50 
51 const char *
52 bu_whereis(const char *cmd)
53 {
54  static const char *gotpath = NULL;
55  char PATH[MAXPATHENV];
56 
57  char *directory = NULL;
58  char *position = NULL;
59  char curr_dir[] = ".";
60 
62  bu_log("bu_whereis: [%s]\n", cmd);
63  }
64 
65  if (UNLIKELY(!cmd)) {
66  return NULL;
67  }
68 
69  /* start fresh */
70  memset(PATH, 0, MAXPATHENV);
71  memset(bu_whereis_result, 0, MAXPATHLEN);
72 
73  /* check for full/relative path match */
74  bu_strlcpy(bu_whereis_result, cmd, MAXPATHLEN);
75  if (!BU_STR_EQUAL(bu_whereis_result, cmd)) {
76  if (UNLIKELY(bu_debug & BU_DEBUG_PATHS)) {
77  bu_log("command [%s] is too long\n", cmd);
78  }
79  return NULL;
80  }
81  if (bu_file_exists(bu_whereis_result, NULL) && strchr(bu_whereis_result, BU_DIR_SEPARATOR)) {
82  if (bu_whereis_result[0] == '\0')
83  return NULL; /* never return empty */
84  return bu_whereis_result;
85  }
86 
87 #if defined(HAVE_SYSCTL) && defined(CTL_USER) && defined(USER_CS_PATH)
88  {
89  int mib[2] = { CTL_USER, USER_CS_PATH };
90  size_t len = MAXPATHENV;
91 
92  /* use sysctl() to get the PATH */
93  if (sysctl(mib, 2, PATH, &len, NULL, 0) != 0) {
94  if (UNLIKELY(bu_debug & BU_DEBUG_PATHS)) {
95  perror("sysctl of user.cs_path");
96  bu_log("user.cs_path is unusable\n");
97  }
98  return NULL;
99  }
100 
101  if (UNLIKELY(bu_debug & BU_DEBUG_PATHS)) {
102  bu_log("PATH is %s\n", PATH);
103  }
104  }
105 #endif /* HAVE_SYSCTL */
106 
107  /* search for the executable */
108  directory = PATH;
109  do {
110  position = strchr(directory, BU_PATH_SEPARATOR);
111  if (position) {
112  /* 'directory' can't be const because we have to change a character here: */
113  *position = '\0';
114  }
115 
116  /* empty means use current dir */
117  if (strlen(directory) == 0) {
118  directory = curr_dir; /* "."; */
119  }
120 
121  snprintf(bu_whereis_result, MAXPATHLEN, "%s/%s", directory, cmd);
122  if (bu_file_exists(bu_whereis_result, NULL)) {
123  if (bu_whereis_result[0] == '\0')
124  return NULL; /* never return empty */
125  return bu_whereis_result;
126  }
127 
128  if (position) {
129  directory = position + 1;
130  } else {
131  directory = NULL;
132  }
133  } while (directory); /* iterate over PATH directories */
134 
135  /* no path or no match */
136  if (UNLIKELY(bu_debug & BU_DEBUG_PATHS)) {
137  bu_log("no %s in %s\n", cmd, gotpath ? gotpath : "(no path)");
138  }
139 
140  return NULL;
141 }
142 
143 /*
144  * Local Variables:
145  * mode: C
146  * tab-width: 8
147  * indent-tabs-mode: t
148  * c-file-style: "stroustrup"
149  * End:
150  * ex: shiftwidth=4 tabstop=8
151  */
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
Header file for the BRL-CAD common definitions.
#define BU_DEBUG_PATHS
Definition: debug.h:68
char * strchr(const char *sp, int c)
void * memset(void *s, int c, size_t n)
#define bu_strlcpy(dst, src, size)
Definition: str.h:60
#define BU_PATH_SEPARATOR
Definition: defines.h:127
#define MAXPATHENV
Definition: whereis.c:45
#define BU_DIR_SEPARATOR
Definition: defines.h:97
int bu_debug
Definition: globals.c:87
const char * bu_whereis(const char *cmd)
Definition: whereis.c:52
int bu_file_exists(const char *path, int *fd)
Definition: file.c:57
#define UNLIKELY(expression)
Definition: common.h:282
#define BU_STR_EQUAL(s1, s2)
Definition: str.h:126
#define MAXPATHLEN
Definition: defines.h:113