1 /* 2 3 Copyright 1988, 1998 The Open Group 4 5 Permission to use, copy, modify, distribute, and sell this software and its 6 documentation for any purpose is hereby granted without fee, provided that 7 the above copyright notice appear in all copies and that both that 8 copyright notice and this permission notice appear in supporting 9 documentation. 10 11 The above copyright notice and this permission notice shall be included 12 in all copies or substantial portions of the Software. 13 14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 OTHER DEALINGS IN THE SOFTWARE. 21 22 Except as contained in this notice, the name of The Open Group shall 23 not be used in advertising or otherwise to promote the sale, use or 24 other dealings in this Software without prior written authorization 25 from The Open Group. 26 27 */ 28 29 /* 30 * xdm - display manager daemon 31 * Author: Keith Packard, MIT X Consortium 32 * 33 * resource.c 34 */ 35 36 #include "dm.h" 37 #include "dm_error.h" 38 39 #include <X11/Intrinsic.h> 40 #include <X11/Xmu/CharSet.h> 41 42 char *config; 43 44 char *servers; 45 int request_port; 46 int debugLevel; 47 char *errorLogFile; 48 int daemonMode; 49 char *pidFile; 50 int lockPidFile; 51 int sourceAddress; 52 char *authDir; 53 int autoRescan; 54 int removeDomainname; 55 char *keyFile; 56 char *accessFile; 57 char **exportList; 58 #if !defined(HAVE_ARC4RANDOM) 59 char *randomFile; 60 #endif 61 #ifdef DEV_RANDOM 62 char *randomDevice; 63 #endif 64 #if !defined(HAVE_ARC4RANDOM) 65 char *prngdSocket; 66 int prngdPort; 67 #endif 68 69 char *greeterLib; 70 char *willing; 71 int choiceTimeout; /* chooser choice timeout */ 72 73 #define DM_STRING 0 74 #define DM_INT 1 75 #define DM_BOOL 2 76 #define DM_ARGV 3 77 78 /* 79 * The following constants are supposed to be set in Makefile or config.h 80 * from parameters set in configure. DO NOT CHANGE THESE DEFINITIONS! 81 */ 82 #ifndef DEF_SERVER_LINE 83 # define DEF_SERVER_LINE ":0 local /usr/bin/X11/X :0" 84 #endif 85 #ifndef XRDB_PROGRAM 86 # define XRDB_PROGRAM "/usr/bin/X11/xrdb" 87 #endif 88 #ifndef DEF_SESSION 89 # define DEF_SESSION "/usr/bin/X11/xterm -ls" 90 #endif 91 #ifndef DEF_USER_PATH 92 # define DEF_USER_PATH ":/bin:/usr/bin:/usr/bin/X11:/usr/ucb" 93 #endif 94 #ifndef DEF_SYSTEM_PATH 95 # define DEF_SYSTEM_PATH "/etc:/bin:/usr/bin:/usr/bin/X11:/usr/ucb" 96 #endif 97 #ifndef DEF_SYSTEM_SHELL 98 # define DEF_SYSTEM_SHELL "/bin/sh" 99 #endif 100 #ifndef DEF_FAILSAFE_CLIENT 101 # define DEF_FAILSAFE_CLIENT "/usr/bin/X11/xterm" 102 #endif 103 #ifndef DEF_XDM_CONFIG 104 # define DEF_XDM_CONFIG "/usr/lib/X11/xdm/xdm-config" 105 #endif 106 #ifndef DEF_CHOOSER 107 # define DEF_CHOOSER "/usr/lib/X11/xdm/chooser" 108 #endif 109 #ifndef DEF_AUTH_NAME 110 # ifdef HASXDMAUTH 111 # define DEF_AUTH_NAME "XDM-AUTHORIZATION-1 MIT-MAGIC-COOKIE-1" 112 # else 113 # define DEF_AUTH_NAME "MIT-MAGIC-COOKIE-1" 114 # endif 115 #endif 116 #ifndef DEF_AUTH_DIR 117 # define DEF_AUTH_DIR "/usr/lib/X11/xdm" 118 #endif 119 #ifndef DEF_USER_AUTH_DIR 120 # define DEF_USER_AUTH_DIR "/tmp" 121 #endif 122 #ifndef DEF_KEY_FILE 123 # define DEF_KEY_FILE "" 124 #endif 125 #ifndef DEF_ACCESS_FILE 126 # define DEF_ACCESS_FILE "" 127 #endif 128 #ifndef DEF_RANDOM_FILE 129 # define DEF_RANDOM_FILE "/dev/mem" 130 #endif 131 #ifndef DEF_PRNGD_SOCKET 132 # define DEF_PRNGD_SOCKET "/tmp/entropy" 133 #endif 134 #ifndef DEF_PRNGD_PORT 135 # define DEF_PRNGD_PORT "0" 136 #endif 137 #ifndef DEF_GREETER_LIB 138 # define DEF_GREETER_LIB "/usr/lib/X11/xdm/libXdmGreet.so" 139 #endif 140 141 #define DEF_UDP_PORT "177" /* registered XDMCP port, don't change */ 142 143 struct dmResources { 144 const char *name, *class; 145 int type; 146 char **dm_value; 147 const char *default_value; 148 } DmResources[] = { 149 { "servers", "Servers", DM_STRING, &servers, 150 DEF_SERVER_LINE} , 151 { "requestPort","RequestPort", DM_INT, (char **) &request_port, 152 DEF_UDP_PORT} , 153 { "debugLevel", "DebugLevel", DM_INT, (char **) &debugLevel, 154 "0"} , 155 { "errorLogFile","ErrorLogFile", DM_STRING, &errorLogFile, 156 ""} , 157 { "daemonMode", "DaemonMode", DM_BOOL, (char **) &daemonMode, 158 "true"} , 159 { "pidFile", "PidFile", DM_STRING, &pidFile, 160 ""} , 161 { "lockPidFile","LockPidFile", DM_BOOL, (char **) &lockPidFile, 162 "true"} , 163 { "authDir", "authDir", DM_STRING, &authDir, 164 DEF_AUTH_DIR} , 165 { "autoRescan", "AutoRescan", DM_BOOL, (char **) &autoRescan, 166 "true"} , 167 { "removeDomainname","RemoveDomainname",DM_BOOL,(char **) &removeDomainname, 168 "true"} , 169 { "keyFile", "KeyFile", DM_STRING, &keyFile, 170 DEF_KEY_FILE} , 171 { "accessFile", "AccessFile", DM_STRING, &accessFile, 172 DEF_ACCESS_FILE} , 173 { "exportList", "ExportList", DM_ARGV, (char **) &exportList, 174 ""} , 175 #if !defined(HAVE_ARC4RANDOM) 176 { "randomFile", "RandomFile", DM_STRING, &randomFile, 177 DEF_RANDOM_FILE} , 178 { "prngdSocket", "PrngdSocket", DM_STRING, &prngdSocket, 179 DEF_PRNGD_SOCKET}, 180 { "prngdPort", "PrngdPort", DM_INT, (char **) &prngdPort, 181 DEF_PRNGD_PORT}, 182 #endif 183 #ifdef DEV_RANDOM 184 { "randomDevice", "RandomDevice", DM_STRING, &randomDevice, 185 DEV_RANDOM} , 186 #endif 187 { "greeterLib", "GreeterLib", DM_STRING, &greeterLib, 188 DEF_GREETER_LIB} , 189 { "choiceTimeout","ChoiceTimeout",DM_INT, (char **) &choiceTimeout, 190 "15"} , 191 { "sourceAddress","SourceAddress",DM_BOOL, (char **) &sourceAddress, 192 "false"} , 193 { "willing", "Willing", DM_STRING, &willing, 194 ""} , 195 }; 196 197 #define NUM_DM_RESOURCES (sizeof DmResources / sizeof DmResources[0]) 198 199 #define boffset(f) XtOffsetOf(struct display, f) 200 201 struct displayResource { 202 const char *name, *class; 203 int type; 204 int offset; 205 const char *default_value; 206 }; 207 208 /* resources for managing the server */ 209 210 struct displayResource serverResources[] = { 211 { "serverAttempts","ServerAttempts",DM_INT, boffset(serverAttempts), 212 "1" }, 213 { "openDelay", "OpenDelay", DM_INT, boffset(openDelay), 214 "15" }, 215 { "openRepeat", "OpenRepeat", DM_INT, boffset(openRepeat), 216 "5" }, 217 { "openTimeout","OpenTimeout", DM_INT, boffset(openTimeout), 218 "120" }, 219 { "startAttempts","StartAttempts",DM_INT, boffset(startAttempts), 220 "4" }, 221 { "reservAttempts","ReservAttempts",DM_INT, boffset(reservAttempts), 222 "2" }, 223 { "pingInterval","PingInterval",DM_INT, boffset(pingInterval), 224 "5" }, 225 { "pingTimeout","PingTimeout", DM_INT, boffset(pingTimeout), 226 "5" }, 227 { "terminateServer","TerminateServer",DM_BOOL, boffset(terminateServer), 228 "false" }, 229 { "grabServer", "GrabServer", DM_BOOL, boffset(grabServer), 230 "false" }, 231 { "grabTimeout","GrabTimeout", DM_INT, boffset(grabTimeout), 232 "3" }, 233 { "resetSignal","Signal", DM_INT, boffset(resetSignal), 234 "1" }, /* SIGHUP */ 235 { "termSignal", "Signal", DM_INT, boffset(termSignal), 236 "15" }, /* SIGTERM */ 237 { "resetForAuth","ResetForAuth",DM_BOOL, boffset(resetForAuth), 238 "false" }, 239 { "authorize", "Authorize", DM_BOOL, boffset(authorize), 240 "true" }, 241 { "authComplain","AuthComplain",DM_BOOL, boffset(authComplain), 242 "true" }, 243 { "authName", "AuthName", DM_ARGV, boffset(authNames), 244 DEF_AUTH_NAME }, 245 { "authFile", "AuthFile", DM_STRING, boffset(clientAuthFile), 246 "" }, 247 }; 248 249 #define NUM_SERVER_RESOURCES (sizeof serverResources/\ 250 sizeof serverResources[0]) 251 252 /* resources which control the session behaviour */ 253 254 struct displayResource sessionResources[] = { 255 { "resources", "Resources", DM_STRING, boffset(resources), 256 "" }, 257 { "xrdb", "Xrdb", DM_STRING, boffset(xrdb), 258 XRDB_PROGRAM }, 259 { "setup", "Setup", DM_STRING, boffset(setup), 260 "" }, 261 { "startup", "Startup", DM_STRING, boffset(startup), 262 "" }, 263 { "reset", "Reset", DM_STRING, boffset(reset), 264 "" }, 265 { "session", "Session", DM_STRING, boffset(session), 266 DEF_SESSION }, 267 { "userPath", "Path", DM_STRING, boffset(userPath), 268 DEF_USER_PATH }, 269 { "systemPath", "Path", DM_STRING, boffset(systemPath), 270 DEF_SYSTEM_PATH }, 271 { "systemShell","Shell", DM_STRING, boffset(systemShell), 272 DEF_SYSTEM_SHELL }, 273 { "failsafeClient","FailsafeClient", DM_STRING, boffset(failsafeClient), 274 DEF_FAILSAFE_CLIENT }, 275 { "userAuthDir","UserAuthDir", DM_STRING, boffset(userAuthDir), 276 DEF_USER_AUTH_DIR }, 277 { "chooser", "Chooser", DM_STRING, boffset(chooser), 278 DEF_CHOOSER }, 279 }; 280 281 #define NUM_SESSION_RESOURCES (sizeof sessionResources/\ 282 sizeof sessionResources[0]) 283 284 XrmDatabase DmResourceDB; 285 286 static void 287 GetResource ( 288 const char *name, 289 const char *class, 290 int valueType, 291 char **valuep, 292 const char *default_value) 293 { 294 char *type; 295 XrmValue value; 296 const char *string; 297 char *new_string; 298 char str_buf[50]; 299 int len; 300 301 if (DmResourceDB && XrmGetResource (DmResourceDB, 302 name, class, 303 &type, &value)) 304 { 305 string = value.addr; 306 len = value.size; 307 } 308 else 309 { 310 string = default_value; 311 len = strlen (string); 312 } 313 314 Debug ("%s/%s value %*.*s\n", name, class, len, len, string); 315 316 if (valueType == DM_STRING && *valuep) 317 { 318 if (strlen (*valuep) == len && !strncmp (*valuep, string, len)) 319 return; 320 else 321 free (*valuep); 322 } 323 324 switch (valueType) { 325 case DM_STRING: 326 new_string = malloc ((unsigned) (len+1)); 327 if (!new_string) { 328 LogOutOfMem ("GetResource"); 329 return; 330 } 331 strncpy (new_string, string, len); 332 new_string[len] = '\0'; 333 *(valuep) = new_string; 334 break; 335 case DM_INT: 336 strncpy (str_buf, string, sizeof (str_buf)); 337 str_buf[sizeof (str_buf)-1] = '\0'; 338 *((int *) valuep) = atoi (str_buf); 339 break; 340 case DM_BOOL: 341 strncpy (str_buf, string, sizeof (str_buf)); 342 str_buf[sizeof (str_buf)-1] = '\0'; 343 XmuCopyISOLatin1Lowered (str_buf, str_buf); 344 if (!strcmp (str_buf, "true") || 345 !strcmp (str_buf, "on") || 346 !strcmp (str_buf, "yes")) 347 *((int *) valuep) = 1; 348 else if (!strcmp (str_buf, "false") || 349 !strcmp (str_buf, "off") || 350 !strcmp (str_buf, "no")) 351 *((int *) valuep) = 0; 352 break; 353 case DM_ARGV: 354 freeArgs (*(char ***) valuep); 355 *((char ***) valuep) = parseArgs ((char **) 0, string); 356 break; 357 } 358 } 359 360 XrmOptionDescRec configTable [] = { 361 {"-server", NULL, XrmoptionSkipArg, (caddr_t) NULL }, 362 {"-udpPort", NULL, XrmoptionSkipArg, (caddr_t) NULL }, 363 {"-error", NULL, XrmoptionSkipArg, (caddr_t) NULL }, 364 {"-resources", NULL, XrmoptionSkipArg, (caddr_t) NULL }, 365 {"-session", NULL, XrmoptionSkipArg, (caddr_t) NULL }, 366 {"-debug", NULL, XrmoptionSkipArg, (caddr_t) NULL }, 367 {"-xrm", NULL, XrmoptionSkipArg, (caddr_t) NULL }, 368 {"-config", ".configFile", XrmoptionSepArg, (caddr_t) NULL } 369 }; 370 371 XrmOptionDescRec optionTable [] = { 372 {"-server", ".servers", XrmoptionSepArg, (caddr_t) NULL }, 373 {"-udpPort", ".requestPort", XrmoptionSepArg, (caddr_t) NULL }, 374 {"-error", ".errorLogFile", XrmoptionSepArg, (caddr_t) NULL }, 375 {"-resources", "*resources", XrmoptionSepArg, (caddr_t) NULL }, 376 {"-session", "*session", XrmoptionSepArg, (caddr_t) NULL }, 377 {"-debug", "*debugLevel", XrmoptionSepArg, (caddr_t) NULL }, 378 {"-xrm", NULL, XrmoptionResArg, (caddr_t) NULL }, 379 {"-daemon", ".daemonMode", XrmoptionNoArg, "true" }, 380 {"-nodaemon", ".daemonMode", XrmoptionNoArg, "false" } 381 }; 382 383 static int originalArgc; 384 static char **originalArgv; 385 386 void 387 InitResources (int argc, char **argv) 388 { 389 XrmInitialize (); 390 originalArgc = argc; 391 originalArgv = argv; 392 ReinitResources (); 393 } 394 395 void 396 ReinitResources (void) 397 { 398 int argc; 399 char **a; 400 char **argv; 401 XrmDatabase newDB; 402 403 argv = malloc ((originalArgc + 1) * sizeof (char *)); 404 if (!argv) 405 LogPanic ("no space for argument realloc\n"); 406 for (argc = 0; argc < originalArgc; argc++) 407 argv[argc] = originalArgv[argc]; 408 argv[argc] = NULL; 409 if (DmResourceDB) 410 XrmDestroyDatabase (DmResourceDB); 411 DmResourceDB = XrmGetStringDatabase (""); 412 /* pre-parse the command line to get the -config option, if any */ 413 XrmParseCommand (&DmResourceDB, configTable, 414 sizeof (configTable) / sizeof (configTable[0]), 415 "DisplayManager", &argc, argv); 416 GetResource ("DisplayManager.configFile", "DisplayManager.ConfigFile", 417 DM_STRING, &config, DEF_XDM_CONFIG); 418 newDB = XrmGetFileDatabase ( config ); 419 if (newDB) 420 { 421 if (DmResourceDB) 422 XrmDestroyDatabase (DmResourceDB); 423 DmResourceDB = newDB; 424 } 425 else if (argc != originalArgc) 426 LogError ("Can't open configuration file %s\n", config ); 427 XrmParseCommand (&DmResourceDB, optionTable, 428 sizeof (optionTable) / sizeof (optionTable[0]), 429 "DisplayManager", &argc, argv); 430 if (argc > 1) 431 { 432 LogError ("extra arguments on command line:"); 433 for (a = argv + 1; *a; a++) 434 LogAppend (" \"%s\"", *a); 435 LogAppend ("\n"); 436 } 437 free (argv); 438 } 439 440 void 441 LoadDMResources (void) 442 { 443 int i; 444 char name[1024], class[1024]; 445 446 for (i = 0; i < NUM_DM_RESOURCES; i++) { 447 snprintf (name, sizeof(name), "DisplayManager.%s", DmResources[i].name); 448 snprintf (class, sizeof(class), "DisplayManager.%s", DmResources[i].class); 449 GetResource (name, class, DmResources[i].type, 450 (char **) DmResources[i].dm_value, 451 DmResources[i].default_value); 452 } 453 } 454 455 static void 456 CleanUpName (char *src, char *dst, int len) 457 { 458 while (*src) { 459 if (--len <= 0) 460 break; 461 switch (*src) 462 { 463 case ':': 464 case '.': 465 *dst++ = '_'; 466 break; 467 default: 468 *dst++ = *src; 469 } 470 ++src; 471 } 472 *dst = '\0'; 473 } 474 475 static void 476 LoadDisplayResources ( 477 struct display *d, 478 struct displayResource *resources, 479 int numResources) 480 { 481 int i; 482 char name[1024], class[1024]; 483 char dpyName[512], dpyClass[512]; 484 485 CleanUpName (d->name, dpyName, sizeof (dpyName)); 486 CleanUpName (d->class ? d->class : d->name, dpyClass, sizeof (dpyClass)); 487 for (i = 0; i < numResources; i++) { 488 snprintf (name, sizeof(name), "DisplayManager.%s.%s", 489 dpyName, resources[i].name); 490 snprintf (class, sizeof(class), "DisplayManager.%s.%s", 491 dpyClass, resources[i].class); 492 GetResource (name, class, resources[i].type, 493 (char **) (((char *) d) + resources[i].offset), 494 resources[i].default_value); 495 } 496 } 497 498 void 499 LoadServerResources (struct display *d) 500 { 501 LoadDisplayResources (d, serverResources, NUM_SERVER_RESOURCES); 502 } 503 504 void 505 LoadSessionResources (struct display *d) 506 { 507 LoadDisplayResources (d, sessionResources, NUM_SESSION_RESOURCES); 508 } 509