3 * Pathname management routines for DWB C programs.
5 * Applications should initialize a dwbinit array with the string
6 * pointers and arrays that need to be updated, and then hand that
7 * array to DWBinit before much else happens in their main program.
8 * DWBinit calls DWBhome to get the current home directory. DWBhome
9 * uses the last definition of DWBENV (usually "DWBHOME") in file
10 * DWBCONFIG (e.g., /usr/lib/dwb3.4) or the value assigned to that
11 * variable in the environment if the DWBCONFIG file doesn't exist,
12 * can't be read, or doesn't define DWBENV.
14 * DWBCONFIG must be a simple shell script - comments, a definition
15 * of DWBHOME, and perhaps an export or echo is about all that's
16 * allowed. The parsing in DWBhome is simple and makes no attempt
17 * to duplicate the shell. It only looks for DWBHOME= as the first
18 * non-white space string on a line, so
21 * # A sample DWBCONFIG shell script
24 * DWBHOME=/usr/add-on/dwb3.4
27 * means DWBhome would return "/usr/add-on/dwb3.4" for the DWB home
28 * directory. A DWBCONFIG file means there can only be one working
29 * copy of a DWB release on a system, which seems like a good idea.
30 * Using DWBCONFIG also means programs will always include correct
31 * versions of files (e.g., prologues or macro packages).
33 * Relying on an environment variable guarantees nothing. You could
34 * execute a version of dpost, but your environment might point at
35 * incorrect font tables or prologues. Despite the obvious problems
36 * we've also implemented an environment variable approach, but it's
37 * only used if there's no DWBCONFIG file.
39 * DWBinit calls DWBhome to get the DWB home directory prefix and
40 * then marches through its dwbinit argument, removing the default
41 * home directory and prepending the new home. DWBinit stops when
42 * it reaches an element that has NULL for its address and value
43 * fields. Pointers in a dwbinit array are reallocated and properly
44 * initialized; arrays are simply reinitialized if there's room.
45 * All pathnames that are to be adjusted should be relative. For
48 * char *fontdir = "lib/font";
49 * char xyzzy[25] = "etc/xyzzy";
51 * would be represented in a dwbinit array as,
53 * dwbinit allpaths[] = {
55 * NULL, xyzzy, sizeof(xyzzy),
59 * The last element must have NULL entries for the address and
60 * value fields. The main() routine would then do,
62 * #include "dwbinit.h"
66 * DWBinit("program name", allpaths);
70 * Debugging is enabled if DWBDEBUG is in the environment and has
71 * the value ON. Output is occasionally useful and probably should
84 #define DWBCONFIG "/dev/null"
88 #define DWBENV "DWBHOME"
96 #define DWBDEBUG "DWBDEBUG"
100 #define DWBPREFIX "\\*(.P"
103 /*****************************************************************************/
105 void DWBdebug(dwbinit
*ptr
, int level
)
110 static char *debug
= NULL
;
114 * Debugging output, but only if DWBDEBUG is defined to be ON in the
115 * environment. Dumps general info the first time through.
119 if ( debug
== NULL
&& (debug
= getenv(DWBDEBUG
)) == NULL
)
122 if ( strcmp(debug
, "ON") == 0 ) {
124 fprintf(stderr
, "Environment variable: %s\n", DWBENV
);
125 fprintf(stderr
, "Configuration file: %s\n", DWBCONFIG
);
126 fprintf(stderr
, "Default home: %s\n", DWBHOME
);
127 if ( (home
= DWBhome()) != NULL
)
128 fprintf(stderr
, "Current home: %s\n", home
);
131 fprintf(stderr
, "\n%s pathnames:\n", level
== 0 ? "Original" : "Final");
132 for ( ; ptr
->value
!= NULL
|| ptr
->address
!= NULL
; ptr
++ ) {
133 if ( (path
= ptr
->value
) == NULL
) {
134 path
= *ptr
->address
;
135 fprintf(stderr
, " pointer: %s\n", path
);
136 } else fprintf(stderr
, " array[%d]: %s\n", ptr
->length
, path
);
137 if ( level
== 0 && *path
== '/' )
138 fprintf(stderr
, " WARNING - absolute path\n");
142 } /* End of DWBdebug */
144 /*****************************************************************************/
158 * Return the DWB home directory. Uses the last definition of DWBENV
159 * (usually "DWBHOME") in file DWBCONFIG (perhaps /usr/lib/dwb3.4) or
160 * the value assigned to the variable named by the DWBENV string in
161 * the environment if DWBCONFIG doesn't exist or doesn't define DWBENV.
162 * Skips the file lookup if DWBCONFIG can't be read. Returns NULL if
163 * there's no home directory.
167 if ( (fp
= fopen(DWBCONFIG
, "r")) != NULL
) {
168 len
= strlen(DWBENV
);
169 while ( fgets(buf
, sizeof(buf
), fp
) != NULL
) {
170 for ( ptr
= buf
; isspace(*ptr
); ptr
++ ) ;
171 if ( strncmp(ptr
, DWBENV
, len
) == 0 && *(ptr
+len
) == '=' ) {
172 path
= ptr
+ len
+ 1;
173 for ( ptr
= path
; !isspace(*ptr
) && *ptr
!= ';'; ptr
++ ) ;
177 if ( (home
= malloc(strlen(path
)+1)) != NULL
)
184 if ( home
== NULL
) {
185 if ( (home
= getenv(DWBENV
)) == NULL
) {
186 if ( (home
= DWBHOME
) == NULL
|| *home
== '\0' || *home
== ' ' )
191 while (home
&& *home
== '/' && *(home
+1) == '/') /* remove extra slashes */
195 } /* End of DWBhome */
197 /*****************************************************************************/
199 void DWBinit(char *prog
, dwbinit
*paths
)
207 dwbinit
*opaths
= paths
;
211 * Adjust the pathnames listed in paths, using the home directory
212 * returned by DWBhome(). Stops when it reaches an element that has
213 * NULL address and value fields. Assumes pathnames are relative,
214 * but changes everything. DWBdebug issues a warning if an original
215 * path begins with a /.
217 * A non-NULL address refers to a pointer, which is reallocated and
218 * then reinitialized. A NULL address implies a non-NULL value field
219 * and describes a character array that we only reinitialize. The
220 * length field for an array is the size of that array. The length
221 * field of a pointer is an increment that's added to the length
222 * required to store the new pathname string - should help when we
223 * want to change character arrays to pointers in applications like
228 if ( (prefix
= DWBhome()) == NULL
) {
229 fprintf(stderr
, "%s: no DWB home directory\n", prog
);
234 plen
= strlen(prefix
);
236 for ( ; paths
->value
!= NULL
|| paths
->address
!= NULL
; paths
++ ) {
237 if ( paths
->address
== NULL
) {
239 value
= paths
->value
;
241 length
= paths
->length
;
242 value
= *paths
->address
;
245 length
+= plen
+ 1 + strlen(value
); /* +1 is for the '/' */
247 if ( (path
= malloc(length
+1)) == NULL
) {
248 fprintf(stderr
, "%s: can't allocate pathname memory\n", prog
);
252 if ( *value
!= '\0' ) {
257 if (*value
!= '/' && *eop
!= '/') {
258 sprintf(path
, "%s/%s", prefix
, value
);
259 } else if (*value
== '/' && *eop
== '/') {
261 sprintf(path
, "%s%s", prefix
, value
);
263 sprintf(path
, "%s%s", prefix
, value
);
265 sprintf(path
, "%s", prefix
);
267 if ( paths
->address
== NULL
) {
268 if ( strlen(path
) >= paths
->length
) {
269 fprintf(stderr
, "%s: no room for %s\n", prog
, path
);
272 strcpy(paths
->value
, path
);
274 } else *paths
->address
= path
;
279 } /* End of DWBinit */
281 /*****************************************************************************/
283 void DWBprefix( char *prog
, char *path
, int length
)
288 int len
= strlen(DWBPREFIX
);
292 * Replace a leading DWBPREFIX string in path by the current DWBhome().
293 * Used by programs that pretend to handle .so requests. Assumes path
294 * is an array with room for length characters. The implementation is
295 * not great, but should be good enough for now. Also probably should
296 * have DWBhome() only do the lookup once, and remember the value if
301 if ( strncmp(path
, DWBPREFIX
, len
) == 0 ) {
302 if ( (home
= DWBhome()) != NULL
) {
303 if ( strlen(home
) + strlen(path
+len
) < length
) {
304 sprintf(buf
, "%s%s", home
, path
+len
);
305 strcpy(path
, buf
); /* assuming there's room in path */
306 } else fprintf(stderr
, "%s: no room to grow path %s", prog
, path
);
310 } /* End of DWBprefix */
312 /*****************************************************************************/