Introduction
Introduction Statistics Contact Development Disclaimer Help
dwbinit.c - 9base - revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log
Files
Refs
README
LICENSE
---
dwbinit.c (9219B)
---
1 /*
2 *
3 * Pathname management routines for DWB C programs.
4 *
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.
13 *
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
19 *
20 * #
21 * # A sample DWBCONFIG shell script
22 * #
23 *
24 * DWBHOME=/usr/add-on/dwb3.4
25 * export DWBHOME
26 *
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).
32 *
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.
38 *
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
46 * example,
47 *
48 * char *fontdir = "lib/font";
49 * char xyzzy[25] = "etc/xyzzy";
50 *
51 * would be represented in a dwbinit array as,
52 *
53 * dwbinit allpaths[] = {
54 * &fontdir, NULL, 0,
55 * NULL, xyzzy, sizeof(xyzzy),
56 * NULL, NULL, 0
57 * };
58 *
59 * The last element must have NULL entries for the address and
60 * value fields. The main() routine would then do,
61 *
62 * #include "dwbinit.h"
63 *
64 * main() {
65 *
66 * DWBinit("program name", allpaths);
67 * ...
68 * }
69 *
70 * Debugging is enabled if DWBDEBUG is in the environment and has
71 * the value ON. Output is occasionally useful and probably should
72 * be documented.
73 *
74 */
75
76 #include <u.h>
77 #include <stdio.h>
78 #include <ctype.h>
79 #include <string.h>
80 #include <stdlib.h>
81
82 #include "dwbinit.h"
83
84 #ifndef DWBCONFIG
85 #define DWBCONFIG "/dev/null"
86 #endif
87
88 #ifndef DWBENV
89 #define DWBENV "DWBHOME"
90 #endif
91
92 #ifndef DWBHOME
93 #define DWBHOME ""
94 #endif
95
96 #ifndef DWBDEBUG
97 #define DWBDEBUG "DWBDEBUG"
98 #endif
99
100 #ifndef DWBPREFIX
101 #define DWBPREFIX "\\*(.P"
102 #endif
103
104 /***********************************************************************…
105
106 void DWBdebug(dwbinit *ptr, int level)
107 {
108
109 char *path;
110 char *home;
111 static char *debug = NULL;
112
113 /*
114 *
115 * Debugging output, but only if DWBDEBUG is defined to be ON in the
116 * environment. Dumps general info the first time through.
117 *
118 */
119
120 if ( debug == NULL && (debug = getenv(DWBDEBUG)) == NULL )
121 debug = "OFF";
122
123 if ( strcmp(debug, "ON") == 0 ) {
124 if ( level == 0 ) {
125 fprintf(stderr, "Environment variable: %s\n", DWBENV);
126 fprintf(stderr, "Configuration file: %s\n", DWBCONFIG);
127 fprintf(stderr, "Default home: %s\n", DWBHOME);
128 if ( (home = DWBhome()) != NULL )
129 fprintf(stderr, "Current home: %s\n", home);
130 } /* End if */
131
132 fprintf(stderr, "\n%s pathnames:\n", level == 0 ? "Original" : "…
133 for ( ; ptr->value != NULL || ptr->address != NULL; ptr++ ) {
134 if ( (path = ptr->value) == NULL ) {
135 path = *ptr->address;
136 fprintf(stderr, " pointer: %s\n", path);
137 } else fprintf(stderr, " array[%d]: %s\n", ptr->length, path…
138 if ( level == 0 && *path == '/' )
139 fprintf(stderr, " WARNING - absolute path\n");
140 } /* End for */
141 } /* End if */
142
143 } /* End of DWBdebug */
144
145 /***********************************************************************…
146
147 extern char *unsharp(char*);
148
149 char *DWBhome(void)
150 {
151
152 FILE *fp;
153 char *ptr;
154 char *path;
155 int len;
156 char buf[200];
157 char *home = NULL;
158
159 /*
160 *
161 * Return the DWB home directory. Uses the last definition of DWBENV
162 * (usually "DWBHOME") in file DWBCONFIG (perhaps /usr/lib/dwb3.4) or
163 * the value assigned to the variable named by the DWBENV string in
164 * the environment if DWBCONFIG doesn't exist or doesn't define DWBENV.
165 * Skips the file lookup if DWBCONFIG can't be read. Returns NULL if
166 * there's no home directory.
167 *
168 */
169
170 if ( (fp = fopen(DWBCONFIG, "r")) != NULL ) {
171 len = strlen(DWBENV);
172 while ( fgets(buf, sizeof(buf), fp) != NULL ) {
173 for ( ptr = buf; isspace((uchar)*ptr); ptr++ ) ;
174 if ( strncmp(ptr, DWBENV, len) == 0 && *(ptr+len) == '=' ) {
175 path = ptr + len + 1;
176 for ( ptr = path; !isspace((uchar)*ptr) && *ptr != ';'; …
177 *ptr = '\0';
178 if ( home != NULL )
179 free(home);
180 if ( (home = malloc(strlen(path)+1)) != NULL )
181 strcpy(home, path);
182 } /* End if */
183 } /* End while */
184 fclose(fp);
185 } /* End if */
186
187 if ( home == NULL ) {
188 if ( (home = getenv(DWBENV)) == NULL ) {
189 if ( (home = DWBHOME) == NULL || *home == '\0' || *home == '…
190 home = NULL;
191 } /* End if */
192 if ( home != NULL )
193 home = unsharp(home);
194 } /* End if */
195
196 while (home && *home == '/' && *(home +1) == '/') /* remove e…
197 home++;
198 return(home);
199
200 } /* End of DWBhome */
201
202 /***********************************************************************…
203
204 void DWBinit(char *prog, dwbinit *paths)
205 {
206
207 char *prefix;
208 char *value;
209 char *path;
210 int plen;
211 int length;
212 dwbinit *opaths = paths;
213
214 /*
215 *
216 * Adjust the pathnames listed in paths, using the home directory
217 * returned by DWBhome(). Stops when it reaches an element that has
218 * NULL address and value fields. Assumes pathnames are relative,
219 * but changes everything. DWBdebug issues a warning if an original
220 * path begins with a /.
221 *
222 * A non-NULL address refers to a pointer, which is reallocated and
223 * then reinitialized. A NULL address implies a non-NULL value field
224 * and describes a character array that we only reinitialize. The
225 * length field for an array is the size of that array. The length
226 * field of a pointer is an increment that's added to the length
227 * required to store the new pathname string - should help when we
228 * want to change character arrays to pointers in applications like
229 * troff.
230 *
231 */
232
233 if ( (prefix = DWBhome()) == NULL ) {
234 fprintf(stderr, "%s: no DWB home directory\n", prog);
235 exit(1);
236 } /* End if */
237
238 DWBdebug(opaths, 0);
239 plen = strlen(prefix);
240
241 for ( ; paths->value != NULL || paths->address != NULL; paths++ ) {
242 if ( paths->address == NULL ) {
243 length = 0;
244 value = paths->value;
245 } else {
246 length = paths->length;
247 value = *paths->address;
248 } /* End else */
249
250 length += plen + 1 + strlen(value); /* +1 is for the '/' …
251
252 if ( (path = malloc(length+1)) == NULL ) {
253 fprintf(stderr, "%s: can't allocate pathname memory\n", prog…
254 exit(1);
255 } /* End if */
256
257 if ( *value != '\0' ) {
258 char *eop = prefix;
259 while(*eop++)
260 ;
261 eop -= 2;
262 if (*value != '/' && *eop != '/') {
263 sprintf(path, "%s/%s", prefix, value);
264 } else if (*value == '/' && *eop == '/') {
265 value++;
266 sprintf(path, "%s%s", prefix, value);
267 } else
268 sprintf(path, "%s%s", prefix, value);
269 } else
270 sprintf(path, "%s", prefix);
271
272 if ( paths->address == NULL ) {
273 if ( strlen(path) >= paths->length ) {
274 fprintf(stderr, "%s: no room for %s\n", prog, path);
275 exit(1);
276 } /* End if */
277 strcpy(paths->value, path);
278 free(path);
279 } else *paths->address = path;
280 } /* End for */
281
282 DWBdebug(opaths, 1);
283
284 } /* End of DWBinit */
285
286 /***********************************************************************…
287
288 void DWBprefix( char *prog, char *path, int length)
289 {
290
291 char *home;
292 char buf[512];
293 int len = strlen(DWBPREFIX);
294
295 /*
296 *
297 * Replace a leading DWBPREFIX string in path by the current DWBhome().
298 * Used by programs that pretend to handle .so requests. Assumes path
299 * is an array with room for length characters. The implementation is
300 * not great, but should be good enough for now. Also probably should
301 * have DWBhome() only do the lookup once, and remember the value if
302 * called again.
303 *
304 */
305
306 if ( strncmp(path, DWBPREFIX, len) == 0 ) {
307 if ( (home = DWBhome()) != NULL ) {
308 if ( strlen(home) + strlen(path+len) < length ) {
309 sprintf(buf, "%s%s", home, path+len);
310 strcpy(path, buf); /* assuming there's ro…
311 } else fprintf(stderr, "%s: no room to grow path %s", prog, …
312 } /* End if */
313 } /* End if */
314
315 } /* End of DWBprefix */
316
317 /***********************************************************************…
318
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.