[__bsdi__]: Alternate decls of getpwuid and getpwnam.
[emacs.git] / src / xrdb.c
blob19ca21f9e02d00c10fd911f802a44697ad59ed88
1 /* Deal with the X Resource Manager.
2 Copyright (C) 1990, 1993 Free Software Foundation.
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
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
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.
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. */
18 /* Written by jla, 4/90 */
20 #ifdef emacs
21 #include "config.h"
22 #endif
24 #if 1 /* I'd really appreciate it if this code could go away... -JimB */
25 /* this avoids lossage in the `dual-universe' headers on AT&T SysV X11 */
26 #ifdef USG5
27 #define SYSV
28 #include <unistd.h>
29 #endif /* USG5 */
31 #endif /* 1 */
33 /* This should be included before the X include files; otherwise, we get
34 warnings about redefining NULL under BSD 4.3. */
35 #include <sys/param.h>
37 #include <X11/Xlib.h>
38 #include <X11/Xatom.h>
39 #if 0
40 #include <X11/Xos.h>
41 #endif
42 #include <X11/X.h>
43 #include <X11/Xutil.h>
44 #include <X11/Xresource.h>
45 #ifdef VMS
46 #include "vms-pwd.h"
47 #else
48 #include <pwd.h>
49 #endif
50 #include <sys/stat.h>
52 #ifndef MAXPATHLEN
53 #define MAXPATHLEN 256
54 #endif
56 extern char *getenv ();
58 /* This does cause trouble on AIX. I'm going to take the comment at
59 face value. */
60 #if 0
61 extern short getuid (); /* If this causes portability problems,
62 I think we should just delete it; it'll
63 default to `int' anyway. */
64 #endif
66 #ifdef __bsdi__
67 extern struct passwd *getpwuid (uid_t);
68 extern struct passwd *getpwnam (const char *);
69 #else
70 extern struct passwd *getpwuid ();
71 extern struct passwd *getpwnam ();
72 #endif
74 static char *
75 gethomedir (dirname)
76 char *dirname;
78 int uid;
79 struct passwd *pw;
80 char *ptr;
82 if ((ptr = getenv ("HOME")) == NULL)
84 if ((ptr = getenv ("USER")) != NULL)
85 pw = getpwnam (ptr);
86 else
88 uid = getuid ();
89 pw = getpwuid (uid);
91 if (pw)
92 ptr = pw->pw_dir;
93 else
95 ptr = NULL;
96 *dirname = '\0';
100 if (ptr != NULL)
101 strcpy (dirname, ptr);
103 dirname += strlen (dirname);
104 *dirname = '/';
105 dirname++;
106 *dirname = '\0';
108 return dirname;
111 static int
112 file_p (path)
113 char *path;
115 struct stat status;
117 return (access (path, 4) == 0 /* exists and is readable */
118 && stat (path, &status) == 0 /* get the status */
119 && (status.st_mode & S_IFDIR) == 0); /* not a directory */
122 #if 0
123 #define X_DEFAULT_SEARCH_PATH "/usr/lib/X11/"
124 #endif
126 /* Isn't this just disgusting? */
128 #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"
130 static int
131 decode_magic (string, file, return_path)
132 char *string, *file, *return_path;
134 char *p = string;
135 char *t = return_path;
137 while (*p)
139 if (*p == '%')
140 switch (*++p)
142 case '%':
143 *t++ = '%';
144 p++;
145 break;
147 case 'N':
148 case 'T':
149 case 'S':
150 case 'L':
151 case 'l':
152 case 't':
153 case 'c':
154 default:
155 p++;
156 if (*t == '/' && *p == '/')
157 p++;
158 break;
160 else
161 *t++ = *p++;
163 *t = '\0';
164 strcat (return_path, file);
166 if (file_p (return_path))
167 return 1;
169 return_path[0] = '\0';
170 return 0;
173 static int
174 magic_searchpath_decoder (incantation_string, file, return_path)
175 char *incantation_string, *return_path, *file;
177 register char *s = incantation_string;
178 register char *p;
180 /* Must be big enough for "%N%S". */
181 register int string_size = MAXPATHLEN;
182 register char *string = (char *) alloca (string_size * sizeof (*string));
184 while (*s)
186 p = s;
188 while (*p && *p != ':')
189 p++;
191 if (*p == ':' && *(p + 1) == ':')
193 /* We know string is big enough for this. */
194 bcopy ("%N%S", string, 5);
195 if (decode_magic (string, file, return_path))
196 return 1;
198 s = p + 1;
199 continue;
202 if (p > s)
204 int len = p - s;
206 if (string_size < len+1)
208 string_size = 2 * len;
209 string = (char *) alloca (string_size * sizeof (*string));
211 bcopy (s, string, len);
212 string[len] = '\0';
213 if (decode_magic (string, file, return_path))
214 return 1;
217 if (p && *p != 0)
218 s = p + 1;
219 else
220 return 0;
223 return 0;
226 static XrmDatabase
227 get_system_app (class)
228 char *class;
230 XrmDatabase db;
231 char path[MAXPATHLEN];
232 char *p;
234 if ((p = getenv ("XFILESEARCHPATH")) == NULL)
235 p = X_DEFAULT_SEARCH_PATH;
237 if (! magic_searchpath_decoder (p, class, path))
238 return NULL;
240 db = XrmGetFileDatabase (path);
241 return db;
244 static XrmDatabase
245 get_fallback (display)
246 Display *display;
248 XrmDatabase db;
250 return NULL;
253 static XrmDatabase
254 get_user_app (class)
255 char *class;
257 XrmDatabase db;
258 char *magic_path;
259 char path[MAXPATHLEN];
261 if ((magic_path = getenv ("XUSERFILESEARCHPATH")) == NULL)
263 char homedir[MAXPATHLEN];
264 char *default_magic;
265 char *p;
267 gethomedir (homedir);
269 if ((p = getenv ("XAPPLRESDIR")) == NULL)
271 default_magic = "%s/%%L/%%N:%s/%%l/%%N:%s/%%N";
272 magic_path = (char *) alloca ((3 * strlen (homedir))
273 + strlen (default_magic));
274 sprintf (magic_path, default_magic, homedir, homedir, homedir);
276 else
278 default_magic = "%s/%%L/%%N:%s/%%l/%%N:%s/%%N:%s/%%N";
279 magic_path = (char *) alloca ((3 * strlen (p))
280 + strlen (default_magic)
281 + strlen (homedir));
282 sprintf (magic_path, default_magic, p, p, p, homedir);
286 if (! magic_searchpath_decoder (magic_path, class, path))
287 return NULL;
289 db = XrmGetFileDatabase (path);
290 return db;
293 static XrmDatabase
294 get_user_db (display)
295 Display *display;
297 XrmDatabase db;
298 char *xdefs;
300 #ifdef PBaseSize /* Cheap way to test for X11R4 or later. */
301 xdefs = XResourceManagerString (display);
302 #else
303 xdefs = display->xdefaults;
304 #endif
306 if (xdefs != NULL)
307 db = XrmGetStringDatabase (xdefs);
308 else
310 char xdefault[MAXPATHLEN];
312 gethomedir (xdefault);
313 strcat (xdefault, ".Xdefaults");
314 db = XrmGetFileDatabase (xdefault);
317 return db;
320 static XrmDatabase
321 get_environ_db ()
323 XrmDatabase db;
324 char *p;
325 char path[MAXPATHLEN];
327 if ((p = getenv ("XENVIRONMENT")) == NULL)
329 gethomedir (path);
330 strcat (path, ".Xdefaults-");
331 gethostname (path + strlen (path), MAXPATHLEN - strlen (path));
332 p = path;
335 db = XrmGetFileDatabase (p);
336 return db;
339 /* Types of values that we can find in a database */
341 #define XrmStringType "String" /* String representation */
342 XrmRepresentation x_rm_string; /* Quark representation */
344 /* Load X resources based on the display and a possible -xrm option. */
346 XrmDatabase
347 x_load_resources (display, xrm_string, myclass)
348 Display *display;
349 char *xrm_string, *myclass;
351 char *xdefs;
352 XrmDatabase rdb;
353 XrmDatabase db;
355 x_rm_string = XrmStringToQuark (XrmStringType);
356 XrmInitialize ();
357 rdb = XrmGetStringDatabase ("");
359 /* Get application system defaults */
360 db = get_system_app (myclass);
361 if (db != NULL)
362 XrmMergeDatabases (db, &rdb);
364 /* Get Fallback resources */
365 db = get_fallback (display);
366 if (db != NULL)
367 XrmMergeDatabases (db, &rdb);
369 /* Get application user defaults */
370 db = get_user_app (myclass);
371 if (db != NULL)
372 XrmMergeDatabases (db, &rdb);
374 /* get User defaults */
375 db = get_user_db (display);
376 if (db != NULL)
377 XrmMergeDatabases (db, &rdb);
379 /* Get Environment defaults. */
380 db = get_environ_db ();
381 if (db != NULL)
382 XrmMergeDatabases (db, &rdb);
384 /* Last, merge in any specification from the command line. */
385 if (xrm_string != NULL)
387 db = XrmGetStringDatabase (xrm_string);
388 if (db != NULL)
389 XrmMergeDatabases (db, &rdb);
392 return rdb;
395 /* Retrieve the value of the resource specified by NAME with class CLASS
396 and of type TYPE from database RDB. The value is returned in RET_VALUE. */
399 x_get_resource (rdb, name, class, expected_type, ret_value)
400 XrmDatabase rdb;
401 char *name, *class;
402 XrmRepresentation expected_type;
403 XrmValue *ret_value;
405 XrmValue value;
406 XrmName namelist[100];
407 XrmClass classlist[100];
408 XrmRepresentation type;
410 XrmStringToNameList(name, namelist);
411 XrmStringToClassList(class, classlist);
413 if (XrmQGetResource (rdb, namelist, classlist, &type, &value) == True
414 && (type == expected_type))
416 if (type == x_rm_string)
417 ret_value->addr = (char *) value.addr;
418 else
419 bcopy (value.addr, ret_value->addr, ret_value->size);
421 return value.size;
424 return 0;
427 /* Retrieve the string resource specified by NAME with CLASS from
428 database RDB. */
430 char *
431 x_get_string_resource (rdb, name, class)
432 XrmDatabase rdb;
433 char *name, *class;
435 XrmValue value;
437 if (x_get_resource (rdb, name, class, x_rm_string, &value))
438 return (char *) value.addr;
440 return (char *) 0;
443 #ifdef TESTRM
444 #include <stdio.h>
445 #include "arg-list.h"
447 static void
448 fatal (msg, prog, x1, x2, x3, x4, x5)
449 char *msg, *prog;
450 int x1, x2, x3, x4, x5;
452 extern int errno;
454 if (errno)
455 perror (prog);
457 (void) fprintf (stderr, msg, prog, x1, x2, x3, x4, x5);
458 exit (1);
461 main (argc, argv)
462 int argc;
463 char **argv;
465 Display *display;
466 char *displayname, *resource_string, *class;
467 XrmDatabase xdb;
468 List *arg_list, *lp;
470 arg_list = arg_listify (argc, argv);
472 lp = member ("-d", arg_list);
473 if (!NIL (lp))
474 displayname = car (cdr (lp));
475 else
476 displayname = "localhost:0.0";
478 lp = member ("-xrm", arg_list);
479 if (! NIL (lp))
480 resource_string = car (cdr (lp));
481 else
482 resource_string = (char *) 0;
484 lp = member ("-c", arg_list);
485 if (! NIL (lp))
486 class = car (cdr (lp));
487 else
488 class = "Emacs";
490 free_arglist (arg_list);
494 if (!(display = XOpenDisplay (displayname)))
495 fatal ("Can't open display '%s'\n", XDisplayName (displayname));
497 xdb = x_load_resources (display, resource_string, class);
499 #if 0
500 /* In a real program, you'd want to also do this: */
501 display->db = xdb;
502 #endif
504 while (1)
506 char line[90];
508 printf ("String: ");
509 gets (line);
510 if (strlen (line))
512 char *value = x_get_string_resource (xdb, line, class);
514 if (value != NULL)
515 printf ("\t%s: %s\n\n", line, value);
516 else
517 printf ("\tNo Value.\n\n");
519 else
520 break;
522 printf ("\tExit.\n\n");
524 XCloseDisplay (display);
526 #endif /* TESTRM */