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