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
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
27
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
28
Copyright 1994 Quarterdeck Office Systems.
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
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.
51
#ifdef HAVE_DIX_CONFIG_H
52
#include <dix-config.h>
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...
62
__stdcall unsigned long GetTickCount(void);
65
#if defined(WIN32) && !defined(__CYGWIN__)
66
#include <X11/Xwinsock.h>
71
#if !defined(WIN32) || !defined(__MINGW32__)
73
#include <sys/resource.h>
74
# define SMART_SCHEDULE_POSSIBLE
81
#include <X11/Xtrans/Xtrans.h>
85
#include "extension.h"
86
#ifdef X_POSIX_C_SOURCE
87
#define _POSIX_C_SOURCE X_POSIX_C_SOURCE
89
#undef _POSIX_C_SOURCE
91
#if defined(_POSIX_SOURCE)
100
#include <sys/wait.h>
102
#if !defined(SYSV) && !defined(WIN32)
103
#include <sys/resource.h>
105
#include <sys/stat.h>
106
#include <ctype.h> /* for isspace */
109
#include <stdlib.h> /* for malloc() */
111
#if defined(TCPCONN) || defined(STREAMSCONN)
119
#include "dixstruct.h"
125
Bool noTestExtensions;
128
Bool noCompositeExtension = FALSE;
132
Bool noDamageExtension = FALSE;
135
Bool noDbeExtension = FALSE;
138
Bool noDPMSExtension = FALSE;
141
Bool noGlxExtension = FALSE;
144
Bool noScreenSaverExtension = FALSE;
147
Bool noMITShmExtension = FALSE;
150
Bool noRRExtension = FALSE;
152
Bool noRenderExtension = FALSE;
155
Bool noSecurityExtension = FALSE;
158
Bool noResExtension = FALSE;
161
Bool noXFree86BigfontExtension = FALSE;
164
Bool noXFree86DGAExtension = FALSE;
167
Bool noXFree86DRIExtension = FALSE;
170
Bool noXFree86VidModeExtension = FALSE;
172
Bool noXFixesExtension = FALSE;
174
/* Xinerama is disabled by default unless enabled via +xinerama */
175
Bool noPanoramiXExtension = TRUE;
178
Bool noSELinuxExtension = FALSE;
179
int selinuxEnforcingState = SELINUX_MODE_DEFAULT;
182
Bool noXvExtension = FALSE;
185
Bool noDRI2Extension = FALSE;
188
Bool noGEExtension = FALSE;
190
#define X_INCLUDE_NETDB_H
191
#include <X11/Xos_r.h>
197
Bool enableIndirectGLX = TRUE;
200
Bool PanoramiXExtensionDisabledHack = FALSE;
203
int auditTrailLevel = 1;
207
sig_atomic_t inSignalContext = FALSE;
209
#if defined(SVR4) || defined(__linux__) || defined(CSRG_BASED)
210
#define HAS_SAVED_IDS_AND_SETEUID
214
OsSignal(int sig, OsSigHandlerPtr handler)
216
#if defined(WIN32) && !defined(__CYGWIN__)
217
return signal(sig, handler);
219
struct sigaction act, oact;
221
sigemptyset(&act.sa_mask);
222
if (handler != SIG_IGN)
223
sigaddset(&act.sa_mask, sig);
225
act.sa_handler = handler;
226
if (sigaction(sig, &act, &oact))
228
return oact.sa_handler;
233
* Explicit support for a server lock file like the ones used for UUCP.
234
* For architectures with virtual terminals that can run more than one
235
* server at a time. This keeps the servers from stomping on each other
236
* if the user forgets to give them different display numbers.
238
#define LOCK_DIR "/tmp"
239
#define LOCK_TMP_PREFIX "/.tX"
240
#define LOCK_PREFIX "/.X"
241
#define LOCK_SUFFIX "-lock"
243
#if !defined(WIN32) || defined(__CYGWIN__)
255
#else /* LOCK_SERVER */
256
static Bool StillLocking = FALSE;
257
static char LockFile[PATH_MAX];
258
static Bool nolock = FALSE;
262
* Check if the server lock file exists. If so, check if the PID
263
* contained inside is valid. If so, then die. Otherwise, create
264
* the lock file containing the PID.
269
char tmp[PATH_MAX], pid_str[12];
270
int lfd, i, haslock, l_pid, t;
271
const char *tmppath = LOCK_DIR;
275
if (nolock || NoListenAll)
280
snprintf(port, sizeof(port), "%d", atoi(display));
281
len = strlen(LOCK_PREFIX) > strlen(LOCK_TMP_PREFIX) ? strlen(LOCK_PREFIX) :
282
strlen(LOCK_TMP_PREFIX);
283
len += strlen(tmppath) + strlen(port) + strlen(LOCK_SUFFIX) + 1;
284
if (len > sizeof(LockFile))
285
FatalError("Display name `%s' is too long\n", port);
286
(void) sprintf(tmp, "%s" LOCK_TMP_PREFIX "%s" LOCK_SUFFIX, tmppath, port);
287
(void) sprintf(LockFile, "%s" LOCK_PREFIX "%s" LOCK_SUFFIX, tmppath, port);
290
* Create a temporary file containing our PID. Attempt three times
291
* to create the file.
297
lfd = open(tmp, O_CREAT | O_EXCL | O_WRONLY, 0644);
308
lfd = open(tmp, O_CREAT | O_EXCL | O_WRONLY, 0644);
316
FatalError("Could not create lock file in %s\n", tmp);
317
snprintf(pid_str, sizeof(pid_str), "%10ld\n", (long) getpid());
318
if (write(lfd, pid_str, 11) != 11)
319
FatalError("Could not write pid to lock file in %s\n", tmp);
320
(void) fchmod(lfd, 0444);
324
* OK. Now the tmp file exists. Try three times to move it in place
329
while ((!haslock) && (i++ < 3)) {
330
haslock = (link(tmp, LockFile) == 0);
339
* Read the pid from the existing file
341
lfd = open(LockFile, O_RDONLY | O_NOFOLLOW);
344
FatalError("Can't read lock file %s\n", LockFile);
347
if (read(lfd, pid_str, 11) != 11) {
356
sscanf(pid_str, "%d", &l_pid);
360
* Now try to kill the PID to see if it exists.
364
if ((t < 0) && (errno == ESRCH)) {
371
else if (((t < 0) && (errno == EPERM)) || (t == 0)) {
373
* Process is still active.
377
("Server is already active for display %s\n%s %s\n%s\n",
378
port, "\tIf this server is no longer running, remove",
379
LockFile, "\tand start again.");
385
FatalError("Could not create server lock file: %s\n", LockFile);
386
StillLocking = FALSE;
391
* Remove the server lock file.
396
if (nolock || NoListenAll)
401
(void) unlink(LockFile);
404
#endif /* LOCK_SERVER */
406
/* Force connections to close on SIGHUP from init */
409
AutoResetServer(int sig)
411
int olderrno = errno;
413
dispatchException |= DE_RESET;
414
isItTimeToYield = TRUE;
418
/* Force connections to close and then exit on SIGTERM, SIGINT */
423
int olderrno = errno;
425
dispatchException |= DE_TERMINATE;
426
isItTimeToYield = TRUE;
430
#if (defined WIN32 && defined __MINGW32__) || defined(__CYGWIN__)
432
GetTimeInMillis(void)
434
return GetTickCount();
437
GetTimeInMicros(void)
439
return (CARD64) GetTickCount() * 1000;
443
GetTimeInMillis(void)
447
#ifdef MONOTONIC_CLOCK
449
static clockid_t clockid;
452
#ifdef CLOCK_MONOTONIC_COARSE
453
if (clock_getres(CLOCK_MONOTONIC_COARSE, &tp) == 0 &&
454
(tp.tv_nsec / 1000) <= 1000 &&
455
clock_gettime(CLOCK_MONOTONIC_COARSE, &tp) == 0)
456
clockid = CLOCK_MONOTONIC_COARSE;
459
if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
460
clockid = CLOCK_MONOTONIC;
464
if (clockid != ~0L && clock_gettime(clockid, &tp) == 0)
465
return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000L);
469
return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
473
GetTimeInMicros(void)
476
#ifdef MONOTONIC_CLOCK
478
static clockid_t clockid;
481
if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
482
clockid = CLOCK_MONOTONIC;
486
if (clockid != ~0L && clock_gettime(clockid, &tp) == 0)
487
return (CARD64) tp.tv_sec * (CARD64)1000000 + tp.tv_nsec / 1000;
491
return (CARD64) tv.tv_sec * (CARD64)1000000000 + (CARD64) tv.tv_usec * 1000;
496
AdjustWaitForDelay(void *waitTime, unsigned long newdelay)
498
static struct timeval delay_val;
499
struct timeval **wt = (struct timeval **) waitTime;
500
unsigned long olddelay;
503
delay_val.tv_sec = newdelay / 1000;
504
delay_val.tv_usec = 1000 * (newdelay % 1000);
508
olddelay = (*wt)->tv_sec * 1000 + (*wt)->tv_usec / 1000;
509
if (newdelay < olddelay) {
510
(*wt)->tv_sec = newdelay / 1000;
511
(*wt)->tv_usec = 1000 * (newdelay % 1000);
519
ErrorF("use: X [:<display>] [option]\n");
520
ErrorF("-a # default pointer acceleration (factor)\n");
521
ErrorF("-ac disable access control restrictions\n");
522
ErrorF("-audit int set audit trail level\n");
523
ErrorF("-auth file select authorization file\n");
524
ErrorF("-br create root window with black background\n");
525
ErrorF("+bs enable any backing store support\n");
526
ErrorF("-bs disable any backing store support\n");
527
ErrorF("-c turns off key-click\n");
528
ErrorF("c # key-click volume (0-100)\n");
529
ErrorF("-cc int default color visual class\n");
530
ErrorF("-nocursor disable the cursor\n");
531
ErrorF("-core generate core dump on fatal error\n");
532
ErrorF("-displayfd fd file descriptor to write display number to when ready to connect\n");
533
ErrorF("-dpi int screen resolution in dots per inch\n");
535
ErrorF("-dpms disables VESA DPMS monitor control\n");
538
("-deferglyphs [none|all|16] defer loading of [no|all|16-bit] glyphs\n");
539
ErrorF("-f # bell base (0-100)\n");
540
ErrorF("-fc string cursor font\n");
541
ErrorF("-fn string default font name\n");
542
ErrorF("-fp string default font path\n");
543
ErrorF("-help prints message with these options\n");
544
ErrorF("+iglx Allow creating indirect GLX contexts (default)\n");
545
ErrorF("-iglx Prohibit creating indirect GLX contexts\n");
546
ErrorF("-I ignore all remaining arguments\n");
548
ErrorF("-ld int limit data space to N Kb\n");
551
ErrorF("-lf int limit number of open files to N\n");
554
ErrorF("-ls int limit stack space to N Kb\n");
557
ErrorF("-nolock disable the locking mechanism\n");
559
ErrorF("-nolisten string don't listen on protocol\n");
560
ErrorF("-noreset don't reset after last client exists\n");
561
ErrorF("-background [none] create root window with no background\n");
562
ErrorF("-reset reset after last client exists\n");
563
ErrorF("-p # screen-saver pattern duration (minutes)\n");
564
ErrorF("-pn accept failure to listen on all ports\n");
565
ErrorF("-nopn reject failure to listen on all ports\n");
566
ErrorF("-r turns off auto-repeat\n");
567
ErrorF("r turns on auto-repeat \n");
568
ErrorF("-render [default|mono|gray|color] set render color alloc policy\n");
569
ErrorF("-retro start with classic stipple and cursor\n");
570
ErrorF("-s # screen-saver timeout (minutes)\n");
571
ErrorF("-seat string seat to run on\n");
572
ErrorF("-t # default pointer threshold (pixels/t)\n");
573
ErrorF("-terminate terminate at server reset\n");
574
ErrorF("-to # connection time out\n");
575
ErrorF("-tst disable testing extensions\n");
576
ErrorF("ttyxx server started from init on /dev/ttyxx\n");
577
ErrorF("v video blanking for screen-saver\n");
578
ErrorF("-v screen-saver without video blanking\n");
579
ErrorF("-wm WhenMapped default backing-store\n");
580
ErrorF("-wr create root window with white background\n");
581
ErrorF("-maxbigreqsize set maximal bigrequest size \n");
583
ErrorF("+xinerama Enable XINERAMA extension\n");
584
ErrorF("-xinerama Disable XINERAMA extension\n");
587
("-dumbSched Disable smart scheduling, enable old behavior\n");
588
ErrorF("-schedInterval int Set scheduler interval in msec\n");
589
ErrorF("-sigstop Enable SIGSTOP based startup\n");
590
ErrorF("+extension name Enable extension\n");
591
ErrorF("-extension name Disable extension\n");
599
/* This function performs a rudimentary sanity check
600
* on the display name passed in on the command-line,
601
* since this string is used to generate filenames.
602
* It is especially important that the display name
603
* not contain a "/" and not start with a "-".
607
VerifyDisplayName(const char *d)
610
int period_found = FALSE;
611
int after_period = 0;
616
return 0; /* empty */
618
return 0; /* could be confused for an option */
620
return 0; /* must not equal "." or ".." */
621
if (strchr(d, '/') != (char *) 0)
622
return 0; /* very important!!! */
624
/* Since we run atoi() on the display later, only allow
625
for digits, or exception of :0.0 and similar (two decimal points max)
627
for (i = 0; i < strlen(d); i++) {
628
if (!isdigit(d[i])) {
629
if (d[i] != '.' || period_found)
632
} else if (period_found)
635
if (after_period > 2)
639
/* don't allow for :0. */
640
if (period_found && after_period == 0)
643
if (atol(d) > INT_MAX)
650
* This function parses the command line. Handles device-independent fields
651
* and allows ddx to handle additional fields. It is not allowed to modify
652
* argc or any of the strings pointed to by argv.
655
ProcessCommandLine(int argc, char *argv[])
659
defaultKeyboardControl.autoRepeat = TRUE;
662
PartialNetwork = FALSE;
664
PartialNetwork = TRUE;
667
for (i = 1; i < argc; i++) {
668
/* call ddx first, so it can peek/override if it wants */
669
if ((skip = ddxProcessArgument(argc, argv, i))) {
672
else if (argv[i][0] == ':') {
673
/* initialize display */
675
explicit_display = TRUE;
677
if (!VerifyDisplayName(display)) {
678
ErrorF("Bad display name: %s\n", display);
680
FatalError("Bad display name, exiting: %s\n", display);
683
else if (strcmp(argv[i], "-a") == 0) {
685
defaultPointerControl.num = atoi(argv[i]);
689
else if (strcmp(argv[i], "-ac") == 0) {
690
defeatAccessControl = TRUE;
692
else if (strcmp(argv[i], "-audit") == 0) {
694
auditTrailLevel = atoi(argv[i]);
698
else if (strcmp(argv[i], "-auth") == 0) {
700
InitAuthorization(argv[i]);
704
else if (strcmp(argv[i], "-br") == 0); /* default */
705
else if (strcmp(argv[i], "+bs") == 0)
706
enableBackingStore = TRUE;
707
else if (strcmp(argv[i], "-bs") == 0)
708
disableBackingStore = TRUE;
709
else if (strcmp(argv[i], "c") == 0) {
711
defaultKeyboardControl.click = atoi(argv[i]);
715
else if (strcmp(argv[i], "-c") == 0) {
716
defaultKeyboardControl.click = 0;
718
else if (strcmp(argv[i], "-cc") == 0) {
720
defaultColorVisualClass = atoi(argv[i]);
724
else if (strcmp(argv[i], "-core") == 0) {
725
#if !defined(WIN32) || !defined(__MINGW32__)
726
struct rlimit core_limit;
728
getrlimit(RLIMIT_CORE, &core_limit);
729
core_limit.rlim_cur = core_limit.rlim_max;
730
setrlimit(RLIMIT_CORE, &core_limit);
734
else if (strcmp(argv[i], "-nocursor") == 0) {
735
EnableCursor = FALSE;
737
else if (strcmp(argv[i], "-dpi") == 0) {
739
monitorResolution = atoi(argv[i]);
743
else if (strcmp(argv[i], "-displayfd") == 0) {
745
displayfd = atoi(argv[i]);
754
else if (strcmp(argv[i], "dpms") == 0)
755
/* ignored for compatibility */ ;
756
else if (strcmp(argv[i], "-dpms") == 0)
757
DPMSDisabledSwitch = TRUE;
759
else if (strcmp(argv[i], "-deferglyphs") == 0) {
760
if (++i >= argc || !ParseGlyphCachingMode(argv[i]))
763
else if (strcmp(argv[i], "-f") == 0) {
765
defaultKeyboardControl.bell = atoi(argv[i]);
769
else if (strcmp(argv[i], "-fc") == 0) {
771
defaultCursorFont = argv[i];
775
else if (strcmp(argv[i], "-fn") == 0) {
777
defaultTextFont = argv[i];
781
else if (strcmp(argv[i], "-fp") == 0) {
783
defaultFontPath = argv[i];
788
else if (strcmp(argv[i], "-help") == 0) {
792
else if (strcmp(argv[i], "+iglx") == 0)
793
enableIndirectGLX = TRUE;
794
else if (strcmp(argv[i], "-iglx") == 0)
795
enableIndirectGLX = FALSE;
796
else if ((skip = XkbProcessArguments(argc, argv, i)) != 0) {
803
else if (strcmp(argv[i], "-ld") == 0) {
805
limitDataSpace = atoi(argv[i]);
806
if (limitDataSpace > 0)
807
limitDataSpace *= 1024;
814
else if (strcmp(argv[i], "-lf") == 0) {
816
limitNoFile = atoi(argv[i]);
822
else if (strcmp(argv[i], "-ls") == 0) {
824
limitStackSpace = atoi(argv[i]);
825
if (limitStackSpace > 0)
826
limitStackSpace *= 1024;
833
else if (strcmp(argv[i], "-nolock") == 0) {
834
#if !defined(WIN32) && !defined(__CYGWIN__)
837
("Warning: the -nolock option can only be used by root\n");
843
else if (strcmp(argv[i], "-nolisten") == 0) {
845
if (_XSERVTransNoListen(argv[i]))
846
ErrorF("Failed to disable listen for %s transport",
852
else if (strcmp(argv[i], "-noreset") == 0) {
853
dispatchExceptionAtReset = 0;
855
else if (strcmp(argv[i], "-reset") == 0) {
856
dispatchExceptionAtReset = DE_RESET;
858
else if (strcmp(argv[i], "-p") == 0) {
860
defaultScreenSaverInterval = ((CARD32) atoi(argv[i])) *
865
else if (strcmp(argv[i], "-pogo") == 0) {
866
dispatchException = DE_TERMINATE;
868
else if (strcmp(argv[i], "-pn") == 0)
869
PartialNetwork = TRUE;
870
else if (strcmp(argv[i], "-nopn") == 0)
871
PartialNetwork = FALSE;
872
else if (strcmp(argv[i], "r") == 0)
873
defaultKeyboardControl.autoRepeat = TRUE;
874
else if (strcmp(argv[i], "-r") == 0)
875
defaultKeyboardControl.autoRepeat = FALSE;
876
else if (strcmp(argv[i], "-retro") == 0)
877
party_like_its_1989 = TRUE;
878
else if (strcmp(argv[i], "-s") == 0) {
880
defaultScreenSaverTime = ((CARD32) atoi(argv[i])) *
885
else if (strcmp(argv[i], "-seat") == 0) {
891
else if (strcmp(argv[i], "-t") == 0) {
893
defaultPointerControl.threshold = atoi(argv[i]);
897
else if (strcmp(argv[i], "-terminate") == 0) {
898
dispatchExceptionAtReset = DE_TERMINATE;
900
else if (strcmp(argv[i], "-to") == 0) {
902
TimeOutValue = ((CARD32) atoi(argv[i])) * MILLI_PER_SECOND;
906
else if (strcmp(argv[i], "-tst") == 0) {
907
noTestExtensions = TRUE;
909
else if (strcmp(argv[i], "v") == 0)
910
defaultScreenSaverBlanking = PreferBlanking;
911
else if (strcmp(argv[i], "-v") == 0)
912
defaultScreenSaverBlanking = DontPreferBlanking;
913
else if (strcmp(argv[i], "-wm") == 0)
914
defaultBackingStore = WhenMapped;
915
else if (strcmp(argv[i], "-wr") == 0)
917
else if (strcmp(argv[i], "-background") == 0) {
919
if (!strcmp(argv[i], "none"))
925
else if (strcmp(argv[i], "-maxbigreqsize") == 0) {
927
long reqSizeArg = atol(argv[i]);
929
/* Request size > 128MB does not make much sense... */
930
if (reqSizeArg > 0L && reqSizeArg < 128L) {
931
maxBigRequestSize = (reqSizeArg * 1048576L) - 1L;
942
else if (strcmp(argv[i], "+xinerama") == 0) {
943
noPanoramiXExtension = FALSE;
945
else if (strcmp(argv[i], "-xinerama") == 0) {
946
noPanoramiXExtension = TRUE;
948
else if (strcmp(argv[i], "-disablexineramaextension") == 0) {
949
PanoramiXExtensionDisabledHack = TRUE;
952
else if (strcmp(argv[i], "-I") == 0) {
953
/* ignore all remaining arguments */
956
else if (strncmp(argv[i], "tty", 3) == 0) {
957
/* init supplies us with this useless information */
960
else if ((skip = XdmcpOptions(argc, argv, i)) != i) {
964
#ifdef SMART_SCHEDULE_POSSIBLE
965
else if (strcmp(argv[i], "-dumbSched") == 0) {
966
SmartScheduleDisable = TRUE;
968
else if (strcmp(argv[i], "-schedInterval") == 0) {
970
SmartScheduleInterval = atoi(argv[i]);
971
SmartScheduleSlice = SmartScheduleInterval;
976
else if (strcmp(argv[i], "-schedMax") == 0) {
978
SmartScheduleMaxSlice = atoi(argv[i]);
984
else if (strcmp(argv[i], "-render") == 0) {
986
int policy = PictureParseCmapPolicy(argv[i]);
988
if (policy != PictureCmapPolicyInvalid)
989
PictureCmapPolicy = policy;
996
else if (strcmp(argv[i], "-sigstop") == 0) {
997
RunFromSigStopParent = TRUE;
999
else if (strcmp(argv[i], "+extension") == 0) {
1001
if (!EnableDisableExtension(argv[i], TRUE))
1002
EnableDisableExtensionError(argv[i], TRUE);
1007
else if (strcmp(argv[i], "-extension") == 0) {
1009
if (!EnableDisableExtension(argv[i], FALSE))
1010
EnableDisableExtensionError(argv[i], FALSE);
1016
ErrorF("Unrecognized option: %s\n", argv[i]);
1018
FatalError("Unrecognized option: %s\n", argv[i]);
1023
/* Implement a simple-minded font authorization scheme. The authorization
1024
name is "hp-hostname-1", the contents are simply the host name. */
1026
set_font_authorizations(char **authorizations, int *authlen, void *client)
1028
#define AUTHORIZATION_NAME "hp-hostname-1"
1029
#if defined(TCPCONN) || defined(STREAMSCONN)
1030
static char *result = NULL;
1031
static char *p = NULL;
1034
char hname[1024], *hnameptr;
1037
#if defined(IPv6) && defined(AF_INET6)
1038
struct addrinfo hints, *ai = NULL;
1040
struct hostent *host;
1042
#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
1043
_Xgethostbynameparams hparams;
1047
gethostname(hname, 1024);
1048
#if defined(IPv6) && defined(AF_INET6)
1049
memset(&hints, 0, sizeof(hints));
1050
hints.ai_flags = AI_CANONNAME;
1051
if (getaddrinfo(hname, NULL, &hints, &ai) == 0) {
1052
hnameptr = ai->ai_canonname;
1058
host = _XGethostbyname(hname, hparams);
1062
hnameptr = host->h_name;
1065
len = strlen(hnameptr) + 1;
1066
result = malloc(len + sizeof(AUTHORIZATION_NAME) + 4);
1069
*p++ = sizeof(AUTHORIZATION_NAME) >> 8;
1070
*p++ = sizeof(AUTHORIZATION_NAME) & 0xff;
1072
*p++ = (len & 0xff);
1074
memmove(p, AUTHORIZATION_NAME, sizeof(AUTHORIZATION_NAME));
1075
p += sizeof(AUTHORIZATION_NAME);
1076
memmove(p, hnameptr, len);
1078
#if defined(IPv6) && defined(AF_INET6)
1084
*authlen = p - result;
1085
*authorizations = result;
1089
#endif /* TCPCONN */
1093
Xalloc(unsigned long amount)
1096
* Xalloc used to return NULL when large amount of memory is requested. In
1097
* order to catch the buggy callers this warning has been added, slated to
1098
* removal by anyone who touches this code (or just looks at it) in 2011.
1100
* -- Mikhail Gusarov
1102
if ((long) amount <= 0)
1103
ErrorF("Warning: Xalloc: "
1104
"requesting unpleasantly large amount of memory: %lu bytes.\n",
1107
return malloc(amount);
1111
XNFalloc(unsigned long amount)
1113
void *ptr = malloc(amount);
1116
FatalError("Out of memory");
1121
Xcalloc(unsigned long amount)
1123
return calloc(1, amount);
1127
XNFcalloc(unsigned long amount)
1129
void *ret = calloc(1, amount);
1132
FatalError("XNFcalloc: Out of memory");
1137
Xrealloc(void *ptr, unsigned long amount)
1140
* Xrealloc used to return NULL when large amount of memory is requested. In
1141
* order to catch the buggy callers this warning has been added, slated to
1142
* removal by anyone who touches this code (or just looks at it) in 2011.
1144
* -- Mikhail Gusarov
1146
if ((long) amount <= 0)
1147
ErrorF("Warning: Xrealloc: "
1148
"requesting unpleasantly large amount of memory: %lu bytes.\n",
1151
return realloc(ptr, amount);
1155
XNFrealloc(void *ptr, unsigned long amount)
1157
void *ret = realloc(ptr, amount);
1160
FatalError("XNFrealloc: Out of memory");
1171
Xstrdup(const char *s)
1179
XNFstrdup(const char *s)
1188
FatalError("XNFstrdup: Out of memory");
1193
SmartScheduleStopTimer(void)
1195
#ifdef SMART_SCHEDULE_POSSIBLE
1196
struct itimerval timer;
1198
if (SmartScheduleDisable)
1200
timer.it_interval.tv_sec = 0;
1201
timer.it_interval.tv_usec = 0;
1202
timer.it_value.tv_sec = 0;
1203
timer.it_value.tv_usec = 0;
1204
(void) setitimer(ITIMER_REAL, &timer, 0);
1209
SmartScheduleStartTimer(void)
1211
#ifdef SMART_SCHEDULE_POSSIBLE
1212
struct itimerval timer;
1214
if (SmartScheduleDisable)
1216
timer.it_interval.tv_sec = 0;
1217
timer.it_interval.tv_usec = SmartScheduleInterval * 1000;
1218
timer.it_value.tv_sec = 0;
1219
timer.it_value.tv_usec = SmartScheduleInterval * 1000;
1220
setitimer(ITIMER_REAL, &timer, 0);
1225
SmartScheduleTimer(int sig)
1227
SmartScheduleTime += SmartScheduleInterval;
1231
SmartScheduleInit(void)
1233
#ifdef SMART_SCHEDULE_POSSIBLE
1234
struct sigaction act;
1236
if (SmartScheduleDisable)
1239
memset((char *) &act, 0, sizeof(struct sigaction));
1241
/* Set up the timer signal function */
1242
act.sa_handler = SmartScheduleTimer;
1243
sigemptyset(&act.sa_mask);
1244
sigaddset(&act.sa_mask, SIGALRM);
1245
if (sigaction(SIGALRM, &act, 0) < 0) {
1246
perror("sigaction for smart scheduler");
1247
SmartScheduleDisable = TRUE;
1253
static sigset_t PreviousSignalMask;
1254
static int BlockedSignalCount;
1258
OsBlockSignals(void)
1261
if (BlockedSignalCount++ == 0) {
1268
sigaddset(&set, SIGALRM);
1269
sigaddset(&set, SIGVTALRM);
1271
sigaddset(&set, SIGWINCH);
1273
sigaddset(&set, SIGTSTP);
1274
sigaddset(&set, SIGTTIN);
1275
sigaddset(&set, SIGTTOU);
1276
sigaddset(&set, SIGCHLD);
1277
sigprocmask(SIG_BLOCK, &set, &PreviousSignalMask);
1283
static sig_atomic_t sigio_blocked;
1284
static sigset_t PreviousSigIOMask;
1288
* returns zero if this call caused SIGIO to be blocked now, non-zero if it
1289
* was already blocked by a previous call to this function.
1296
if (sigio_blocked++ == 0) {
1301
sigaddset(&set, SIGIO);
1302
sigprocmask(SIG_BLOCK, &set, &PreviousSigIOMask);
1303
ret = sigismember(&PreviousSigIOMask, SIGIO);
1312
OsReleaseSIGIO(void)
1316
if (--sigio_blocked == 0) {
1317
sigprocmask(SIG_SETMASK, &PreviousSigIOMask, 0);
1318
} else if (sigio_blocked < 0) {
1319
BUG_WARN(sigio_blocked < 0);
1327
OsReleaseSignals(void)
1330
if (--BlockedSignalCount == 0) {
1331
sigprocmask(SIG_SETMASK, &PreviousSignalMask, 0);
1338
OsResetSignals(void)
1341
while (BlockedSignalCount > 0)
1344
while (sigio_blocked > 0)
1351
* Pending signals may interfere with core dumping. Provide a
1352
* mechanism to block signals when aborting.
1366
* "safer" versions of system(3), popen(3) and pclose(3) which give up
1367
* all privs before running a command.
1369
* This is based on the code in FreeBSD 2.2 libc.
1371
* XXX It'd be good to redirect stderr so that it ends up in the log file
1372
* as well. As it is now, xkbcomp messages don't end up in the log file.
1376
System(const char *command)
1385
csig = signal(SIGCHLD, SIG_DFL);
1386
if (csig == SIG_ERR) {
1390
DebugF("System: `%s'\n", command);
1392
switch (pid = fork()) {
1393
case -1: /* error */
1396
if (setgid(getgid()) == -1)
1398
if (setuid(getuid()) == -1)
1400
execl("/bin/sh", "sh", "-c", command, (char *) NULL);
1402
default: /* parent */
1404
p = waitpid(pid, &status, 0);
1405
} while (p == -1 && errno == EINTR);
1409
if (signal(SIGCHLD, csig) == SIG_ERR) {
1414
return p == -1 ? -1 : status;
1423
OsSigHandlerPtr old_alarm = NULL; /* XXX horrible awful hack */
1426
Popen(const char *command, const char *type)
1432
if (command == NULL || type == NULL)
1435
if ((*type != 'r' && *type != 'w') || type[1])
1438
if ((cur = malloc(sizeof(struct pid))) == NULL)
1441
if (pipe(pdes) < 0) {
1446
/* Ignore the smart scheduler while this is going on */
1447
old_alarm = OsSignal(SIGALRM, SIG_IGN);
1448
if (old_alarm == SIG_ERR) {
1456
switch (pid = fork()) {
1457
case -1: /* error */
1461
if (OsSignal(SIGALRM, old_alarm) == SIG_ERR)
1465
if (setgid(getgid()) == -1)
1467
if (setuid(getuid()) == -1)
1485
execl("/bin/sh", "sh", "-c", command, (char *) NULL);
1489
/* Avoid EINTR during stdio calls */
1494
iop = fdopen(pdes[0], type);
1498
iop = fdopen(pdes[1], type);
1504
cur->next = pidlist;
1507
DebugF("Popen: `%s', fp = %p\n", command, iop);
1512
/* fopen that drops privileges */
1514
Fopen(const char *file, const char *type)
1518
#ifndef HAS_SAVED_IDS_AND_SETEUID
1522
if (file == NULL || type == NULL)
1525
if ((*type != 'r' && *type != 'w') || type[1])
1528
if ((cur = malloc(sizeof(struct pid))) == NULL)
1531
if (pipe(pdes) < 0) {
1536
switch (pid = fork()) {
1537
case -1: /* error */
1543
if (setgid(getgid()) == -1)
1545
if (setuid(getuid()) == -1)
1563
execl("/bin/cat", "cat", file, (char *) NULL);
1567
/* Avoid EINTR during stdio calls */
1572
iop = fdopen(pdes[0], type);
1576
iop = fdopen(pdes[1], type);
1582
cur->next = pidlist;
1585
DebugF("Fopen(%s), fp = %p\n", file, iop);
1594
if (seteuid(ruid) == -1) {
1597
iop = fopen(file, type);
1599
if (seteuid(euid) == -1) {
1604
#endif /* HAS_SAVED_IDS_AND_SETEUID */
1610
struct pid *cur, *last;
1614
DebugF("Pclose: fp = %p\n", iop);
1617
for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next)
1624
pid = waitpid(cur->pid, &pstat, 0);
1625
} while (pid == -1 && errno == EINTR);
1628
pidlist = cur->next;
1630
last->next = cur->next;
1633
/* allow EINTR again */
1636
if (old_alarm && OsSignal(SIGALRM, old_alarm) == SIG_ERR) {
1641
return pid == -1 ? -1 : pstat;
1647
#ifdef HAS_SAVED_IDS_AND_SETEUID
1658
#include <X11/Xwindows.h>
1663
static char buffer[PATH_MAX];
1665
if (GetTempPath(sizeof(buffer), buffer)) {
1668
buffer[sizeof(buffer) - 1] = 0;
1669
len = strlen(buffer);
1671
if (buffer[len - 1] == '\\')
1672
buffer[len - 1] = 0;
1675
if (getenv("TEMP") != NULL)
1676
return getenv("TEMP");
1677
else if (getenv("TMP") != NULL)
1678
return getenv("TMP");
1684
System(const char *cmdline)
1687
PROCESS_INFORMATION pi;
1689
char *cmd = strdup(cmdline);
1691
ZeroMemory(&si, sizeof(si));
1693
ZeroMemory(&pi, sizeof(pi));
1695
if (!CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
1698
if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
1699
FORMAT_MESSAGE_FROM_SYSTEM |
1700
FORMAT_MESSAGE_IGNORE_INSERTS,
1703
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
1704
(LPTSTR) &buffer, 0, NULL)) {
1705
ErrorF("[xkb] Starting '%s' failed!\n", cmdline);
1708
ErrorF("[xkb] Starting '%s' failed: %s", cmdline, (char *) buffer);
1715
/* Wait until child process exits. */
1716
WaitForSingleObject(pi.hProcess, INFINITE);
1718
GetExitCodeProcess(pi.hProcess, &dwExitCode);
1720
/* Close process and thread handles. */
1721
CloseHandle(pi.hProcess);
1722
CloseHandle(pi.hThread);
1730
* CheckUserParameters: check for long command line arguments and long
1731
* environment variables. By default, these checks are only done when
1732
* the server's euid != ruid. In 3.3.x, these checks were done in an
1733
* external wrapper utility.
1736
/* Consider LD* variables insecure? */
1737
#ifndef REMOVE_ENV_LD
1738
#define REMOVE_ENV_LD 1
1741
/* Remove long environment variables? */
1742
#ifndef REMOVE_LONG_ENV
1743
#define REMOVE_LONG_ENV 1
1747
* Disallow stdout or stderr as pipes? It's possible to block the X server
1748
* when piping stdout+stderr to a pipe.
1750
* Don't enable this because it looks like it's going to cause problems.
1752
#ifndef NO_OUTPUT_PIPES
1753
#define NO_OUTPUT_PIPES 0
1756
/* Check args and env only if running setuid (euid == 0 && euid != uid) ? */
1759
#define CHECK_EUID 1
1761
#define CHECK_EUID 0
1766
* Maybe the locale can be faked to make isprint(3) report that everything
1767
* is printable? Avoid it by default.
1770
#define USE_ISPRINT 0
1773
#define MAX_ARG_LENGTH 128
1774
#define MAX_ENV_LENGTH 256
1775
#define MAX_ENV_PATH_LENGTH 2048 /* Limit for *PATH and TERMCAP */
1779
#define checkPrintable(c) isprint(c)
1781
#define checkPrintable(c) (((c) & 0x7f) >= 0x20 && ((c) & 0x7f) != 0x7f)
1794
#if defined(VENDORSUPPORT)
1795
#define BUGADDRESS VENDORSUPPORT
1796
#elif defined(BUILDERADDR)
1797
#define BUGADDRESS BUILDERADDR
1799
#define BUGADDRESS "xorg@freedesktop.org"
1803
CheckUserParameters(int argc, char **argv, char **envp)
1805
enum BadCode bad = NotBad;
1810
if (geteuid() == 0 && getuid() != geteuid())
1813
/* Check each argv[] */
1814
for (i = 1; i < argc; i++) {
1815
if (strcmp(argv[i], "-fp") == 0) {
1816
i++; /* continue with next argument. skip the length check */
1821
if (strlen(argv[i]) > MAX_ARG_LENGTH) {
1828
if (checkPrintable(*a) == 0) {
1829
bad = UnprintableArg;
1838
/* Check each envp[] */
1839
for (i = 0; envp[i]; i++) {
1841
/* Check for bad environment variables and values */
1843
while (envp[i] && (strncmp(envp[i], "LD", 2) == 0)) {
1844
for (j = i; envp[j]; j++) {
1845
envp[j] = envp[j + 1];
1849
if (envp[i] && (strlen(envp[i]) > MAX_ENV_LENGTH)) {
1851
for (j = i; envp[j]; j++) {
1852
envp[j] = envp[j + 1];
1859
eq = strchr(envp[i], '=');
1863
e = strndup(envp[i], len);
1865
bad = InternalError;
1869
(strcmp(e + len - 4, "PATH") == 0 ||
1870
strcmp(e, "TERMCAP") == 0)) {
1871
if (strlen(envp[i]) > MAX_ENV_PATH_LENGTH) {
1891
if (fstat(fileno(stdout), &buf) == 0 && S_ISFIFO(buf.st_mode))
1893
if (fstat(fileno(stderr), &buf) == 0 && S_ISFIFO(buf.st_mode))
1902
ErrorF("Command line argument number %d is unsafe\n", i);
1905
ErrorF("Command line argument number %d is too long\n", i);
1907
case UnprintableArg:
1908
ErrorF("Command line argument number %d contains unprintable"
1909
" characters\n", i);
1912
ErrorF("Environment variable `%s' is too long\n", e);
1915
ErrorF("Stdout and/or stderr is a pipe\n");
1918
ErrorF("Internal Error\n");
1921
ErrorF("Unknown error\n");
1924
FatalError("X server aborted because of unsafe environment\n");
1928
* CheckUserAuthorization: check if the user is allowed to start the
1929
* X server. This usually means some sort of PAM checking, and it is
1930
* usually only done for setuid servers (uid != euid).
1934
#include <security/pam_appl.h>
1935
#include <security/pam_misc.h>
1937
#endif /* USE_PAM */
1940
CheckUserAuthorization(void)
1943
static struct pam_conv conv = {
1948
pam_handle_t *pamh = NULL;
1952
if (getuid() != geteuid()) {
1953
pw = getpwuid(getuid());
1955
FatalError("getpwuid() failed for uid %d\n", getuid());
1957
retval = pam_start("xserver", pw->pw_name, &conv, &pamh);
1958
if (retval != PAM_SUCCESS)
1959
FatalError("pam_start() failed.\n"
1960
"\tMissing or mangled PAM config file or module?\n");
1962
retval = pam_authenticate(pamh, 0);
1963
if (retval != PAM_SUCCESS) {
1964
pam_end(pamh, retval);
1965
FatalError("PAM authentication failed, cannot start X server.\n"
1966
"\tPerhaps you do not have console ownership?\n");
1969
retval = pam_acct_mgmt(pamh, 0);
1970
if (retval != PAM_SUCCESS) {
1971
pam_end(pamh, retval);
1972
FatalError("PAM authentication failed, cannot start X server.\n"
1973
"\tPerhaps you do not have console ownership?\n");
1976
/* this is not a session, so do not do session management */
1977
pam_end(pamh, PAM_SUCCESS);
1983
* Tokenize a string into a NULL terminated array of strings. Always returns
1984
* an allocated array unless an error occurs.
1987
xstrtokenize(const char *str, const char *separators)
1989
char **list, **nlist;
1991
unsigned num = 0, n;
1995
list = calloc(1, sizeof(*list));
2001
for (tok = strtok(tmp, separators); tok; tok = strtok(NULL, separators)) {
2002
nlist = realloc(list, (num + 2) * sizeof(*list));
2006
list[num] = strdup(tok);
2016
for (n = 0; n < num; n++)
2022
/* Format a signed number into a string in a signal safe manner. The string
2023
* should be at least 21 characters in order to handle all int64_t values.
2026
FormatInt64(int64_t num, char *string)
2033
FormatUInt64(num, string);
2036
/* Format a number into a string in a signal safe manner. The string should be
2037
* at least 21 characters in order to handle all uint64_t values. */
2039
FormatUInt64(uint64_t num, char *string)
2045
for (len = 1, divisor = 10;
2046
len < 20 && num / divisor;
2047
len++, divisor *= 10);
2049
for (i = len, divisor = 1; i > 0; i--, divisor *= 10)
2050
string[i - 1] = '0' + ((num / divisor) % 10);
2056
* Format a double number as %.2f.
2059
FormatDouble(double dbl, char *string)
2064
frac = (dbl > 0 ? dbl : -dbl) * 100.0 + 0.5;
2067
/* write decimal part to string */
2068
if (dbl < 0 && dbl > -1)
2069
string[slen++] = '-';
2070
FormatInt64((int64_t)dbl, &string[slen]);
2072
while(string[slen] != '\0')
2075
/* append fractional part, but only if we have enough characters. We
2076
* expect string to be 21 chars (incl trailing \0) */
2078
string[slen++] = '.';
2080
string[slen++] = '0';
2082
FormatUInt64(frac, &string[slen]);
2087
/* Format a number into a hexadecimal string in a signal safe manner. The string
2088
* should be at least 17 characters in order to handle all uint64_t values. */
2090
FormatUInt64Hex(uint64_t num, char *string)
2096
for (len = 1, divisor = 0x10;
2097
len < 16 && num / divisor;
2098
len++, divisor *= 0x10);
2100
for (i = len, divisor = 1; i > 0; i--, divisor *= 0x10) {
2101
int val = (num / divisor) % 0x10;
2104
string[i - 1] = '0' + val;
2106
string[i - 1] = 'a' + val - 10;
2112
/* Move a file descriptor out of the way of our select mask; this
2113
* is useful for file descriptors which will never appear in the
2114
* select mask to avoid reducing the number of clients that can
2115
* connect to the server
2122
#ifdef F_DUPFD_CLOEXEC
2123
newfd = fcntl(fd, F_DUPFD_CLOEXEC, MAXCLIENTS);
2125
newfd = fcntl(fd, F_DUPFD, MAXCLIENTS);
2129
#ifndef F_DUPFD_CLOEXEC
2130
fcntl(newfd, F_SETFD, FD_CLOEXEC);