dwbinit.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  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. #include <stdio.h>
  76. #include <ctype.h>
  77. #include <string.h>
  78. #include <stdlib.h>
  79. #include "dwbinit.h"
  80. #ifndef DWBCONFIG
  81. #define DWBCONFIG "/dev/null"
  82. #endif
  83. #ifndef DWBENV
  84. #define DWBENV "DWBHOME"
  85. #endif
  86. #ifndef DWBHOME
  87. #define DWBHOME ""
  88. #endif
  89. #ifndef DWBDEBUG
  90. #define DWBDEBUG "DWBDEBUG"
  91. #endif
  92. #ifndef DWBPREFIX
  93. #define DWBPREFIX "\\*(.P"
  94. #endif
  95. /*****************************************************************************/
  96. void DWBdebug(dwbinit *ptr, int level)
  97. {
  98. char *path;
  99. char *home;
  100. static char *debug = NULL;
  101. /*
  102. *
  103. * Debugging output, but only if DWBDEBUG is defined to be ON in the
  104. * environment. Dumps general info the first time through.
  105. *
  106. */
  107. if ( debug == NULL && (debug = getenv(DWBDEBUG)) == NULL )
  108. debug = "OFF";
  109. if ( strcmp(debug, "ON") == 0 ) {
  110. if ( level == 0 ) {
  111. fprintf(stderr, "Environment variable: %s\n", DWBENV);
  112. fprintf(stderr, "Configuration file: %s\n", DWBCONFIG);
  113. fprintf(stderr, "Default home: %s\n", DWBHOME);
  114. if ( (home = DWBhome()) != NULL )
  115. fprintf(stderr, "Current home: %s\n", home);
  116. } /* End if */
  117. fprintf(stderr, "\n%s pathnames:\n", level == 0 ? "Original" : "Final");
  118. for ( ; ptr->value != NULL || ptr->address != NULL; ptr++ ) {
  119. if ( (path = ptr->value) == NULL ) {
  120. path = *ptr->address;
  121. fprintf(stderr, " pointer: %s\n", path);
  122. } else fprintf(stderr, " array[%d]: %s\n", ptr->length, path);
  123. if ( level == 0 && *path == '/' )
  124. fprintf(stderr, " WARNING - absolute path\n");
  125. } /* End for */
  126. } /* End if */
  127. } /* End of DWBdebug */
  128. /*****************************************************************************/
  129. char *DWBhome(void)
  130. {
  131. FILE *fp;
  132. char *ptr;
  133. char *path;
  134. int len;
  135. char buf[200];
  136. char *home = NULL;
  137. /*
  138. *
  139. * Return the DWB home directory. Uses the last definition of DWBENV
  140. * (usually "DWBHOME") in file DWBCONFIG (perhaps /usr/lib/dwb3.4) or
  141. * the value assigned to the variable named by the DWBENV string in
  142. * the environment if DWBCONFIG doesn't exist or doesn't define DWBENV.
  143. * Skips the file lookup if DWBCONFIG can't be read. Returns NULL if
  144. * there's no home directory.
  145. *
  146. */
  147. if ( (fp = fopen(DWBCONFIG, "r")) != NULL ) {
  148. len = strlen(DWBENV);
  149. while ( fgets(buf, sizeof(buf), fp) != NULL ) {
  150. for ( ptr = buf; isspace(*ptr); ptr++ ) ;
  151. if ( strncmp(ptr, DWBENV, len) == 0 && *(ptr+len) == '=' ) {
  152. path = ptr + len + 1;
  153. for ( ptr = path; !isspace(*ptr) && *ptr != ';'; ptr++ ) ;
  154. *ptr = '\0';
  155. if ( home != NULL )
  156. free(home);
  157. if ( (home = malloc(strlen(path)+1)) != NULL )
  158. strcpy(home, path);
  159. } /* End if */
  160. } /* End while */
  161. fclose(fp);
  162. } /* End if */
  163. if ( home == NULL ) {
  164. if ( (home = getenv(DWBENV)) == NULL ) {
  165. if ( (home = DWBHOME) == NULL || *home == '\0' || *home == ' ' )
  166. home = NULL;
  167. } /* End if */
  168. } /* End if */
  169. while (home && *home == '/' && *(home +1) == '/') /* remove extra slashes */
  170. home++;
  171. return(home);
  172. } /* End of DWBhome */
  173. /*****************************************************************************/
  174. void DWBinit(char *prog, dwbinit *paths)
  175. {
  176. char *prefix;
  177. char *value;
  178. char *path;
  179. int plen;
  180. int length;
  181. dwbinit *opaths = paths;
  182. /*
  183. *
  184. * Adjust the pathnames listed in paths, using the home directory
  185. * returned by DWBhome(). Stops when it reaches an element that has
  186. * NULL address and value fields. Assumes pathnames are relative,
  187. * but changes everything. DWBdebug issues a warning if an original
  188. * path begins with a /.
  189. *
  190. * A non-NULL address refers to a pointer, which is reallocated and
  191. * then reinitialized. A NULL address implies a non-NULL value field
  192. * and describes a character array that we only reinitialize. The
  193. * length field for an array is the size of that array. The length
  194. * field of a pointer is an increment that's added to the length
  195. * required to store the new pathname string - should help when we
  196. * want to change character arrays to pointers in applications like
  197. * troff.
  198. *
  199. */
  200. if ( (prefix = DWBhome()) == NULL ) {
  201. fprintf(stderr, "%s: no DWB home directory\n", prog);
  202. exit(1);
  203. } /* End if */
  204. DWBdebug(opaths, 0);
  205. plen = strlen(prefix);
  206. for ( ; paths->value != NULL || paths->address != NULL; paths++ ) {
  207. if ( paths->address == NULL ) {
  208. length = 0;
  209. value = paths->value;
  210. } else {
  211. length = paths->length;
  212. value = *paths->address;
  213. } /* End else */
  214. length += plen + 1 + strlen(value); /* +1 is for the '/' */
  215. if ( (path = malloc(length+1)) == NULL ) {
  216. fprintf(stderr, "%s: can't allocate pathname memory\n", prog);
  217. exit(1);
  218. } /* End if */
  219. if ( *value != '\0' ) {
  220. char *eop = prefix;
  221. while(*eop++)
  222. ;
  223. eop -= 2;
  224. if (*value != '/' && *eop != '/') {
  225. sprintf(path, "%s/%s", prefix, value);
  226. } else if (*value == '/' && *eop == '/') {
  227. value++;
  228. sprintf(path, "%s%s", prefix, value);
  229. } else
  230. sprintf(path, "%s%s", prefix, value);
  231. } else
  232. sprintf(path, "%s", prefix);
  233. if ( paths->address == NULL ) {
  234. if ( strlen(path) >= paths->length ) {
  235. fprintf(stderr, "%s: no room for %s\n", prog, path);
  236. exit(1);
  237. } /* End if */
  238. strcpy(paths->value, path);
  239. free(path);
  240. } else *paths->address = path;
  241. } /* End for */
  242. DWBdebug(opaths, 1);
  243. } /* End of DWBinit */
  244. /*****************************************************************************/
  245. void DWBprefix( char *prog, char *path, int length)
  246. {
  247. char *home;
  248. char buf[512];
  249. int len = strlen(DWBPREFIX);
  250. /*
  251. *
  252. * Replace a leading DWBPREFIX string in path by the current DWBhome().
  253. * Used by programs that pretend to handle .so requests. Assumes path
  254. * is an array with room for length characters. The implementation is
  255. * not great, but should be good enough for now. Also probably should
  256. * have DWBhome() only do the lookup once, and remember the value if
  257. * called again.
  258. *
  259. */
  260. if ( strncmp(path, DWBPREFIX, len) == 0 ) {
  261. if ( (home = DWBhome()) != NULL ) {
  262. if ( strlen(home) + strlen(path+len) < length ) {
  263. sprintf(buf, "%s%s", home, path+len);
  264. strcpy(path, buf); /* assuming there's room in path */
  265. } else fprintf(stderr, "%s: no room to grow path %s", prog, path);
  266. } /* End if */
  267. } /* End if */
  268. } /* End of DWBprefix */
  269. /*****************************************************************************/