utils.c revision 05b261ec
1/* 2 3Copyright 1987, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included 12in all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 18OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20OTHER DEALINGS IN THE SOFTWARE. 21 22Except as contained in this notice, the name of The Open Group shall 23not be used in advertising or otherwise to promote the sale, use or 24other dealings in this Software without prior written authorization 25from The Open Group. 26 27 28Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, 29Copyright 1994 Quarterdeck Office Systems. 30 31 All Rights Reserved 32 33Permission to use, copy, modify, and distribute this software and its 34documentation for any purpose and without fee is hereby granted, 35provided that the above copyright notice appear in all copies and that 36both that copyright notice and this permission notice appear in 37supporting documentation, and that the names of Digital and 38Quarterdeck not be used in advertising or publicity pertaining to 39distribution of the software without specific, written prior 40permission. 41 42DIGITAL AND QUARTERDECK DISCLAIM ALL WARRANTIES WITH REGARD TO THIS 43SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 44FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT 45OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 46OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 47OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE 48OR PERFORMANCE OF THIS SOFTWARE. 49 50*/ 51 52#ifdef HAVE_DIX_CONFIG_H 53#include <dix-config.h> 54#endif 55 56#ifdef __CYGWIN__ 57#include <stdlib.h> 58#include <signal.h> 59#endif 60 61#if defined(WIN32) && !defined(__CYGWIN__) 62#include <X11/Xwinsock.h> 63#endif 64#include <X11/Xos.h> 65#include <stdio.h> 66#include <time.h> 67#if !defined(WIN32) || !defined(__MINGW32__) 68#include <sys/time.h> 69#include <sys/resource.h> 70#endif 71#include "misc.h" 72#include <X11/X.h> 73#define XSERV_t 74#define TRANS_SERVER 75#define TRANS_REOPEN 76#include <X11/Xtrans/Xtrans.h> 77#include "input.h" 78#include "dixfont.h" 79#include "osdep.h" 80#include "extension.h" 81#ifdef X_POSIX_C_SOURCE 82#define _POSIX_C_SOURCE X_POSIX_C_SOURCE 83#include <signal.h> 84#undef _POSIX_C_SOURCE 85#else 86#if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE) 87#include <signal.h> 88#else 89#define _POSIX_SOURCE 90#include <signal.h> 91#undef _POSIX_SOURCE 92#endif 93#endif 94#ifndef WIN32 95#include <sys/wait.h> 96#endif 97#if !defined(SYSV) && !defined(WIN32) && !defined(Lynx) && !defined(QNX4) 98#include <sys/resource.h> 99#endif 100#include <sys/stat.h> 101#include <ctype.h> /* for isspace */ 102#include <stdarg.h> 103 104#if defined(DGUX) 105#include <sys/resource.h> 106#include <netdb.h> 107#endif 108 109#include <stdlib.h> /* for malloc() */ 110 111#if defined(TCPCONN) || defined(STREAMSCONN) 112# ifndef WIN32 113# include <netdb.h> 114# endif 115#endif 116 117#include "opaque.h" 118 119#ifdef SMART_SCHEDULE 120#include "dixstruct.h" 121#endif 122 123#ifdef XKB 124#include <xkbsrv.h> 125#endif 126#ifdef XCSECURITY 127#include "securitysrv.h" 128#endif 129 130#ifdef RENDER 131#include "picture.h" 132#endif 133 134#ifdef XPRINT 135#include "DiPrint.h" 136#endif 137 138_X_EXPORT Bool noTestExtensions; 139#ifdef BIGREQS 140_X_EXPORT Bool noBigReqExtension = FALSE; 141#endif 142#ifdef COMPOSITE 143_X_EXPORT Bool noCompositeExtension = FALSE; 144#endif 145 146#ifdef DAMAGE 147_X_EXPORT Bool noDamageExtension = FALSE; 148#endif 149#ifdef DBE 150_X_EXPORT Bool noDbeExtension = FALSE; 151#endif 152#ifdef DPMSExtension 153_X_EXPORT Bool noDPMSExtension = FALSE; 154#endif 155#ifdef EVI 156_X_EXPORT Bool noEVIExtension = FALSE; 157#endif 158#ifdef FONTCACHE 159_X_EXPORT Bool noFontCacheExtension = FALSE; 160#endif 161#ifdef GLXEXT 162_X_EXPORT Bool noGlxExtension = FALSE; 163#endif 164#ifdef SCREENSAVER 165_X_EXPORT Bool noScreenSaverExtension = FALSE; 166#endif 167#ifdef MITSHM 168_X_EXPORT Bool noMITShmExtension = FALSE; 169#endif 170#ifdef MITMISC 171_X_EXPORT Bool noMITMiscExtension = FALSE; 172#endif 173#ifdef MULTIBUFFER 174_X_EXPORT Bool noMultibufferExtension = FALSE; 175#endif 176#ifdef RANDR 177_X_EXPORT Bool noRRExtension = FALSE; 178#endif 179#ifdef RENDER 180_X_EXPORT Bool noRenderExtension = FALSE; 181#endif 182#ifdef SHAPE 183_X_EXPORT Bool noShapeExtension = FALSE; 184#endif 185#ifdef XCSECURITY 186_X_EXPORT Bool noSecurityExtension = FALSE; 187#endif 188#ifdef XSYNC 189_X_EXPORT Bool noSyncExtension = FALSE; 190#endif 191#ifdef TOGCUP 192_X_EXPORT Bool noXcupExtension = FALSE; 193#endif 194#ifdef RES 195_X_EXPORT Bool noResExtension = FALSE; 196#endif 197#ifdef XAPPGROUP 198_X_EXPORT Bool noXagExtension = FALSE; 199#endif 200#ifdef XCMISC 201_X_EXPORT Bool noXCMiscExtension = FALSE; 202#endif 203#ifdef XEVIE 204/* Xevie is disabled by default for now until the 205 * interface is stable */ 206_X_EXPORT Bool noXevieExtension = TRUE; 207#endif 208#ifdef XF86BIGFONT 209_X_EXPORT Bool noXFree86BigfontExtension = FALSE; 210#endif 211#ifdef XFreeXDGA 212_X_EXPORT Bool noXFree86DGAExtension = FALSE; 213#endif 214#ifdef XF86DRI 215_X_EXPORT Bool noXFree86DRIExtension = FALSE; 216#endif 217#ifdef XF86MISC 218_X_EXPORT Bool noXFree86MiscExtension = FALSE; 219#endif 220#ifdef XF86VIDMODE 221_X_EXPORT Bool noXFree86VidModeExtension = FALSE; 222#endif 223#ifdef XFIXES 224_X_EXPORT Bool noXFixesExtension = FALSE; 225#endif 226/* |noXkbExtension| is defined in xc/programs/Xserver/xkb/xkbInit.c */ 227#ifdef PANORAMIX 228/* Xinerama is disabled by default unless enabled via +xinerama */ 229_X_EXPORT Bool noPanoramiXExtension = TRUE; 230#endif 231#ifdef XINPUT 232_X_EXPORT Bool noXInputExtension = FALSE; 233#endif 234#ifdef XIDLE 235_X_EXPORT Bool noXIdleExtension = FALSE; 236#endif 237#ifdef XV 238_X_EXPORT Bool noXvExtension = FALSE; 239#endif 240 241#define X_INCLUDE_NETDB_H 242#include <X11/Xos_r.h> 243 244#include <errno.h> 245 246Bool CoreDump; 247 248#ifdef PANORAMIX 249Bool PanoramiXExtensionDisabledHack = FALSE; 250#endif 251 252int auditTrailLevel = 1; 253 254_X_EXPORT Bool Must_have_memory = FALSE; 255 256#ifdef AIXV3 257int SyncOn = 0; 258extern int SelectWaitTime; 259#endif 260 261#if defined(SVR4) || defined(__linux__) || defined(CSRG_BASED) 262#define HAS_SAVED_IDS_AND_SETEUID 263#endif 264 265#ifdef MEMBUG 266#define MEM_FAIL_SCALE 100000 267long Memory_fail = 0; 268#include <stdlib.h> /* for random() */ 269#endif 270 271static char *dev_tty_from_init = NULL; /* since we need to parse it anyway */ 272 273OsSigHandlerPtr 274OsSignal(sig, handler) 275 int sig; 276 OsSigHandlerPtr handler; 277{ 278#ifdef X_NOT_POSIX 279 return signal(sig, handler); 280#else 281 struct sigaction act, oact; 282 283 sigemptyset(&act.sa_mask); 284 if (handler != SIG_IGN) 285 sigaddset(&act.sa_mask, sig); 286 act.sa_flags = 0; 287 act.sa_handler = handler; 288 if (sigaction(sig, &act, &oact)) 289 perror("sigaction"); 290 return oact.sa_handler; 291#endif 292} 293 294#ifdef SERVER_LOCK 295/* 296 * Explicit support for a server lock file like the ones used for UUCP. 297 * For architectures with virtual terminals that can run more than one 298 * server at a time. This keeps the servers from stomping on each other 299 * if the user forgets to give them different display numbers. 300 */ 301#define LOCK_DIR "/tmp" 302#define LOCK_TMP_PREFIX "/.tX" 303#define LOCK_PREFIX "/.X" 304#define LOCK_SUFFIX "-lock" 305 306#if defined(DGUX) 307#include <limits.h> 308#include <sys/param.h> 309#endif 310 311#ifndef PATH_MAX 312#ifndef Lynx 313#include <sys/param.h> 314#else 315#include <param.h> 316#endif 317#ifndef PATH_MAX 318#ifdef MAXPATHLEN 319#define PATH_MAX MAXPATHLEN 320#else 321#define PATH_MAX 1024 322#endif 323#endif 324#endif 325 326static Bool StillLocking = FALSE; 327static char LockFile[PATH_MAX]; 328static Bool nolock = FALSE; 329 330/* 331 * LockServer -- 332 * Check if the server lock file exists. If so, check if the PID 333 * contained inside is valid. If so, then die. Otherwise, create 334 * the lock file containing the PID. 335 */ 336void 337LockServer(void) 338{ 339 char tmp[PATH_MAX], pid_str[12]; 340 int lfd, i, haslock, l_pid, t; 341 char *tmppath = NULL; 342 int len; 343 char port[20]; 344 345 if (nolock) return; 346 /* 347 * Path names 348 */ 349 tmppath = LOCK_DIR; 350 351 sprintf(port, "%d", atoi(display)); 352 len = strlen(LOCK_PREFIX) > strlen(LOCK_TMP_PREFIX) ? strlen(LOCK_PREFIX) : 353 strlen(LOCK_TMP_PREFIX); 354 len += strlen(tmppath) + strlen(port) + strlen(LOCK_SUFFIX) + 1; 355 if (len > sizeof(LockFile)) 356 FatalError("Display name `%s' is too long\n", port); 357 (void)sprintf(tmp, "%s" LOCK_TMP_PREFIX "%s" LOCK_SUFFIX, tmppath, port); 358 (void)sprintf(LockFile, "%s" LOCK_PREFIX "%s" LOCK_SUFFIX, tmppath, port); 359 360 /* 361 * Create a temporary file containing our PID. Attempt three times 362 * to create the file. 363 */ 364 StillLocking = TRUE; 365 i = 0; 366 do { 367 i++; 368 lfd = open(tmp, O_CREAT | O_EXCL | O_WRONLY, 0644); 369 if (lfd < 0) 370 sleep(2); 371 else 372 break; 373 } while (i < 3); 374 if (lfd < 0) { 375 unlink(tmp); 376 i = 0; 377 do { 378 i++; 379 lfd = open(tmp, O_CREAT | O_EXCL | O_WRONLY, 0644); 380 if (lfd < 0) 381 sleep(2); 382 else 383 break; 384 } while (i < 3); 385 } 386 if (lfd < 0) 387 FatalError("Could not create lock file in %s\n", tmp); 388 (void) sprintf(pid_str, "%10ld\n", (long)getpid()); 389 (void) write(lfd, pid_str, 11); 390#ifndef USE_CHMOD 391 (void) fchmod(lfd, 0444); 392#else 393 (void) chmod(tmp, 0444); 394#endif 395 (void) close(lfd); 396 397 /* 398 * OK. Now the tmp file exists. Try three times to move it in place 399 * for the lock. 400 */ 401 i = 0; 402 haslock = 0; 403 while ((!haslock) && (i++ < 3)) { 404 haslock = (link(tmp,LockFile) == 0); 405 if (haslock) { 406 /* 407 * We're done. 408 */ 409 break; 410 } 411 else { 412 /* 413 * Read the pid from the existing file 414 */ 415 lfd = open(LockFile, O_RDONLY); 416 if (lfd < 0) { 417 unlink(tmp); 418 FatalError("Can't read lock file %s\n", LockFile); 419 } 420 pid_str[0] = '\0'; 421 if (read(lfd, pid_str, 11) != 11) { 422 /* 423 * Bogus lock file. 424 */ 425 unlink(LockFile); 426 close(lfd); 427 continue; 428 } 429 pid_str[11] = '\0'; 430 sscanf(pid_str, "%d", &l_pid); 431 close(lfd); 432 433 /* 434 * Now try to kill the PID to see if it exists. 435 */ 436 errno = 0; 437 t = kill(l_pid, 0); 438 if ((t< 0) && (errno == ESRCH)) { 439 /* 440 * Stale lock file. 441 */ 442 unlink(LockFile); 443 continue; 444 } 445 else if (((t < 0) && (errno == EPERM)) || (t == 0)) { 446 /* 447 * Process is still active. 448 */ 449 unlink(tmp); 450 FatalError("Server is already active for display %s\n%s %s\n%s\n", 451 port, "\tIf this server is no longer running, remove", 452 LockFile, "\tand start again."); 453 } 454 } 455 } 456 unlink(tmp); 457 if (!haslock) 458 FatalError("Could not create server lock file: %s\n", LockFile); 459 StillLocking = FALSE; 460} 461 462/* 463 * UnlockServer -- 464 * Remove the server lock file. 465 */ 466void 467UnlockServer(void) 468{ 469 if (nolock) return; 470 471 if (!StillLocking){ 472 473 (void) unlink(LockFile); 474 } 475} 476#endif /* SERVER_LOCK */ 477 478/* Force connections to close on SIGHUP from init */ 479 480/*ARGSUSED*/ 481SIGVAL 482AutoResetServer (int sig) 483{ 484 int olderrno = errno; 485 486 dispatchException |= DE_RESET; 487 isItTimeToYield = TRUE; 488#ifdef GPROF 489 chdir ("/tmp"); 490 exit (0); 491#endif 492#if defined(SYSV) && defined(X_NOT_POSIX) 493 OsSignal (SIGHUP, AutoResetServer); 494#endif 495 errno = olderrno; 496} 497 498/* Force connections to close and then exit on SIGTERM, SIGINT */ 499 500/*ARGSUSED*/ 501_X_EXPORT SIGVAL 502GiveUp(int sig) 503{ 504 int olderrno = errno; 505 506 dispatchException |= DE_TERMINATE; 507 isItTimeToYield = TRUE; 508#if defined(SYSV) && defined(X_NOT_POSIX) 509 if (sig) 510 OsSignal(sig, SIG_IGN); 511#endif 512 errno = olderrno; 513} 514 515#if defined WIN32 && defined __MINGW32__ 516_X_EXPORT CARD32 517GetTimeInMillis (void) 518{ 519 return GetTickCount (); 520} 521#else 522_X_EXPORT CARD32 523GetTimeInMillis(void) 524{ 525 struct timeval tv; 526 527#ifdef MONOTONIC_CLOCK 528 struct timespec tp; 529 if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) 530 return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000L); 531#endif 532 533 X_GETTIMEOFDAY(&tv); 534 return(tv.tv_sec * 1000) + (tv.tv_usec / 1000); 535} 536#endif 537 538_X_EXPORT void 539AdjustWaitForDelay (pointer waitTime, unsigned long newdelay) 540{ 541 static struct timeval delay_val; 542 struct timeval **wt = (struct timeval **) waitTime; 543 unsigned long olddelay; 544 545 if (*wt == NULL) 546 { 547 delay_val.tv_sec = newdelay / 1000; 548 delay_val.tv_usec = 1000 * (newdelay % 1000); 549 *wt = &delay_val; 550 } 551 else 552 { 553 olddelay = (*wt)->tv_sec * 1000 + (*wt)->tv_usec / 1000; 554 if (newdelay < olddelay) 555 { 556 (*wt)->tv_sec = newdelay / 1000; 557 (*wt)->tv_usec = 1000 * (newdelay % 1000); 558 } 559 } 560} 561 562void UseMsg(void) 563{ 564#if !defined(AIXrt) && !defined(AIX386) 565 ErrorF("use: X [:<display>] [option]\n"); 566 ErrorF("-a # mouse acceleration (pixels)\n"); 567 ErrorF("-ac disable access control restrictions\n"); 568#ifdef MEMBUG 569 ErrorF("-alloc int chance alloc should fail\n"); 570#endif 571 ErrorF("-audit int set audit trail level\n"); 572 ErrorF("-auth file select authorization file\n"); 573 ErrorF("-br create root window with black background\n"); 574 ErrorF("+bs enable any backing store support\n"); 575 ErrorF("-bs disable any backing store support\n"); 576 ErrorF("-c turns off key-click\n"); 577 ErrorF("c # key-click volume (0-100)\n"); 578 ErrorF("-cc int default color visual class\n"); 579 ErrorF("-co file color database file\n"); 580#ifdef COMMANDLINE_CHALLENGED_OPERATING_SYSTEMS 581 ErrorF("-config file read options from file\n"); 582#endif 583 ErrorF("-core generate core dump on fatal error\n"); 584 ErrorF("-dpi int screen resolution in dots per inch\n"); 585#ifdef DPMSExtension 586 ErrorF("dpms enables VESA DPMS monitor control\n"); 587 ErrorF("-dpms disables VESA DPMS monitor control\n"); 588#endif 589 ErrorF("-deferglyphs [none|all|16] defer loading of [no|all|16-bit] glyphs\n"); 590 ErrorF("-f # bell base (0-100)\n"); 591 ErrorF("-fc string cursor font\n"); 592 ErrorF("-fn string default font name\n"); 593 ErrorF("-fp string default font path\n"); 594 ErrorF("-help prints message with these options\n"); 595 ErrorF("-I ignore all remaining arguments\n"); 596#ifdef RLIMIT_DATA 597 ErrorF("-ld int limit data space to N Kb\n"); 598#endif 599#ifdef RLIMIT_NOFILE 600 ErrorF("-lf int limit number of open files to N\n"); 601#endif 602#ifdef RLIMIT_STACK 603 ErrorF("-ls int limit stack space to N Kb\n"); 604#endif 605#ifdef SERVER_LOCK 606 ErrorF("-nolock disable the locking mechanism\n"); 607#endif 608#ifndef NOLOGOHACK 609 ErrorF("-logo enable logo in screen saver\n"); 610 ErrorF("nologo disable logo in screen saver\n"); 611#endif 612 ErrorF("-nolisten string don't listen on protocol\n"); 613 ErrorF("-noreset don't reset after last client exists\n"); 614 ErrorF("-reset reset after last client exists\n"); 615 ErrorF("-p # screen-saver pattern duration (minutes)\n"); 616 ErrorF("-pn accept failure to listen on all ports\n"); 617 ErrorF("-nopn reject failure to listen on all ports\n"); 618 ErrorF("-r turns off auto-repeat\n"); 619 ErrorF("r turns on auto-repeat \n"); 620#ifdef RENDER 621 ErrorF("-render [default|mono|gray|color] set render color alloc policy\n"); 622#endif 623 ErrorF("-s # screen-saver timeout (minutes)\n"); 624#ifdef XCSECURITY 625 ErrorF("-sp file security policy file\n"); 626#endif 627#ifdef XPRINT 628 PrinterUseMsg(); 629#endif 630 ErrorF("-su disable any save under support\n"); 631 ErrorF("-t # mouse threshold (pixels)\n"); 632 ErrorF("-terminate terminate at server reset\n"); 633 ErrorF("-to # connection time out\n"); 634 ErrorF("-tst disable testing extensions\n"); 635 ErrorF("ttyxx server started from init on /dev/ttyxx\n"); 636 ErrorF("v video blanking for screen-saver\n"); 637 ErrorF("-v screen-saver without video blanking\n"); 638 ErrorF("-wm WhenMapped default backing-store\n"); 639 ErrorF("-wr create root window with white background\n"); 640 ErrorF("-x string loads named extension at init time \n"); 641 ErrorF("-maxbigreqsize set maximal bigrequest size \n"); 642#ifdef PANORAMIX 643 ErrorF("+xinerama Enable XINERAMA extension\n"); 644 ErrorF("-xinerama Disable XINERAMA extension\n"); 645#endif 646#ifdef SMART_SCHEDULE 647 ErrorF("-dumbSched Disable smart scheduling, enable old behavior\n"); 648 ErrorF("-schedInterval int Set scheduler interval in msec\n"); 649#endif 650 ErrorF("+extension name Enable extension\n"); 651 ErrorF("-extension name Disable extension\n"); 652#ifdef XDMCP 653 XdmcpUseMsg(); 654#endif 655#endif /* !AIXrt && ! AIX386 */ 656#ifdef XKB 657 XkbUseMsg(); 658#endif 659 ddxUseMsg(); 660} 661 662/* This function performs a rudimentary sanity check 663 * on the display name passed in on the command-line, 664 * since this string is used to generate filenames. 665 * It is especially important that the display name 666 * not contain a "/" and not start with a "-". 667 * --kvajk 668 */ 669static int 670VerifyDisplayName(const char *d) 671{ 672 if ( d == (char *)0 ) return( 0 ); /* null */ 673 if ( *d == '\0' ) return( 0 ); /* empty */ 674 if ( *d == '-' ) return( 0 ); /* could be confused for an option */ 675 if ( *d == '.' ) return( 0 ); /* must not equal "." or ".." */ 676 if ( strchr(d, '/') != (char *)0 ) return( 0 ); /* very important!!! */ 677 return( 1 ); 678} 679 680/* 681 * This function is responsible for doing initalisation of any global 682 * variables at an very early point of server startup (even before 683 * |ProcessCommandLine()|. 684 */ 685void InitGlobals(void) 686{ 687 ddxInitGlobals(); 688} 689 690 691/* 692 * This function parses the command line. Handles device-independent fields 693 * and allows ddx to handle additional fields. It is not allowed to modify 694 * argc or any of the strings pointed to by argv. 695 */ 696void 697ProcessCommandLine(int argc, char *argv[]) 698{ 699 int i, skip; 700 701 defaultKeyboardControl.autoRepeat = TRUE; 702 703#ifdef NO_PART_NET 704 PartialNetwork = FALSE; 705#else 706 PartialNetwork = TRUE; 707#endif 708 709 for ( i = 1; i < argc; i++ ) 710 { 711 /* call ddx first, so it can peek/override if it wants */ 712 if((skip = ddxProcessArgument(argc, argv, i))) 713 { 714 i += (skip - 1); 715 } 716 else if(argv[i][0] == ':') 717 { 718 /* initialize display */ 719 display = argv[i]; 720 display++; 721 if( ! VerifyDisplayName( display ) ) { 722 ErrorF("Bad display name: %s\n", display); 723 UseMsg(); 724 FatalError("Bad display name, exiting: %s\n", display); 725 } 726 } 727 else if ( strcmp( argv[i], "-a") == 0) 728 { 729 if(++i < argc) 730 defaultPointerControl.num = atoi(argv[i]); 731 else 732 UseMsg(); 733 } 734 else if ( strcmp( argv[i], "-ac") == 0) 735 { 736 defeatAccessControl = TRUE; 737 } 738#ifdef MEMBUG 739 else if ( strcmp( argv[i], "-alloc") == 0) 740 { 741 if(++i < argc) 742 Memory_fail = atoi(argv[i]); 743 else 744 UseMsg(); 745 } 746#endif 747 else if ( strcmp( argv[i], "-audit") == 0) 748 { 749 if(++i < argc) 750 auditTrailLevel = atoi(argv[i]); 751 else 752 UseMsg(); 753 } 754 else if ( strcmp( argv[i], "-auth") == 0) 755 { 756 if(++i < argc) 757 InitAuthorization (argv[i]); 758 else 759 UseMsg(); 760 } 761 else if ( strcmp( argv[i], "-br") == 0) 762 blackRoot = TRUE; 763 else if ( strcmp( argv[i], "+bs") == 0) 764 enableBackingStore = TRUE; 765 else if ( strcmp( argv[i], "-bs") == 0) 766 disableBackingStore = TRUE; 767 else if ( strcmp( argv[i], "c") == 0) 768 { 769 if(++i < argc) 770 defaultKeyboardControl.click = atoi(argv[i]); 771 else 772 UseMsg(); 773 } 774 else if ( strcmp( argv[i], "-c") == 0) 775 { 776 defaultKeyboardControl.click = 0; 777 } 778 else if ( strcmp( argv[i], "-cc") == 0) 779 { 780 if(++i < argc) 781 defaultColorVisualClass = atoi(argv[i]); 782 else 783 UseMsg(); 784 } 785 else if ( strcmp( argv[i], "-co") == 0) 786 { 787 if(++i < argc) 788 rgbPath = argv[i]; 789 else 790 UseMsg(); 791 } 792 else if ( strcmp( argv[i], "-core") == 0) 793 { 794 CoreDump = TRUE; 795#if !defined(WIN32) || !defined(__MINGW32__) 796 struct rlimit core_limit; 797 getrlimit (RLIMIT_CORE, &core_limit); 798 core_limit.rlim_cur = core_limit.rlim_max; 799 setrlimit (RLIMIT_CORE, &core_limit); 800#endif 801 } 802 else if ( strcmp( argv[i], "-dpi") == 0) 803 { 804 if(++i < argc) 805 monitorResolution = atoi(argv[i]); 806 else 807 UseMsg(); 808 } 809#ifdef DPMSExtension 810 else if ( strcmp( argv[i], "dpms") == 0) 811 DPMSEnabledSwitch = TRUE; 812 else if ( strcmp( argv[i], "-dpms") == 0) 813 DPMSDisabledSwitch = TRUE; 814#endif 815 else if ( strcmp( argv[i], "-deferglyphs") == 0) 816 { 817 if(++i >= argc || !ParseGlyphCachingMode(argv[i])) 818 UseMsg(); 819 } 820 else if ( strcmp( argv[i], "-f") == 0) 821 { 822 if(++i < argc) 823 defaultKeyboardControl.bell = atoi(argv[i]); 824 else 825 UseMsg(); 826 } 827 else if ( strcmp( argv[i], "-fc") == 0) 828 { 829 if(++i < argc) 830 defaultCursorFont = argv[i]; 831 else 832 UseMsg(); 833 } 834 else if ( strcmp( argv[i], "-fn") == 0) 835 { 836 if(++i < argc) 837 defaultTextFont = argv[i]; 838 else 839 UseMsg(); 840 } 841 else if ( strcmp( argv[i], "-fp") == 0) 842 { 843 if(++i < argc) 844 { 845 defaultFontPath = argv[i]; 846 } 847 else 848 UseMsg(); 849 } 850 else if ( strcmp( argv[i], "-help") == 0) 851 { 852 UseMsg(); 853 exit(0); 854 } 855#ifdef XKB 856 else if ( (skip=XkbProcessArguments(argc,argv,i))!=0 ) { 857 if (skip>0) 858 i+= skip-1; 859 else UseMsg(); 860 } 861#endif 862#ifdef RLIMIT_DATA 863 else if ( strcmp( argv[i], "-ld") == 0) 864 { 865 if(++i < argc) 866 { 867 limitDataSpace = atoi(argv[i]); 868 if (limitDataSpace > 0) 869 limitDataSpace *= 1024; 870 } 871 else 872 UseMsg(); 873 } 874#endif 875#ifdef RLIMIT_NOFILE 876 else if ( strcmp( argv[i], "-lf") == 0) 877 { 878 if(++i < argc) 879 limitNoFile = atoi(argv[i]); 880 else 881 UseMsg(); 882 } 883#endif 884#ifdef RLIMIT_STACK 885 else if ( strcmp( argv[i], "-ls") == 0) 886 { 887 if(++i < argc) 888 { 889 limitStackSpace = atoi(argv[i]); 890 if (limitStackSpace > 0) 891 limitStackSpace *= 1024; 892 } 893 else 894 UseMsg(); 895 } 896#endif 897#ifdef SERVER_LOCK 898 else if ( strcmp ( argv[i], "-nolock") == 0) 899 { 900#if !defined(WIN32) && !defined(__CYGWIN__) 901 if (getuid() != 0) 902 ErrorF("Warning: the -nolock option can only be used by root\n"); 903 else 904#endif 905 nolock = TRUE; 906 } 907#endif 908#ifndef NOLOGOHACK 909 else if ( strcmp( argv[i], "-logo") == 0) 910 { 911 logoScreenSaver = 1; 912 } 913 else if ( strcmp( argv[i], "nologo") == 0) 914 { 915 logoScreenSaver = 0; 916 } 917#endif 918 else if ( strcmp( argv[i], "-nolisten") == 0) 919 { 920 if(++i < argc) { 921 if (_XSERVTransNoListen(argv[i])) 922 FatalError ("Failed to disable listen for %s transport", 923 argv[i]); 924 } else 925 UseMsg(); 926 } 927 else if ( strcmp( argv[i], "-noreset") == 0) 928 { 929 dispatchExceptionAtReset = 0; 930 } 931 else if ( strcmp( argv[i], "-reset") == 0) 932 { 933 dispatchExceptionAtReset = DE_RESET; 934 } 935 else if ( strcmp( argv[i], "-p") == 0) 936 { 937 if(++i < argc) 938 defaultScreenSaverInterval = ((CARD32)atoi(argv[i])) * 939 MILLI_PER_MIN; 940 else 941 UseMsg(); 942 } 943 else if ( strcmp( argv[i], "-pn") == 0) 944 PartialNetwork = TRUE; 945 else if ( strcmp( argv[i], "-nopn") == 0) 946 PartialNetwork = FALSE; 947 else if ( strcmp( argv[i], "r") == 0) 948 defaultKeyboardControl.autoRepeat = TRUE; 949 else if ( strcmp( argv[i], "-r") == 0) 950 defaultKeyboardControl.autoRepeat = FALSE; 951 else if ( strcmp( argv[i], "-s") == 0) 952 { 953 if(++i < argc) 954 defaultScreenSaverTime = ((CARD32)atoi(argv[i])) * 955 MILLI_PER_MIN; 956 else 957 UseMsg(); 958 } 959 else if ( strcmp( argv[i], "-su") == 0) 960 disableSaveUnders = TRUE; 961 else if ( strcmp( argv[i], "-t") == 0) 962 { 963 if(++i < argc) 964 defaultPointerControl.threshold = atoi(argv[i]); 965 else 966 UseMsg(); 967 } 968 else if ( strcmp( argv[i], "-terminate") == 0) 969 { 970 dispatchExceptionAtReset = DE_TERMINATE; 971 } 972 else if ( strcmp( argv[i], "-to") == 0) 973 { 974 if(++i < argc) 975 TimeOutValue = ((CARD32)atoi(argv[i])) * MILLI_PER_SECOND; 976 else 977 UseMsg(); 978 } 979 else if ( strcmp( argv[i], "-tst") == 0) 980 { 981 noTestExtensions = TRUE; 982 } 983 else if ( strcmp( argv[i], "v") == 0) 984 defaultScreenSaverBlanking = PreferBlanking; 985 else if ( strcmp( argv[i], "-v") == 0) 986 defaultScreenSaverBlanking = DontPreferBlanking; 987 else if ( strcmp( argv[i], "-wm") == 0) 988 defaultBackingStore = WhenMapped; 989 else if ( strcmp( argv[i], "-wr") == 0) 990 whiteRoot = TRUE; 991 else if ( strcmp( argv[i], "-maxbigreqsize") == 0) { 992 if(++i < argc) { 993 long reqSizeArg = atol(argv[i]); 994 995 /* Request size > 128MB does not make much sense... */ 996 if( reqSizeArg > 0L && reqSizeArg < 128L ) { 997 maxBigRequestSize = (reqSizeArg * 1048576L) - 1L; 998 } 999 else 1000 { 1001 UseMsg(); 1002 } 1003 } 1004 else 1005 { 1006 UseMsg(); 1007 } 1008 } 1009#ifdef PANORAMIX 1010 else if ( strcmp( argv[i], "+xinerama") == 0){ 1011 noPanoramiXExtension = FALSE; 1012 } 1013 else if ( strcmp( argv[i], "-xinerama") == 0){ 1014 noPanoramiXExtension = TRUE; 1015 } 1016 else if ( strcmp( argv[i], "-disablexineramaextension") == 0){ 1017 PanoramiXExtensionDisabledHack = TRUE; 1018 } 1019#endif 1020 else if ( strcmp( argv[i], "-x") == 0) 1021 { 1022 if(++i >= argc) 1023 UseMsg(); 1024 /* For U**x, which doesn't support dynamic loading, there's nothing 1025 * to do when we see a -x. Either the extension is linked in or 1026 * it isn't */ 1027 } 1028 else if ( strcmp( argv[i], "-I") == 0) 1029 { 1030 /* ignore all remaining arguments */ 1031 break; 1032 } 1033 else if (strncmp (argv[i], "tty", 3) == 0) 1034 { 1035 /* just in case any body is interested */ 1036 dev_tty_from_init = argv[i]; 1037 } 1038#ifdef XDMCP 1039 else if ((skip = XdmcpOptions(argc, argv, i)) != i) 1040 { 1041 i = skip - 1; 1042 } 1043#endif 1044#ifdef XPRINT 1045 else if ((skip = PrinterOptions(argc, argv, i)) != i) 1046 { 1047 i = skip - 1; 1048 } 1049#endif 1050#ifdef XCSECURITY 1051 else if ((skip = XSecurityOptions(argc, argv, i)) != i) 1052 { 1053 i = skip - 1; 1054 } 1055#endif 1056#ifdef AIXV3 1057 else if ( strcmp( argv[i], "-timeout") == 0) 1058 { 1059 if(++i < argc) 1060 SelectWaitTime = atoi(argv[i]); 1061 else 1062 UseMsg(); 1063 } 1064 else if ( strcmp( argv[i], "-sync") == 0) 1065 { 1066 SyncOn++; 1067 } 1068#endif 1069#ifdef SMART_SCHEDULE 1070 else if ( strcmp( argv[i], "-dumbSched") == 0) 1071 { 1072 SmartScheduleDisable = TRUE; 1073 } 1074 else if ( strcmp( argv[i], "-schedInterval") == 0) 1075 { 1076 if (++i < argc) 1077 { 1078 SmartScheduleInterval = atoi(argv[i]); 1079 SmartScheduleSlice = SmartScheduleInterval; 1080 } 1081 else 1082 UseMsg(); 1083 } 1084 else if ( strcmp( argv[i], "-schedMax") == 0) 1085 { 1086 if (++i < argc) 1087 { 1088 SmartScheduleMaxSlice = atoi(argv[i]); 1089 } 1090 else 1091 UseMsg(); 1092 } 1093#endif 1094#ifdef RENDER 1095 else if ( strcmp( argv[i], "-render" ) == 0) 1096 { 1097 if (++i < argc) 1098 { 1099 int policy = PictureParseCmapPolicy (argv[i]); 1100 1101 if (policy != PictureCmapPolicyInvalid) 1102 PictureCmapPolicy = policy; 1103 else 1104 UseMsg (); 1105 } 1106 else 1107 UseMsg (); 1108 } 1109#endif 1110 else if ( strcmp( argv[i], "+extension") == 0) 1111 { 1112 if (++i < argc) 1113 { 1114 if (!EnableDisableExtension(argv[i], TRUE)) 1115 EnableDisableExtensionError(argv[i], TRUE); 1116 } 1117 else 1118 UseMsg(); 1119 } 1120 else if ( strcmp( argv[i], "-extension") == 0) 1121 { 1122 if (++i < argc) 1123 { 1124 if (!EnableDisableExtension(argv[i], FALSE)) 1125 EnableDisableExtensionError(argv[i], FALSE); 1126 } 1127 else 1128 UseMsg(); 1129 } 1130 else 1131 { 1132 ErrorF("Unrecognized option: %s\n", argv[i]); 1133 UseMsg(); 1134 FatalError("Unrecognized option: %s\n", argv[i]); 1135 } 1136 } 1137} 1138 1139#ifdef COMMANDLINE_CHALLENGED_OPERATING_SYSTEMS 1140static void 1141InsertFileIntoCommandLine( 1142 int *resargc, char ***resargv, 1143 int prefix_argc, char **prefix_argv, 1144 char *filename, 1145 int suffix_argc, char **suffix_argv) 1146{ 1147 struct stat st; 1148 FILE *f; 1149 char *p; 1150 char *q; 1151 int insert_argc; 1152 char *buf; 1153 int len; 1154 int i; 1155 1156 f = fopen(filename, "r"); 1157 if (!f) 1158 FatalError("Can't open option file %s\n", filename); 1159 1160 fstat(fileno(f), &st); 1161 1162 buf = (char *) xalloc((unsigned) st.st_size + 1); 1163 if (!buf) 1164 FatalError("Out of Memory\n"); 1165 1166 len = fread(buf, 1, (unsigned) st.st_size, f); 1167 1168 fclose(f); 1169 1170 if (len < 0) 1171 FatalError("Error reading option file %s\n", filename); 1172 1173 buf[len] = '\0'; 1174 1175 p = buf; 1176 q = buf; 1177 insert_argc = 0; 1178 1179 while (*p) 1180 { 1181 while (isspace(*p)) 1182 p++; 1183 if (!*p) 1184 break; 1185 if (*p == '#') 1186 { 1187 while (*p && *p != '\n') 1188 p++; 1189 } else 1190 { 1191 while (*p && !isspace(*p)) 1192 *q++ = *p++; 1193 /* Since p and q might still be pointing at the same place, we */ 1194 /* need to step p over the whitespace now before we add the null. */ 1195 if (*p) 1196 p++; 1197 *q++ = '\0'; 1198 insert_argc++; 1199 } 1200 } 1201 1202 buf = (char *) xrealloc(buf, q - buf); 1203 if (!buf) 1204 FatalError("Out of memory reallocing option buf\n"); 1205 1206 *resargc = prefix_argc + insert_argc + suffix_argc; 1207 *resargv = (char **) xalloc((*resargc + 1) * sizeof(char *)); 1208 if (!*resargv) 1209 FatalError("Out of Memory\n"); 1210 1211 memcpy(*resargv, prefix_argv, prefix_argc * sizeof(char *)); 1212 1213 p = buf; 1214 for (i = 0; i < insert_argc; i++) 1215 { 1216 (*resargv)[prefix_argc + i] = p; 1217 p += strlen(p) + 1; 1218 } 1219 1220 memcpy(*resargv + prefix_argc + insert_argc, 1221 suffix_argv, suffix_argc * sizeof(char *)); 1222 1223 (*resargv)[*resargc] = NULL; 1224} /* end InsertFileIntoCommandLine */ 1225 1226 1227void 1228ExpandCommandLine(int *pargc, char ***pargv) 1229{ 1230 int i; 1231 1232#if !defined(WIN32) && !defined(__CYGWIN__) 1233 if (getuid() != geteuid()) 1234 return; 1235#endif 1236 1237 for (i = 1; i < *pargc; i++) 1238 { 1239 if ( (0 == strcmp((*pargv)[i], "-config")) && (i < (*pargc - 1)) ) 1240 { 1241 InsertFileIntoCommandLine(pargc, pargv, 1242 i, *pargv, 1243 (*pargv)[i+1], /* filename */ 1244 *pargc - i - 2, *pargv + i + 2); 1245 i--; 1246 } 1247 } 1248} /* end ExpandCommandLine */ 1249#endif 1250 1251/* Implement a simple-minded font authorization scheme. The authorization 1252 name is "hp-hostname-1", the contents are simply the host name. */ 1253int 1254set_font_authorizations(char **authorizations, int *authlen, pointer client) 1255{ 1256#define AUTHORIZATION_NAME "hp-hostname-1" 1257#if defined(TCPCONN) || defined(STREAMSCONN) 1258 static char *result = NULL; 1259 static char *p = NULL; 1260 1261 if (p == NULL) 1262 { 1263 char hname[1024], *hnameptr; 1264 unsigned int len; 1265#if defined(IPv6) && defined(AF_INET6) 1266 struct addrinfo hints, *ai = NULL; 1267#else 1268 struct hostent *host; 1269#ifdef XTHREADS_NEEDS_BYNAMEPARAMS 1270 _Xgethostbynameparams hparams; 1271#endif 1272#endif 1273 1274 gethostname(hname, 1024); 1275#if defined(IPv6) && defined(AF_INET6) 1276 bzero(&hints, sizeof(hints)); 1277 hints.ai_flags = AI_CANONNAME; 1278 if (getaddrinfo(hname, NULL, &hints, &ai) == 0) { 1279 hnameptr = ai->ai_canonname; 1280 } else { 1281 hnameptr = hname; 1282 } 1283#else 1284 host = _XGethostbyname(hname, hparams); 1285 if (host == NULL) 1286 hnameptr = hname; 1287 else 1288 hnameptr = host->h_name; 1289#endif 1290 1291 len = strlen(hnameptr) + 1; 1292 result = xalloc(len + sizeof(AUTHORIZATION_NAME) + 4); 1293 1294 p = result; 1295 *p++ = sizeof(AUTHORIZATION_NAME) >> 8; 1296 *p++ = sizeof(AUTHORIZATION_NAME) & 0xff; 1297 *p++ = (len) >> 8; 1298 *p++ = (len & 0xff); 1299 1300 memmove(p, AUTHORIZATION_NAME, sizeof(AUTHORIZATION_NAME)); 1301 p += sizeof(AUTHORIZATION_NAME); 1302 memmove(p, hnameptr, len); 1303 p += len; 1304#if defined(IPv6) && defined(AF_INET6) 1305 if (ai) { 1306 freeaddrinfo(ai); 1307 } 1308#endif 1309 } 1310 *authlen = p - result; 1311 *authorizations = result; 1312 return 1; 1313#else /* TCPCONN */ 1314 return 0; 1315#endif /* TCPCONN */ 1316} 1317 1318/* XALLOC -- X's internal memory allocator. Why does it return unsigned 1319 * long * instead of the more common char *? Well, if you read K&R you'll 1320 * see they say that alloc must return a pointer "suitable for conversion" 1321 * to whatever type you really want. In a full-blown generic allocator 1322 * there's no way to solve the alignment problems without potentially 1323 * wasting lots of space. But we have a more limited problem. We know 1324 * we're only ever returning pointers to structures which will have to 1325 * be long word aligned. So we are making a stronger guarantee. It might 1326 * have made sense to make Xalloc return char * to conform with people's 1327 * expectations of malloc, but this makes lint happier. 1328 */ 1329 1330#ifndef INTERNAL_MALLOC 1331 1332_X_EXPORT void * 1333Xalloc(unsigned long amount) 1334{ 1335 register pointer ptr; 1336 1337 if ((long)amount <= 0) { 1338 return (unsigned long *)NULL; 1339 } 1340 /* aligned extra on long word boundary */ 1341 amount = (amount + (sizeof(long) - 1)) & ~(sizeof(long) - 1); 1342#ifdef MEMBUG 1343 if (!Must_have_memory && Memory_fail && 1344 ((random() % MEM_FAIL_SCALE) < Memory_fail)) 1345 return (unsigned long *)NULL; 1346#endif 1347 if ((ptr = (pointer)malloc(amount))) { 1348 return (unsigned long *)ptr; 1349 } 1350 if (Must_have_memory) 1351 FatalError("Out of memory"); 1352 return (unsigned long *)NULL; 1353} 1354 1355/***************** 1356 * XNFalloc 1357 * "no failure" realloc, alternate interface to Xalloc w/o Must_have_memory 1358 *****************/ 1359 1360_X_EXPORT void * 1361XNFalloc(unsigned long amount) 1362{ 1363 register pointer ptr; 1364 1365 if ((long)amount <= 0) 1366 { 1367 return (unsigned long *)NULL; 1368 } 1369 /* aligned extra on long word boundary */ 1370 amount = (amount + (sizeof(long) - 1)) & ~(sizeof(long) - 1); 1371 ptr = (pointer)malloc(amount); 1372 if (!ptr) 1373 { 1374 FatalError("Out of memory"); 1375 } 1376 return ((unsigned long *)ptr); 1377} 1378 1379/***************** 1380 * Xcalloc 1381 *****************/ 1382 1383_X_EXPORT void * 1384Xcalloc(unsigned long amount) 1385{ 1386 unsigned long *ret; 1387 1388 ret = Xalloc (amount); 1389 if (ret) 1390 bzero ((char *) ret, (int) amount); 1391 return ret; 1392} 1393 1394/***************** 1395 * XNFcalloc 1396 *****************/ 1397 1398_X_EXPORT void * 1399XNFcalloc(unsigned long amount) 1400{ 1401 unsigned long *ret; 1402 1403 ret = Xalloc (amount); 1404 if (ret) 1405 bzero ((char *) ret, (int) amount); 1406 else if ((long)amount > 0) 1407 FatalError("Out of memory"); 1408 return ret; 1409} 1410 1411/***************** 1412 * Xrealloc 1413 *****************/ 1414 1415_X_EXPORT void * 1416Xrealloc(pointer ptr, unsigned long amount) 1417{ 1418#ifdef MEMBUG 1419 if (!Must_have_memory && Memory_fail && 1420 ((random() % MEM_FAIL_SCALE) < Memory_fail)) 1421 return (unsigned long *)NULL; 1422#endif 1423 if ((long)amount <= 0) 1424 { 1425 if (ptr && !amount) 1426 free(ptr); 1427 return (unsigned long *)NULL; 1428 } 1429 amount = (amount + (sizeof(long) - 1)) & ~(sizeof(long) - 1); 1430 if (ptr) 1431 ptr = (pointer)realloc((char *)ptr, amount); 1432 else 1433 ptr = (pointer)malloc(amount); 1434 if (ptr) 1435 return (unsigned long *)ptr; 1436 if (Must_have_memory) 1437 FatalError("Out of memory"); 1438 return (unsigned long *)NULL; 1439} 1440 1441/***************** 1442 * XNFrealloc 1443 * "no failure" realloc, alternate interface to Xrealloc w/o Must_have_memory 1444 *****************/ 1445 1446_X_EXPORT void * 1447XNFrealloc(pointer ptr, unsigned long amount) 1448{ 1449 if (( ptr = (pointer)Xrealloc( ptr, amount ) ) == NULL) 1450 { 1451 if ((long)amount > 0) 1452 FatalError( "Out of memory" ); 1453 } 1454 return ((unsigned long *)ptr); 1455} 1456 1457/***************** 1458 * Xfree 1459 * calls free 1460 *****************/ 1461 1462_X_EXPORT void 1463Xfree(pointer ptr) 1464{ 1465 if (ptr) 1466 free((char *)ptr); 1467} 1468 1469void 1470OsInitAllocator (void) 1471{ 1472#ifdef MEMBUG 1473 static int been_here; 1474 1475 /* Check the memory system after each generation */ 1476 if (been_here) 1477 CheckMemory (); 1478 else 1479 been_here = 1; 1480#endif 1481} 1482#endif /* !INTERNAL_MALLOC */ 1483 1484 1485char * 1486Xstrdup(const char *s) 1487{ 1488 char *sd; 1489 1490 if (s == NULL) 1491 return NULL; 1492 1493 sd = (char *)Xalloc(strlen(s) + 1); 1494 if (sd != NULL) 1495 strcpy(sd, s); 1496 return sd; 1497} 1498 1499 1500_X_EXPORT char * 1501XNFstrdup(const char *s) 1502{ 1503 char *sd; 1504 1505 if (s == NULL) 1506 return NULL; 1507 1508 sd = (char *)XNFalloc(strlen(s) + 1); 1509 strcpy(sd, s); 1510 return sd; 1511} 1512 1513#ifdef SMART_SCHEDULE 1514 1515unsigned long SmartScheduleIdleCount; 1516Bool SmartScheduleIdle; 1517Bool SmartScheduleTimerStopped; 1518 1519#ifdef SIGVTALRM 1520#define SMART_SCHEDULE_POSSIBLE 1521#endif 1522 1523#ifdef SMART_SCHEDULE_POSSIBLE 1524#define SMART_SCHEDULE_SIGNAL SIGALRM 1525#define SMART_SCHEDULE_TIMER ITIMER_REAL 1526#endif 1527 1528static void 1529SmartScheduleStopTimer (void) 1530{ 1531#ifdef SMART_SCHEDULE_POSSIBLE 1532 struct itimerval timer; 1533 1534 timer.it_interval.tv_sec = 0; 1535 timer.it_interval.tv_usec = 0; 1536 timer.it_value.tv_sec = 0; 1537 timer.it_value.tv_usec = 0; 1538 (void) setitimer (ITIMER_REAL, &timer, 0); 1539 SmartScheduleTimerStopped = TRUE; 1540#endif 1541} 1542 1543Bool 1544SmartScheduleStartTimer (void) 1545{ 1546#ifdef SMART_SCHEDULE_POSSIBLE 1547 struct itimerval timer; 1548 1549 SmartScheduleTimerStopped = FALSE; 1550 timer.it_interval.tv_sec = 0; 1551 timer.it_interval.tv_usec = SmartScheduleInterval * 1000; 1552 timer.it_value.tv_sec = 0; 1553 timer.it_value.tv_usec = SmartScheduleInterval * 1000; 1554 return setitimer (ITIMER_REAL, &timer, 0) >= 0; 1555#endif 1556 return FALSE; 1557} 1558 1559#ifdef SMART_SCHEDULE_POSSIBLE 1560static void 1561SmartScheduleTimer (int sig) 1562{ 1563 int olderrno = errno; 1564 1565 SmartScheduleTime += SmartScheduleInterval; 1566 if (SmartScheduleIdle) 1567 { 1568 SmartScheduleStopTimer (); 1569 } 1570 errno = olderrno; 1571} 1572#endif 1573 1574Bool 1575SmartScheduleInit (void) 1576{ 1577#ifdef SMART_SCHEDULE_POSSIBLE 1578 struct sigaction act; 1579 1580 if (SmartScheduleDisable) 1581 return TRUE; 1582 1583 bzero ((char *) &act, sizeof(struct sigaction)); 1584 1585 /* Set up the timer signal function */ 1586 act.sa_handler = SmartScheduleTimer; 1587 sigemptyset (&act.sa_mask); 1588 sigaddset (&act.sa_mask, SMART_SCHEDULE_SIGNAL); 1589 if (sigaction (SMART_SCHEDULE_SIGNAL, &act, 0) < 0) 1590 { 1591 perror ("sigaction for smart scheduler"); 1592 return FALSE; 1593 } 1594 /* Set up the virtual timer */ 1595 if (!SmartScheduleStartTimer ()) 1596 { 1597 perror ("scheduling timer"); 1598 return FALSE; 1599 } 1600 /* stop the timer and wait for WaitForSomething to start it */ 1601 SmartScheduleStopTimer (); 1602 return TRUE; 1603#else 1604 return FALSE; 1605#endif 1606} 1607#endif 1608 1609#ifdef SIG_BLOCK 1610static sigset_t PreviousSignalMask; 1611static int BlockedSignalCount; 1612#endif 1613 1614void 1615OsBlockSignals (void) 1616{ 1617#ifdef SIG_BLOCK 1618 if (BlockedSignalCount++ == 0) 1619 { 1620 sigset_t set; 1621 1622 sigemptyset (&set); 1623#ifdef SIGALRM 1624 sigaddset (&set, SIGALRM); 1625#endif 1626#ifdef SIGVTALRM 1627 sigaddset (&set, SIGVTALRM); 1628#endif 1629#ifdef SIGWINCH 1630 sigaddset (&set, SIGWINCH); 1631#endif 1632#ifdef SIGIO 1633 sigaddset (&set, SIGIO); 1634#endif 1635#ifdef SIGTSTP 1636 sigaddset (&set, SIGTSTP); 1637#endif 1638#ifdef SIGTTIN 1639 sigaddset (&set, SIGTTIN); 1640#endif 1641#ifdef SIGTTOU 1642 sigaddset (&set, SIGTTOU); 1643#endif 1644#ifdef SIGCHLD 1645 sigaddset (&set, SIGCHLD); 1646#endif 1647 sigprocmask (SIG_BLOCK, &set, &PreviousSignalMask); 1648 } 1649#endif 1650} 1651 1652void 1653OsReleaseSignals (void) 1654{ 1655#ifdef SIG_BLOCK 1656 if (--BlockedSignalCount == 0) 1657 { 1658 sigprocmask (SIG_SETMASK, &PreviousSignalMask, 0); 1659 } 1660#endif 1661} 1662 1663#if !defined(WIN32) 1664/* 1665 * "safer" versions of system(3), popen(3) and pclose(3) which give up 1666 * all privs before running a command. 1667 * 1668 * This is based on the code in FreeBSD 2.2 libc. 1669 * 1670 * XXX It'd be good to redirect stderr so that it ends up in the log file 1671 * as well. As it is now, xkbcomp messages don't end up in the log file. 1672 */ 1673 1674int 1675System(char *command) 1676{ 1677 int pid, p; 1678#ifdef SIGCHLD 1679 void (*csig)(int); 1680#endif 1681 int status; 1682 1683 if (!command) 1684 return(1); 1685 1686#ifdef SIGCHLD 1687 csig = signal(SIGCHLD, SIG_DFL); 1688 if (csig == SIG_ERR) { 1689 perror("signal"); 1690 return -1; 1691 } 1692#endif 1693 1694#ifdef DEBUG 1695 ErrorF("System: `%s'\n", command); 1696#endif 1697 1698 switch (pid = fork()) { 1699 case -1: /* error */ 1700 p = -1; 1701 case 0: /* child */ 1702 if (setgid(getgid()) == -1) 1703 _exit(127); 1704 if (setuid(getuid()) == -1) 1705 _exit(127); 1706 execl("/bin/sh", "sh", "-c", command, (char *)NULL); 1707 _exit(127); 1708 default: /* parent */ 1709 do { 1710 p = waitpid(pid, &status, 0); 1711 } while (p == -1 && errno == EINTR); 1712 1713 } 1714 1715#ifdef SIGCHLD 1716 if (signal(SIGCHLD, csig) == SIG_ERR) { 1717 perror("signal"); 1718 return -1; 1719 } 1720#endif 1721 1722 return p == -1 ? -1 : status; 1723} 1724 1725static struct pid { 1726 struct pid *next; 1727 FILE *fp; 1728 int pid; 1729} *pidlist; 1730 1731void (*old_alarm)(int) = NULL; /* XXX horrible awful hack */ 1732 1733pointer 1734Popen(char *command, char *type) 1735{ 1736 struct pid *cur; 1737 FILE *iop; 1738 int pdes[2], pid; 1739 1740 if (command == NULL || type == NULL) 1741 return NULL; 1742 1743 if ((*type != 'r' && *type != 'w') || type[1]) 1744 return NULL; 1745 1746 if ((cur = (struct pid *)xalloc(sizeof(struct pid))) == NULL) 1747 return NULL; 1748 1749 if (pipe(pdes) < 0) { 1750 xfree(cur); 1751 return NULL; 1752 } 1753 1754 /* Ignore the smart scheduler while this is going on */ 1755 old_alarm = signal(SIGALRM, SIG_IGN); 1756 if (old_alarm == SIG_ERR) { 1757 perror("signal"); 1758 return NULL; 1759 } 1760 1761 switch (pid = fork()) { 1762 case -1: /* error */ 1763 close(pdes[0]); 1764 close(pdes[1]); 1765 xfree(cur); 1766 if (signal(SIGALRM, old_alarm) == SIG_ERR) 1767 perror("signal"); 1768 return NULL; 1769 case 0: /* child */ 1770 if (setgid(getgid()) == -1) 1771 _exit(127); 1772 if (setuid(getuid()) == -1) 1773 _exit(127); 1774 if (*type == 'r') { 1775 if (pdes[1] != 1) { 1776 /* stdout */ 1777 dup2(pdes[1], 1); 1778 close(pdes[1]); 1779 } 1780 close(pdes[0]); 1781 } else { 1782 if (pdes[0] != 0) { 1783 /* stdin */ 1784 dup2(pdes[0], 0); 1785 close(pdes[0]); 1786 } 1787 close(pdes[1]); 1788 } 1789 execl("/bin/sh", "sh", "-c", command, (char *)NULL); 1790 _exit(127); 1791 } 1792 1793 /* Avoid EINTR during stdio calls */ 1794 OsBlockSignals (); 1795 1796 /* parent */ 1797 if (*type == 'r') { 1798 iop = fdopen(pdes[0], type); 1799 close(pdes[1]); 1800 } else { 1801 iop = fdopen(pdes[1], type); 1802 close(pdes[0]); 1803 } 1804 1805 cur->fp = iop; 1806 cur->pid = pid; 1807 cur->next = pidlist; 1808 pidlist = cur; 1809 1810#ifdef DEBUG 1811 ErrorF("Popen: `%s', fp = %p\n", command, iop); 1812#endif 1813 1814 return iop; 1815} 1816 1817/* fopen that drops privileges */ 1818pointer 1819Fopen(char *file, char *type) 1820{ 1821 FILE *iop; 1822#ifndef HAS_SAVED_IDS_AND_SETEUID 1823 struct pid *cur; 1824 int pdes[2], pid; 1825 1826 if (file == NULL || type == NULL) 1827 return NULL; 1828 1829 if ((*type != 'r' && *type != 'w') || type[1]) 1830 return NULL; 1831 1832 if ((cur = (struct pid *)xalloc(sizeof(struct pid))) == NULL) 1833 return NULL; 1834 1835 if (pipe(pdes) < 0) { 1836 xfree(cur); 1837 return NULL; 1838 } 1839 1840 switch (pid = fork()) { 1841 case -1: /* error */ 1842 close(pdes[0]); 1843 close(pdes[1]); 1844 xfree(cur); 1845 return NULL; 1846 case 0: /* child */ 1847 if (setgid(getgid()) == -1) 1848 _exit(127); 1849 if (setuid(getuid()) == -1) 1850 _exit(127); 1851 if (*type == 'r') { 1852 if (pdes[1] != 1) { 1853 /* stdout */ 1854 dup2(pdes[1], 1); 1855 close(pdes[1]); 1856 } 1857 close(pdes[0]); 1858 } else { 1859 if (pdes[0] != 0) { 1860 /* stdin */ 1861 dup2(pdes[0], 0); 1862 close(pdes[0]); 1863 } 1864 close(pdes[1]); 1865 } 1866 execl("/bin/cat", "cat", file, (char *)NULL); 1867 _exit(127); 1868 } 1869 1870 /* Avoid EINTR during stdio calls */ 1871 OsBlockSignals (); 1872 1873 /* parent */ 1874 if (*type == 'r') { 1875 iop = fdopen(pdes[0], type); 1876 close(pdes[1]); 1877 } else { 1878 iop = fdopen(pdes[1], type); 1879 close(pdes[0]); 1880 } 1881 1882 cur->fp = iop; 1883 cur->pid = pid; 1884 cur->next = pidlist; 1885 pidlist = cur; 1886 1887#ifdef DEBUG 1888 ErrorF("Fopen(%s), fp = %p\n", file, iop); 1889#endif 1890 1891 return iop; 1892#else 1893 int ruid, euid; 1894 1895 ruid = getuid(); 1896 euid = geteuid(); 1897 1898 if (seteuid(ruid) == -1) { 1899 return NULL; 1900 } 1901 iop = fopen(file, type); 1902 1903 if (seteuid(euid) == -1) { 1904 fclose(iop); 1905 return NULL; 1906 } 1907 return iop; 1908#endif /* HAS_SAVED_IDS_AND_SETEUID */ 1909} 1910 1911int 1912Pclose(pointer iop) 1913{ 1914 struct pid *cur, *last; 1915 int pstat; 1916 int pid; 1917 1918#ifdef DEBUG 1919 ErrorF("Pclose: fp = %p\n", iop); 1920#endif 1921 1922 fclose(iop); 1923 1924 for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next) 1925 if (cur->fp == iop) 1926 break; 1927 if (cur == NULL) 1928 return -1; 1929 1930 do { 1931 pid = waitpid(cur->pid, &pstat, 0); 1932 } while (pid == -1 && errno == EINTR); 1933 1934 if (last == NULL) 1935 pidlist = cur->next; 1936 else 1937 last->next = cur->next; 1938 xfree(cur); 1939 1940 /* allow EINTR again */ 1941 OsReleaseSignals (); 1942 1943 if (old_alarm && signal(SIGALRM, old_alarm) == SIG_ERR) { 1944 perror("signal"); 1945 return -1; 1946 } 1947 1948 return pid == -1 ? -1 : pstat; 1949} 1950 1951int 1952Fclose(pointer iop) 1953{ 1954#ifdef HAS_SAVED_IDS_AND_SETEUID 1955 return fclose(iop); 1956#else 1957 return Pclose(iop); 1958#endif 1959} 1960 1961#endif /* !WIN32 */ 1962 1963 1964/* 1965 * CheckUserParameters: check for long command line arguments and long 1966 * environment variables. By default, these checks are only done when 1967 * the server's euid != ruid. In 3.3.x, these checks were done in an 1968 * external wrapper utility. 1969 */ 1970 1971/* Consider LD* variables insecure? */ 1972#ifndef REMOVE_ENV_LD 1973#define REMOVE_ENV_LD 1 1974#endif 1975 1976/* Remove long environment variables? */ 1977#ifndef REMOVE_LONG_ENV 1978#define REMOVE_LONG_ENV 1 1979#endif 1980 1981/* 1982 * Disallow stdout or stderr as pipes? It's possible to block the X server 1983 * when piping stdout+stderr to a pipe. 1984 * 1985 * Don't enable this because it looks like it's going to cause problems. 1986 */ 1987#ifndef NO_OUTPUT_PIPES 1988#define NO_OUTPUT_PIPES 0 1989#endif 1990 1991 1992/* Check args and env only if running setuid (euid == 0 && euid != uid) ? */ 1993#ifndef CHECK_EUID 1994#ifndef WIN32 1995#define CHECK_EUID 1 1996#else 1997#define CHECK_EUID 0 1998#endif 1999#endif 2000 2001/* 2002 * Maybe the locale can be faked to make isprint(3) report that everything 2003 * is printable? Avoid it by default. 2004 */ 2005#ifndef USE_ISPRINT 2006#define USE_ISPRINT 0 2007#endif 2008 2009#define MAX_ARG_LENGTH 128 2010#define MAX_ENV_LENGTH 256 2011#define MAX_ENV_PATH_LENGTH 2048 /* Limit for *PATH and TERMCAP */ 2012 2013#if USE_ISPRINT 2014#include <ctype.h> 2015#define checkPrintable(c) isprint(c) 2016#else 2017#define checkPrintable(c) (((c) & 0x7f) >= 0x20 && ((c) & 0x7f) != 0x7f) 2018#endif 2019 2020enum BadCode { 2021 NotBad = 0, 2022 UnsafeArg, 2023 ArgTooLong, 2024 UnprintableArg, 2025 EnvTooLong, 2026 OutputIsPipe, 2027 InternalError 2028}; 2029 2030#if defined(VENDORSUPPORT) 2031#define BUGADDRESS VENDORSUPPORT 2032#elif defined(BUILDERADDR) 2033#define BUGADDRESS BUILDERADDR 2034#else 2035#define BUGADDRESS "xorg@freedesktop.org" 2036#endif 2037 2038#define ARGMSG \ 2039 "\nIf the arguments used are valid, and have been rejected incorrectly\n" \ 2040 "please send details of the arguments and why they are valid to\n" \ 2041 "%s. In the meantime, you can start the Xserver as\n" \ 2042 "the \"super user\" (root).\n" 2043 2044#define ENVMSG \ 2045 "\nIf the environment is valid, and have been rejected incorrectly\n" \ 2046 "please send details of the environment and why it is valid to\n" \ 2047 "%s. In the meantime, you can start the Xserver as\n" \ 2048 "the \"super user\" (root).\n" 2049 2050void 2051CheckUserParameters(int argc, char **argv, char **envp) 2052{ 2053 enum BadCode bad = NotBad; 2054 int i = 0, j; 2055 char *a, *e = NULL; 2056#if defined(__QNX__) && !defined(__QNXNTO__) 2057 char cmd_name[64]; 2058#endif 2059 2060#if CHECK_EUID 2061 if (geteuid() == 0 && getuid() != geteuid()) 2062#endif 2063 { 2064 /* Check each argv[] */ 2065 for (i = 1; i < argc; i++) { 2066 if (strcmp(argv[i], "-fp") == 0) 2067 { 2068 i++; /* continue with next argument. skip the length check */ 2069 if (i >= argc) 2070 break; 2071 } else 2072 { 2073 if (strlen(argv[i]) > MAX_ARG_LENGTH) { 2074 bad = ArgTooLong; 2075 break; 2076 } 2077 } 2078 a = argv[i]; 2079 while (*a) { 2080 if (checkPrintable(*a) == 0) { 2081 bad = UnprintableArg; 2082 break; 2083 } 2084 a++; 2085 } 2086 if (bad) 2087 break; 2088 } 2089 if (!bad) { 2090 /* Check each envp[] */ 2091 for (i = 0; envp[i]; i++) { 2092 2093 /* Check for bad environment variables and values */ 2094#if REMOVE_ENV_LD 2095 while (envp[i] && (strncmp(envp[i], "LD", 2) == 0)) { 2096#ifdef ENVDEBUG 2097 ErrorF("CheckUserParameters: removing %s from the " 2098 "environment\n", strtok(envp[i], "=")); 2099#endif 2100 for (j = i; envp[j]; j++) { 2101 envp[j] = envp[j+1]; 2102 } 2103 } 2104#endif 2105 if (envp[i] && (strlen(envp[i]) > MAX_ENV_LENGTH)) { 2106#if REMOVE_LONG_ENV 2107#ifdef ENVDEBUG 2108 ErrorF("CheckUserParameters: removing %s from the " 2109 "environment\n", strtok(envp[i], "=")); 2110#endif 2111 for (j = i; envp[j]; j++) { 2112 envp[j] = envp[j+1]; 2113 } 2114 i--; 2115#else 2116 char *eq; 2117 int len; 2118 2119 eq = strchr(envp[i], '='); 2120 if (!eq) 2121 continue; 2122 len = eq - envp[i]; 2123 e = malloc(len + 1); 2124 if (!e) { 2125 bad = InternalError; 2126 break; 2127 } 2128 strncpy(e, envp[i], len); 2129 e[len] = 0; 2130 if (len >= 4 && 2131 (strcmp(e + len - 4, "PATH") == 0 || 2132 strcmp(e, "TERMCAP") == 0)) { 2133 if (strlen(envp[i]) > MAX_ENV_PATH_LENGTH) { 2134 bad = EnvTooLong; 2135 break; 2136 } else { 2137 free(e); 2138 } 2139 } else { 2140 bad = EnvTooLong; 2141 break; 2142 } 2143#endif 2144 } 2145 } 2146 } 2147#if NO_OUTPUT_PIPES 2148 if (!bad) { 2149 struct stat buf; 2150 2151 if (fstat(fileno(stdout), &buf) == 0 && S_ISFIFO(buf.st_mode)) 2152 bad = OutputIsPipe; 2153 if (fstat(fileno(stderr), &buf) == 0 && S_ISFIFO(buf.st_mode)) 2154 bad = OutputIsPipe; 2155 } 2156#endif 2157 } 2158 switch (bad) { 2159 case NotBad: 2160 return; 2161 case UnsafeArg: 2162 ErrorF("Command line argument number %d is unsafe\n", i); 2163 ErrorF(ARGMSG, BUGADDRESS); 2164 break; 2165 case ArgTooLong: 2166 ErrorF("Command line argument number %d is too long\n", i); 2167 ErrorF(ARGMSG, BUGADDRESS); 2168 break; 2169 case UnprintableArg: 2170 ErrorF("Command line argument number %d contains unprintable" 2171 " characters\n", i); 2172 ErrorF(ARGMSG, BUGADDRESS); 2173 break; 2174 case EnvTooLong: 2175 ErrorF("Environment variable `%s' is too long\n", e); 2176 ErrorF(ENVMSG, BUGADDRESS); 2177 break; 2178 case OutputIsPipe: 2179 ErrorF("Stdout and/or stderr is a pipe\n"); 2180 break; 2181 case InternalError: 2182 ErrorF("Internal Error\n"); 2183 break; 2184 default: 2185 ErrorF("Unknown error\n"); 2186 ErrorF(ARGMSG, BUGADDRESS); 2187 ErrorF(ENVMSG, BUGADDRESS); 2188 break; 2189 } 2190 FatalError("X server aborted because of unsafe environment\n"); 2191} 2192 2193/* 2194 * CheckUserAuthorization: check if the user is allowed to start the 2195 * X server. This usually means some sort of PAM checking, and it is 2196 * usually only done for setuid servers (uid != euid). 2197 */ 2198 2199#ifdef USE_PAM 2200#include <security/pam_appl.h> 2201#include <security/pam_misc.h> 2202#include <pwd.h> 2203#endif /* USE_PAM */ 2204 2205void 2206CheckUserAuthorization(void) 2207{ 2208#ifdef USE_PAM 2209 static struct pam_conv conv = { 2210 misc_conv, 2211 NULL 2212 }; 2213 2214 pam_handle_t *pamh = NULL; 2215 struct passwd *pw; 2216 int retval; 2217 2218 if (getuid() != geteuid()) { 2219 pw = getpwuid(getuid()); 2220 if (pw == NULL) 2221 FatalError("getpwuid() failed for uid %d\n", getuid()); 2222 2223 retval = pam_start("xserver", pw->pw_name, &conv, &pamh); 2224 if (retval != PAM_SUCCESS) 2225 FatalError("pam_start() failed.\n" 2226 "\tMissing or mangled PAM config file or module?\n"); 2227 2228 retval = pam_authenticate(pamh, 0); 2229 if (retval != PAM_SUCCESS) { 2230 pam_end(pamh, retval); 2231 FatalError("PAM authentication failed, cannot start X server.\n" 2232 "\tPerhaps you do not have console ownership?\n"); 2233 } 2234 2235 retval = pam_acct_mgmt(pamh, 0); 2236 if (retval != PAM_SUCCESS) { 2237 pam_end(pamh, retval); 2238 FatalError("PAM authentication failed, cannot start X server.\n" 2239 "\tPerhaps you do not have console ownership?\n"); 2240 } 2241 2242 /* this is not a session, so do not do session management */ 2243 pam_end(pamh, PAM_SUCCESS); 2244 } 2245#endif 2246} 2247 2248#ifdef __SCO__ 2249#include <fcntl.h> 2250 2251static void 2252lockit (int fd, short what) 2253{ 2254 struct flock lck; 2255 2256 lck.l_whence = 0; 2257 lck.l_start = 0; 2258 lck.l_len = 1; 2259 lck.l_type = what; 2260 2261 (void)fcntl (fd, F_SETLKW, &lck); 2262} 2263 2264/* SCO OpenServer 5 lacks pread/pwrite. Emulate them. */ 2265ssize_t 2266pread (int fd, void *buf, size_t nbytes, off_t offset) 2267{ 2268 off_t saved; 2269 ssize_t ret; 2270 2271 lockit (fd, F_RDLCK); 2272 saved = lseek (fd, 0, SEEK_CUR); 2273 lseek (fd, offset, SEEK_SET); 2274 ret = read (fd, buf, nbytes); 2275 lseek (fd, saved, SEEK_SET); 2276 lockit (fd, F_UNLCK); 2277 2278 return ret; 2279} 2280 2281ssize_t 2282pwrite (int fd, const void *buf, size_t nbytes, off_t offset) 2283{ 2284 off_t saved; 2285 ssize_t ret; 2286 2287 lockit (fd, F_WRLCK); 2288 saved = lseek (fd, 0, SEEK_CUR); 2289 lseek (fd, offset, SEEK_SET); 2290 ret = write (fd, buf, nbytes); 2291 lseek (fd, saved, SEEK_SET); 2292 lockit (fd, F_UNLCK); 2293 2294 return ret; 2295} 2296#endif /* __SCO__ */ 2297