159
|
1 /* Deal with the X Resource Manager.
|
620
|
2 Copyright (C) 1990, 1992 Free Software Foundation.
|
159
|
3
|
|
4 This program is free software; you can redistribute it and/or modify
|
|
5 it under the terms of the GNU General Public License as published by
|
620
|
6 the Free Software Foundation; either version 2, or (at your option)
|
159
|
7 any later version.
|
|
8
|
|
9 This program is distributed in the hope that it will be useful,
|
|
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12 GNU General Public License for more details.
|
|
13
|
|
14 You should have received a copy of the GNU General Public License
|
|
15 along with this program; see the file COPYING. If not, write to
|
|
16 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|
17
|
|
18 /* Written by jla, 4/90 */
|
|
19
|
|
20 #include <X11/Xlib.h>
|
|
21 #include <X11/Xatom.h>
|
|
22 #include <X11/Xos.h>
|
|
23 #include <X11/X.h>
|
|
24 #include <X11/Xutil.h>
|
|
25 #include <X11/Xresource.h>
|
|
26 #include <sys/param.h>
|
556
|
27 #ifdef VMS
|
|
28 #include "vms-pwd.h"
|
|
29 #else
|
159
|
30 #include <pwd.h>
|
556
|
31 #endif
|
159
|
32 #include <sys/stat.h>
|
485
|
33 #include <sys/types.h>
|
159
|
34
|
|
35 #ifdef emacs
|
|
36 #include "config.h"
|
|
37 #endif
|
|
38
|
|
39 extern char *getenv ();
|
485
|
40 extern uid_t getuid ();
|
159
|
41 extern struct passwd *getpwuid ();
|
|
42 extern struct passwd *getpwnam ();
|
|
43
|
|
44 static char *
|
|
45 gethomedir (dirname)
|
|
46 char *dirname;
|
|
47 {
|
|
48 int uid;
|
|
49 struct passwd *pw;
|
|
50 char *ptr;
|
|
51
|
|
52 if ((ptr = getenv ("HOME")) == NULL)
|
|
53 {
|
|
54 if ((ptr = getenv ("USER")) != NULL)
|
|
55 pw = getpwnam (ptr);
|
|
56 else
|
|
57 {
|
|
58 uid = getuid ();
|
|
59 pw = getpwuid (uid);
|
|
60 }
|
|
61 if (pw)
|
|
62 ptr = pw->pw_dir;
|
|
63 else
|
|
64 {
|
|
65 ptr = NULL;
|
|
66 *dirname = '\0';
|
|
67 }
|
|
68 }
|
|
69
|
|
70 if (ptr != NULL)
|
|
71 strcpy (dirname, ptr);
|
|
72
|
|
73 dirname += strlen (dirname);
|
|
74 *dirname = '/';
|
|
75 dirname++;
|
|
76 *dirname = '\0';
|
|
77
|
|
78 return dirname;
|
|
79 }
|
|
80
|
|
81 static int
|
|
82 file_p (path)
|
|
83 char *path;
|
|
84 {
|
|
85 struct stat status;
|
|
86
|
|
87 return (access (path, R_OK) == 0 /* exists and is readable */
|
|
88 && stat (path, &status) == 0 /* get the status */
|
|
89 && (status.st_mode & S_IFDIR) == 0); /* not a directory */
|
|
90 }
|
|
91
|
|
92 #if 0
|
|
93 #define X_DEFAULT_SEARCH_PATH "/usr/lib/X11/"
|
|
94 #endif
|
|
95
|
|
96 /* Isn't this just disgusting? */
|
|
97
|
|
98 #define X_DEFAULT_SEARCH_PATH "/usr/lib/X11/%L/%T/%N%S:/usr/lib/X11/%l/%T/%N%S:/usr/lib/X11/%T/%N%S"
|
|
99
|
|
100 static int
|
|
101 decode_magic (string, file, return_path)
|
|
102 char *string, *file, *return_path;
|
|
103 {
|
|
104 char *p = string;
|
|
105 char *t = return_path;
|
|
106
|
|
107 while (*p)
|
|
108 {
|
|
109 if (*p == '%')
|
|
110 switch (*++p)
|
|
111 {
|
|
112 case '%':
|
|
113 *t++ = '%';
|
|
114 p++;
|
|
115 break;
|
|
116
|
|
117 case 'N':
|
|
118 case 'T':
|
|
119 case 'S':
|
|
120 case 'L':
|
|
121 case 'l':
|
|
122 case 't':
|
|
123 case 'c':
|
|
124 default:
|
|
125 p++;
|
|
126 if (*t == '/' && *p == '/')
|
|
127 p++;
|
|
128 break;
|
|
129 }
|
|
130 else
|
|
131 *t++ = *p++;
|
|
132 }
|
|
133 *t = '\0';
|
|
134 strcat (return_path, file);
|
|
135
|
|
136 if (file_p (return_path))
|
|
137 return 1;
|
|
138
|
|
139 return_path[0] = '\0';
|
|
140 return 0;
|
|
141 }
|
|
142
|
|
143 static int
|
|
144 magic_searchpath_decoder (incantation_string, file, return_path)
|
|
145 char *incantation_string, *return_path, *file;
|
|
146 {
|
|
147 register char *s = incantation_string;
|
|
148 register char *p;
|
620
|
149
|
|
150 /* Must be big enough for "%N%S". */
|
|
151 register int string_size = MAXPATHLEN;
|
|
152 register char *string = (char *) alloca (string_size * sizeof (*string));
|
159
|
153
|
|
154 while (*s)
|
|
155 {
|
|
156 p = s;
|
|
157
|
|
158 while (*p && *p != ':')
|
|
159 p++;
|
|
160
|
|
161 if (*p == ':' && *(p + 1) == ':')
|
|
162 {
|
620
|
163 /* We know string is big enough for this. */
|
159
|
164 bcopy ("%N%S", string, 5);
|
|
165 if (decode_magic (string, file, return_path))
|
|
166 return 1;
|
|
167
|
|
168 s = p + 1;
|
|
169 continue;
|
|
170 }
|
|
171
|
|
172 if (p > s)
|
|
173 {
|
|
174 int len = p - s;
|
|
175
|
620
|
176 if (string_size < len+1)
|
|
177 {
|
|
178 string_size = 2 * len;
|
|
179 string = (char *) alloca (string_size * sizeof (*string));
|
|
180 }
|
159
|
181 bcopy (s, string, len);
|
|
182 string[len + 1] = '\0';
|
|
183 if (decode_magic (string, file, return_path))
|
|
184 return 1;
|
|
185 }
|
|
186
|
|
187 if (p)
|
|
188 s = p + 1;
|
|
189 else
|
|
190 return 0;
|
|
191 }
|
|
192
|
|
193 return 0;
|
|
194 }
|
|
195
|
|
196 static XrmDatabase
|
|
197 get_system_app (class)
|
|
198 char *class;
|
|
199 {
|
|
200 XrmDatabase db;
|
|
201 char path[MAXPATHLEN];
|
|
202 char *p;
|
|
203
|
|
204 if ((p = getenv ("XFILESEARCHPATH")) == NULL)
|
|
205 p = X_DEFAULT_SEARCH_PATH;
|
|
206
|
|
207 if (! magic_searchpath_decoder (p, class, path))
|
|
208 return NULL;
|
|
209
|
|
210 db = XrmGetFileDatabase (path);
|
|
211 return db;
|
|
212 }
|
|
213
|
|
214 static XrmDatabase
|
|
215 get_fallback (display)
|
|
216 Display *display;
|
|
217 {
|
|
218 XrmDatabase db;
|
|
219
|
|
220 return NULL;
|
|
221 }
|
|
222
|
|
223 static XrmDatabase
|
|
224 get_user_app (class)
|
|
225 char *class;
|
|
226 {
|
|
227 XrmDatabase db;
|
|
228 char *magic_path;
|
|
229 char path[MAXPATHLEN];
|
|
230
|
|
231 if ((magic_path = getenv ("XUSERFILESEARCHPATH")) == NULL)
|
|
232 {
|
|
233 char homedir[MAXPATHLEN];
|
|
234 char *default_magic;
|
|
235 char *p;
|
|
236
|
|
237 gethomedir (homedir);
|
|
238
|
|
239 if ((p = getenv ("XAPPLRESDIR")) == NULL)
|
|
240 {
|
|
241 default_magic = "%s/%%L/%%N:%s/%%l/%%N:%s/%%N";
|
|
242 magic_path = (char *) alloca ((3 * strlen (homedir))
|
|
243 + strlen (default_magic));
|
|
244 sprintf (magic_path, default_magic, homedir, homedir, homedir);
|
|
245 }
|
|
246 else
|
|
247 {
|
|
248 default_magic = "%s/%%L/%%N:%s/%%l/%%N:%s/%%N:%s/%%N";
|
|
249 magic_path = (char *) alloca ((3 * strlen (p))
|
|
250 + strlen (default_magic)
|
|
251 + strlen (homedir));
|
|
252 sprintf (magic_path, default_magic, p, p, p, homedir);
|
|
253 }
|
|
254 }
|
|
255
|
|
256 if (! magic_searchpath_decoder (magic_path, class, path))
|
|
257 return NULL;
|
|
258
|
|
259 db = XrmGetFileDatabase (path);
|
|
260 return db;
|
|
261 }
|
|
262
|
|
263 static XrmDatabase
|
|
264 get_user_db (display)
|
|
265 Display *display;
|
|
266 {
|
|
267 XrmDatabase db;
|
|
268 char *xdefs;
|
|
269
|
|
270 xdefs = XResourceManagerString (display);
|
|
271 if (xdefs != NULL)
|
|
272 db = XrmGetStringDatabase (xdefs);
|
|
273 else
|
|
274 {
|
|
275 char xdefault[MAXPATHLEN];
|
|
276
|
|
277 gethomedir (xdefault);
|
|
278 strcat (xdefault, ".Xdefaults");
|
|
279 db = XrmGetFileDatabase (xdefault);
|
|
280 }
|
|
281
|
|
282 return db;
|
|
283 }
|
|
284
|
|
285 static XrmDatabase
|
|
286 get_environ_db ()
|
|
287 {
|
|
288 XrmDatabase db;
|
|
289 char *p;
|
|
290 char path[MAXPATHLEN];
|
|
291
|
|
292 if ((p = getenv ("XENVIRONMENT")) == NULL)
|
|
293 {
|
|
294 gethomedir (path);
|
|
295 strcat (path, ".Xdefaults-");
|
|
296 gethostname (path + strlen (path), MAXPATHLEN - strlen (path));
|
|
297 p = path;
|
|
298 }
|
|
299
|
|
300 db = XrmGetFileDatabase (p);
|
|
301 return db;
|
|
302 }
|
|
303
|
|
304 /* Types of values that we can find in a database */
|
|
305
|
|
306 #define XrmStringType "String" /* String representation */
|
|
307 XrmRepresentation x_rm_string; /* Quark representation */
|
|
308
|
|
309 /* Load X resources based on the display and a possible -xrm option. */
|
|
310
|
|
311 XrmDatabase
|
|
312 x_load_resources (display, xrm_string, myclass)
|
|
313 Display *display;
|
|
314 char *xrm_string, *myclass;
|
|
315 {
|
|
316 char *xdefs;
|
|
317 XrmDatabase rdb;
|
|
318 XrmDatabase db;
|
|
319
|
|
320 x_rm_string = XrmStringToQuark (XrmStringType);
|
|
321 XrmInitialize ();
|
|
322 rdb = XrmGetStringDatabase ("");
|
|
323
|
|
324 /* Get application system defaults */
|
|
325 db = get_system_app (myclass);
|
|
326 if (db != NULL)
|
|
327 XrmMergeDatabases (db, &rdb);
|
|
328
|
|
329 /* Get Fallback resources */
|
|
330 db = get_fallback (display);
|
|
331 if (db != NULL)
|
|
332 XrmMergeDatabases (db, &rdb);
|
|
333
|
|
334 /* Get application user defaults */
|
|
335 db = get_user_app (myclass);
|
|
336 if (db != NULL)
|
|
337 XrmMergeDatabases (db, &rdb);
|
|
338
|
|
339 /* get User defaults */
|
|
340 db = get_user_db (display);
|
|
341 if (db != NULL)
|
|
342 XrmMergeDatabases (db, &rdb);
|
|
343
|
|
344 /* Get Environment defaults. */
|
|
345 db = get_environ_db ();
|
|
346 if (db != NULL)
|
|
347 XrmMergeDatabases (db, &rdb);
|
|
348
|
|
349 /* Last, merge in any specification from the command line. */
|
|
350 if (xrm_string != NULL)
|
|
351 {
|
|
352 db = XrmGetStringDatabase (xrm_string);
|
|
353 if (db != NULL)
|
|
354 XrmMergeDatabases (db, &rdb);
|
|
355 }
|
|
356
|
|
357 return rdb;
|
|
358 }
|
|
359
|
|
360 /* Retrieve the value of the resource specified by NAME with class CLASS
|
|
361 and of type TYPE from database RDB. The value is returned in RET_VALUE. */
|
|
362
|
|
363 int
|
|
364 x_get_resource (rdb, name, class, expected_type, ret_value)
|
|
365 XrmDatabase rdb;
|
|
366 char *name, *class;
|
|
367 XrmRepresentation expected_type;
|
|
368 XrmValue *ret_value;
|
|
369 {
|
|
370 XrmValue value;
|
|
371 XrmName namelist[100];
|
|
372 XrmClass classlist[100];
|
|
373 XrmRepresentation type;
|
|
374
|
|
375 XrmStringToNameList(name, namelist);
|
|
376 XrmStringToClassList(class, classlist);
|
|
377
|
|
378 if (XrmQGetResource (rdb, namelist, classlist, &type, &value) == True
|
|
379 && (type == expected_type))
|
|
380 {
|
|
381 if (type == x_rm_string)
|
|
382 (char *) ret_value->addr = value.addr;
|
|
383 else
|
|
384 bcopy (value.addr, ret_value->addr, ret_value->size);
|
|
385
|
|
386 return value.size;
|
|
387 }
|
|
388
|
|
389 return 0;
|
|
390 }
|
|
391
|
|
392 /* Retrieve the string resource specified by NAME with CLASS from
|
|
393 database RDB. */
|
|
394
|
|
395 char *
|
|
396 x_get_string_resource (rdb, name, class)
|
|
397 XrmDatabase rdb;
|
|
398 char *name, *class;
|
|
399 {
|
|
400 XrmValue value;
|
|
401
|
|
402 if (x_get_resource (rdb, name, class, x_rm_string, &value))
|
|
403 return (char *) value.addr;
|
|
404
|
|
405 return (char *) 0;
|
|
406 }
|
|
407
|
|
408 #ifdef TESTRM
|
|
409 #include <stdio.h>
|
|
410 #include "arg-list.h"
|
|
411
|
|
412 static void
|
|
413 fatal (msg, prog, x1, x2, x3, x4, x5)
|
|
414 char *msg, *prog;
|
|
415 int x1, x2, x3, x4, x5;
|
|
416 {
|
|
417 extern int errno;
|
|
418
|
|
419 if (errno)
|
|
420 perror (prog);
|
|
421
|
|
422 (void) fprintf (stderr, msg, prog, x1, x2, x3, x4, x5);
|
|
423 exit (1);
|
|
424 }
|
|
425
|
|
426 main (argc, argv)
|
|
427 int argc;
|
|
428 char **argv;
|
|
429 {
|
|
430 Display *display;
|
|
431 char *displayname, *resource_string, *class;
|
|
432 XrmDatabase xdb;
|
|
433 List *arg_list, *lp;
|
|
434
|
|
435 arg_list = arg_listify (argc, argv);
|
|
436
|
|
437 lp = member ("-d", arg_list);
|
|
438 if (!NIL (lp))
|
|
439 displayname = car (cdr (lp));
|
|
440 else
|
|
441 displayname = "localhost:0.0";
|
|
442
|
|
443 lp = member ("-xrm", arg_list);
|
|
444 if (! NIL (lp))
|
|
445 resource_string = car (cdr (lp));
|
|
446 else
|
|
447 resource_string = (char *) 0;
|
|
448
|
|
449 lp = member ("-c", arg_list);
|
|
450 if (! NIL (lp))
|
|
451 class = car (cdr (lp));
|
|
452 else
|
|
453 class = "Emacs";
|
|
454
|
|
455 free_arglist (arg_list);
|
|
456
|
|
457
|
|
458
|
|
459 if (!(display = XOpenDisplay (displayname)))
|
|
460 fatal ("Can't open display '%s'\n", XDisplayName (displayname));
|
|
461
|
|
462 xdb = x_load_resources (display, resource_string, class);
|
|
463
|
|
464 #if 0
|
|
465 /* In a real program, you'd want to also do this: */
|
|
466 display->db = xdb;
|
|
467 #endif
|
|
468
|
|
469 while (1)
|
|
470 {
|
|
471 char line[90];
|
|
472
|
|
473 printf ("String: ");
|
|
474 gets (line);
|
|
475 if (strlen (line))
|
|
476 {
|
|
477 char *value = x_get_string_resource (xdb, line, class);
|
|
478
|
|
479 if (value != NULL)
|
|
480 printf ("\t%s: %s\n\n", line, value);
|
|
481 else
|
|
482 printf ("\tNo Value.\n\n");
|
|
483 }
|
|
484 else
|
|
485 break;
|
|
486 }
|
|
487 printf ("\tExit.\n\n");
|
|
488
|
|
489 XCloseDisplay (display);
|
|
490 }
|
|
491 #endif /* TESTRM */
|