First import
[xorg_rtime.git] / xorg-server-1.4 / os / utils.c
blob3bb7dbebaaece908214dd12c5af7828d2c7f9a88
1 /*
3 Copyright 1987, 1998 The Open Group
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.
11 The above copyright notice and this permission notice shall be included
12 in all copies or substantial portions of the Software.
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.
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.
28 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
29 Copyright 1994 Quarterdeck Office Systems.
31 All Rights Reserved
33 Permission to use, copy, modify, and distribute this software and its
34 documentation for any purpose and without fee is hereby granted,
35 provided that the above copyright notice appear in all copies and that
36 both that copyright notice and this permission notice appear in
37 supporting documentation, and that the names of Digital and
38 Quarterdeck not be used in advertising or publicity pertaining to
39 distribution of the software without specific, written prior
40 permission.
42 DIGITAL AND QUARTERDECK DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
43 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
44 FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT
45 OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
46 OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
47 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
48 OR PERFORMANCE OF THIS SOFTWARE.
52 #ifdef HAVE_DIX_CONFIG_H
53 #include <dix-config.h>
54 #endif
56 #ifdef __CYGWIN__
57 #include <stdlib.h>
58 #include <signal.h>
59 #endif
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>
104 #if defined(DGUX)
105 #include <sys/resource.h>
106 #include <netdb.h>
107 #endif
109 #include <stdlib.h> /* for malloc() */
111 #if defined(TCPCONN) || defined(STREAMSCONN)
112 # ifndef WIN32
113 # include <netdb.h>
114 # endif
115 #endif
117 #include "opaque.h"
119 #ifdef SMART_SCHEDULE
120 #include "dixstruct.h"
121 #endif
123 #ifdef XKB
124 #include <xkbsrv.h>
125 #endif
126 #ifdef XCSECURITY
127 #include "securitysrv.h"
128 #endif
130 #ifdef RENDER
131 #include "picture.h"
132 #endif
134 #ifdef XPRINT
135 #include "DiPrint.h"
136 #endif
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
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
241 #define X_INCLUDE_NETDB_H
242 #include <X11/Xos_r.h>
244 #include <errno.h>
246 Bool CoreDump;
248 #ifdef PANORAMIX
249 Bool PanoramiXExtensionDisabledHack = FALSE;
250 #endif
252 int auditTrailLevel = 1;
254 _X_EXPORT Bool Must_have_memory = FALSE;
256 #ifdef AIXV3
257 int SyncOn = 0;
258 extern int SelectWaitTime;
259 #endif
261 #if defined(SVR4) || defined(__linux__) || defined(CSRG_BASED)
262 #define HAS_SAVED_IDS_AND_SETEUID
263 #endif
265 #ifdef MEMBUG
266 #define MEM_FAIL_SCALE 100000
267 long Memory_fail = 0;
268 #include <stdlib.h> /* for random() */
269 #endif
271 static char *dev_tty_from_init = NULL; /* since we need to parse it anyway */
273 OsSigHandlerPtr
274 OsSignal(sig, handler)
275 int sig;
276 OsSigHandlerPtr handler;
278 #ifdef X_NOT_POSIX
279 return signal(sig, handler);
280 #else
281 struct sigaction act, oact;
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 sigaction(sig, &act, &oact);
289 return oact.sa_handler;
290 #endif
293 #ifdef SERVER_LOCK
295 * Explicit support for a server lock file like the ones used for UUCP.
296 * For architectures with virtual terminals that can run more than one
297 * server at a time. This keeps the servers from stomping on each other
298 * if the user forgets to give them different display numbers.
300 #define LOCK_DIR "/tmp"
301 #define LOCK_TMP_PREFIX "/.tX"
302 #define LOCK_PREFIX "/.X"
303 #define LOCK_SUFFIX "-lock"
305 #if defined(DGUX)
306 #include <limits.h>
307 #include <sys/param.h>
308 #endif
310 #ifndef PATH_MAX
311 #ifndef Lynx
312 #include <sys/param.h>
313 #else
314 #include <param.h>
315 #endif
316 #ifndef PATH_MAX
317 #ifdef MAXPATHLEN
318 #define PATH_MAX MAXPATHLEN
319 #else
320 #define PATH_MAX 1024
321 #endif
322 #endif
323 #endif
325 static Bool StillLocking = FALSE;
326 static char LockFile[PATH_MAX];
327 static Bool nolock = FALSE;
330 * LockServer --
331 * Check if the server lock file exists. If so, check if the PID
332 * contained inside is valid. If so, then die. Otherwise, create
333 * the lock file containing the PID.
335 void
336 LockServer(void)
338 char tmp[PATH_MAX], pid_str[12];
339 int lfd, i, haslock, l_pid, t;
340 char *tmppath = NULL;
341 int len;
342 char port[20];
344 if (nolock) return;
346 * Path names
348 tmppath = LOCK_DIR;
350 sprintf(port, "%d", atoi(display));
351 len = strlen(LOCK_PREFIX) > strlen(LOCK_TMP_PREFIX) ? strlen(LOCK_PREFIX) :
352 strlen(LOCK_TMP_PREFIX);
353 len += strlen(tmppath) + strlen(port) + strlen(LOCK_SUFFIX) + 1;
354 if (len > sizeof(LockFile))
355 FatalError("Display name `%s' is too long\n", port);
356 (void)sprintf(tmp, "%s" LOCK_TMP_PREFIX "%s" LOCK_SUFFIX, tmppath, port);
357 (void)sprintf(LockFile, "%s" LOCK_PREFIX "%s" LOCK_SUFFIX, tmppath, port);
360 * Create a temporary file containing our PID. Attempt three times
361 * to create the file.
363 StillLocking = TRUE;
364 i = 0;
365 do {
366 i++;
367 lfd = open(tmp, O_CREAT | O_EXCL | O_WRONLY, 0644);
368 if (lfd < 0)
369 sleep(2);
370 else
371 break;
372 } while (i < 3);
373 if (lfd < 0) {
374 unlink(tmp);
375 i = 0;
376 do {
377 i++;
378 lfd = open(tmp, O_CREAT | O_EXCL | O_WRONLY, 0644);
379 if (lfd < 0)
380 sleep(2);
381 else
382 break;
383 } while (i < 3);
385 if (lfd < 0)
386 FatalError("Could not create lock file in %s\n", tmp);
387 (void) sprintf(pid_str, "%10ld\n", (long)getpid());
388 (void) write(lfd, pid_str, 11);
389 #ifndef USE_CHMOD
390 (void) fchmod(lfd, 0444);
391 #else
392 (void) chmod(tmp, 0444);
393 #endif
394 (void) close(lfd);
397 * OK. Now the tmp file exists. Try three times to move it in place
398 * for the lock.
400 i = 0;
401 haslock = 0;
402 while ((!haslock) && (i++ < 3)) {
403 haslock = (link(tmp,LockFile) == 0);
404 if (haslock) {
406 * We're done.
408 break;
410 else {
412 * Read the pid from the existing file
414 lfd = open(LockFile, O_RDONLY);
415 if (lfd < 0) {
416 unlink(tmp);
417 FatalError("Can't read lock file %s\n", LockFile);
419 pid_str[0] = '\0';
420 if (read(lfd, pid_str, 11) != 11) {
422 * Bogus lock file.
424 unlink(LockFile);
425 close(lfd);
426 continue;
428 pid_str[11] = '\0';
429 sscanf(pid_str, "%d", &l_pid);
430 close(lfd);
433 * Now try to kill the PID to see if it exists.
435 errno = 0;
436 t = kill(l_pid, 0);
437 if ((t< 0) && (errno == ESRCH)) {
439 * Stale lock file.
441 unlink(LockFile);
442 continue;
444 else if (((t < 0) && (errno == EPERM)) || (t == 0)) {
446 * Process is still active.
448 unlink(tmp);
449 FatalError("Server is already active for display %s\n%s %s\n%s\n",
450 port, "\tIf this server is no longer running, remove",
451 LockFile, "\tand start again.");
455 unlink(tmp);
456 if (!haslock)
457 FatalError("Could not create server lock file: %s\n", LockFile);
458 StillLocking = FALSE;
462 * UnlockServer --
463 * Remove the server lock file.
465 void
466 UnlockServer(void)
468 if (nolock) return;
470 if (!StillLocking){
472 (void) unlink(LockFile);
475 #endif /* SERVER_LOCK */
477 /* Force connections to close on SIGHUP from init */
479 /*ARGSUSED*/
480 SIGVAL
481 AutoResetServer (int sig)
483 int olderrno = errno;
485 dispatchException |= DE_RESET;
486 isItTimeToYield = TRUE;
487 #ifdef GPROF
488 chdir ("/tmp");
489 exit (0);
490 #endif
491 #if defined(SYSV) && defined(X_NOT_POSIX)
492 OsSignal (SIGHUP, AutoResetServer);
493 #endif
494 errno = olderrno;
497 /* Force connections to close and then exit on SIGTERM, SIGINT */
499 /*ARGSUSED*/
500 _X_EXPORT SIGVAL
501 GiveUp(int sig)
503 int olderrno = errno;
505 dispatchException |= DE_TERMINATE;
506 isItTimeToYield = TRUE;
507 #if defined(SYSV) && defined(X_NOT_POSIX)
508 if (sig)
509 OsSignal(sig, SIG_IGN);
510 #endif
511 errno = olderrno;
514 #if defined WIN32 && defined __MINGW32__
515 _X_EXPORT CARD32
516 GetTimeInMillis (void)
518 return GetTickCount ();
520 #else
521 _X_EXPORT CARD32
522 GetTimeInMillis(void)
524 struct timeval tv;
526 #ifdef MONOTONIC_CLOCK
527 struct timespec tp;
528 if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
529 return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000L);
530 #endif
532 X_GETTIMEOFDAY(&tv);
533 return(tv.tv_sec * 1000) + (tv.tv_usec / 1000);
535 #endif
537 _X_EXPORT void
538 AdjustWaitForDelay (pointer waitTime, unsigned long newdelay)
540 static struct timeval delay_val;
541 struct timeval **wt = (struct timeval **) waitTime;
542 unsigned long olddelay;
544 if (*wt == NULL)
546 delay_val.tv_sec = newdelay / 1000;
547 delay_val.tv_usec = 1000 * (newdelay % 1000);
548 *wt = &delay_val;
550 else
552 olddelay = (*wt)->tv_sec * 1000 + (*wt)->tv_usec / 1000;
553 if (newdelay < olddelay)
555 (*wt)->tv_sec = newdelay / 1000;
556 (*wt)->tv_usec = 1000 * (newdelay % 1000);
561 void UseMsg(void)
563 #if !defined(AIXrt) && !defined(AIX386)
564 ErrorF("use: X [:<display>] [option]\n");
565 ErrorF("-a # mouse acceleration (pixels)\n");
566 ErrorF("-ac disable access control restrictions\n");
567 #ifdef MEMBUG
568 ErrorF("-alloc int chance alloc should fail\n");
569 #endif
570 ErrorF("-audit int set audit trail level\n");
571 ErrorF("-auth file select authorization file\n");
572 ErrorF("-br create root window with black background\n");
573 ErrorF("+bs enable any backing store support\n");
574 ErrorF("-bs disable any backing store support\n");
575 ErrorF("-c turns off key-click\n");
576 ErrorF("c # key-click volume (0-100)\n");
577 ErrorF("-cc int default color visual class\n");
578 ErrorF("-co file color database file\n");
579 #ifdef COMMANDLINE_CHALLENGED_OPERATING_SYSTEMS
580 ErrorF("-config file read options from file\n");
581 #endif
582 ErrorF("-core generate core dump on fatal error\n");
583 ErrorF("-dpi int screen resolution in dots per inch\n");
584 #ifdef DPMSExtension
585 ErrorF("dpms enables VESA DPMS monitor control\n");
586 ErrorF("-dpms disables VESA DPMS monitor control\n");
587 #endif
588 ErrorF("-deferglyphs [none|all|16] defer loading of [no|all|16-bit] glyphs\n");
589 ErrorF("-f # bell base (0-100)\n");
590 ErrorF("-fc string cursor font\n");
591 ErrorF("-fn string default font name\n");
592 ErrorF("-fp string default font path\n");
593 ErrorF("-help prints message with these options\n");
594 ErrorF("-I ignore all remaining arguments\n");
595 #ifdef RLIMIT_DATA
596 ErrorF("-ld int limit data space to N Kb\n");
597 #endif
598 #ifdef RLIMIT_NOFILE
599 ErrorF("-lf int limit number of open files to N\n");
600 #endif
601 #ifdef RLIMIT_STACK
602 ErrorF("-ls int limit stack space to N Kb\n");
603 #endif
604 #ifdef SERVER_LOCK
605 ErrorF("-nolock disable the locking mechanism\n");
606 #endif
607 #ifndef NOLOGOHACK
608 ErrorF("-logo enable logo in screen saver\n");
609 ErrorF("nologo disable logo in screen saver\n");
610 #endif
611 ErrorF("-nolisten string don't listen on protocol\n");
612 ErrorF("-noreset don't reset after last client exists\n");
613 ErrorF("-reset reset after last client exists\n");
614 ErrorF("-p # screen-saver pattern duration (minutes)\n");
615 ErrorF("-pn accept failure to listen on all ports\n");
616 ErrorF("-nopn reject failure to listen on all ports\n");
617 ErrorF("-r turns off auto-repeat\n");
618 ErrorF("r turns on auto-repeat \n");
619 #ifdef RENDER
620 ErrorF("-render [default|mono|gray|color] set render color alloc policy\n");
621 #endif
622 ErrorF("-s # screen-saver timeout (minutes)\n");
623 #ifdef XCSECURITY
624 ErrorF("-sp file security policy file\n");
625 #endif
626 #ifdef XPRINT
627 PrinterUseMsg();
628 #endif
629 ErrorF("-su disable any save under support\n");
630 ErrorF("-t # mouse threshold (pixels)\n");
631 ErrorF("-terminate terminate at server reset\n");
632 ErrorF("-to # connection time out\n");
633 ErrorF("-tst disable testing extensions\n");
634 ErrorF("ttyxx server started from init on /dev/ttyxx\n");
635 ErrorF("v video blanking for screen-saver\n");
636 ErrorF("-v screen-saver without video blanking\n");
637 ErrorF("-wm WhenMapped default backing-store\n");
638 ErrorF("-wr create root window with white background\n");
639 ErrorF("-x string loads named extension at init time \n");
640 ErrorF("-maxbigreqsize set maximal bigrequest size \n");
641 #ifdef PANORAMIX
642 ErrorF("+xinerama Enable XINERAMA extension\n");
643 ErrorF("-xinerama Disable XINERAMA extension\n");
644 #endif
645 #ifdef SMART_SCHEDULE
646 ErrorF("-dumbSched Disable smart scheduling, enable old behavior\n");
647 ErrorF("-schedInterval int Set scheduler interval in msec\n");
648 #endif
649 ErrorF("+extension name Enable extension\n");
650 ErrorF("-extension name Disable extension\n");
651 #ifdef XDMCP
652 XdmcpUseMsg();
653 #endif
654 #endif /* !AIXrt && ! AIX386 */
655 #ifdef XKB
656 XkbUseMsg();
657 #endif
658 ddxUseMsg();
661 /* This function performs a rudimentary sanity check
662 * on the display name passed in on the command-line,
663 * since this string is used to generate filenames.
664 * It is especially important that the display name
665 * not contain a "/" and not start with a "-".
666 * --kvajk
668 static int
669 VerifyDisplayName(const char *d)
671 if ( d == (char *)0 ) return( 0 ); /* null */
672 if ( *d == '\0' ) return( 0 ); /* empty */
673 if ( *d == '-' ) return( 0 ); /* could be confused for an option */
674 if ( *d == '.' ) return( 0 ); /* must not equal "." or ".." */
675 if ( strchr(d, '/') != (char *)0 ) return( 0 ); /* very important!!! */
676 return( 1 );
680 * This function is responsible for doing initalisation of any global
681 * variables at an very early point of server startup (even before
682 * |ProcessCommandLine()|.
684 void InitGlobals(void)
686 ddxInitGlobals();
691 * This function parses the command line. Handles device-independent fields
692 * and allows ddx to handle additional fields. It is not allowed to modify
693 * argc or any of the strings pointed to by argv.
695 void
696 ProcessCommandLine(int argc, char *argv[])
698 int i, skip;
700 defaultKeyboardControl.autoRepeat = TRUE;
702 #ifdef NO_PART_NET
703 PartialNetwork = FALSE;
704 #else
705 PartialNetwork = TRUE;
706 #endif
708 for ( i = 1; i < argc; i++ )
710 /* call ddx first, so it can peek/override if it wants */
711 if((skip = ddxProcessArgument(argc, argv, i)))
713 i += (skip - 1);
715 else if(argv[i][0] == ':')
717 /* initialize display */
718 display = argv[i];
719 display++;
720 if( ! VerifyDisplayName( display ) ) {
721 ErrorF("Bad display name: %s\n", display);
722 UseMsg();
723 FatalError("Bad display name, exiting: %s\n", display);
726 else if ( strcmp( argv[i], "-a") == 0)
728 if(++i < argc)
729 defaultPointerControl.num = atoi(argv[i]);
730 else
731 UseMsg();
733 else if ( strcmp( argv[i], "-ac") == 0)
735 defeatAccessControl = TRUE;
737 #ifdef MEMBUG
738 else if ( strcmp( argv[i], "-alloc") == 0)
740 if(++i < argc)
741 Memory_fail = atoi(argv[i]);
742 else
743 UseMsg();
745 #endif
746 else if ( strcmp( argv[i], "-audit") == 0)
748 if(++i < argc)
749 auditTrailLevel = atoi(argv[i]);
750 else
751 UseMsg();
753 else if ( strcmp( argv[i], "-auth") == 0)
755 if(++i < argc)
756 InitAuthorization (argv[i]);
757 else
758 UseMsg();
760 else if ( strcmp( argv[i], "-br") == 0)
761 blackRoot = TRUE;
762 else if ( strcmp( argv[i], "+bs") == 0)
763 enableBackingStore = TRUE;
764 else if ( strcmp( argv[i], "-bs") == 0)
765 disableBackingStore = TRUE;
766 else if ( strcmp( argv[i], "c") == 0)
768 if(++i < argc)
769 defaultKeyboardControl.click = atoi(argv[i]);
770 else
771 UseMsg();
773 else if ( strcmp( argv[i], "-c") == 0)
775 defaultKeyboardControl.click = 0;
777 else if ( strcmp( argv[i], "-cc") == 0)
779 if(++i < argc)
780 defaultColorVisualClass = atoi(argv[i]);
781 else
782 UseMsg();
784 else if ( strcmp( argv[i], "-co") == 0)
786 if(++i < argc)
787 rgbPath = argv[i];
788 else
789 UseMsg();
791 else if ( strcmp( argv[i], "-core") == 0)
793 CoreDump = TRUE;
794 #if !defined(WIN32) || !defined(__MINGW32__)
795 struct rlimit core_limit;
796 getrlimit (RLIMIT_CORE, &core_limit);
797 core_limit.rlim_cur = core_limit.rlim_max;
798 setrlimit (RLIMIT_CORE, &core_limit);
799 #endif
801 else if ( strcmp( argv[i], "-dpi") == 0)
803 if(++i < argc)
804 monitorResolution = atoi(argv[i]);
805 else
806 UseMsg();
808 #ifdef DPMSExtension
809 else if ( strcmp( argv[i], "dpms") == 0)
810 DPMSEnabledSwitch = TRUE;
811 else if ( strcmp( argv[i], "-dpms") == 0)
812 DPMSDisabledSwitch = TRUE;
813 #endif
814 else if ( strcmp( argv[i], "-deferglyphs") == 0)
816 if(++i >= argc || !ParseGlyphCachingMode(argv[i]))
817 UseMsg();
819 else if ( strcmp( argv[i], "-f") == 0)
821 if(++i < argc)
822 defaultKeyboardControl.bell = atoi(argv[i]);
823 else
824 UseMsg();
826 else if ( strcmp( argv[i], "-fc") == 0)
828 if(++i < argc)
829 defaultCursorFont = argv[i];
830 else
831 UseMsg();
833 else if ( strcmp( argv[i], "-fn") == 0)
835 if(++i < argc)
836 defaultTextFont = argv[i];
837 else
838 UseMsg();
840 else if ( strcmp( argv[i], "-fp") == 0)
842 if(++i < argc)
844 defaultFontPath = argv[i];
846 else
847 UseMsg();
849 else if ( strcmp( argv[i], "-help") == 0)
851 UseMsg();
852 exit(0);
854 #ifdef XKB
855 else if ( (skip=XkbProcessArguments(argc,argv,i))!=0 ) {
856 if (skip>0)
857 i+= skip-1;
858 else UseMsg();
860 #endif
861 #ifdef RLIMIT_DATA
862 else if ( strcmp( argv[i], "-ld") == 0)
864 if(++i < argc)
866 limitDataSpace = atoi(argv[i]);
867 if (limitDataSpace > 0)
868 limitDataSpace *= 1024;
870 else
871 UseMsg();
873 #endif
874 #ifdef RLIMIT_NOFILE
875 else if ( strcmp( argv[i], "-lf") == 0)
877 if(++i < argc)
878 limitNoFile = atoi(argv[i]);
879 else
880 UseMsg();
882 #endif
883 #ifdef RLIMIT_STACK
884 else if ( strcmp( argv[i], "-ls") == 0)
886 if(++i < argc)
888 limitStackSpace = atoi(argv[i]);
889 if (limitStackSpace > 0)
890 limitStackSpace *= 1024;
892 else
893 UseMsg();
895 #endif
896 #ifdef SERVER_LOCK
897 else if ( strcmp ( argv[i], "-nolock") == 0)
899 #if !defined(WIN32) && !defined(__CYGWIN__)
900 if (getuid() != 0)
901 ErrorF("Warning: the -nolock option can only be used by root\n");
902 else
903 #endif
904 nolock = TRUE;
906 #endif
907 #ifndef NOLOGOHACK
908 else if ( strcmp( argv[i], "-logo") == 0)
910 logoScreenSaver = 1;
912 else if ( strcmp( argv[i], "nologo") == 0)
914 logoScreenSaver = 0;
916 #endif
917 else if ( strcmp( argv[i], "-nolisten") == 0)
919 if(++i < argc) {
920 if (_XSERVTransNoListen(argv[i]))
921 FatalError ("Failed to disable listen for %s transport",
922 argv[i]);
923 } else
924 UseMsg();
926 else if ( strcmp( argv[i], "-noreset") == 0)
928 dispatchExceptionAtReset = 0;
930 else if ( strcmp( argv[i], "-reset") == 0)
932 dispatchExceptionAtReset = DE_RESET;
934 else if ( strcmp( argv[i], "-p") == 0)
936 if(++i < argc)
937 defaultScreenSaverInterval = ((CARD32)atoi(argv[i])) *
938 MILLI_PER_MIN;
939 else
940 UseMsg();
942 else if ( strcmp( argv[i], "-pn") == 0)
943 PartialNetwork = TRUE;
944 else if ( strcmp( argv[i], "-nopn") == 0)
945 PartialNetwork = FALSE;
946 else if ( strcmp( argv[i], "r") == 0)
947 defaultKeyboardControl.autoRepeat = TRUE;
948 else if ( strcmp( argv[i], "-r") == 0)
949 defaultKeyboardControl.autoRepeat = FALSE;
950 else if ( strcmp( argv[i], "-s") == 0)
952 if(++i < argc)
953 defaultScreenSaverTime = ((CARD32)atoi(argv[i])) *
954 MILLI_PER_MIN;
955 else
956 UseMsg();
958 else if ( strcmp( argv[i], "-su") == 0)
959 disableSaveUnders = TRUE;
960 else if ( strcmp( argv[i], "-t") == 0)
962 if(++i < argc)
963 defaultPointerControl.threshold = atoi(argv[i]);
964 else
965 UseMsg();
967 else if ( strcmp( argv[i], "-terminate") == 0)
969 dispatchExceptionAtReset = DE_TERMINATE;
971 else if ( strcmp( argv[i], "-to") == 0)
973 if(++i < argc)
974 TimeOutValue = ((CARD32)atoi(argv[i])) * MILLI_PER_SECOND;
975 else
976 UseMsg();
978 else if ( strcmp( argv[i], "-tst") == 0)
980 noTestExtensions = TRUE;
982 else if ( strcmp( argv[i], "v") == 0)
983 defaultScreenSaverBlanking = PreferBlanking;
984 else if ( strcmp( argv[i], "-v") == 0)
985 defaultScreenSaverBlanking = DontPreferBlanking;
986 else if ( strcmp( argv[i], "-wm") == 0)
987 defaultBackingStore = WhenMapped;
988 else if ( strcmp( argv[i], "-wr") == 0)
989 whiteRoot = TRUE;
990 else if ( strcmp( argv[i], "-maxbigreqsize") == 0) {
991 if(++i < argc) {
992 long reqSizeArg = atol(argv[i]);
994 /* Request size > 128MB does not make much sense... */
995 if( reqSizeArg > 0L && reqSizeArg < 128L ) {
996 maxBigRequestSize = (reqSizeArg * 1048576L) - 1L;
998 else
1000 UseMsg();
1003 else
1005 UseMsg();
1008 #ifdef PANORAMIX
1009 else if ( strcmp( argv[i], "+xinerama") == 0){
1010 noPanoramiXExtension = FALSE;
1012 else if ( strcmp( argv[i], "-xinerama") == 0){
1013 noPanoramiXExtension = TRUE;
1015 else if ( strcmp( argv[i], "-disablexineramaextension") == 0){
1016 PanoramiXExtensionDisabledHack = TRUE;
1018 #endif
1019 else if ( strcmp( argv[i], "-x") == 0)
1021 if(++i >= argc)
1022 UseMsg();
1023 /* For U**x, which doesn't support dynamic loading, there's nothing
1024 * to do when we see a -x. Either the extension is linked in or
1025 * it isn't */
1027 else if ( strcmp( argv[i], "-I") == 0)
1029 /* ignore all remaining arguments */
1030 break;
1032 else if (strncmp (argv[i], "tty", 3) == 0)
1034 /* just in case any body is interested */
1035 dev_tty_from_init = argv[i];
1037 #ifdef XDMCP
1038 else if ((skip = XdmcpOptions(argc, argv, i)) != i)
1040 i = skip - 1;
1042 #endif
1043 #ifdef XPRINT
1044 else if ((skip = PrinterOptions(argc, argv, i)) != i)
1046 i = skip - 1;
1048 #endif
1049 #ifdef XCSECURITY
1050 else if ((skip = XSecurityOptions(argc, argv, i)) != i)
1052 i = skip - 1;
1054 #endif
1055 #ifdef AIXV3
1056 else if ( strcmp( argv[i], "-timeout") == 0)
1058 if(++i < argc)
1059 SelectWaitTime = atoi(argv[i]);
1060 else
1061 UseMsg();
1063 else if ( strcmp( argv[i], "-sync") == 0)
1065 SyncOn++;
1067 #endif
1068 #ifdef SMART_SCHEDULE
1069 else if ( strcmp( argv[i], "-dumbSched") == 0)
1071 SmartScheduleDisable = TRUE;
1073 else if ( strcmp( argv[i], "-schedInterval") == 0)
1075 if (++i < argc)
1077 SmartScheduleInterval = atoi(argv[i]);
1078 SmartScheduleSlice = SmartScheduleInterval;
1080 else
1081 UseMsg();
1083 else if ( strcmp( argv[i], "-schedMax") == 0)
1085 if (++i < argc)
1087 SmartScheduleMaxSlice = atoi(argv[i]);
1089 else
1090 UseMsg();
1092 #endif
1093 #ifdef RENDER
1094 else if ( strcmp( argv[i], "-render" ) == 0)
1096 if (++i < argc)
1098 int policy = PictureParseCmapPolicy (argv[i]);
1100 if (policy != PictureCmapPolicyInvalid)
1101 PictureCmapPolicy = policy;
1102 else
1103 UseMsg ();
1105 else
1106 UseMsg ();
1108 #endif
1109 else if ( strcmp( argv[i], "+extension") == 0)
1111 if (++i < argc)
1113 if (!EnableDisableExtension(argv[i], TRUE))
1114 EnableDisableExtensionError(argv[i], TRUE);
1116 else
1117 UseMsg();
1119 else if ( strcmp( argv[i], "-extension") == 0)
1121 if (++i < argc)
1123 if (!EnableDisableExtension(argv[i], FALSE))
1124 EnableDisableExtensionError(argv[i], FALSE);
1126 else
1127 UseMsg();
1129 else
1131 ErrorF("Unrecognized option: %s\n", argv[i]);
1132 UseMsg();
1133 FatalError("Unrecognized option: %s\n", argv[i]);
1138 #ifdef COMMANDLINE_CHALLENGED_OPERATING_SYSTEMS
1139 static void
1140 InsertFileIntoCommandLine(
1141 int *resargc, char ***resargv,
1142 int prefix_argc, char **prefix_argv,
1143 char *filename,
1144 int suffix_argc, char **suffix_argv)
1146 struct stat st;
1147 FILE *f;
1148 char *p;
1149 char *q;
1150 int insert_argc;
1151 char *buf;
1152 int len;
1153 int i;
1155 f = fopen(filename, "r");
1156 if (!f)
1157 FatalError("Can't open option file %s\n", filename);
1159 fstat(fileno(f), &st);
1161 buf = (char *) xalloc((unsigned) st.st_size + 1);
1162 if (!buf)
1163 FatalError("Out of Memory\n");
1165 len = fread(buf, 1, (unsigned) st.st_size, f);
1167 fclose(f);
1169 if (len < 0)
1170 FatalError("Error reading option file %s\n", filename);
1172 buf[len] = '\0';
1174 p = buf;
1175 q = buf;
1176 insert_argc = 0;
1178 while (*p)
1180 while (isspace(*p))
1181 p++;
1182 if (!*p)
1183 break;
1184 if (*p == '#')
1186 while (*p && *p != '\n')
1187 p++;
1188 } else
1190 while (*p && !isspace(*p))
1191 *q++ = *p++;
1192 /* Since p and q might still be pointing at the same place, we */
1193 /* need to step p over the whitespace now before we add the null. */
1194 if (*p)
1195 p++;
1196 *q++ = '\0';
1197 insert_argc++;
1201 buf = (char *) xrealloc(buf, q - buf);
1202 if (!buf)
1203 FatalError("Out of memory reallocing option buf\n");
1205 *resargc = prefix_argc + insert_argc + suffix_argc;
1206 *resargv = (char **) xalloc((*resargc + 1) * sizeof(char *));
1207 if (!*resargv)
1208 FatalError("Out of Memory\n");
1210 memcpy(*resargv, prefix_argv, prefix_argc * sizeof(char *));
1212 p = buf;
1213 for (i = 0; i < insert_argc; i++)
1215 (*resargv)[prefix_argc + i] = p;
1216 p += strlen(p) + 1;
1219 memcpy(*resargv + prefix_argc + insert_argc,
1220 suffix_argv, suffix_argc * sizeof(char *));
1222 (*resargv)[*resargc] = NULL;
1223 } /* end InsertFileIntoCommandLine */
1226 void
1227 ExpandCommandLine(int *pargc, char ***pargv)
1229 int i;
1231 #if !defined(WIN32) && !defined(__CYGWIN__)
1232 if (getuid() != geteuid())
1233 return;
1234 #endif
1236 for (i = 1; i < *pargc; i++)
1238 if ( (0 == strcmp((*pargv)[i], "-config")) && (i < (*pargc - 1)) )
1240 InsertFileIntoCommandLine(pargc, pargv,
1241 i, *pargv,
1242 (*pargv)[i+1], /* filename */
1243 *pargc - i - 2, *pargv + i + 2);
1244 i--;
1247 } /* end ExpandCommandLine */
1248 #endif
1250 /* Implement a simple-minded font authorization scheme. The authorization
1251 name is "hp-hostname-1", the contents are simply the host name. */
1253 set_font_authorizations(char **authorizations, int *authlen, pointer client)
1255 #define AUTHORIZATION_NAME "hp-hostname-1"
1256 #if defined(TCPCONN) || defined(STREAMSCONN)
1257 static char *result = NULL;
1258 static char *p = NULL;
1260 if (p == NULL)
1262 char hname[1024], *hnameptr;
1263 unsigned int len;
1264 #if defined(IPv6) && defined(AF_INET6)
1265 struct addrinfo hints, *ai = NULL;
1266 #else
1267 struct hostent *host;
1268 #ifdef XTHREADS_NEEDS_BYNAMEPARAMS
1269 _Xgethostbynameparams hparams;
1270 #endif
1271 #endif
1273 gethostname(hname, 1024);
1274 #if defined(IPv6) && defined(AF_INET6)
1275 bzero(&hints, sizeof(hints));
1276 hints.ai_flags = AI_CANONNAME;
1277 if (getaddrinfo(hname, NULL, &hints, &ai) == 0) {
1278 hnameptr = ai->ai_canonname;
1279 } else {
1280 hnameptr = hname;
1282 #else
1283 host = _XGethostbyname(hname, hparams);
1284 if (host == NULL)
1285 hnameptr = hname;
1286 else
1287 hnameptr = host->h_name;
1288 #endif
1290 len = strlen(hnameptr) + 1;
1291 result = xalloc(len + sizeof(AUTHORIZATION_NAME) + 4);
1293 p = result;
1294 *p++ = sizeof(AUTHORIZATION_NAME) >> 8;
1295 *p++ = sizeof(AUTHORIZATION_NAME) & 0xff;
1296 *p++ = (len) >> 8;
1297 *p++ = (len & 0xff);
1299 memmove(p, AUTHORIZATION_NAME, sizeof(AUTHORIZATION_NAME));
1300 p += sizeof(AUTHORIZATION_NAME);
1301 memmove(p, hnameptr, len);
1302 p += len;
1303 #if defined(IPv6) && defined(AF_INET6)
1304 if (ai) {
1305 freeaddrinfo(ai);
1307 #endif
1309 *authlen = p - result;
1310 *authorizations = result;
1311 return 1;
1312 #else /* TCPCONN */
1313 return 0;
1314 #endif /* TCPCONN */
1317 /* XALLOC -- X's internal memory allocator. Why does it return unsigned
1318 * long * instead of the more common char *? Well, if you read K&R you'll
1319 * see they say that alloc must return a pointer "suitable for conversion"
1320 * to whatever type you really want. In a full-blown generic allocator
1321 * there's no way to solve the alignment problems without potentially
1322 * wasting lots of space. But we have a more limited problem. We know
1323 * we're only ever returning pointers to structures which will have to
1324 * be long word aligned. So we are making a stronger guarantee. It might
1325 * have made sense to make Xalloc return char * to conform with people's
1326 * expectations of malloc, but this makes lint happier.
1329 #ifndef INTERNAL_MALLOC
1331 _X_EXPORT void *
1332 Xalloc(unsigned long amount)
1334 register pointer ptr;
1336 if ((long)amount <= 0) {
1337 return (unsigned long *)NULL;
1339 /* aligned extra on long word boundary */
1340 amount = (amount + (sizeof(long) - 1)) & ~(sizeof(long) - 1);
1341 #ifdef MEMBUG
1342 if (!Must_have_memory && Memory_fail &&
1343 ((random() % MEM_FAIL_SCALE) < Memory_fail))
1344 return (unsigned long *)NULL;
1345 #endif
1346 if ((ptr = (pointer)malloc(amount))) {
1347 return (unsigned long *)ptr;
1349 if (Must_have_memory)
1350 FatalError("Out of memory");
1351 return (unsigned long *)NULL;
1354 /*****************
1355 * XNFalloc
1356 * "no failure" realloc, alternate interface to Xalloc w/o Must_have_memory
1357 *****************/
1359 _X_EXPORT void *
1360 XNFalloc(unsigned long amount)
1362 register pointer ptr;
1364 if ((long)amount <= 0)
1366 return (unsigned long *)NULL;
1368 /* aligned extra on long word boundary */
1369 amount = (amount + (sizeof(long) - 1)) & ~(sizeof(long) - 1);
1370 ptr = (pointer)malloc(amount);
1371 if (!ptr)
1373 FatalError("Out of memory");
1375 return ((unsigned long *)ptr);
1378 /*****************
1379 * Xcalloc
1380 *****************/
1382 _X_EXPORT void *
1383 Xcalloc(unsigned long amount)
1385 unsigned long *ret;
1387 ret = Xalloc (amount);
1388 if (ret)
1389 bzero ((char *) ret, (int) amount);
1390 return ret;
1393 /*****************
1394 * XNFcalloc
1395 *****************/
1397 _X_EXPORT void *
1398 XNFcalloc(unsigned long amount)
1400 unsigned long *ret;
1402 ret = Xalloc (amount);
1403 if (ret)
1404 bzero ((char *) ret, (int) amount);
1405 else if ((long)amount > 0)
1406 FatalError("Out of memory");
1407 return ret;
1410 /*****************
1411 * Xrealloc
1412 *****************/
1414 _X_EXPORT void *
1415 Xrealloc(pointer ptr, unsigned long amount)
1417 #ifdef MEMBUG
1418 if (!Must_have_memory && Memory_fail &&
1419 ((random() % MEM_FAIL_SCALE) < Memory_fail))
1420 return (unsigned long *)NULL;
1421 #endif
1422 if ((long)amount <= 0)
1424 if (ptr && !amount)
1425 free(ptr);
1426 return (unsigned long *)NULL;
1428 amount = (amount + (sizeof(long) - 1)) & ~(sizeof(long) - 1);
1429 if (ptr)
1430 ptr = (pointer)realloc((char *)ptr, amount);
1431 else
1432 ptr = (pointer)malloc(amount);
1433 if (ptr)
1434 return (unsigned long *)ptr;
1435 if (Must_have_memory)
1436 FatalError("Out of memory");
1437 return (unsigned long *)NULL;
1440 /*****************
1441 * XNFrealloc
1442 * "no failure" realloc, alternate interface to Xrealloc w/o Must_have_memory
1443 *****************/
1445 _X_EXPORT void *
1446 XNFrealloc(pointer ptr, unsigned long amount)
1448 if (( ptr = (pointer)Xrealloc( ptr, amount ) ) == NULL)
1450 if ((long)amount > 0)
1451 FatalError( "Out of memory" );
1453 return ((unsigned long *)ptr);
1456 /*****************
1457 * Xfree
1458 * calls free
1459 *****************/
1461 _X_EXPORT void
1462 Xfree(pointer ptr)
1464 if (ptr)
1465 free((char *)ptr);
1468 void
1469 OsInitAllocator (void)
1471 #ifdef MEMBUG
1472 static int been_here;
1474 /* Check the memory system after each generation */
1475 if (been_here)
1476 CheckMemory ();
1477 else
1478 been_here = 1;
1479 #endif
1481 #endif /* !INTERNAL_MALLOC */
1484 char *
1485 Xstrdup(const char *s)
1487 char *sd;
1489 if (s == NULL)
1490 return NULL;
1492 sd = (char *)Xalloc(strlen(s) + 1);
1493 if (sd != NULL)
1494 strcpy(sd, s);
1495 return sd;
1499 _X_EXPORT char *
1500 XNFstrdup(const char *s)
1502 char *sd;
1504 if (s == NULL)
1505 return NULL;
1507 sd = (char *)XNFalloc(strlen(s) + 1);
1508 strcpy(sd, s);
1509 return sd;
1512 #ifdef SMART_SCHEDULE
1514 unsigned long SmartScheduleIdleCount;
1515 Bool SmartScheduleIdle;
1516 Bool SmartScheduleTimerStopped;
1518 #ifdef SIGVTALRM
1519 #define SMART_SCHEDULE_POSSIBLE
1520 #endif
1522 #ifdef SMART_SCHEDULE_POSSIBLE
1523 #define SMART_SCHEDULE_SIGNAL SIGALRM
1524 #define SMART_SCHEDULE_TIMER ITIMER_REAL
1525 #endif
1527 static void
1528 SmartScheduleStopTimer (void)
1530 #ifdef SMART_SCHEDULE_POSSIBLE
1531 struct itimerval timer;
1533 timer.it_interval.tv_sec = 0;
1534 timer.it_interval.tv_usec = 0;
1535 timer.it_value.tv_sec = 0;
1536 timer.it_value.tv_usec = 0;
1537 (void) setitimer (ITIMER_REAL, &timer, 0);
1538 SmartScheduleTimerStopped = TRUE;
1539 #endif
1542 Bool
1543 SmartScheduleStartTimer (void)
1545 #ifdef SMART_SCHEDULE_POSSIBLE
1546 struct itimerval timer;
1548 SmartScheduleTimerStopped = FALSE;
1549 timer.it_interval.tv_sec = 0;
1550 timer.it_interval.tv_usec = SmartScheduleInterval * 1000;
1551 timer.it_value.tv_sec = 0;
1552 timer.it_value.tv_usec = SmartScheduleInterval * 1000;
1553 return setitimer (ITIMER_REAL, &timer, 0) >= 0;
1554 #endif
1555 return FALSE;
1558 #ifdef SMART_SCHEDULE_POSSIBLE
1559 static void
1560 SmartScheduleTimer (int sig)
1562 int olderrno = errno;
1564 SmartScheduleTime += SmartScheduleInterval;
1565 if (SmartScheduleIdle)
1567 SmartScheduleStopTimer ();
1569 errno = olderrno;
1571 #endif
1573 Bool
1574 SmartScheduleInit (void)
1576 #ifdef SMART_SCHEDULE_POSSIBLE
1577 struct sigaction act;
1579 if (SmartScheduleDisable)
1580 return TRUE;
1582 bzero ((char *) &act, sizeof(struct sigaction));
1584 /* Set up the timer signal function */
1585 act.sa_handler = SmartScheduleTimer;
1586 sigemptyset (&act.sa_mask);
1587 sigaddset (&act.sa_mask, SMART_SCHEDULE_SIGNAL);
1588 if (sigaction (SMART_SCHEDULE_SIGNAL, &act, 0) < 0)
1590 perror ("sigaction for smart scheduler");
1591 return FALSE;
1593 /* Set up the virtual timer */
1594 if (!SmartScheduleStartTimer ())
1596 perror ("scheduling timer");
1597 return FALSE;
1599 /* stop the timer and wait for WaitForSomething to start it */
1600 SmartScheduleStopTimer ();
1601 return TRUE;
1602 #else
1603 return FALSE;
1604 #endif
1606 #endif
1608 #ifdef SIG_BLOCK
1609 static sigset_t PreviousSignalMask;
1610 static int BlockedSignalCount;
1611 #endif
1613 void
1614 OsBlockSignals (void)
1616 #ifdef SIG_BLOCK
1617 if (BlockedSignalCount++ == 0)
1619 sigset_t set;
1621 sigemptyset (&set);
1622 #ifdef SIGALRM
1623 sigaddset (&set, SIGALRM);
1624 #endif
1625 #ifdef SIGVTALRM
1626 sigaddset (&set, SIGVTALRM);
1627 #endif
1628 #ifdef SIGWINCH
1629 sigaddset (&set, SIGWINCH);
1630 #endif
1631 #ifdef SIGIO
1632 sigaddset (&set, SIGIO);
1633 #endif
1634 #ifdef SIGTSTP
1635 sigaddset (&set, SIGTSTP);
1636 #endif
1637 #ifdef SIGTTIN
1638 sigaddset (&set, SIGTTIN);
1639 #endif
1640 #ifdef SIGTTOU
1641 sigaddset (&set, SIGTTOU);
1642 #endif
1643 #ifdef SIGCHLD
1644 sigaddset (&set, SIGCHLD);
1645 #endif
1646 sigprocmask (SIG_BLOCK, &set, &PreviousSignalMask);
1648 #endif
1651 void
1652 OsReleaseSignals (void)
1654 #ifdef SIG_BLOCK
1655 if (--BlockedSignalCount == 0)
1657 sigprocmask (SIG_SETMASK, &PreviousSignalMask, 0);
1659 #endif
1662 #if !defined(WIN32)
1664 * "safer" versions of system(3), popen(3) and pclose(3) which give up
1665 * all privs before running a command.
1667 * This is based on the code in FreeBSD 2.2 libc.
1669 * XXX It'd be good to redirect stderr so that it ends up in the log file
1670 * as well. As it is now, xkbcomp messages don't end up in the log file.
1674 System(char *command)
1676 int pid, p;
1677 #ifdef SIGCHLD
1678 void (*csig)(int);
1679 #endif
1680 int status;
1682 if (!command)
1683 return(1);
1685 #ifdef SIGCHLD
1686 csig = signal(SIGCHLD, SIG_DFL);
1687 #endif
1689 #ifdef DEBUG
1690 ErrorF("System: `%s'\n", command);
1691 #endif
1693 switch (pid = fork()) {
1694 case -1: /* error */
1695 p = -1;
1696 case 0: /* child */
1697 if (setgid(getgid()) == -1)
1698 _exit(127);
1699 if (setuid(getuid()) == -1)
1700 _exit(127);
1701 execl("/bin/sh", "sh", "-c", command, (char *)NULL);
1702 _exit(127);
1703 default: /* parent */
1704 do {
1705 p = waitpid(pid, &status, 0);
1706 } while (p == -1 && errno == EINTR);
1710 #ifdef SIGCHLD
1711 signal(SIGCHLD, csig);
1712 #endif
1714 return p == -1 ? -1 : status;
1717 static struct pid {
1718 struct pid *next;
1719 FILE *fp;
1720 int pid;
1721 } *pidlist;
1723 pointer
1724 Popen(char *command, char *type)
1726 struct pid *cur;
1727 FILE *iop;
1728 int pdes[2], pid;
1730 if (command == NULL || type == NULL)
1731 return NULL;
1733 if ((*type != 'r' && *type != 'w') || type[1])
1734 return NULL;
1736 if ((cur = (struct pid *)xalloc(sizeof(struct pid))) == NULL)
1737 return NULL;
1739 if (pipe(pdes) < 0) {
1740 xfree(cur);
1741 return NULL;
1744 switch (pid = fork()) {
1745 case -1: /* error */
1746 close(pdes[0]);
1747 close(pdes[1]);
1748 xfree(cur);
1749 return NULL;
1750 case 0: /* child */
1751 if (setgid(getgid()) == -1)
1752 _exit(127);
1753 if (setuid(getuid()) == -1)
1754 _exit(127);
1755 if (*type == 'r') {
1756 if (pdes[1] != 1) {
1757 /* stdout */
1758 dup2(pdes[1], 1);
1759 close(pdes[1]);
1761 close(pdes[0]);
1762 } else {
1763 if (pdes[0] != 0) {
1764 /* stdin */
1765 dup2(pdes[0], 0);
1766 close(pdes[0]);
1768 close(pdes[1]);
1770 execl("/bin/sh", "sh", "-c", command, (char *)NULL);
1771 _exit(127);
1774 /* Avoid EINTR during stdio calls */
1775 OsBlockSignals ();
1777 /* parent */
1778 if (*type == 'r') {
1779 iop = fdopen(pdes[0], type);
1780 close(pdes[1]);
1781 } else {
1782 iop = fdopen(pdes[1], type);
1783 close(pdes[0]);
1786 cur->fp = iop;
1787 cur->pid = pid;
1788 cur->next = pidlist;
1789 pidlist = cur;
1791 #ifdef DEBUG
1792 ErrorF("Popen: `%s', fp = %p\n", command, iop);
1793 #endif
1795 return iop;
1798 /* fopen that drops privileges */
1799 pointer
1800 Fopen(char *file, char *type)
1802 FILE *iop;
1803 #ifndef HAS_SAVED_IDS_AND_SETEUID
1804 struct pid *cur;
1805 int pdes[2], pid;
1807 if (file == NULL || type == NULL)
1808 return NULL;
1810 if ((*type != 'r' && *type != 'w') || type[1])
1811 return NULL;
1813 if ((cur = (struct pid *)xalloc(sizeof(struct pid))) == NULL)
1814 return NULL;
1816 if (pipe(pdes) < 0) {
1817 xfree(cur);
1818 return NULL;
1821 switch (pid = fork()) {
1822 case -1: /* error */
1823 close(pdes[0]);
1824 close(pdes[1]);
1825 xfree(cur);
1826 return NULL;
1827 case 0: /* child */
1828 if (setgid(getgid()) == -1)
1829 _exit(127);
1830 if (setuid(getuid()) == -1)
1831 _exit(127);
1832 if (*type == 'r') {
1833 if (pdes[1] != 1) {
1834 /* stdout */
1835 dup2(pdes[1], 1);
1836 close(pdes[1]);
1838 close(pdes[0]);
1839 } else {
1840 if (pdes[0] != 0) {
1841 /* stdin */
1842 dup2(pdes[0], 0);
1843 close(pdes[0]);
1845 close(pdes[1]);
1847 execl("/bin/cat", "cat", file, (char *)NULL);
1848 _exit(127);
1851 /* Avoid EINTR during stdio calls */
1852 OsBlockSignals ();
1854 /* parent */
1855 if (*type == 'r') {
1856 iop = fdopen(pdes[0], type);
1857 close(pdes[1]);
1858 } else {
1859 iop = fdopen(pdes[1], type);
1860 close(pdes[0]);
1863 cur->fp = iop;
1864 cur->pid = pid;
1865 cur->next = pidlist;
1866 pidlist = cur;
1868 #ifdef DEBUG
1869 ErrorF("Fopen(%s), fp = %p\n", file, iop);
1870 #endif
1872 return iop;
1873 #else
1874 int ruid, euid;
1876 ruid = getuid();
1877 euid = geteuid();
1879 if (seteuid(ruid) == -1) {
1880 return NULL;
1882 iop = fopen(file, type);
1884 if (seteuid(euid) == -1) {
1885 fclose(iop);
1886 return NULL;
1888 return iop;
1889 #endif /* HAS_SAVED_IDS_AND_SETEUID */
1893 Pclose(pointer iop)
1895 struct pid *cur, *last;
1896 int pstat;
1897 int pid;
1899 #ifdef DEBUG
1900 ErrorF("Pclose: fp = %p\n", iop);
1901 #endif
1903 fclose(iop);
1905 for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next)
1906 if (cur->fp == iop)
1907 break;
1908 if (cur == NULL)
1909 return -1;
1911 do {
1912 pid = waitpid(cur->pid, &pstat, 0);
1913 } while (pid == -1 && errno == EINTR);
1915 if (last == NULL)
1916 pidlist = cur->next;
1917 else
1918 last->next = cur->next;
1919 xfree(cur);
1921 /* allow EINTR again */
1922 OsReleaseSignals ();
1924 return pid == -1 ? -1 : pstat;
1927 int
1928 Fclose(pointer iop)
1930 #ifdef HAS_SAVED_IDS_AND_SETEUID
1931 return fclose(iop);
1932 #else
1933 return Pclose(iop);
1934 #endif
1937 #endif /* !WIN32 */
1941 * CheckUserParameters: check for long command line arguments and long
1942 * environment variables. By default, these checks are only done when
1943 * the server's euid != ruid. In 3.3.x, these checks were done in an
1944 * external wrapper utility.
1947 /* Consider LD* variables insecure? */
1948 #ifndef REMOVE_ENV_LD
1949 #define REMOVE_ENV_LD 1
1950 #endif
1952 /* Remove long environment variables? */
1953 #ifndef REMOVE_LONG_ENV
1954 #define REMOVE_LONG_ENV 1
1955 #endif
1958 * Disallow stdout or stderr as pipes? It's possible to block the X server
1959 * when piping stdout+stderr to a pipe.
1961 * Don't enable this because it looks like it's going to cause problems.
1963 #ifndef NO_OUTPUT_PIPES
1964 #define NO_OUTPUT_PIPES 0
1965 #endif
1968 /* Check args and env only if running setuid (euid == 0 && euid != uid) ? */
1969 #ifndef CHECK_EUID
1970 #ifndef WIN32
1971 #define CHECK_EUID 1
1972 #else
1973 #define CHECK_EUID 0
1974 #endif
1975 #endif
1978 * Maybe the locale can be faked to make isprint(3) report that everything
1979 * is printable? Avoid it by default.
1981 #ifndef USE_ISPRINT
1982 #define USE_ISPRINT 0
1983 #endif
1985 #define MAX_ARG_LENGTH 128
1986 #define MAX_ENV_LENGTH 256
1987 #define MAX_ENV_PATH_LENGTH 2048 /* Limit for *PATH and TERMCAP */
1989 #if USE_ISPRINT
1990 #include <ctype.h>
1991 #define checkPrintable(c) isprint(c)
1992 #else
1993 #define checkPrintable(c) (((c) & 0x7f) >= 0x20 && ((c) & 0x7f) != 0x7f)
1994 #endif
1996 enum BadCode {
1997 NotBad = 0,
1998 UnsafeArg,
1999 ArgTooLong,
2000 UnprintableArg,
2001 EnvTooLong,
2002 OutputIsPipe,
2003 InternalError
2006 #if defined(VENDORSUPPORT)
2007 #define BUGADDRESS VENDORSUPPORT
2008 #elif defined(BUILDERADDR)
2009 #define BUGADDRESS BUILDERADDR
2010 #else
2011 #define BUGADDRESS "xorg@freedesktop.org"
2012 #endif
2014 #define ARGMSG \
2015 "\nIf the arguments used are valid, and have been rejected incorrectly\n" \
2016 "please send details of the arguments and why they are valid to\n" \
2017 "%s. In the meantime, you can start the Xserver as\n" \
2018 "the \"super user\" (root).\n"
2020 #define ENVMSG \
2021 "\nIf the environment is valid, and have been rejected incorrectly\n" \
2022 "please send details of the environment and why it is valid to\n" \
2023 "%s. In the meantime, you can start the Xserver as\n" \
2024 "the \"super user\" (root).\n"
2026 void
2027 CheckUserParameters(int argc, char **argv, char **envp)
2029 enum BadCode bad = NotBad;
2030 int i = 0, j;
2031 char *a, *e = NULL;
2032 #if defined(__QNX__) && !defined(__QNXNTO__)
2033 char cmd_name[64];
2034 #endif
2036 #if CHECK_EUID
2037 if (geteuid() == 0 && getuid() != geteuid())
2038 #endif
2040 /* Check each argv[] */
2041 for (i = 1; i < argc; i++) {
2042 if (strcmp(argv[i], "-fp") == 0)
2044 i++; /* continue with next argument. skip the length check */
2045 if (i >= argc)
2046 break;
2047 } else
2049 if (strlen(argv[i]) > MAX_ARG_LENGTH) {
2050 bad = ArgTooLong;
2051 break;
2054 a = argv[i];
2055 while (*a) {
2056 if (checkPrintable(*a) == 0) {
2057 bad = UnprintableArg;
2058 break;
2060 a++;
2062 if (bad)
2063 break;
2065 if (!bad) {
2066 /* Check each envp[] */
2067 for (i = 0; envp[i]; i++) {
2069 /* Check for bad environment variables and values */
2070 #if REMOVE_ENV_LD
2071 while (envp[i] && (strncmp(envp[i], "LD", 2) == 0)) {
2072 #ifdef ENVDEBUG
2073 ErrorF("CheckUserParameters: removing %s from the "
2074 "environment\n", strtok(envp[i], "="));
2075 #endif
2076 for (j = i; envp[j]; j++) {
2077 envp[j] = envp[j+1];
2080 #endif
2081 if (envp[i] && (strlen(envp[i]) > MAX_ENV_LENGTH)) {
2082 #if REMOVE_LONG_ENV
2083 #ifdef ENVDEBUG
2084 ErrorF("CheckUserParameters: removing %s from the "
2085 "environment\n", strtok(envp[i], "="));
2086 #endif
2087 for (j = i; envp[j]; j++) {
2088 envp[j] = envp[j+1];
2090 i--;
2091 #else
2092 char *eq;
2093 int len;
2095 eq = strchr(envp[i], '=');
2096 if (!eq)
2097 continue;
2098 len = eq - envp[i];
2099 e = malloc(len + 1);
2100 if (!e) {
2101 bad = InternalError;
2102 break;
2104 strncpy(e, envp[i], len);
2105 e[len] = 0;
2106 if (len >= 4 &&
2107 (strcmp(e + len - 4, "PATH") == 0 ||
2108 strcmp(e, "TERMCAP") == 0)) {
2109 if (strlen(envp[i]) > MAX_ENV_PATH_LENGTH) {
2110 bad = EnvTooLong;
2111 break;
2112 } else {
2113 free(e);
2115 } else {
2116 bad = EnvTooLong;
2117 break;
2119 #endif
2123 #if NO_OUTPUT_PIPES
2124 if (!bad) {
2125 struct stat buf;
2127 if (fstat(fileno(stdout), &buf) == 0 && S_ISFIFO(buf.st_mode))
2128 bad = OutputIsPipe;
2129 if (fstat(fileno(stderr), &buf) == 0 && S_ISFIFO(buf.st_mode))
2130 bad = OutputIsPipe;
2132 #endif
2134 switch (bad) {
2135 case NotBad:
2136 return;
2137 case UnsafeArg:
2138 ErrorF("Command line argument number %d is unsafe\n", i);
2139 ErrorF(ARGMSG, BUGADDRESS);
2140 break;
2141 case ArgTooLong:
2142 ErrorF("Command line argument number %d is too long\n", i);
2143 ErrorF(ARGMSG, BUGADDRESS);
2144 break;
2145 case UnprintableArg:
2146 ErrorF("Command line argument number %d contains unprintable"
2147 " characters\n", i);
2148 ErrorF(ARGMSG, BUGADDRESS);
2149 break;
2150 case EnvTooLong:
2151 ErrorF("Environment variable `%s' is too long\n", e);
2152 ErrorF(ENVMSG, BUGADDRESS);
2153 break;
2154 case OutputIsPipe:
2155 ErrorF("Stdout and/or stderr is a pipe\n");
2156 break;
2157 case InternalError:
2158 ErrorF("Internal Error\n");
2159 break;
2160 default:
2161 ErrorF("Unknown error\n");
2162 ErrorF(ARGMSG, BUGADDRESS);
2163 ErrorF(ENVMSG, BUGADDRESS);
2164 break;
2166 FatalError("X server aborted because of unsafe environment\n");
2170 * CheckUserAuthorization: check if the user is allowed to start the
2171 * X server. This usually means some sort of PAM checking, and it is
2172 * usually only done for setuid servers (uid != euid).
2175 #ifdef USE_PAM
2176 #include <security/pam_appl.h>
2177 #include <security/pam_misc.h>
2178 #include <pwd.h>
2179 #endif /* USE_PAM */
2181 void
2182 CheckUserAuthorization(void)
2184 #ifdef USE_PAM
2185 static struct pam_conv conv = {
2186 misc_conv,
2187 NULL
2190 pam_handle_t *pamh = NULL;
2191 struct passwd *pw;
2192 int retval;
2194 if (getuid() != geteuid()) {
2195 pw = getpwuid(getuid());
2196 if (pw == NULL)
2197 FatalError("getpwuid() failed for uid %d\n", getuid());
2199 retval = pam_start("xserver", pw->pw_name, &conv, &pamh);
2200 if (retval != PAM_SUCCESS)
2201 FatalError("pam_start() failed.\n"
2202 "\tMissing or mangled PAM config file or module?\n");
2204 retval = pam_authenticate(pamh, 0);
2205 if (retval != PAM_SUCCESS) {
2206 pam_end(pamh, retval);
2207 FatalError("PAM authentication failed, cannot start X server.\n"
2208 "\tPerhaps you do not have console ownership?\n");
2211 retval = pam_acct_mgmt(pamh, 0);
2212 if (retval != PAM_SUCCESS) {
2213 pam_end(pamh, retval);
2214 FatalError("PAM authentication failed, cannot start X server.\n"
2215 "\tPerhaps you do not have console ownership?\n");
2218 /* this is not a session, so do not do session management */
2219 pam_end(pamh, PAM_SUCCESS);
2221 #endif
2224 #ifdef __SCO__
2225 #include <fcntl.h>
2227 static void
2228 lockit (int fd, short what)
2230 struct flock lck;
2232 lck.l_whence = 0;
2233 lck.l_start = 0;
2234 lck.l_len = 1;
2235 lck.l_type = what;
2237 (void)fcntl (fd, F_SETLKW, &lck);
2240 /* SCO OpenServer 5 lacks pread/pwrite. Emulate them. */
2241 ssize_t
2242 pread (int fd, void *buf, size_t nbytes, off_t offset)
2244 off_t saved;
2245 ssize_t ret;
2247 lockit (fd, F_RDLCK);
2248 saved = lseek (fd, 0, SEEK_CUR);
2249 lseek (fd, offset, SEEK_SET);
2250 ret = read (fd, buf, nbytes);
2251 lseek (fd, saved, SEEK_SET);
2252 lockit (fd, F_UNLCK);
2254 return ret;
2257 ssize_t
2258 pwrite (int fd, const void *buf, size_t nbytes, off_t offset)
2260 off_t saved;
2261 ssize_t ret;
2263 lockit (fd, F_WRLCK);
2264 saved = lseek (fd, 0, SEEK_CUR);
2265 lseek (fd, offset, SEEK_SET);
2266 ret = write (fd, buf, nbytes);
2267 lseek (fd, saved, SEEK_SET);
2268 lockit (fd, F_UNLCK);
2270 return ret;
2272 #endif /* __SCO__ */