brlcad_path.c

Go to the documentation of this file.
00001 /*                   B R L C A D _ P A T H . C
00002  * BRL-CAD
00003  *
00004  * Copyright (c) 2004-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 brlcad_path.c
00025  * @brief
00026  *  A support routine to provide the executable code with the path
00027  *  to where the BRL-CAD programs and libraries are installed.
00028  *
00029  *  @author     Christopher Sean Morrison
00030  *  @author     Michael John Muuss
00031  *
00032  *  @par Source
00033  *      The U. S. Army Research Laboratory                      @n
00034  *      Aberdeen Proving Ground, Maryland  21005-5068  USA
00035  */
00036 static const char RCSbrlcad_path[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/libbu/brlcad_path.c,v 14.29 2006/08/31 23:16:38 lbutler Exp $ (BRL)";
00037 
00038 #include "common.h"
00039 
00040 #include <stdlib.h>
00041 #include <stdio.h>
00042 #ifdef HAVE_STRING_H
00043 #  include <string.h>
00044 #else
00045 #  include <strings.h>
00046 #endif
00047 #ifdef HAVE_SYS_PARAM_H
00048 #  include <sys/param.h>
00049 #endif
00050 
00051 #include "machine.h"
00052 #include "bu.h"
00053 
00054 
00055 /** 
00056  *      b u _ i p w d
00057  * @brief
00058  * set/return the path to the initial working directory.
00059  * bu_setprogname() must be called on app startup for the correct pwd to
00060  * be acquired/set.
00061  */
00062 static const char *
00063 bu_ipwd()
00064 {
00065     static const char *pwd = NULL;
00066 
00067     if (pwd) {
00068         return pwd;
00069     }
00070 
00071 #ifdef HAVE_GETENV
00072     pwd = getenv("PWD");
00073 #else
00074     pwd = (char *)NULL;
00075 #endif
00076 
00077     return pwd;
00078 }
00079 
00080 
00081 /** 
00082  *              b u _ a r g v 0
00083  *
00084  * set the location of argv[0], used by the brlcad-path-finding
00085  * routines when attempting to locate binaries, libraries, and
00086  * resources.  This routine may only be called once to set argv0.
00087  */
00088 static const char *
00089 bu_argv0(const char *path)
00090 {
00091     static const char *argv0 = NULL;
00092 
00093     /* set our initial pwd if we have not already */
00094     (void)bu_ipwd();
00095 
00096     if (path) {
00097         argv0 = path;
00098     }
00099 
00100     if (argv0) {
00101         return (argv0);
00102     }
00103 
00104     /* we were called without a bu_setprogname() so fallback to
00105      * getprogname() before returning NULL.
00106      */
00107 #ifdef HAVE_GETPROGNAME
00108     argv0 = getprogname();
00109 #endif
00110 
00111     return argv0;
00112 }
00113 
00114 
00115 /** b u _ g e t p r o g n a m e
00116  *
00117  * get the name of the running application if they ran
00118  * bu_setprogname() first or if we know what it's supposed to be
00119  * anyways.
00120  */
00121 const char *
00122 bu_getprogname(void) {
00123     return bu_argv0(NULL);
00124 }
00125 
00126 
00127 
00128 /** b u _ s e t p r o g n a m e
00129  *
00130  * Set the name of the running application.  This isn't necessary on
00131  * modern systems that support getprogname() and call setprogname()
00132  * before main() for you, but necessary otherwise for portability.
00133  */
00134 void
00135 bu_setprogname(const char *progname) {
00136 #ifdef HAVE_SETPROGNAME
00137     setprogname(progname);
00138 #endif
00139     (void)bu_argv0(progname);
00140     return;
00141 }
00142 
00143 
00144 /** b u _ r o o t _ m i s s i n g
00145  *
00146  *print out an error/warning message if we cannot find the specified
00147  * BRLCAD_ROOT (compile-time install path)
00148  */
00149 static void
00150 bu_root_missing(const char *paths)
00151 {
00152     bu_log("\
00153 Unable to locate where BRL-CAD %s is installed while searching:\n\
00154 %s\n\
00155 This version of BRL-CAD was compiled to be installed at:\n\
00156         %s\n\n", BRLCAD_VERSION, paths, BRLCAD_ROOT);
00157 
00158 #ifndef _WIN32
00159     bu_log("\
00160 You may specify where to locate BRL-CAD by setting the BRLCAD_ROOT\n\
00161 environment variable.  For example:\n\
00162 \n\
00163 for csh/tcsh users:\n\
00164         setenv BRLCAD_ROOT /path/to/brlcad\n\
00165 for sh/bash users:\n\
00166         BRLCAD_ROOT=/path/to/brlcad ; export BRLCAD_ROOT\n\n");
00167 #endif
00168 
00169     return;
00170 }
00171 
00172 
00173 /** b u _ d a t a _ m i s s i n g
00174  *
00175  * print out an error/warning message if we cannot find the specified
00176  * BRLCAD_DATA (compile-time install path)
00177  */
00178 static void
00179 bu_data_missing(const char *paths)
00180 {
00181     bu_log("\
00182 Unable to locate where BRL-CAD %s data resources are installed\n\
00183 while searching:\n\
00184 %s\n\
00185 This release of BRL-CAD expects data resources to be at:\n\
00186         %s\n\n", BRLCAD_VERSION, paths, BRLCAD_DATA);
00187 
00188 #ifndef _WIN32
00189     bu_log("\
00190 You may specify where to locate BRL-CAD data resources by setting\n\
00191 the BRLCAD_DATA environment variable.  For example:\n\
00192 \n\
00193 for csh/tcsh users:\n\
00194         setenv BRLCAD_DATA /path/to/brlcad/data\n\
00195 for sh/bash users:\n\
00196         BRLCAD_DATA=/path/to/brlcad/data ; export BRLCAD_DATA\n\n");
00197 #endif
00198 
00199     return;
00200 }
00201 
00202 
00203 /**
00204  * put a left-hand and right-hand path together and test whether they
00205  * exist or not.  
00206  *
00207  * @return boolean on whether a match was found.
00208  */
00209 static int
00210 bu_find_path(char result[MAXPATHLEN], const char *lhs, const char *rhs, struct bu_vls *searched, const char *where)
00211 {
00212     int llen,rlen;
00213     static const char *currdir=".";
00214 
00215     /* swap right with left if there is no left so logic is simplified
00216      * later on.
00217      */
00218     if (lhs == NULL && rhs != NULL) {
00219         lhs = rhs;
00220         rhs = NULL;
00221     }
00222 
00223     if (lhs == NULL) {
00224         if (searched && where) {
00225             bu_vls_strcat(searched, where);
00226         }
00227         return 0;
00228     }
00229 
00230     rlen = llen = 0;
00231     if (rhs) {
00232         rlen = strlen(rhs);
00233     }
00234 
00235     /* be safe */
00236     if (rlen + 2 > MAXPATHLEN) {
00237         bu_log("Warning: path is way too long (%d characters > %d)\n", rlen+2, MAXPATHLEN);
00238         if (searched && where) {
00239             bu_vls_strcat(searched, where);
00240         }
00241         return 0;
00242     }
00243 
00244     /* an empty left hand implies current directory (plus a slash is appended later) */
00245     if (lhs[0] == '\0') {
00246         lhs = currdir;
00247     }
00248 
00249     /* left-hand path should exist independent of right-hand path */
00250     if (!bu_file_exists(lhs)) {
00251         if (searched && where) {
00252             bu_vls_strcat(searched, where);
00253         }
00254         return 0;
00255     }
00256 
00257     /* start fresh */
00258     memset(result, 0, MAXPATHLEN);
00259     strncpy(result, lhs, MAXPATHLEN);
00260 
00261     /* nothing to add, so just return what we have */
00262     if (!rhs || (rlen == 0)) {
00263         return 1;
00264     }
00265 
00266     /* be safe again */
00267     llen = strlen(result);
00268     if (llen + rlen + 3 > MAXPATHLEN) {
00269         bu_log("Warning: path is way too long (%d characters > %d)\n", llen+rlen+3, MAXPATHLEN);
00270         if (searched && where) {
00271             bu_vls_strcat(searched, where);
00272         }
00273         return 0;
00274     }
00275 
00276     if ( (*(result+llen-1) != BU_DIR_SEPARATOR) && (rhs[0] != BU_DIR_SEPARATOR) ) {
00277         /* let the caller give "/usr/brlcad" and "bin" and get "/usr/brlcad/bin" */
00278         *(result+llen) = BU_DIR_SEPARATOR;
00279         llen++;
00280     } else if ( (*(result+llen-1) == BU_DIR_SEPARATOR) && (rhs[0] == BU_DIR_SEPARATOR) ) {
00281         /* let the caller give "/usr/brlcad/" and "/bin" and get "/usr/brlcad/bin"*/
00282         rhs++;
00283         rlen--;
00284     }
00285 
00286     /* found a match */
00287     strncpy(result+llen, rhs, MAXPATHLEN - llen);
00288     if (bu_file_exists(result)) {
00289         return 1;
00290     }
00291 
00292     /* close, but no match */
00293     if (searched && where) {
00294         bu_vls_strcat(searched, where);
00295     }
00296     return 0;
00297 }
00298 
00299 
00300 /**     B U _ B R L C A D _ R O O T
00301  *@brief
00302  * Locate where the BRL-CAD applications and libraries are installed.
00303  *
00304  * The BRL-CAD root is searched for in the following order of
00305  * precedence by testing for the rhs existence if provided or the
00306  * directory existence otherwise:
00307  *
00308  *   BRLCAD_ROOT environment variable if set
00309  *   BRLCAD_ROOT compile-time path
00310  *   run-time path identification
00311  *   /usr/brlcad static path
00312  *   current directory
00313  *
00314  * @return
00315  * A STATIC buffer is returned.
00316  * It is the caller's responsibility to call bu_strdup() or make
00317  * other provisions to save the returned string, before calling again.
00318  */
00319 char *
00320 bu_brlcad_root(const char *rhs, int fail_quietly)
00321 {
00322     static char result[MAXPATHLEN] = {0};
00323     const char *lhs;
00324     struct bu_vls searched;
00325     char where[MAXPATHLEN + 64] = {0};
00326 
00327     /* !!!   bu_debug=1; */
00328 
00329     bu_vls_init(&searched);
00330 
00331     if (bu_debug) {
00332         bu_log("bu_brlcad_root: searching for [%s]\n", rhs);
00333     }
00334 
00335     /* BRLCAD_ROOT environment variable if set */
00336     lhs = getenv("BRLCAD_ROOT");
00337     if (lhs) {
00338         snprintf(where, MAXPATHLEN + 64, "\tBRLCAD_ROOT environment variable [%s]\n", lhs);
00339         if (bu_find_path(result, lhs, rhs, &searched, where)) {
00340             if (bu_debug) {
00341                 bu_log("Found: BRLCAD_ROOT environment variable [%s]\n", result);
00342             }
00343             return result;
00344         }
00345     } else {
00346         snprintf(where, MAXPATHLEN + 64, "\tBRLCAD_ROOT environment variable\n");
00347         bu_vls_strcat(&searched, where);
00348     }
00349 
00350     /* BRLCAD_ROOT compile-time path */
00351     lhs = BRLCAD_ROOT;
00352     if (lhs) {
00353         snprintf(where, MAXPATHLEN + 64, "\tBRLCAD_ROOT compile-time path [%s]\n", lhs);
00354         if (bu_find_path(result, lhs, rhs, &searched, where)) {
00355             if (bu_debug) {
00356                 bu_log("Found: BRLCAD_ROOT compile-time path [%s]\n", result);
00357             }
00358             return result;
00359         }
00360     } else {
00361         snprintf(where, MAXPATHLEN + 64, "\tBRLCAD_ROOT compile-time path [UNKNOWN]\n");
00362         bu_vls_strcat(&searched, where);
00363     }
00364 
00365     /* run-time path identification */
00366     lhs = bu_getprogname();
00367     if (lhs) {
00368         char argv0[MAXPATHLEN + 64] = {0};
00369         int len = strlen(lhs);
00370         snprintf(argv0, MAXPATHLEN + 64, "%s", lhs);
00371 
00372         /* need to trim off the trailing binary */
00373         while (len-1 > 0) {
00374             if (argv0[len-1] == BU_DIR_SEPARATOR) {
00375                 argv0[len] = '.';
00376                 argv0[len+1] = '.';
00377                 argv0[len+2] = '\0';
00378                 break;
00379             }
00380             len--;
00381         }
00382 
00383         snprintf(where, MAXPATHLEN + 64, "\trun-time path identification [%s]\n", argv0);
00384         if (bu_find_path(result, argv0, rhs, &searched, where)) {
00385             if (bu_debug) {
00386                 bu_log("Found: Run-time path identification [%s]\n", result);
00387             }
00388             return result;
00389         }
00390     } else {
00391         snprintf(where, MAXPATHLEN + 64, "\trun-time path identification [UNKNOWN]\n");
00392         bu_vls_strcat(&searched, where);
00393     }
00394 
00395     /* /usr/brlcad static path */
00396     if (strncmp("/usr/brlcad", BRLCAD_ROOT, 12) != 0) {
00397         if (bu_find_path(result, "/usr/brlcad", rhs, &searched, "\t/usr/brlcad default path\n")) {
00398             if (bu_debug) {
00399                 bu_log("Found: /usr/brlcad default path [%s]\n", result);
00400             }
00401             return result;
00402         }
00403     }
00404 
00405     /* current directory */
00406     if (bu_find_path(result, ".", rhs, &searched, "\tcurrent directory\n")) {
00407         if (bu_debug) {
00408             bu_log("Found: current directory [%s]\n", result);
00409         }
00410         return result;
00411     }
00412 
00413     if (!fail_quietly) {
00414         bu_root_missing(bu_vls_addr(&searched));
00415         if (rhs) {
00416             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);
00417         } else {
00418             bu_log("Unable to find the BRL-CAD software installation.\nThis copy of BRL-CAD may not be properly installed.\n\n");
00419         }
00420     }
00421     return NULL;
00422 }
00423 
00424 
00425 /**
00426  *      B U _ B R L C A D _ D A T A
00427  *
00428  * @brief
00429  * Locate where the BRL-CAD data resources are installed.
00430  *
00431  * The BRL-CAD data resources are searched for in the following order
00432  * of precedence by testing for the existence of rhs if provided or
00433  * the directory existence otherwise:
00434  *
00435  *   BRLCAD_DATA environment variable if set
00436  *   BRLCAD_DATA compile-time path
00437  *   bu_brlcad_root/share/brlcad/VERSION path
00438  *   bu_brlcad_root path
00439  *   current directory
00440  *
00441  * A STATIC buffer is returned.
00442  * It is the caller's responsibility to call bu_strdup() or make
00443  * other provisions to save the returned string, before calling again.
00444  */
00445 char *
00446 bu_brlcad_data(const char *rhs, int fail_quietly)
00447 {
00448     static char result[MAXPATHLEN] = {0};
00449     const char *lhs;
00450     struct bu_vls searched;
00451     char where[MAXPATHLEN + 64] = {0};
00452     char path[64] = {0};
00453 
00454     /* !!!   bu_debug=1; */
00455 
00456     bu_vls_init(&searched);
00457 
00458     if (bu_debug) {
00459         bu_log("bu_brlcad_data: looking for [%s]\n", rhs);
00460     }
00461 
00462     /* BRLCAD_DATA environment variable if set */
00463     lhs = getenv("BRLCAD_DATA");
00464     if (lhs) {
00465         snprintf(where, MAXPATHLEN + 64, "\tBRLCAD_DATA environment variable [%s]\n", lhs);
00466         if (bu_find_path(result, lhs, rhs, &searched, where)) {
00467             if (bu_debug) {
00468                 bu_log("Found: BRLCAD_DATA environment variable [%s]\n", result);
00469             }
00470             return result;
00471         }
00472     } else {
00473         snprintf(where, MAXPATHLEN + 64, "\tBRLCAD_DATA environment variable\n");
00474         bu_vls_strcat(&searched, where);
00475     }
00476 
00477     /* BRLCAD_DATA compile-time path */
00478     lhs = BRLCAD_DATA;
00479     if (lhs) {
00480         snprintf(where, MAXPATHLEN + 64, "\tBRLCAD_DATA compile-time path [%s]\n", lhs);
00481         if (bu_find_path(result, lhs, rhs, &searched, where)) {
00482             if (bu_debug) {
00483                 bu_log("Found: BRLCAD_DATA compile-time path [%s]\n", result);
00484             }
00485             return result;
00486         }
00487     } else {
00488         snprintf(where, MAXPATHLEN + 64, "\tBRLCAD_DATA compile-time path [UNKNOWN]\n");
00489         bu_vls_strcat(&searched, where);
00490     }
00491 
00492     /* bu_brlcad_root/share/brlcad/VERSION path */
00493     snprintf(path, MAXPATHLEN, "share/brlcad/%s", BRLCAD_VERSION);
00494     lhs = bu_brlcad_root(path, 1);
00495     if (lhs) {
00496         snprintf(where, MAXPATHLEN + 64, "\tBRLCAD_ROOT common data path  [%s]\n", path);
00497         if (bu_find_path(result, lhs, rhs, &searched, where)) {
00498             if (bu_debug) {
00499                 bu_log("Found: BRLCAD_ROOT common data path [%s]\n", result);
00500             }
00501             return result;
00502         }
00503     }
00504 
00505     /* bu_brlcad_root/share/brlcad path */
00506     lhs = bu_brlcad_root("share/brlcad", 1);
00507     if (lhs) {  
00508         snprintf(where, MAXPATHLEN + 64, "\tBRLCAD_ROOT common data path  [%s]\n", lhs);
00509         if (bu_find_path(result, lhs, rhs, &searched, where)) {
00510             if (bu_debug) {
00511                 bu_log("Found: BRLCAD_ROOT common data path [%s]\n", result);
00512             }
00513             return result;
00514         }
00515     }
00516 
00517     /* bu_brlcad_root/share path */
00518     lhs = bu_brlcad_root("share", 1);
00519     if (lhs) {  
00520         snprintf(where, MAXPATHLEN + 64, "\tBRLCAD_ROOT common data path  [%s]\n", lhs);
00521         if (bu_find_path(result, lhs, rhs, &searched, where)) {
00522             if (bu_debug) {
00523                 bu_log("Found: BRLCAD_ROOT common data path [%s]\n", result);
00524             }
00525             return result;
00526         }
00527     }
00528 
00529     /* bu_brlcad_root path */
00530     lhs = bu_brlcad_root("", 1);
00531     if (lhs) {  
00532         snprintf(where, MAXPATHLEN + 64, "\tBRLCAD_ROOT common data path  [%s]\n", lhs);
00533         if (bu_find_path(result, lhs, rhs, &searched, where)) {
00534             if (bu_debug) {
00535                 bu_log("Found: BRLCAD_ROOT common data path [%s]\n", result);
00536             }
00537             return result;
00538         }
00539     }
00540 
00541     /* current directory (running from uninstalled source distribution) */
00542     if (bu_find_path(result, ".", rhs, &searched, "\tcurrent directory\n")) {
00543         if (bu_debug) {
00544             bu_log("Found: current directory [%s]\n", result);
00545         }
00546         return result;
00547     }
00548 
00549     if (!fail_quietly) {
00550         bu_data_missing(bu_vls_addr(&searched));
00551         if (rhs) {
00552             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);
00553         } else {
00554             bu_log("Unable to find the BRL-CAD software installation.\nThis copy of BRL-CAD may not be properly installed.\n\n");
00555         }
00556     }
00557     return NULL;
00558 }
00559 
00560 /**
00561  *      B U _ B R L C A D _ P A T H
00562  *
00563  *  @deprecated
00564  *  Do not use.  Locate where the BRL-CAD programs and
00565  *  libraries are located, contatenate on the rest of the string
00566  *  provided by the caller, and return a pointer to a STATIC buffer
00567  *  with the full path.  It is the caller's responsibility to call
00568  *  bu_strdup() or make other provisions to save the returned string,
00569  *  before calling again.  bu_bomb() if unable to find the base path.
00570  *
00571  */
00572 char *
00573 bu_brlcad_path(const char *rhs, int fail_quietly)
00574 {
00575         bu_log("\
00576 WARNING: bu_brlcad_path is deprecated and will likely disappear in\n\
00577 a future release of BRL-CAD.  Programs and scripts should utilize\n\
00578 bu_brlcad_root and bu_brlcad_data instead.\n\
00579 \n\
00580 Use bu_brlcad_root for the path of applications and libraries.\n\
00581 Use bu_brlcad_data for the path to the data resources.\n\n");
00582 
00583         return bu_brlcad_root(rhs, fail_quietly);
00584 }
00585 /*@}*/
00586 /*
00587  * Local Variables:
00588  * mode: C
00589  * tab-width: 8
00590  * c-basic-offset: 4
00591  * indent-tabs-mode: t
00592  * End:
00593  * ex: shiftwidth=4 tabstop=8
00594  */

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