BRL-CAD
progname.c
Go to the documentation of this file.
1 /* P R O G N A M E . 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 #ifndef _GNU_SOURCE
22 # define _GNU_SOURCE /* must come before common.h */
23 #endif
24 
25 #include "common.h"
26 
27 #ifdef HAVE_SYS_PARAM_H /* for MAXPATHLEN */
28 # include <sys/param.h>
29 #endif
30 
31 #include <stdlib.h>
32 #include <string.h>
33 #include <errno.h>
34 #include "bio.h"
35 
36 #include "bu/file.h"
37 #include "bu/log.h"
38 #include "bu/malloc.h"
39 #include "bu/parallel.h"
40 #include "bu/str.h"
41 
42 /* internal storage for bu_getprogname/bu_setprogname */
43 static char bu_progname[MAXPATHLEN] = {0};
44 const char *DEFAULT_PROGNAME = "(BRL-CAD)";
45 
46 
47 const char *
49 {
50  static char buffer[MAXPATHLEN] = {0};
51 
52  const char *argv0 = bu_progname;
53  const char *which;
54 
55 #ifdef HAVE_PROGRAM_INVOCATION_NAME
56  /* GLIBC provides a way */
57  if (argv0[0] == '\0' && program_invocation_name)
58  argv0 = program_invocation_name;
59 #endif
60 
61  if (argv0[0] == BU_DIR_SEPARATOR) {
62  /* seems to already be a full path */
63  snprintf(buffer, MAXPATHLEN, "%s", argv0);
64  return buffer;
65  }
66 
67  /* running from PATH */
68  which = bu_which(argv0);
69  if (which && which[0] != '\0') {
70  argv0 = which;
71  }
72 
73  while (argv0[0] == '.' && argv0[1] == BU_DIR_SEPARATOR) {
74  /* remove ./ if present, relative paths are appended to pwd */
75  argv0 += 2;
76  }
77 
78  /* running from relative dir */
79 
80  /* FIXME: this is technically wrong. if the current working
81  * directory is changed, we'll get the wrong path for argv0.
82  */
83  bu_getcwd(buffer, MAXPATHLEN);
84  snprintf(buffer+strlen(buffer), MAXPATHLEN-strlen(buffer), "%c%s", BU_DIR_SEPARATOR, argv0);
85  if (bu_file_exists(buffer, NULL)) {
86  return buffer;
87  }
88 
89  /* give up */
90  snprintf(buffer, MAXPATHLEN, "%s", argv0);
91  return buffer;
92 }
93 
94 
95 const char *
97 {
98  /* this static buffer is needed so we don't have to write into
99  * bu_progname[], which potentially holds a full path. we have to
100  * free the bu_basename() memory, so we need to copy the string
101  * somewhere before returning.
102  */
103  static char buffer[MAXPATHLEN] = {0};
104  const char *name = bu_progname;
105  char *tmp_basename = NULL;
106 
107 #ifdef HAVE_PROGRAM_INVOCATION_NAME
108  /* GLIBC provides a way */
109  if (name[0] == '\0' && program_invocation_name)
110  name = program_invocation_name;
111 #endif
112 
113 #ifdef HAVE_GETPROGNAME
114  /* BSD's libc provides a way */
115  if (name[0] == '\0') {
116  name = getprogname(); /* not malloc'd memory, may return NULL */
117  if (!name)
118  name = bu_progname;
119  }
120 #endif
121 
122  /* want just the basename from paths, otherwise default result */
123  tmp_basename = (char *)bu_calloc(strlen(name), sizeof(char), "bu_getprogname tmp_basename");
124  bu_basename(tmp_basename, name);
125  if (BU_STR_EQUAL(tmp_basename, ".") || BU_STR_EQUAL(tmp_basename, "/")) {
126  name = DEFAULT_PROGNAME;
127  } else {
128  name = tmp_basename;
129  }
130 
131  /* stash for return since we need to free the basename */
133  bu_strlcpy(buffer, name, MAXPATHLEN);
135 
136  bu_free(tmp_basename, "tmp_basename free");
137 
138  return buffer;
139 }
140 
141 
142 void
143 bu_setprogname(const char *argv0)
144 {
146  if (argv0) {
147  bu_strlcpy(bu_progname, argv0, MAXPATHLEN);
148  } else {
149  bu_progname[0] = '\0'; /* zap */
150  }
152 
153  return;
154 }
155 
156 
157 /* DEPRECATED: Do not use. */
158 const char *
159 bu_argv0(void)
160 {
161  return bu_getprogname();
162 }
163 
164 
165 /*
166  * Local Variables:
167  * mode: C
168  * tab-width: 8
169  * indent-tabs-mode: t
170  * c-file-style: "stroustrup"
171  * End:
172  * ex: shiftwidth=4 tabstop=8
173  */
Definition: clone.c:90
void bu_semaphore_acquire(unsigned int i)
Definition: semaphore.c:180
Header file for the BRL-CAD common definitions.
void * bu_calloc(size_t nelem, size_t elsize, const char *str)
Definition: malloc.c:321
#define bu_strlcpy(dst, src, size)
Definition: str.h:60
const char * bu_which(const char *cmd)
Definition: which.c:43
const char * bu_getprogname(void)
Definition: progname.c:96
const char * bu_argv0(void)
Definition: progname.c:159
void bu_semaphore_release(unsigned int i)
Definition: semaphore.c:218
#define BU_DIR_SEPARATOR
Definition: defines.h:97
void bu_basename(char *basename, const char *path)
Definition: basename.c:30
char * bu_getcwd(char *buf, size_t size)
Definition: getcwd.c:45
#define BU_SEM_SYSCALL
Definition: parallel.h:178
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
int bu_file_exists(const char *path, int *fd)
Definition: file.c:57
const char * bu_argv0_full_path(void)
Definition: progname.c:48
const char * DEFAULT_PROGNAME
Definition: progname.c:44
void bu_setprogname(const char *argv0)
Definition: progname.c:143
#define BU_STR_EQUAL(s1, s2)
Definition: str.h:126
#define MAXPATHLEN
Definition: defines.h:113