BRL-CAD
brlcad_path.c
Go to the documentation of this file.
1 /* B R L C A D _ P A T H . C
2  * BRL-CAD
3  *
4  * Copyright (c) 2004-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 #ifdef HAVE_SYS_PARAM_H /* for MAXPATHLEN */
24 # include <sys/param.h>
25 #endif
26 
27 #include <stdlib.h>
28 #include <string.h>
29 #include "bio.h"
30 
31 #include "bu/debug.h"
32 #include "bu/file.h"
33 #include "bu/log.h"
34 #include "bu/malloc.h"
35 #include "bu/str.h"
36 #include "bu/vls.h"
37 #include "sysv.h"
38 
39 /* private headers */
40 #include "brlcad_version.h"
41 
42 
43 /* defaults for configure-less compiles */
44 #ifndef BRLCAD_ROOT
45 # define BRLCAD_ROOT "/usr/brlcad"
46 #endif
47 
48 
49 /* arbitrary buffer size large enough to hold a couple paths and a label */
50 #define MAX_WHERE_SIZE (size_t)((MAXPATHLEN*2) + 64)
51 
52 
53 HIDDEN const char *
55 {
56  static char path[MAXPATHLEN] = {0};
57 
58 #ifndef BRLCAD_DATA
59 # ifdef BRLCAD_DATA_DIR
60  if (find_path(path, BRLCAD_ROOT, BRLCAD_DATA_DIR, NULL, 0))
61  return path;
62 # endif
63 
64  snprintf(path, MAXPATHLEN, "%s%cshare", BRLCAD_ROOT, BU_DIR_SEPARATOR);
65 
66 #else
67  /* do this instead of just returning BRLCAD_DATA to keep compiler
68  * quiet about unreachable code.
69  */
70  snprintf(path, MAXPATHLEN, "%s", BRLCAD_DATA);
71 #endif
72 
73  return path;
74 }
75 
76 
77 /**
78  *print out an error/warning message if we cannot find the specified
79  * BRLCAD_ROOT (compile-time install path)
80  */
81 HIDDEN void
82 root_missing(const char *paths)
83 {
84  bu_log("\
85 Unable to locate where BRL-CAD %s is installed while searching:\n\
86 %s\n\
87 This version of BRL-CAD was compiled to be installed at:\n\
88  %s\n\n", brlcad_version(), paths, BRLCAD_ROOT);
89 
90 #ifndef _WIN32
91  bu_log("\
92 You may specify where to locate BRL-CAD by setting the BRLCAD_ROOT\n\
93 environment variable. For example:\n\
94 \n\
95 for csh/tcsh users:\n\
96  setenv BRLCAD_ROOT /path/to/brlcad\n\
97 for sh/bash users:\n\
98  BRLCAD_ROOT=/path/to/brlcad ; export BRLCAD_ROOT\n\n");
99 #endif
100 
101  return;
102 }
103 
104 
105 /**
106  * print out an error/warning message if we cannot find the specified
107  * BRLCAD_DATA (compile-time install path)
108  */
109 HIDDEN void
110 data_missing(const char *paths)
111 {
112  bu_log("\
113 Unable to locate where BRL-CAD %s data resources are installed\n\
114 while searching:\n\
115 %s\n\
116 This release of BRL-CAD expects data resources to be at:\n\
117  %s\n\n", brlcad_version(), paths, _brlcad_data());
118 
119 #ifndef _WIN32
120  bu_log("\
121 You may specify where to locate BRL-CAD data resources by setting\n\
122 the BRLCAD_DATA environment variable. For example:\n\
123 \n\
124 for csh/tcsh users:\n\
125  setenv BRLCAD_DATA /path/to/brlcad/data\n\
126 for sh/bash users:\n\
127  BRLCAD_DATA=/path/to/brlcad/data ; export BRLCAD_DATA\n\n");
128 #endif
129 
130  return;
131 }
132 
133 
134 /**
135  * put a left-hand and right-hand path together and test whether they
136  * exist or not.
137  *
138  * @return boolean on whether a match was found.
139  */
140 HIDDEN int
141 find_path(char result[MAXPATHLEN], const char *lhs, const char *rhs, struct bu_vls *searched, const char *where)
142 {
143  size_t llen, rlen;
144  static const char *currdir=".";
145 
146  /* swap right with left if there is no left so logic is simplified
147  * later on.
148  */
149  if (lhs == NULL && rhs != NULL) {
150  lhs = rhs;
151  rhs = NULL;
152  }
153 
154  if (lhs == NULL) {
155  if (searched && where) {
156  bu_vls_strcat(searched, where);
157  }
158  return 0;
159  }
160 
161  rlen = llen = 0;
162  if (rhs) {
163  rlen = strlen(rhs);
164  }
165 
166  /* be safe */
167  if (rlen + 2 > MAXPATHLEN) {
168  bu_log("Warning: path is way too long (%zu characters > %d)\n", rlen+2, MAXPATHLEN);
169  if (searched && where) {
170  bu_vls_strcat(searched, where);
171  }
172  return 0;
173  }
174 
175  /* an empty left hand implies current directory (plus a slash is appended later) */
176  if (lhs[0] == '\0') {
177  lhs = currdir;
178  }
179 
180  /* left-hand path should exist independent of right-hand path */
181  if (!bu_file_exists(lhs, NULL)) {
182  if (searched && where) {
183  bu_vls_strcat(searched, where);
184  }
185  return 0;
186  }
187 
188  /* start fresh */
189  memset(result, 0, (size_t)MAXPATHLEN);
190  bu_strlcpy(result, lhs, (size_t)MAXPATHLEN);
191 
192  /* nothing to add, so just return what we have */
193  if (!rhs || (rlen == 0)) {
194  return 1;
195  }
196 
197  /* be safe again */
198  llen = strlen(result);
199  if (llen + rlen + 3 > MAXPATHLEN) {
200  bu_log("Warning: path is way too long (%zu characters > %d)\n", llen+rlen+3, MAXPATHLEN);
201  if (searched && where) {
202  bu_vls_strcat(searched, where);
203  }
204  return 0;
205  }
206 
207  if ((*(result+llen-1) != BU_DIR_SEPARATOR) && (rhs[0] != BU_DIR_SEPARATOR)) {
208  /* let the caller give "/usr/brlcad" and "bin" and get "/usr/brlcad/bin" */
209  *(result+llen) = BU_DIR_SEPARATOR;
210  llen++;
211  } else if ((*(result+llen-1) == BU_DIR_SEPARATOR) && (rhs[0] == BU_DIR_SEPARATOR)) {
212  /* let the caller give "/usr/brlcad/" and "/bin" and get "/usr/brlcad/bin"*/
213  rhs++;
214  rlen--;
215  }
216 
217  /* found a match */
218  bu_strlcpy(result+llen, rhs, (size_t)(MAXPATHLEN - llen));
219  if (bu_file_exists(result, NULL)) {
220  return 1;
221  }
222 
223  /* close, but no match */
224  if (searched && where) {
225  bu_vls_strcat(searched, where);
226  }
227  return 0;
228 }
229 
230 const char *
231 bu_brlcad_dir(const char *dirkey, int fail_quietly)
232 {
233  static char result[MAXPATHLEN] = {0};
234  if (BU_STR_EQUAL(dirkey, "bin")) {
235 #if defined(BRLCAD_BIN_DIR)
236  snprintf(result, MAXPATHLEN, "%s", BRLCAD_BIN_DIR);
237 #else
238  snprintf(result, MAXPATHLEN, "%s", "bin");
239 #endif
240  return result;
241  }
242  if (BU_STR_EQUAL(dirkey, "lib")) {
243 #if defined(BRLCAD_LIB_DIR)
244  snprintf(result, MAXPATHLEN, "%s", BRLCAD_LIB_DIR);
245 #else
246  snprintf(result, MAXPATHLEN, "%s", "lib");
247 #endif
248  return result;
249  }
250  if (BU_STR_EQUAL(dirkey, "include")) {
251 #if defined(BRLCAD_INCLUDE_DIR)
252  snprintf(result, MAXPATHLEN, "%s", BRLCAD_INCLUDE_DIR);
253 #else
254  snprintf(result, MAXPATHLEN, "%s", "include");
255 #endif
256  return result;
257  }
258  if (BU_STR_EQUAL(dirkey, "data") || BU_STR_EQUAL(dirkey, "share")) {
259 #if defined(BRLCAD_DATA_DIR)
260  snprintf(result, MAXPATHLEN, "%s", BRLCAD_DATA_DIR);
261 #else
262  snprintf(result, MAXPATHLEN, "%s", "share");
263 #endif
264  return result;
265  }
266  if (BU_STR_EQUAL(dirkey, "doc")) {
267 #if defined(BRLCAD_DOC_DIR)
268  snprintf(result, MAXPATHLEN, "%s", BRLCAD_DOC_DIR);
269 #else
270  snprintf(result, MAXPATHLEN, "%s", "doc");
271 #endif
272  return result;
273  }
274  if (BU_STR_EQUAL(dirkey, "man")) {
275 #if defined(BRLCAD_MAN_DIR)
276  snprintf(result, MAXPATHLEN, "%s", BRLCAD_MAN_DIR);
277 #else
278  snprintf(result, MAXPATHLEN, "%s", "share/man");
279 #endif
280  return result;
281  }
282 
283 
284  if (!fail_quietly) {
285  snprintf(result, MAXPATHLEN, "Unknown directory key %s", dirkey);
286  return result;
287  }
288  return NULL;
289 }
290 
291 const char *
292 bu_brlcad_root(const char *rhs, int fail_quietly)
293 {
294  static char result[MAXPATHLEN] = {0};
295  const char *lhs;
296  struct bu_vls searched = BU_VLS_INIT_ZERO;
297  char where[MAX_WHERE_SIZE] = {0};
298 
300  bu_log("bu_brlcad_root: searching for [%s]\n", rhs?rhs:"");
301  }
302 
303  /* BRLCAD_ROOT environment variable if set */
304  lhs = getenv("BRLCAD_ROOT");
305  if (lhs) {
306  snprintf(where, MAX_WHERE_SIZE, "\tBRLCAD_ROOT environment variable [%s]\n", lhs);
307  if (find_path(result, lhs, rhs, &searched, where)) {
308  if (UNLIKELY(bu_debug & BU_DEBUG_PATHS)) {
309  bu_log("Found: BRLCAD_ROOT environment variable [%s]\n", result);
310  }
311  bu_vls_free(&searched);
312  return result;
313  }
314  } else {
315  snprintf(where, MAX_WHERE_SIZE, "\tBRLCAD_ROOT environment variable\n");
316  bu_vls_strcat(&searched, where);
317  }
318 
319  /* BRLCAD_ROOT compile-time path */
320 #ifdef BRLCAD_ROOT
321  lhs = BRLCAD_ROOT;
322  if (lhs) {
323  snprintf(where, MAX_WHERE_SIZE, "\tBRLCAD_ROOT compile-time path [%s]\n", lhs);
324  if (find_path(result, lhs, rhs, &searched, where)) {
325  if (UNLIKELY(bu_debug & BU_DEBUG_PATHS)) {
326  bu_log("Found: BRLCAD_ROOT compile-time path [%s]\n", result);
327  }
328  bu_vls_free(&searched);
329  return result;
330  }
331  }
332 #else
333  snprintf(where, MAX_WHERE_SIZE, "\tBRLCAD_ROOT compile-time path [UNKNOWN]\n");
334  bu_vls_strcat(&searched, where);
335 #endif
336 
337  /* run-time path identification */
338  lhs = bu_argv0_full_path();
339  if (lhs) {
340  char *dirpath;
341  char *real_path = bu_realpath(lhs, NULL);
342  dirpath = bu_dirname(real_path);
343  snprintf(real_path, MAXPATHLEN, "%s", dirpath);
344  bu_free(dirpath, "free bu_dirname");
345  dirpath = bu_dirname(real_path);
346  snprintf(real_path, MAXPATHLEN, "%s", dirpath);
347  bu_free(dirpath, "free bu_dirname");
348  if (find_path(result, real_path, rhs, &searched, where)) {
349  if (UNLIKELY(bu_debug & BU_DEBUG_PATHS)) {
350  bu_log("Found: Run-time path identification [%s]\n", result);
351  }
352  bu_vls_free(&searched);
353  bu_free(real_path, "free real_path");
354  return result;
355  }
356  bu_free(real_path, "free real_path");
357  } else {
358  snprintf(where, MAX_WHERE_SIZE, "\trun-time path identification [UNKNOWN]\n");
359  bu_vls_strcat(&searched, where);
360  }
361 
362  /* /usr/brlcad static path */
363  {
364  const char *root = BRLCAD_ROOT;
365  /* only check /usr/brlcad if not already tested earlier via BRLCAD_ROOT */
366 
367  if (root[0] != '/' || root[1] != 'u' || root[ 2] != 's' || root[ 3] != 'r' ||
368  root[4] != '/' || root[5] != 'b' || root[ 6] != 'r' || root[ 7] != 'l' ||
369  root[8] != 'c' || root[9] != 'a' || root[10] != 'd' || root[11] != '\0') {
370 
371  if (find_path(result, "/usr/brlcad", rhs, &searched, "\t/usr/brlcad default path\n")) {
372  if (UNLIKELY(bu_debug & BU_DEBUG_PATHS)) {
373  bu_log("Found: /usr/brlcad default path [%s]\n", result);
374  }
375  bu_vls_free(&searched);
376  return result;
377  }
378  }
379  }
380 
381  /* current directory */
382  if (find_path(result, ".", rhs, &searched, "\tcurrent directory\n")) {
383  if (UNLIKELY(bu_debug & BU_DEBUG_PATHS)) {
384  bu_log("Found: current directory [%s]\n", result);
385  }
386  bu_vls_free(&searched);
387  return result;
388  }
389 
390  if (!fail_quietly) {
391  root_missing(bu_vls_addr(&searched));
392  if (rhs) {
393  bu_log("Unable to find '%s' within the BRL-CAD software installation.\nThis copy of BRL-CAD may not be properly installed.\n\n", rhs);
394  } else {
395  bu_log("Unable to find the BRL-CAD software installation.\nThis copy of BRL-CAD may not be properly installed.\n\n");
396  }
397  }
398 
399  bu_vls_free(&searched);
400  return NULL;
401 }
402 
403 
404 const char *
405 bu_brlcad_data(const char *rhs, int fail_quietly)
406 {
407  static char result[MAXPATHLEN] = {0};
408  const char *lhs;
409  struct bu_vls searched = BU_VLS_INIT_ZERO;
410  char where[MAX_WHERE_SIZE] = {0};
411 
413  bu_log("bu_brlcad_data: looking for [%s]\n", rhs?rhs:"");
414  }
415 
416  /* BRLCAD_DATA environment variable if set */
417  lhs = getenv("BRLCAD_DATA");
418  if (lhs) {
419  snprintf(where, MAX_WHERE_SIZE, "\tBRLCAD_DATA environment variable [%s]\n", lhs);
420  if (find_path(result, lhs, rhs, &searched, where)) {
421  if (UNLIKELY(bu_debug & BU_DEBUG_PATHS)) {
422  bu_log("Found: BRLCAD_DATA environment variable [%s]\n", result);
423  }
424  bu_vls_free(&searched);
425  return result;
426  }
427  } else {
428  snprintf(where, MAX_WHERE_SIZE, "\tBRLCAD_DATA environment variable\n");
429  bu_vls_strcat(&searched, where);
430  }
431 
432  /* BRLCAD_DATA compile-time path */
433  lhs = _brlcad_data();
434  snprintf(where, MAX_WHERE_SIZE, "\tBRLCAD_DATA compile-time path [%s]\n", lhs);
435  if (find_path(result, lhs, rhs, &searched, where)) {
436  if (UNLIKELY(bu_debug & BU_DEBUG_PATHS)) {
437  bu_log("Found: BRLCAD_DATA compile-time path [%s]\n", result);
438  }
439  bu_vls_free(&searched);
440  return result;
441  }
442 
443  /* bu_brlcad_root/BRLCAD_DATA_DIR path */
444 #ifdef BRLCAD_DATA_DIR
445  {
446  char path[MAXPATHLEN] = {0};
447  snprintf(path, MAXPATHLEN, "%s", BRLCAD_DATA_DIR);
448  lhs = bu_brlcad_root(path, 1);
449  if (lhs) {
450  snprintf(where, MAX_WHERE_SIZE, "\tBRLCAD_ROOT common data path [%s]\n", path);
451  if (find_path(result, lhs, rhs, &searched, where)) {
452  if (UNLIKELY(bu_debug & BU_DEBUG_PATHS)) {
453  bu_log("Found: BRLCAD_ROOT common data path [%s]\n", result);
454  }
455  bu_vls_free(&searched);
456  return result;
457  }
458  }
459  }
460 #endif
461 
462  /* bu_brlcad_root/share path */
463  lhs = bu_brlcad_root("share", 1);
464  if (lhs) {
465  snprintf(where, MAX_WHERE_SIZE, "\tBRLCAD_ROOT common data path [%s]\n", lhs);
466  if (find_path(result, lhs, rhs, &searched, where)) {
467  if (UNLIKELY(bu_debug & BU_DEBUG_PATHS)) {
468  bu_log("Found: BRLCAD_ROOT common data path [%s]\n", result);
469  }
470  bu_vls_free(&searched);
471  return result;
472  }
473  }
474 
475  /* bu_brlcad_root path */
476  lhs = bu_brlcad_root("", 1);
477  if (lhs) {
478  snprintf(where, MAX_WHERE_SIZE, "\tBRLCAD_ROOT common data path [%s]\n", lhs);
479  if (find_path(result, lhs, rhs, &searched, where)) {
480  if (UNLIKELY(bu_debug & BU_DEBUG_PATHS)) {
481  bu_log("Found: BRLCAD_ROOT common data path [%s]\n", result);
482  }
483  bu_vls_free(&searched);
484  return result;
485  }
486  }
487 
488  /* current directory (running from uninstalled source distribution) */
489  if (find_path(result, ".", rhs, &searched, "\tcurrent directory\n")) {
490  if (UNLIKELY(bu_debug & BU_DEBUG_PATHS)) {
491  bu_log("Found: current directory [%s]\n", result);
492  }
493  bu_vls_free(&searched);
494  return result;
495  }
496 
497  /* running from uninstalled source distribution, look for THIS file */
498 #define BPC "/src/libbu/" __FILE__
499  if (bu_file_exists("." BPC, NULL)) {
500  if (find_path(result, ".", rhs, NULL, NULL)) {
501  if (UNLIKELY(bu_debug & BU_DEBUG_PATHS)) {
502  bu_log("Found: source directory [%s]\n", result);
503  }
504  bu_vls_free(&searched);
505  return result;
506  } else if (find_path(result, "./src", rhs, NULL, NULL)) {
507  if (UNLIKELY(bu_debug & BU_DEBUG_PATHS)) {
508  bu_log("Found: source directory [%s]\n", result);
509  }
510  bu_vls_free(&searched);
511  return result;
512  }
513  }
514  if (bu_file_exists(".." BPC, NULL)) {
515  if (find_path(result, "..", rhs, NULL, NULL)) {
516  if (UNLIKELY(bu_debug & BU_DEBUG_PATHS)) {
517  bu_log("Found: source directory [%s]\n", result);
518  }
519  bu_vls_free(&searched);
520  return result;
521  } else if (find_path(result, "../src", rhs, NULL, NULL)) {
522  if (UNLIKELY(bu_debug & BU_DEBUG_PATHS)) {
523  bu_log("Found: source directory [%s]\n", result);
524  }
525  bu_vls_free(&searched);
526  return result;
527  }
528  }
529  if (bu_file_exists("../.." BPC, NULL)) {
530  if (find_path(result, "../..", rhs, NULL, NULL)) {
531  if (UNLIKELY(bu_debug & BU_DEBUG_PATHS)) {
532  bu_log("Found: source directory [%s]\n", result);
533  }
534  bu_vls_free(&searched);
535  return result;
536  } else if (find_path(result, "../../src", rhs, NULL, NULL)) {
537  if (UNLIKELY(bu_debug & BU_DEBUG_PATHS)) {
538  bu_log("Found: source directory [%s]\n", result);
539  }
540  bu_vls_free(&searched);
541  return result;
542  }
543  }
544  if (bu_file_exists("../../.." BPC, NULL)) {
545  if (find_path(result, "../../..", rhs, NULL, NULL)) {
546  if (UNLIKELY(bu_debug & BU_DEBUG_PATHS)) {
547  bu_log("Found: source directory [%s]\n", result);
548  }
549  bu_vls_free(&searched);
550  return result;
551  } else if (find_path(result, "../../../src", rhs, NULL, NULL)) {
552  if (UNLIKELY(bu_debug & BU_DEBUG_PATHS)) {
553  bu_log("Found: source directory [%s]\n", result);
554  }
555  bu_vls_free(&searched);
556  return result;
557  }
558  }
559  if (bu_file_exists("../../../.." BPC, NULL)) {
560  if (find_path(result, "../../../..", rhs, NULL, NULL)) {
561  if (UNLIKELY(bu_debug & BU_DEBUG_PATHS)) {
562  bu_log("Found: source directory [%s]\n", result);
563  }
564  bu_vls_free(&searched);
565  return result;
566  } else if (find_path(result, "../../../../src", rhs, NULL, NULL)) {
567  if (UNLIKELY(bu_debug & BU_DEBUG_PATHS)) {
568  bu_log("Found: source directory [%s]\n", result);
569  }
570  bu_vls_free(&searched);
571  return result;
572  }
573  }
574 
575  if (!fail_quietly) {
576  data_missing(bu_vls_addr(&searched));
577  if (rhs) {
578  bu_log("Unable to find '%s' within the BRL-CAD software installation.\nThis copy of BRL-CAD may not be properly installed.\n\n", rhs);
579  } else {
580  bu_log("Unable to find the BRL-CAD software installation.\nThis copy of BRL-CAD may not be properly installed.\n\n");
581  }
582  }
583 
584  bu_vls_free(&searched);
585  return NULL;
586 }
587 
588 
589 /*
590  * Local Variables:
591  * mode: C
592  * tab-width: 8
593  * indent-tabs-mode: t
594  * c-file-style: "stroustrup"
595  * End:
596  * ex: shiftwidth=4 tabstop=8
597  */
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
#define BRLCAD_ROOT
Definition: brlcad_path.c:45
void bu_vls_strcat(struct bu_vls *vp, const char *s)
Definition: vls.c:368
Header file for the BRL-CAD common definitions.
#define BU_DEBUG_PATHS
Definition: debug.h:68
#define HIDDEN
Definition: common.h:86
HIDDEN const char * _brlcad_data(void)
Definition: brlcad_path.c:54
const char * bu_brlcad_data(const char *rhs, int fail_quietly)
Definition: brlcad_path.c:405
HIDDEN void data_missing(const char *paths)
Definition: brlcad_path.c:110
void bu_vls_free(struct bu_vls *vp)
Definition: vls.c:248
void * memset(void *s, int c, size_t n)
#define BPC
HIDDEN void root_missing(const char *paths)
Definition: brlcad_path.c:82
#define bu_strlcpy(dst, src, size)
Definition: str.h:60
char * bu_vls_addr(const struct bu_vls *vp)
Definition: vls.c:111
HIDDEN int find_path(char result[MAXPATHLEN], const char *lhs, const char *rhs, struct bu_vls *searched, const char *where)
Definition: brlcad_path.c:141
#define BU_DIR_SEPARATOR
Definition: defines.h:97
const char * bu_brlcad_dir(const char *dirkey, int fail_quietly)
Definition: brlcad_path.c:231
int bu_debug
Definition: globals.c:87
#define MAX_WHERE_SIZE
Definition: brlcad_path.c:50
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
#define BU_VLS_INIT_ZERO
Definition: vls.h:84
const char * bu_brlcad_root(const char *rhs, int fail_quietly)
Definition: brlcad_path.c:292
char * bu_realpath(const char *path, char *resolved_path)
Definition: realpath.c:33
Definition: vls.h:56
int bu_file_exists(const char *path, int *fd)
Definition: file.c:57
const char * bu_argv0_full_path(void)
Definition: progname.c:48
char * bu_dirname(const char *path)
Definition: dirname.c:30
#define UNLIKELY(expression)
Definition: common.h:282
#define BU_STR_EQUAL(s1, s2)
Definition: str.h:126
#define MAXPATHLEN
Definition: defines.h:113