~brandontschaefer/+junk/break-x

« back to all changes in this revision

Viewing changes to os/utils.c

  • Committer: Brandon Schaefer
  • Date: 2014-09-30 19:38:40 UTC
  • Revision ID: brandon.schaefer@canonical.com-20140930193840-a65z6qk8ze02cgsb
* Init commit to back this up

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
# define SMART_SCHEDULE_POSSIBLE
 
75
#endif
 
76
#include "misc.h"
 
77
#include <X11/X.h>
 
78
#define XSERV_t
 
79
#define TRANS_SERVER
 
80
#define TRANS_REOPEN
 
81
#include <X11/Xtrans/Xtrans.h>
 
82
#include "input.h"
 
83
#include "dixfont.h"
 
84
#include "osdep.h"
 
85
#include "extension.h"
 
86
#ifdef X_POSIX_C_SOURCE
 
87
#define _POSIX_C_SOURCE X_POSIX_C_SOURCE
 
88
#include <signal.h>
 
89
#undef _POSIX_C_SOURCE
 
90
#else
 
91
#if defined(_POSIX_SOURCE)
 
92
#include <signal.h>
 
93
#else
 
94
#define _POSIX_SOURCE
 
95
#include <signal.h>
 
96
#undef _POSIX_SOURCE
 
97
#endif
 
98
#endif
 
99
#ifndef WIN32
 
100
#include <sys/wait.h>
 
101
#endif
 
102
#if !defined(SYSV) && !defined(WIN32)
 
103
#include <sys/resource.h>
 
104
#endif
 
105
#include <sys/stat.h>
 
106
#include <ctype.h>              /* for isspace */
 
107
#include <stdarg.h>
 
108
 
 
109
#include <stdlib.h>             /* for malloc() */
 
110
 
 
111
#if defined(TCPCONN) || defined(STREAMSCONN)
 
112
#ifndef WIN32
 
113
#include <netdb.h>
 
114
#endif
 
115
#endif
 
116
 
 
117
#include "opaque.h"
 
118
 
 
119
#include "dixstruct.h"
 
120
 
 
121
#include "xkbsrv.h"
 
122
 
 
123
#include "picture.h"
 
124
 
 
125
Bool noTestExtensions;
 
126
 
 
127
#ifdef COMPOSITE
 
128
Bool noCompositeExtension = FALSE;
 
129
#endif
 
130
 
 
131
#ifdef DAMAGE
 
132
Bool noDamageExtension = FALSE;
 
133
#endif
 
134
#ifdef DBE
 
135
Bool noDbeExtension = FALSE;
 
136
#endif
 
137
#ifdef DPMSExtension
 
138
Bool noDPMSExtension = FALSE;
 
139
#endif
 
140
#ifdef GLXEXT
 
141
Bool noGlxExtension = FALSE;
 
142
#endif
 
143
#ifdef SCREENSAVER
 
144
Bool noScreenSaverExtension = FALSE;
 
145
#endif
 
146
#ifdef MITSHM
 
147
Bool noMITShmExtension = FALSE;
 
148
#endif
 
149
#ifdef RANDR
 
150
Bool noRRExtension = FALSE;
 
151
#endif
 
152
Bool noRenderExtension = FALSE;
 
153
 
 
154
#ifdef XCSECURITY
 
155
Bool noSecurityExtension = FALSE;
 
156
#endif
 
157
#ifdef RES
 
158
Bool noResExtension = FALSE;
 
159
#endif
 
160
#ifdef XF86BIGFONT
 
161
Bool noXFree86BigfontExtension = FALSE;
 
162
#endif
 
163
#ifdef XFreeXDGA
 
164
Bool noXFree86DGAExtension = FALSE;
 
165
#endif
 
166
#ifdef XF86DRI
 
167
Bool noXFree86DRIExtension = FALSE;
 
168
#endif
 
169
#ifdef XF86VIDMODE
 
170
Bool noXFree86VidModeExtension = FALSE;
 
171
#endif
 
172
Bool noXFixesExtension = FALSE;
 
173
#ifdef PANORAMIX
 
174
/* Xinerama is disabled by default unless enabled via +xinerama */
 
175
Bool noPanoramiXExtension = TRUE;
 
176
#endif
 
177
#ifdef XSELINUX
 
178
Bool noSELinuxExtension = FALSE;
 
179
int selinuxEnforcingState = SELINUX_MODE_DEFAULT;
 
180
#endif
 
181
#ifdef XV
 
182
Bool noXvExtension = FALSE;
 
183
#endif
 
184
#ifdef DRI2
 
185
Bool noDRI2Extension = FALSE;
 
186
#endif
 
187
 
 
188
Bool noGEExtension = FALSE;
 
189
 
 
190
#define X_INCLUDE_NETDB_H
 
191
#include <X11/Xos_r.h>
 
192
 
 
193
#include <errno.h>
 
194
 
 
195
Bool CoreDump;
 
196
 
 
197
Bool enableIndirectGLX = TRUE;
 
198
 
 
199
#ifdef PANORAMIX
 
200
Bool PanoramiXExtensionDisabledHack = FALSE;
 
201
#endif
 
202
 
 
203
int auditTrailLevel = 1;
 
204
 
 
205
char *SeatId = NULL;
 
206
 
 
207
sig_atomic_t inSignalContext = FALSE;
 
208
 
 
209
#if defined(SVR4) || defined(__linux__) || defined(CSRG_BASED)
 
210
#define HAS_SAVED_IDS_AND_SETEUID
 
211
#endif
 
212
 
 
213
OsSigHandlerPtr
 
214
OsSignal(int sig, OsSigHandlerPtr handler)
 
215
{
 
216
#if defined(WIN32) && !defined(__CYGWIN__)
 
217
    return signal(sig, handler);
 
218
#else
 
219
    struct sigaction act, oact;
 
220
 
 
221
    sigemptyset(&act.sa_mask);
 
222
    if (handler != SIG_IGN)
 
223
        sigaddset(&act.sa_mask, sig);
 
224
    act.sa_flags = 0;
 
225
    act.sa_handler = handler;
 
226
    if (sigaction(sig, &act, &oact))
 
227
        perror("sigaction");
 
228
    return oact.sa_handler;
 
229
#endif
 
230
}
 
231
 
 
232
/*
 
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.
 
237
 */
 
238
#define LOCK_DIR "/tmp"
 
239
#define LOCK_TMP_PREFIX "/.tX"
 
240
#define LOCK_PREFIX "/.X"
 
241
#define LOCK_SUFFIX "-lock"
 
242
 
 
243
#if !defined(WIN32) || defined(__CYGWIN__)
 
244
#define LOCK_SERVER
 
245
#endif
 
246
 
 
247
#ifndef LOCK_SERVER
 
248
void
 
249
LockServer(void)
 
250
{}
 
251
 
 
252
void
 
253
UnlockServer(void)
 
254
{}
 
255
#else /* LOCK_SERVER */
 
256
static Bool StillLocking = FALSE;
 
257
static char LockFile[PATH_MAX];
 
258
static Bool nolock = FALSE;
 
259
 
 
260
/*
 
261
 * LockServer --
 
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.
 
265
 */
 
266
void
 
267
LockServer(void)
 
268
{
 
269
    char tmp[PATH_MAX], pid_str[12];
 
270
    int lfd, i, haslock, l_pid, t;
 
271
    const char *tmppath = LOCK_DIR;
 
272
    int len;
 
273
    char port[20];
 
274
 
 
275
    if (nolock || NoListenAll)
 
276
        return;
 
277
    /*
 
278
     * Path names
 
279
     */
 
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);
 
288
 
 
289
    /*
 
290
     * Create a temporary file containing our PID.  Attempt three times
 
291
     * to create the file.
 
292
     */
 
293
    StillLocking = TRUE;
 
294
    i = 0;
 
295
    do {
 
296
        i++;
 
297
        lfd = open(tmp, O_CREAT | O_EXCL | O_WRONLY, 0644);
 
298
        if (lfd < 0)
 
299
            sleep(2);
 
300
        else
 
301
            break;
 
302
    } while (i < 3);
 
303
    if (lfd < 0) {
 
304
        unlink(tmp);
 
305
        i = 0;
 
306
        do {
 
307
            i++;
 
308
            lfd = open(tmp, O_CREAT | O_EXCL | O_WRONLY, 0644);
 
309
            if (lfd < 0)
 
310
                sleep(2);
 
311
            else
 
312
                break;
 
313
        } while (i < 3);
 
314
    }
 
315
    if (lfd < 0)
 
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);
 
321
    (void) close(lfd);
 
322
 
 
323
    /*
 
324
     * OK.  Now the tmp file exists.  Try three times to move it in place
 
325
     * for the lock.
 
326
     */
 
327
    i = 0;
 
328
    haslock = 0;
 
329
    while ((!haslock) && (i++ < 3)) {
 
330
        haslock = (link(tmp, LockFile) == 0);
 
331
        if (haslock) {
 
332
            /*
 
333
             * We're done.
 
334
             */
 
335
            break;
 
336
        }
 
337
        else {
 
338
            /*
 
339
             * Read the pid from the existing file
 
340
             */
 
341
            lfd = open(LockFile, O_RDONLY | O_NOFOLLOW);
 
342
            if (lfd < 0) {
 
343
                unlink(tmp);
 
344
                FatalError("Can't read lock file %s\n", LockFile);
 
345
            }
 
346
            pid_str[0] = '\0';
 
347
            if (read(lfd, pid_str, 11) != 11) {
 
348
                /*
 
349
                 * Bogus lock file.
 
350
                 */
 
351
                unlink(LockFile);
 
352
                close(lfd);
 
353
                continue;
 
354
            }
 
355
            pid_str[11] = '\0';
 
356
            sscanf(pid_str, "%d", &l_pid);
 
357
            close(lfd);
 
358
 
 
359
            /*
 
360
             * Now try to kill the PID to see if it exists.
 
361
             */
 
362
            errno = 0;
 
363
            t = kill(l_pid, 0);
 
364
            if ((t < 0) && (errno == ESRCH)) {
 
365
                /*
 
366
                 * Stale lock file.
 
367
                 */
 
368
                unlink(LockFile);
 
369
                continue;
 
370
            }
 
371
            else if (((t < 0) && (errno == EPERM)) || (t == 0)) {
 
372
                /*
 
373
                 * Process is still active.
 
374
                 */
 
375
                unlink(tmp);
 
376
                FatalError
 
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.");
 
380
            }
 
381
        }
 
382
    }
 
383
    unlink(tmp);
 
384
    if (!haslock)
 
385
        FatalError("Could not create server lock file: %s\n", LockFile);
 
386
    StillLocking = FALSE;
 
387
}
 
388
 
 
389
/*
 
390
 * UnlockServer --
 
391
 *      Remove the server lock file.
 
392
 */
 
393
void
 
394
UnlockServer(void)
 
395
{
 
396
    if (nolock || NoListenAll)
 
397
        return;
 
398
 
 
399
    if (!StillLocking) {
 
400
 
 
401
        (void) unlink(LockFile);
 
402
    }
 
403
}
 
404
#endif /* LOCK_SERVER */
 
405
 
 
406
/* Force connections to close on SIGHUP from init */
 
407
 
 
408
void
 
409
AutoResetServer(int sig)
 
410
{
 
411
    int olderrno = errno;
 
412
 
 
413
    dispatchException |= DE_RESET;
 
414
    isItTimeToYield = TRUE;
 
415
    errno = olderrno;
 
416
}
 
417
 
 
418
/* Force connections to close and then exit on SIGTERM, SIGINT */
 
419
 
 
420
void
 
421
GiveUp(int sig)
 
422
{
 
423
    int olderrno = errno;
 
424
 
 
425
    dispatchException |= DE_TERMINATE;
 
426
    isItTimeToYield = TRUE;
 
427
    errno = olderrno;
 
428
}
 
429
 
 
430
#if (defined WIN32 && defined __MINGW32__) || defined(__CYGWIN__)
 
431
CARD32
 
432
GetTimeInMillis(void)
 
433
{
 
434
    return GetTickCount();
 
435
}
 
436
CARD64
 
437
GetTimeInMicros(void)
 
438
{
 
439
    return (CARD64) GetTickCount() * 1000;
 
440
}
 
441
#else
 
442
CARD32
 
443
GetTimeInMillis(void)
 
444
{
 
445
    struct timeval tv;
 
446
 
 
447
#ifdef MONOTONIC_CLOCK
 
448
    struct timespec tp;
 
449
    static clockid_t clockid;
 
450
 
 
451
    if (!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;
 
457
        else
 
458
#endif
 
459
        if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
 
460
            clockid = CLOCK_MONOTONIC;
 
461
        else
 
462
            clockid = ~0L;
 
463
    }
 
464
    if (clockid != ~0L && clock_gettime(clockid, &tp) == 0)
 
465
        return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000L);
 
466
#endif
 
467
 
 
468
    X_GETTIMEOFDAY(&tv);
 
469
    return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
 
470
}
 
471
 
 
472
CARD64
 
473
GetTimeInMicros(void)
 
474
{
 
475
    struct timeval tv;
 
476
#ifdef MONOTONIC_CLOCK
 
477
    struct timespec tp;
 
478
    static clockid_t clockid;
 
479
 
 
480
    if (!clockid) {
 
481
        if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
 
482
            clockid = CLOCK_MONOTONIC;
 
483
        else
 
484
            clockid = ~0L;
 
485
    }
 
486
    if (clockid != ~0L && clock_gettime(clockid, &tp) == 0)
 
487
        return (CARD64) tp.tv_sec * (CARD64)1000000 + tp.tv_nsec / 1000;
 
488
#endif
 
489
 
 
490
    X_GETTIMEOFDAY(&tv);
 
491
    return (CARD64) tv.tv_sec * (CARD64)1000000000 + (CARD64) tv.tv_usec * 1000;
 
492
}
 
493
#endif
 
494
 
 
495
void
 
496
AdjustWaitForDelay(void *waitTime, unsigned long newdelay)
 
497
{
 
498
    static struct timeval delay_val;
 
499
    struct timeval **wt = (struct timeval **) waitTime;
 
500
    unsigned long olddelay;
 
501
 
 
502
    if (*wt == NULL) {
 
503
        delay_val.tv_sec = newdelay / 1000;
 
504
        delay_val.tv_usec = 1000 * (newdelay % 1000);
 
505
        *wt = &delay_val;
 
506
    }
 
507
    else {
 
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);
 
512
        }
 
513
    }
 
514
}
 
515
 
 
516
void
 
517
UseMsg(void)
 
518
{
 
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");
 
534
#ifdef DPMSExtension
 
535
    ErrorF("-dpms                  disables VESA DPMS monitor control\n");
 
536
#endif
 
537
    ErrorF
 
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");
 
547
#ifdef RLIMIT_DATA
 
548
    ErrorF("-ld int                limit data space to N Kb\n");
 
549
#endif
 
550
#ifdef RLIMIT_NOFILE
 
551
    ErrorF("-lf int                limit number of open files to N\n");
 
552
#endif
 
553
#ifdef RLIMIT_STACK
 
554
    ErrorF("-ls int                limit stack space to N Kb\n");
 
555
#endif
 
556
#ifdef LOCK_SERVER
 
557
    ErrorF("-nolock                disable the locking mechanism\n");
 
558
#endif
 
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");
 
582
#ifdef PANORAMIX
 
583
    ErrorF("+xinerama              Enable XINERAMA extension\n");
 
584
    ErrorF("-xinerama              Disable XINERAMA extension\n");
 
585
#endif
 
586
    ErrorF
 
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");
 
592
#ifdef XDMCP
 
593
    XdmcpUseMsg();
 
594
#endif
 
595
    XkbUseMsg();
 
596
    ddxUseMsg();
 
597
}
 
598
 
 
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 "-".
 
604
 *                                            --kvajk
 
605
 */
 
606
static int
 
607
VerifyDisplayName(const char *d)
 
608
{
 
609
    int i;
 
610
    int period_found = FALSE;
 
611
    int after_period = 0;
 
612
 
 
613
    if (d == (char *) 0)
 
614
        return 0;               /*  null  */
 
615
    if (*d == '\0')
 
616
        return 0;               /*  empty  */
 
617
    if (*d == '-')
 
618
        return 0;               /*  could be confused for an option  */
 
619
    if (*d == '.')
 
620
        return 0;               /*  must not equal "." or ".."  */
 
621
    if (strchr(d, '/') != (char *) 0)
 
622
        return 0;               /*  very important!!!  */
 
623
 
 
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)
 
626
       */
 
627
    for (i = 0; i < strlen(d); i++) {
 
628
        if (!isdigit(d[i])) {
 
629
            if (d[i] != '.' || period_found)
 
630
                return 0;
 
631
            period_found = TRUE;
 
632
        } else if (period_found)
 
633
            after_period++;
 
634
 
 
635
        if (after_period > 2)
 
636
            return 0;
 
637
    }
 
638
 
 
639
    /* don't allow for :0. */
 
640
    if (period_found && after_period == 0)
 
641
        return 0;
 
642
 
 
643
    if (atol(d) > INT_MAX)
 
644
        return 0;
 
645
 
 
646
    return 1;
 
647
}
 
648
 
 
649
/*
 
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.
 
653
 */
 
654
void
 
655
ProcessCommandLine(int argc, char *argv[])
 
656
{
 
657
    int i, skip;
 
658
 
 
659
    defaultKeyboardControl.autoRepeat = TRUE;
 
660
 
 
661
#ifdef NO_PART_NET
 
662
    PartialNetwork = FALSE;
 
663
#else
 
664
    PartialNetwork = TRUE;
 
665
#endif
 
666
 
 
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))) {
 
670
            i += (skip - 1);
 
671
        }
 
672
        else if (argv[i][0] == ':') {
 
673
            /* initialize display */
 
674
            display = argv[i];
 
675
            explicit_display = TRUE;
 
676
            display++;
 
677
            if (!VerifyDisplayName(display)) {
 
678
                ErrorF("Bad display name: %s\n", display);
 
679
                UseMsg();
 
680
                FatalError("Bad display name, exiting: %s\n", display);
 
681
            }
 
682
        }
 
683
        else if (strcmp(argv[i], "-a") == 0) {
 
684
            if (++i < argc)
 
685
                defaultPointerControl.num = atoi(argv[i]);
 
686
            else
 
687
                UseMsg();
 
688
        }
 
689
        else if (strcmp(argv[i], "-ac") == 0) {
 
690
            defeatAccessControl = TRUE;
 
691
        }
 
692
        else if (strcmp(argv[i], "-audit") == 0) {
 
693
            if (++i < argc)
 
694
                auditTrailLevel = atoi(argv[i]);
 
695
            else
 
696
                UseMsg();
 
697
        }
 
698
        else if (strcmp(argv[i], "-auth") == 0) {
 
699
            if (++i < argc)
 
700
                InitAuthorization(argv[i]);
 
701
            else
 
702
                UseMsg();
 
703
        }
 
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) {
 
710
            if (++i < argc)
 
711
                defaultKeyboardControl.click = atoi(argv[i]);
 
712
            else
 
713
                UseMsg();
 
714
        }
 
715
        else if (strcmp(argv[i], "-c") == 0) {
 
716
            defaultKeyboardControl.click = 0;
 
717
        }
 
718
        else if (strcmp(argv[i], "-cc") == 0) {
 
719
            if (++i < argc)
 
720
                defaultColorVisualClass = atoi(argv[i]);
 
721
            else
 
722
                UseMsg();
 
723
        }
 
724
        else if (strcmp(argv[i], "-core") == 0) {
 
725
#if !defined(WIN32) || !defined(__MINGW32__)
 
726
            struct rlimit core_limit;
 
727
 
 
728
            getrlimit(RLIMIT_CORE, &core_limit);
 
729
            core_limit.rlim_cur = core_limit.rlim_max;
 
730
            setrlimit(RLIMIT_CORE, &core_limit);
 
731
#endif
 
732
            CoreDump = TRUE;
 
733
        }
 
734
        else if (strcmp(argv[i], "-nocursor") == 0) {
 
735
            EnableCursor = FALSE;
 
736
        }
 
737
        else if (strcmp(argv[i], "-dpi") == 0) {
 
738
            if (++i < argc)
 
739
                monitorResolution = atoi(argv[i]);
 
740
            else
 
741
                UseMsg();
 
742
        }
 
743
        else if (strcmp(argv[i], "-displayfd") == 0) {
 
744
            if (++i < argc) {
 
745
                displayfd = atoi(argv[i]);
 
746
#ifdef LOCK_SERVER
 
747
                nolock = TRUE;
 
748
#endif
 
749
            }
 
750
            else
 
751
                UseMsg();
 
752
        }
 
753
#ifdef DPMSExtension
 
754
        else if (strcmp(argv[i], "dpms") == 0)
 
755
            /* ignored for compatibility */ ;
 
756
        else if (strcmp(argv[i], "-dpms") == 0)
 
757
            DPMSDisabledSwitch = TRUE;
 
758
#endif
 
759
        else if (strcmp(argv[i], "-deferglyphs") == 0) {
 
760
            if (++i >= argc || !ParseGlyphCachingMode(argv[i]))
 
761
                UseMsg();
 
762
        }
 
763
        else if (strcmp(argv[i], "-f") == 0) {
 
764
            if (++i < argc)
 
765
                defaultKeyboardControl.bell = atoi(argv[i]);
 
766
            else
 
767
                UseMsg();
 
768
        }
 
769
        else if (strcmp(argv[i], "-fc") == 0) {
 
770
            if (++i < argc)
 
771
                defaultCursorFont = argv[i];
 
772
            else
 
773
                UseMsg();
 
774
        }
 
775
        else if (strcmp(argv[i], "-fn") == 0) {
 
776
            if (++i < argc)
 
777
                defaultTextFont = argv[i];
 
778
            else
 
779
                UseMsg();
 
780
        }
 
781
        else if (strcmp(argv[i], "-fp") == 0) {
 
782
            if (++i < argc) {
 
783
                defaultFontPath = argv[i];
 
784
            }
 
785
            else
 
786
                UseMsg();
 
787
        }
 
788
        else if (strcmp(argv[i], "-help") == 0) {
 
789
            UseMsg();
 
790
            exit(0);
 
791
        }
 
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) {
 
797
            if (skip > 0)
 
798
                i += skip - 1;
 
799
            else
 
800
                UseMsg();
 
801
        }
 
802
#ifdef RLIMIT_DATA
 
803
        else if (strcmp(argv[i], "-ld") == 0) {
 
804
            if (++i < argc) {
 
805
                limitDataSpace = atoi(argv[i]);
 
806
                if (limitDataSpace > 0)
 
807
                    limitDataSpace *= 1024;
 
808
            }
 
809
            else
 
810
                UseMsg();
 
811
        }
 
812
#endif
 
813
#ifdef RLIMIT_NOFILE
 
814
        else if (strcmp(argv[i], "-lf") == 0) {
 
815
            if (++i < argc)
 
816
                limitNoFile = atoi(argv[i]);
 
817
            else
 
818
                UseMsg();
 
819
        }
 
820
#endif
 
821
#ifdef RLIMIT_STACK
 
822
        else if (strcmp(argv[i], "-ls") == 0) {
 
823
            if (++i < argc) {
 
824
                limitStackSpace = atoi(argv[i]);
 
825
                if (limitStackSpace > 0)
 
826
                    limitStackSpace *= 1024;
 
827
            }
 
828
            else
 
829
                UseMsg();
 
830
        }
 
831
#endif
 
832
#ifdef LOCK_SERVER
 
833
        else if (strcmp(argv[i], "-nolock") == 0) {
 
834
#if !defined(WIN32) && !defined(__CYGWIN__)
 
835
            if (getuid() != 0)
 
836
                ErrorF
 
837
                    ("Warning: the -nolock option can only be used by root\n");
 
838
            else
 
839
#endif
 
840
                nolock = TRUE;
 
841
        }
 
842
#endif
 
843
        else if (strcmp(argv[i], "-nolisten") == 0) {
 
844
            if (++i < argc) {
 
845
                if (_XSERVTransNoListen(argv[i]))
 
846
                    ErrorF("Failed to disable listen for %s transport",
 
847
                           argv[i]);
 
848
            }
 
849
            else
 
850
                UseMsg();
 
851
        }
 
852
        else if (strcmp(argv[i], "-noreset") == 0) {
 
853
            dispatchExceptionAtReset = 0;
 
854
        }
 
855
        else if (strcmp(argv[i], "-reset") == 0) {
 
856
            dispatchExceptionAtReset = DE_RESET;
 
857
        }
 
858
        else if (strcmp(argv[i], "-p") == 0) {
 
859
            if (++i < argc)
 
860
                defaultScreenSaverInterval = ((CARD32) atoi(argv[i])) *
 
861
                    MILLI_PER_MIN;
 
862
            else
 
863
                UseMsg();
 
864
        }
 
865
        else if (strcmp(argv[i], "-pogo") == 0) {
 
866
            dispatchException = DE_TERMINATE;
 
867
        }
 
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) {
 
879
            if (++i < argc)
 
880
                defaultScreenSaverTime = ((CARD32) atoi(argv[i])) *
 
881
                    MILLI_PER_MIN;
 
882
            else
 
883
                UseMsg();
 
884
        }
 
885
        else if (strcmp(argv[i], "-seat") == 0) {
 
886
            if (++i < argc)
 
887
                SeatId = argv[i];
 
888
            else
 
889
                UseMsg();
 
890
        }
 
891
        else if (strcmp(argv[i], "-t") == 0) {
 
892
            if (++i < argc)
 
893
                defaultPointerControl.threshold = atoi(argv[i]);
 
894
            else
 
895
                UseMsg();
 
896
        }
 
897
        else if (strcmp(argv[i], "-terminate") == 0) {
 
898
            dispatchExceptionAtReset = DE_TERMINATE;
 
899
        }
 
900
        else if (strcmp(argv[i], "-to") == 0) {
 
901
            if (++i < argc)
 
902
                TimeOutValue = ((CARD32) atoi(argv[i])) * MILLI_PER_SECOND;
 
903
            else
 
904
                UseMsg();
 
905
        }
 
906
        else if (strcmp(argv[i], "-tst") == 0) {
 
907
            noTestExtensions = TRUE;
 
908
        }
 
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)
 
916
            whiteRoot = TRUE;
 
917
        else if (strcmp(argv[i], "-background") == 0) {
 
918
            if (++i < argc) {
 
919
                if (!strcmp(argv[i], "none"))
 
920
                    bgNoneRoot = TRUE;
 
921
                else
 
922
                    UseMsg();
 
923
            }
 
924
        }
 
925
        else if (strcmp(argv[i], "-maxbigreqsize") == 0) {
 
926
            if (++i < argc) {
 
927
                long reqSizeArg = atol(argv[i]);
 
928
 
 
929
                /* Request size > 128MB does not make much sense... */
 
930
                if (reqSizeArg > 0L && reqSizeArg < 128L) {
 
931
                    maxBigRequestSize = (reqSizeArg * 1048576L) - 1L;
 
932
                }
 
933
                else {
 
934
                    UseMsg();
 
935
                }
 
936
            }
 
937
            else {
 
938
                UseMsg();
 
939
            }
 
940
        }
 
941
#ifdef PANORAMIX
 
942
        else if (strcmp(argv[i], "+xinerama") == 0) {
 
943
            noPanoramiXExtension = FALSE;
 
944
        }
 
945
        else if (strcmp(argv[i], "-xinerama") == 0) {
 
946
            noPanoramiXExtension = TRUE;
 
947
        }
 
948
        else if (strcmp(argv[i], "-disablexineramaextension") == 0) {
 
949
            PanoramiXExtensionDisabledHack = TRUE;
 
950
        }
 
951
#endif
 
952
        else if (strcmp(argv[i], "-I") == 0) {
 
953
            /* ignore all remaining arguments */
 
954
            break;
 
955
        }
 
956
        else if (strncmp(argv[i], "tty", 3) == 0) {
 
957
            /* init supplies us with this useless information */
 
958
        }
 
959
#ifdef XDMCP
 
960
        else if ((skip = XdmcpOptions(argc, argv, i)) != i) {
 
961
            i = skip - 1;
 
962
        }
 
963
#endif
 
964
#ifdef SMART_SCHEDULE_POSSIBLE
 
965
        else if (strcmp(argv[i], "-dumbSched") == 0) {
 
966
            SmartScheduleDisable = TRUE;
 
967
        }
 
968
        else if (strcmp(argv[i], "-schedInterval") == 0) {
 
969
            if (++i < argc) {
 
970
                SmartScheduleInterval = atoi(argv[i]);
 
971
                SmartScheduleSlice = SmartScheduleInterval;
 
972
            }
 
973
            else
 
974
                UseMsg();
 
975
        }
 
976
        else if (strcmp(argv[i], "-schedMax") == 0) {
 
977
            if (++i < argc) {
 
978
                SmartScheduleMaxSlice = atoi(argv[i]);
 
979
            }
 
980
            else
 
981
                UseMsg();
 
982
        }
 
983
#endif
 
984
        else if (strcmp(argv[i], "-render") == 0) {
 
985
            if (++i < argc) {
 
986
                int policy = PictureParseCmapPolicy(argv[i]);
 
987
 
 
988
                if (policy != PictureCmapPolicyInvalid)
 
989
                    PictureCmapPolicy = policy;
 
990
                else
 
991
                    UseMsg();
 
992
            }
 
993
            else
 
994
                UseMsg();
 
995
        }
 
996
        else if (strcmp(argv[i], "-sigstop") == 0) {
 
997
            RunFromSigStopParent = TRUE;
 
998
        }
 
999
        else if (strcmp(argv[i], "+extension") == 0) {
 
1000
            if (++i < argc) {
 
1001
                if (!EnableDisableExtension(argv[i], TRUE))
 
1002
                    EnableDisableExtensionError(argv[i], TRUE);
 
1003
            }
 
1004
            else
 
1005
                UseMsg();
 
1006
        }
 
1007
        else if (strcmp(argv[i], "-extension") == 0) {
 
1008
            if (++i < argc) {
 
1009
                if (!EnableDisableExtension(argv[i], FALSE))
 
1010
                    EnableDisableExtensionError(argv[i], FALSE);
 
1011
            }
 
1012
            else
 
1013
                UseMsg();
 
1014
        }
 
1015
        else {
 
1016
            ErrorF("Unrecognized option: %s\n", argv[i]);
 
1017
            UseMsg();
 
1018
            FatalError("Unrecognized option: %s\n", argv[i]);
 
1019
        }
 
1020
    }
 
1021
}
 
1022
 
 
1023
/* Implement a simple-minded font authorization scheme.  The authorization
 
1024
   name is "hp-hostname-1", the contents are simply the host name. */
 
1025
int
 
1026
set_font_authorizations(char **authorizations, int *authlen, void *client)
 
1027
{
 
1028
#define AUTHORIZATION_NAME "hp-hostname-1"
 
1029
#if defined(TCPCONN) || defined(STREAMSCONN)
 
1030
    static char *result = NULL;
 
1031
    static char *p = NULL;
 
1032
 
 
1033
    if (p == NULL) {
 
1034
        char hname[1024], *hnameptr;
 
1035
        unsigned int len;
 
1036
 
 
1037
#if defined(IPv6) && defined(AF_INET6)
 
1038
        struct addrinfo hints, *ai = NULL;
 
1039
#else
 
1040
        struct hostent *host;
 
1041
 
 
1042
#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
 
1043
        _Xgethostbynameparams hparams;
 
1044
#endif
 
1045
#endif
 
1046
 
 
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;
 
1053
        }
 
1054
        else {
 
1055
            hnameptr = hname;
 
1056
        }
 
1057
#else
 
1058
        host = _XGethostbyname(hname, hparams);
 
1059
        if (host == NULL)
 
1060
            hnameptr = hname;
 
1061
        else
 
1062
            hnameptr = host->h_name;
 
1063
#endif
 
1064
 
 
1065
        len = strlen(hnameptr) + 1;
 
1066
        result = malloc(len + sizeof(AUTHORIZATION_NAME) + 4);
 
1067
 
 
1068
        p = result;
 
1069
        *p++ = sizeof(AUTHORIZATION_NAME) >> 8;
 
1070
        *p++ = sizeof(AUTHORIZATION_NAME) & 0xff;
 
1071
        *p++ = (len) >> 8;
 
1072
        *p++ = (len & 0xff);
 
1073
 
 
1074
        memmove(p, AUTHORIZATION_NAME, sizeof(AUTHORIZATION_NAME));
 
1075
        p += sizeof(AUTHORIZATION_NAME);
 
1076
        memmove(p, hnameptr, len);
 
1077
        p += len;
 
1078
#if defined(IPv6) && defined(AF_INET6)
 
1079
        if (ai) {
 
1080
            freeaddrinfo(ai);
 
1081
        }
 
1082
#endif
 
1083
    }
 
1084
    *authlen = p - result;
 
1085
    *authorizations = result;
 
1086
    return 1;
 
1087
#else                           /* TCPCONN */
 
1088
    return 0;
 
1089
#endif                          /* TCPCONN */
 
1090
}
 
1091
 
 
1092
void *
 
1093
Xalloc(unsigned long amount)
 
1094
{
 
1095
    /*
 
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.
 
1099
     *
 
1100
     * -- Mikhail Gusarov
 
1101
     */
 
1102
    if ((long) amount <= 0)
 
1103
        ErrorF("Warning: Xalloc: "
 
1104
               "requesting unpleasantly large amount of memory: %lu bytes.\n",
 
1105
               amount);
 
1106
 
 
1107
    return malloc(amount);
 
1108
}
 
1109
 
 
1110
void *
 
1111
XNFalloc(unsigned long amount)
 
1112
{
 
1113
    void *ptr = malloc(amount);
 
1114
 
 
1115
    if (!ptr)
 
1116
        FatalError("Out of memory");
 
1117
    return ptr;
 
1118
}
 
1119
 
 
1120
void *
 
1121
Xcalloc(unsigned long amount)
 
1122
{
 
1123
    return calloc(1, amount);
 
1124
}
 
1125
 
 
1126
void *
 
1127
XNFcalloc(unsigned long amount)
 
1128
{
 
1129
    void *ret = calloc(1, amount);
 
1130
 
 
1131
    if (!ret)
 
1132
        FatalError("XNFcalloc: Out of memory");
 
1133
    return ret;
 
1134
}
 
1135
 
 
1136
void *
 
1137
Xrealloc(void *ptr, unsigned long amount)
 
1138
{
 
1139
    /*
 
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.
 
1143
     *
 
1144
     * -- Mikhail Gusarov
 
1145
     */
 
1146
    if ((long) amount <= 0)
 
1147
        ErrorF("Warning: Xrealloc: "
 
1148
               "requesting unpleasantly large amount of memory: %lu bytes.\n",
 
1149
               amount);
 
1150
 
 
1151
    return realloc(ptr, amount);
 
1152
}
 
1153
 
 
1154
void *
 
1155
XNFrealloc(void *ptr, unsigned long amount)
 
1156
{
 
1157
    void *ret = realloc(ptr, amount);
 
1158
 
 
1159
    if (!ret)
 
1160
        FatalError("XNFrealloc: Out of memory");
 
1161
    return ret;
 
1162
}
 
1163
 
 
1164
void
 
1165
Xfree(void *ptr)
 
1166
{
 
1167
    free(ptr);
 
1168
}
 
1169
 
 
1170
char *
 
1171
Xstrdup(const char *s)
 
1172
{
 
1173
    if (s == NULL)
 
1174
        return NULL;
 
1175
    return strdup(s);
 
1176
}
 
1177
 
 
1178
char *
 
1179
XNFstrdup(const char *s)
 
1180
{
 
1181
    char *ret;
 
1182
 
 
1183
    if (s == NULL)
 
1184
        return NULL;
 
1185
 
 
1186
    ret = strdup(s);
 
1187
    if (!ret)
 
1188
        FatalError("XNFstrdup: Out of memory");
 
1189
    return ret;
 
1190
}
 
1191
 
 
1192
void
 
1193
SmartScheduleStopTimer(void)
 
1194
{
 
1195
#ifdef SMART_SCHEDULE_POSSIBLE
 
1196
    struct itimerval timer;
 
1197
 
 
1198
    if (SmartScheduleDisable)
 
1199
        return;
 
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);
 
1205
#endif
 
1206
}
 
1207
 
 
1208
void
 
1209
SmartScheduleStartTimer(void)
 
1210
{
 
1211
#ifdef SMART_SCHEDULE_POSSIBLE
 
1212
    struct itimerval timer;
 
1213
 
 
1214
    if (SmartScheduleDisable)
 
1215
        return;
 
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);
 
1221
#endif
 
1222
}
 
1223
 
 
1224
static void
 
1225
SmartScheduleTimer(int sig)
 
1226
{
 
1227
    SmartScheduleTime += SmartScheduleInterval;
 
1228
}
 
1229
 
 
1230
void
 
1231
SmartScheduleInit(void)
 
1232
{
 
1233
#ifdef SMART_SCHEDULE_POSSIBLE
 
1234
    struct sigaction act;
 
1235
 
 
1236
    if (SmartScheduleDisable)
 
1237
        return;
 
1238
 
 
1239
    memset((char *) &act, 0, sizeof(struct sigaction));
 
1240
 
 
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;
 
1248
    }
 
1249
#endif
 
1250
}
 
1251
 
 
1252
#ifdef SIG_BLOCK
 
1253
static sigset_t PreviousSignalMask;
 
1254
static int BlockedSignalCount;
 
1255
#endif
 
1256
 
 
1257
void
 
1258
OsBlockSignals(void)
 
1259
{
 
1260
#ifdef SIG_BLOCK
 
1261
    if (BlockedSignalCount++ == 0) {
 
1262
        sigset_t set;
 
1263
 
 
1264
#ifdef SIGIO
 
1265
        OsBlockSIGIO();
 
1266
#endif
 
1267
        sigemptyset(&set);
 
1268
        sigaddset(&set, SIGALRM);
 
1269
        sigaddset(&set, SIGVTALRM);
 
1270
#ifdef SIGWINCH
 
1271
        sigaddset(&set, SIGWINCH);
 
1272
#endif
 
1273
        sigaddset(&set, SIGTSTP);
 
1274
        sigaddset(&set, SIGTTIN);
 
1275
        sigaddset(&set, SIGTTOU);
 
1276
        sigaddset(&set, SIGCHLD);
 
1277
        sigprocmask(SIG_BLOCK, &set, &PreviousSignalMask);
 
1278
    }
 
1279
#endif
 
1280
}
 
1281
 
 
1282
#ifdef SIG_BLOCK
 
1283
static sig_atomic_t sigio_blocked;
 
1284
static sigset_t PreviousSigIOMask;
 
1285
#endif
 
1286
 
 
1287
/**
 
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.
 
1290
 */
 
1291
int
 
1292
OsBlockSIGIO(void)
 
1293
{
 
1294
#ifdef SIGIO
 
1295
#ifdef SIG_BLOCK
 
1296
    if (sigio_blocked++ == 0) {
 
1297
        sigset_t set;
 
1298
        int ret;
 
1299
 
 
1300
        sigemptyset(&set);
 
1301
        sigaddset(&set, SIGIO);
 
1302
        sigprocmask(SIG_BLOCK, &set, &PreviousSigIOMask);
 
1303
        ret = sigismember(&PreviousSigIOMask, SIGIO);
 
1304
        return ret;
 
1305
    }
 
1306
#endif
 
1307
#endif
 
1308
    return 1;
 
1309
}
 
1310
 
 
1311
void
 
1312
OsReleaseSIGIO(void)
 
1313
{
 
1314
#ifdef SIGIO
 
1315
#ifdef SIG_BLOCK
 
1316
    if (--sigio_blocked == 0) {
 
1317
        sigprocmask(SIG_SETMASK, &PreviousSigIOMask, 0);
 
1318
    } else if (sigio_blocked < 0) {
 
1319
        BUG_WARN(sigio_blocked < 0);
 
1320
        sigio_blocked = 0;
 
1321
    }
 
1322
#endif
 
1323
#endif
 
1324
}
 
1325
 
 
1326
void
 
1327
OsReleaseSignals(void)
 
1328
{
 
1329
#ifdef SIG_BLOCK
 
1330
    if (--BlockedSignalCount == 0) {
 
1331
        sigprocmask(SIG_SETMASK, &PreviousSignalMask, 0);
 
1332
        OsReleaseSIGIO();
 
1333
    }
 
1334
#endif
 
1335
}
 
1336
 
 
1337
void
 
1338
OsResetSignals(void)
 
1339
{
 
1340
#ifdef SIG_BLOCK
 
1341
    while (BlockedSignalCount > 0)
 
1342
        OsReleaseSignals();
 
1343
#ifdef SIGIO
 
1344
    while (sigio_blocked > 0)
 
1345
        OsReleaseSIGIO();
 
1346
#endif
 
1347
#endif
 
1348
}
 
1349
 
 
1350
/*
 
1351
 * Pending signals may interfere with core dumping. Provide a
 
1352
 * mechanism to block signals when aborting.
 
1353
 */
 
1354
 
 
1355
void
 
1356
OsAbort(void)
 
1357
{
 
1358
#ifndef __APPLE__
 
1359
    OsBlockSignals();
 
1360
#endif
 
1361
    abort();
 
1362
}
 
1363
 
 
1364
#if !defined(WIN32)
 
1365
/*
 
1366
 * "safer" versions of system(3), popen(3) and pclose(3) which give up
 
1367
 * all privs before running a command.
 
1368
 *
 
1369
 * This is based on the code in FreeBSD 2.2 libc.
 
1370
 *
 
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.
 
1373
 */
 
1374
 
 
1375
int
 
1376
System(const char *command)
 
1377
{
 
1378
    int pid, p;
 
1379
    void (*csig) (int);
 
1380
    int status;
 
1381
 
 
1382
    if (!command)
 
1383
        return 1;
 
1384
 
 
1385
    csig = signal(SIGCHLD, SIG_DFL);
 
1386
    if (csig == SIG_ERR) {
 
1387
        perror("signal");
 
1388
        return -1;
 
1389
    }
 
1390
    DebugF("System: `%s'\n", command);
 
1391
 
 
1392
    switch (pid = fork()) {
 
1393
    case -1:                   /* error */
 
1394
        p = -1;
 
1395
    case 0:                    /* child */
 
1396
        if (setgid(getgid()) == -1)
 
1397
            _exit(127);
 
1398
        if (setuid(getuid()) == -1)
 
1399
            _exit(127);
 
1400
        execl("/bin/sh", "sh", "-c", command, (char *) NULL);
 
1401
        _exit(127);
 
1402
    default:                   /* parent */
 
1403
        do {
 
1404
            p = waitpid(pid, &status, 0);
 
1405
        } while (p == -1 && errno == EINTR);
 
1406
 
 
1407
    }
 
1408
 
 
1409
    if (signal(SIGCHLD, csig) == SIG_ERR) {
 
1410
        perror("signal");
 
1411
        return -1;
 
1412
    }
 
1413
 
 
1414
    return p == -1 ? -1 : status;
 
1415
}
 
1416
 
 
1417
static struct pid {
 
1418
    struct pid *next;
 
1419
    FILE *fp;
 
1420
    int pid;
 
1421
} *pidlist;
 
1422
 
 
1423
OsSigHandlerPtr old_alarm = NULL;       /* XXX horrible awful hack */
 
1424
 
 
1425
void *
 
1426
Popen(const char *command, const char *type)
 
1427
{
 
1428
    struct pid *cur;
 
1429
    FILE *iop;
 
1430
    int pdes[2], pid;
 
1431
 
 
1432
    if (command == NULL || type == NULL)
 
1433
        return NULL;
 
1434
 
 
1435
    if ((*type != 'r' && *type != 'w') || type[1])
 
1436
        return NULL;
 
1437
 
 
1438
    if ((cur = malloc(sizeof(struct pid))) == NULL)
 
1439
        return NULL;
 
1440
 
 
1441
    if (pipe(pdes) < 0) {
 
1442
        free(cur);
 
1443
        return NULL;
 
1444
    }
 
1445
 
 
1446
    /* Ignore the smart scheduler while this is going on */
 
1447
    old_alarm = OsSignal(SIGALRM, SIG_IGN);
 
1448
    if (old_alarm == SIG_ERR) {
 
1449
        close(pdes[0]);
 
1450
        close(pdes[1]);
 
1451
        free(cur);
 
1452
        perror("signal");
 
1453
        return NULL;
 
1454
    }
 
1455
 
 
1456
    switch (pid = fork()) {
 
1457
    case -1:                   /* error */
 
1458
        close(pdes[0]);
 
1459
        close(pdes[1]);
 
1460
        free(cur);
 
1461
        if (OsSignal(SIGALRM, old_alarm) == SIG_ERR)
 
1462
            perror("signal");
 
1463
        return NULL;
 
1464
    case 0:                    /* child */
 
1465
        if (setgid(getgid()) == -1)
 
1466
            _exit(127);
 
1467
        if (setuid(getuid()) == -1)
 
1468
            _exit(127);
 
1469
        if (*type == 'r') {
 
1470
            if (pdes[1] != 1) {
 
1471
                /* stdout */
 
1472
                dup2(pdes[1], 1);
 
1473
                close(pdes[1]);
 
1474
            }
 
1475
            close(pdes[0]);
 
1476
        }
 
1477
        else {
 
1478
            if (pdes[0] != 0) {
 
1479
                /* stdin */
 
1480
                dup2(pdes[0], 0);
 
1481
                close(pdes[0]);
 
1482
            }
 
1483
            close(pdes[1]);
 
1484
        }
 
1485
        execl("/bin/sh", "sh", "-c", command, (char *) NULL);
 
1486
        _exit(127);
 
1487
    }
 
1488
 
 
1489
    /* Avoid EINTR during stdio calls */
 
1490
    OsBlockSignals();
 
1491
 
 
1492
    /* parent */
 
1493
    if (*type == 'r') {
 
1494
        iop = fdopen(pdes[0], type);
 
1495
        close(pdes[1]);
 
1496
    }
 
1497
    else {
 
1498
        iop = fdopen(pdes[1], type);
 
1499
        close(pdes[0]);
 
1500
    }
 
1501
 
 
1502
    cur->fp = iop;
 
1503
    cur->pid = pid;
 
1504
    cur->next = pidlist;
 
1505
    pidlist = cur;
 
1506
 
 
1507
    DebugF("Popen: `%s', fp = %p\n", command, iop);
 
1508
 
 
1509
    return iop;
 
1510
}
 
1511
 
 
1512
/* fopen that drops privileges */
 
1513
void *
 
1514
Fopen(const char *file, const char *type)
 
1515
{
 
1516
    FILE *iop;
 
1517
 
 
1518
#ifndef HAS_SAVED_IDS_AND_SETEUID
 
1519
    struct pid *cur;
 
1520
    int pdes[2], pid;
 
1521
 
 
1522
    if (file == NULL || type == NULL)
 
1523
        return NULL;
 
1524
 
 
1525
    if ((*type != 'r' && *type != 'w') || type[1])
 
1526
        return NULL;
 
1527
 
 
1528
    if ((cur = malloc(sizeof(struct pid))) == NULL)
 
1529
        return NULL;
 
1530
 
 
1531
    if (pipe(pdes) < 0) {
 
1532
        free(cur);
 
1533
        return NULL;
 
1534
    }
 
1535
 
 
1536
    switch (pid = fork()) {
 
1537
    case -1:                   /* error */
 
1538
        close(pdes[0]);
 
1539
        close(pdes[1]);
 
1540
        free(cur);
 
1541
        return NULL;
 
1542
    case 0:                    /* child */
 
1543
        if (setgid(getgid()) == -1)
 
1544
            _exit(127);
 
1545
        if (setuid(getuid()) == -1)
 
1546
            _exit(127);
 
1547
        if (*type == 'r') {
 
1548
            if (pdes[1] != 1) {
 
1549
                /* stdout */
 
1550
                dup2(pdes[1], 1);
 
1551
                close(pdes[1]);
 
1552
            }
 
1553
            close(pdes[0]);
 
1554
        }
 
1555
        else {
 
1556
            if (pdes[0] != 0) {
 
1557
                /* stdin */
 
1558
                dup2(pdes[0], 0);
 
1559
                close(pdes[0]);
 
1560
            }
 
1561
            close(pdes[1]);
 
1562
        }
 
1563
        execl("/bin/cat", "cat", file, (char *) NULL);
 
1564
        _exit(127);
 
1565
    }
 
1566
 
 
1567
    /* Avoid EINTR during stdio calls */
 
1568
    OsBlockSignals();
 
1569
 
 
1570
    /* parent */
 
1571
    if (*type == 'r') {
 
1572
        iop = fdopen(pdes[0], type);
 
1573
        close(pdes[1]);
 
1574
    }
 
1575
    else {
 
1576
        iop = fdopen(pdes[1], type);
 
1577
        close(pdes[0]);
 
1578
    }
 
1579
 
 
1580
    cur->fp = iop;
 
1581
    cur->pid = pid;
 
1582
    cur->next = pidlist;
 
1583
    pidlist = cur;
 
1584
 
 
1585
    DebugF("Fopen(%s), fp = %p\n", file, iop);
 
1586
 
 
1587
    return iop;
 
1588
#else
 
1589
    int ruid, euid;
 
1590
 
 
1591
    ruid = getuid();
 
1592
    euid = geteuid();
 
1593
 
 
1594
    if (seteuid(ruid) == -1) {
 
1595
        return NULL;
 
1596
    }
 
1597
    iop = fopen(file, type);
 
1598
 
 
1599
    if (seteuid(euid) == -1) {
 
1600
        fclose(iop);
 
1601
        return NULL;
 
1602
    }
 
1603
    return iop;
 
1604
#endif                          /* HAS_SAVED_IDS_AND_SETEUID */
 
1605
}
 
1606
 
 
1607
int
 
1608
Pclose(void *iop)
 
1609
{
 
1610
    struct pid *cur, *last;
 
1611
    int pstat;
 
1612
    int pid;
 
1613
 
 
1614
    DebugF("Pclose: fp = %p\n", iop);
 
1615
    fclose(iop);
 
1616
 
 
1617
    for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next)
 
1618
        if (cur->fp == iop)
 
1619
            break;
 
1620
    if (cur == NULL)
 
1621
        return -1;
 
1622
 
 
1623
    do {
 
1624
        pid = waitpid(cur->pid, &pstat, 0);
 
1625
    } while (pid == -1 && errno == EINTR);
 
1626
 
 
1627
    if (last == NULL)
 
1628
        pidlist = cur->next;
 
1629
    else
 
1630
        last->next = cur->next;
 
1631
    free(cur);
 
1632
 
 
1633
    /* allow EINTR again */
 
1634
    OsReleaseSignals();
 
1635
 
 
1636
    if (old_alarm && OsSignal(SIGALRM, old_alarm) == SIG_ERR) {
 
1637
        perror("signal");
 
1638
        return -1;
 
1639
    }
 
1640
 
 
1641
    return pid == -1 ? -1 : pstat;
 
1642
}
 
1643
 
 
1644
int
 
1645
Fclose(void *iop)
 
1646
{
 
1647
#ifdef HAS_SAVED_IDS_AND_SETEUID
 
1648
    return fclose(iop);
 
1649
#else
 
1650
    return Pclose(iop);
 
1651
#endif
 
1652
}
 
1653
 
 
1654
#endif                          /* !WIN32 */
 
1655
 
 
1656
#ifdef WIN32
 
1657
 
 
1658
#include <X11/Xwindows.h>
 
1659
 
 
1660
const char *
 
1661
Win32TempDir()
 
1662
{
 
1663
    static char buffer[PATH_MAX];
 
1664
 
 
1665
    if (GetTempPath(sizeof(buffer), buffer)) {
 
1666
        int len;
 
1667
 
 
1668
        buffer[sizeof(buffer) - 1] = 0;
 
1669
        len = strlen(buffer);
 
1670
        if (len > 0)
 
1671
            if (buffer[len - 1] == '\\')
 
1672
                buffer[len - 1] = 0;
 
1673
        return buffer;
 
1674
    }
 
1675
    if (getenv("TEMP") != NULL)
 
1676
        return getenv("TEMP");
 
1677
    else if (getenv("TMP") != NULL)
 
1678
        return getenv("TMP");
 
1679
    else
 
1680
        return "/tmp";
 
1681
}
 
1682
 
 
1683
int
 
1684
System(const char *cmdline)
 
1685
{
 
1686
    STARTUPINFO si;
 
1687
    PROCESS_INFORMATION pi;
 
1688
    DWORD dwExitCode;
 
1689
    char *cmd = strdup(cmdline);
 
1690
 
 
1691
    ZeroMemory(&si, sizeof(si));
 
1692
    si.cb = sizeof(si);
 
1693
    ZeroMemory(&pi, sizeof(pi));
 
1694
 
 
1695
    if (!CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
 
1696
        LPVOID buffer;
 
1697
 
 
1698
        if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
 
1699
                           FORMAT_MESSAGE_FROM_SYSTEM |
 
1700
                           FORMAT_MESSAGE_IGNORE_INSERTS,
 
1701
                           NULL,
 
1702
                           GetLastError(),
 
1703
                           MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
 
1704
                           (LPTSTR) &buffer, 0, NULL)) {
 
1705
            ErrorF("[xkb] Starting '%s' failed!\n", cmdline);
 
1706
        }
 
1707
        else {
 
1708
            ErrorF("[xkb] Starting '%s' failed: %s", cmdline, (char *) buffer);
 
1709
            LocalFree(buffer);
 
1710
        }
 
1711
 
 
1712
        free(cmd);
 
1713
        return -1;
 
1714
    }
 
1715
    /* Wait until child process exits. */
 
1716
    WaitForSingleObject(pi.hProcess, INFINITE);
 
1717
 
 
1718
    GetExitCodeProcess(pi.hProcess, &dwExitCode);
 
1719
 
 
1720
    /* Close process and thread handles. */
 
1721
    CloseHandle(pi.hProcess);
 
1722
    CloseHandle(pi.hThread);
 
1723
    free(cmd);
 
1724
 
 
1725
    return dwExitCode;
 
1726
}
 
1727
#endif
 
1728
 
 
1729
/*
 
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.
 
1734
 */
 
1735
 
 
1736
/* Consider LD* variables insecure? */
 
1737
#ifndef REMOVE_ENV_LD
 
1738
#define REMOVE_ENV_LD 1
 
1739
#endif
 
1740
 
 
1741
/* Remove long environment variables? */
 
1742
#ifndef REMOVE_LONG_ENV
 
1743
#define REMOVE_LONG_ENV 1
 
1744
#endif
 
1745
 
 
1746
/*
 
1747
 * Disallow stdout or stderr as pipes?  It's possible to block the X server
 
1748
 * when piping stdout+stderr to a pipe.
 
1749
 *
 
1750
 * Don't enable this because it looks like it's going to cause problems.
 
1751
 */
 
1752
#ifndef NO_OUTPUT_PIPES
 
1753
#define NO_OUTPUT_PIPES 0
 
1754
#endif
 
1755
 
 
1756
/* Check args and env only if running setuid (euid == 0 && euid != uid) ? */
 
1757
#ifndef CHECK_EUID
 
1758
#ifndef WIN32
 
1759
#define CHECK_EUID 1
 
1760
#else
 
1761
#define CHECK_EUID 0
 
1762
#endif
 
1763
#endif
 
1764
 
 
1765
/*
 
1766
 * Maybe the locale can be faked to make isprint(3) report that everything
 
1767
 * is printable?  Avoid it by default.
 
1768
 */
 
1769
#ifndef USE_ISPRINT
 
1770
#define USE_ISPRINT 0
 
1771
#endif
 
1772
 
 
1773
#define MAX_ARG_LENGTH          128
 
1774
#define MAX_ENV_LENGTH          256
 
1775
#define MAX_ENV_PATH_LENGTH     2048    /* Limit for *PATH and TERMCAP */
 
1776
 
 
1777
#if USE_ISPRINT
 
1778
#include <ctype.h>
 
1779
#define checkPrintable(c) isprint(c)
 
1780
#else
 
1781
#define checkPrintable(c) (((c) & 0x7f) >= 0x20 && ((c) & 0x7f) != 0x7f)
 
1782
#endif
 
1783
 
 
1784
enum BadCode {
 
1785
    NotBad = 0,
 
1786
    UnsafeArg,
 
1787
    ArgTooLong,
 
1788
    UnprintableArg,
 
1789
    EnvTooLong,
 
1790
    OutputIsPipe,
 
1791
    InternalError
 
1792
};
 
1793
 
 
1794
#if defined(VENDORSUPPORT)
 
1795
#define BUGADDRESS VENDORSUPPORT
 
1796
#elif defined(BUILDERADDR)
 
1797
#define BUGADDRESS BUILDERADDR
 
1798
#else
 
1799
#define BUGADDRESS "xorg@freedesktop.org"
 
1800
#endif
 
1801
 
 
1802
void
 
1803
CheckUserParameters(int argc, char **argv, char **envp)
 
1804
{
 
1805
    enum BadCode bad = NotBad;
 
1806
    int i = 0, j;
 
1807
    char *a, *e = NULL;
 
1808
 
 
1809
#if CHECK_EUID
 
1810
    if (geteuid() == 0 && getuid() != geteuid())
 
1811
#endif
 
1812
    {
 
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 */
 
1817
                if (i >= argc)
 
1818
                    break;
 
1819
            }
 
1820
            else {
 
1821
                if (strlen(argv[i]) > MAX_ARG_LENGTH) {
 
1822
                    bad = ArgTooLong;
 
1823
                    break;
 
1824
                }
 
1825
            }
 
1826
            a = argv[i];
 
1827
            while (*a) {
 
1828
                if (checkPrintable(*a) == 0) {
 
1829
                    bad = UnprintableArg;
 
1830
                    break;
 
1831
                }
 
1832
                a++;
 
1833
            }
 
1834
            if (bad)
 
1835
                break;
 
1836
        }
 
1837
        if (!bad) {
 
1838
            /* Check each envp[] */
 
1839
            for (i = 0; envp[i]; i++) {
 
1840
 
 
1841
                /* Check for bad environment variables and values */
 
1842
#if REMOVE_ENV_LD
 
1843
                while (envp[i] && (strncmp(envp[i], "LD", 2) == 0)) {
 
1844
                    for (j = i; envp[j]; j++) {
 
1845
                        envp[j] = envp[j + 1];
 
1846
                    }
 
1847
                }
 
1848
#endif
 
1849
                if (envp[i] && (strlen(envp[i]) > MAX_ENV_LENGTH)) {
 
1850
#if REMOVE_LONG_ENV
 
1851
                    for (j = i; envp[j]; j++) {
 
1852
                        envp[j] = envp[j + 1];
 
1853
                    }
 
1854
                    i--;
 
1855
#else
 
1856
                    char *eq;
 
1857
                    int len;
 
1858
 
 
1859
                    eq = strchr(envp[i], '=');
 
1860
                    if (!eq)
 
1861
                        continue;
 
1862
                    len = eq - envp[i];
 
1863
                    e = strndup(envp[i], len);
 
1864
                    if (!e) {
 
1865
                        bad = InternalError;
 
1866
                        break;
 
1867
                    }
 
1868
                    if (len >= 4 &&
 
1869
                        (strcmp(e + len - 4, "PATH") == 0 ||
 
1870
                         strcmp(e, "TERMCAP") == 0)) {
 
1871
                        if (strlen(envp[i]) > MAX_ENV_PATH_LENGTH) {
 
1872
                            bad = EnvTooLong;
 
1873
                            break;
 
1874
                        }
 
1875
                        else {
 
1876
                            free(e);
 
1877
                        }
 
1878
                    }
 
1879
                    else {
 
1880
                        bad = EnvTooLong;
 
1881
                        break;
 
1882
                    }
 
1883
#endif
 
1884
                }
 
1885
            }
 
1886
        }
 
1887
#if NO_OUTPUT_PIPES
 
1888
        if (!bad) {
 
1889
            struct stat buf;
 
1890
 
 
1891
            if (fstat(fileno(stdout), &buf) == 0 && S_ISFIFO(buf.st_mode))
 
1892
                bad = OutputIsPipe;
 
1893
            if (fstat(fileno(stderr), &buf) == 0 && S_ISFIFO(buf.st_mode))
 
1894
                bad = OutputIsPipe;
 
1895
        }
 
1896
#endif
 
1897
    }
 
1898
    switch (bad) {
 
1899
    case NotBad:
 
1900
        return;
 
1901
    case UnsafeArg:
 
1902
        ErrorF("Command line argument number %d is unsafe\n", i);
 
1903
        break;
 
1904
    case ArgTooLong:
 
1905
        ErrorF("Command line argument number %d is too long\n", i);
 
1906
        break;
 
1907
    case UnprintableArg:
 
1908
        ErrorF("Command line argument number %d contains unprintable"
 
1909
               " characters\n", i);
 
1910
        break;
 
1911
    case EnvTooLong:
 
1912
        ErrorF("Environment variable `%s' is too long\n", e);
 
1913
        break;
 
1914
    case OutputIsPipe:
 
1915
        ErrorF("Stdout and/or stderr is a pipe\n");
 
1916
        break;
 
1917
    case InternalError:
 
1918
        ErrorF("Internal Error\n");
 
1919
        break;
 
1920
    default:
 
1921
        ErrorF("Unknown error\n");
 
1922
        break;
 
1923
    }
 
1924
    FatalError("X server aborted because of unsafe environment\n");
 
1925
}
 
1926
 
 
1927
/*
 
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).
 
1931
 */
 
1932
 
 
1933
#ifdef USE_PAM
 
1934
#include <security/pam_appl.h>
 
1935
#include <security/pam_misc.h>
 
1936
#include <pwd.h>
 
1937
#endif                          /* USE_PAM */
 
1938
 
 
1939
void
 
1940
CheckUserAuthorization(void)
 
1941
{
 
1942
#ifdef USE_PAM
 
1943
    static struct pam_conv conv = {
 
1944
        misc_conv,
 
1945
        NULL
 
1946
    };
 
1947
 
 
1948
    pam_handle_t *pamh = NULL;
 
1949
    struct passwd *pw;
 
1950
    int retval;
 
1951
 
 
1952
    if (getuid() != geteuid()) {
 
1953
        pw = getpwuid(getuid());
 
1954
        if (pw == NULL)
 
1955
            FatalError("getpwuid() failed for uid %d\n", getuid());
 
1956
 
 
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");
 
1961
 
 
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");
 
1967
        }
 
1968
 
 
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");
 
1974
        }
 
1975
 
 
1976
        /* this is not a session, so do not do session management */
 
1977
        pam_end(pamh, PAM_SUCCESS);
 
1978
    }
 
1979
#endif
 
1980
}
 
1981
 
 
1982
/*
 
1983
 * Tokenize a string into a NULL terminated array of strings. Always returns
 
1984
 * an allocated array unless an error occurs.
 
1985
 */
 
1986
char **
 
1987
xstrtokenize(const char *str, const char *separators)
 
1988
{
 
1989
    char **list, **nlist;
 
1990
    char *tok, *tmp;
 
1991
    unsigned num = 0, n;
 
1992
 
 
1993
    if (!str)
 
1994
        return NULL;
 
1995
    list = calloc(1, sizeof(*list));
 
1996
    if (!list)
 
1997
        return NULL;
 
1998
    tmp = strdup(str);
 
1999
    if (!tmp)
 
2000
        goto error;
 
2001
    for (tok = strtok(tmp, separators); tok; tok = strtok(NULL, separators)) {
 
2002
        nlist = realloc(list, (num + 2) * sizeof(*list));
 
2003
        if (!nlist)
 
2004
            goto error;
 
2005
        list = nlist;
 
2006
        list[num] = strdup(tok);
 
2007
        if (!list[num])
 
2008
            goto error;
 
2009
        list[++num] = NULL;
 
2010
    }
 
2011
    free(tmp);
 
2012
    return list;
 
2013
 
 
2014
 error:
 
2015
    free(tmp);
 
2016
    for (n = 0; n < num; n++)
 
2017
        free(list[n]);
 
2018
    free(list);
 
2019
    return NULL;
 
2020
}
 
2021
 
 
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.
 
2024
 */
 
2025
void
 
2026
FormatInt64(int64_t num, char *string)
 
2027
{
 
2028
    if (num < 0) {
 
2029
        string[0] = '-';
 
2030
        num *= -1;
 
2031
        string++;
 
2032
    }
 
2033
    FormatUInt64(num, string);
 
2034
}
 
2035
 
 
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. */
 
2038
void
 
2039
FormatUInt64(uint64_t num, char *string)
 
2040
{
 
2041
    uint64_t divisor;
 
2042
    int len;
 
2043
    int i;
 
2044
 
 
2045
    for (len = 1, divisor = 10;
 
2046
         len < 20 && num / divisor;
 
2047
         len++, divisor *= 10);
 
2048
 
 
2049
    for (i = len, divisor = 1; i > 0; i--, divisor *= 10)
 
2050
        string[i - 1] = '0' + ((num / divisor) % 10);
 
2051
 
 
2052
    string[len] = '\0';
 
2053
}
 
2054
 
 
2055
/**
 
2056
 * Format a double number as %.2f.
 
2057
 */
 
2058
void
 
2059
FormatDouble(double dbl, char *string)
 
2060
{
 
2061
    int slen = 0;
 
2062
    uint64_t frac;
 
2063
 
 
2064
    frac = (dbl > 0 ? dbl : -dbl) * 100.0 + 0.5;
 
2065
    frac %= 100;
 
2066
 
 
2067
    /* write decimal part to string */
 
2068
    if (dbl < 0 && dbl > -1)
 
2069
        string[slen++] = '-';
 
2070
    FormatInt64((int64_t)dbl, &string[slen]);
 
2071
 
 
2072
    while(string[slen] != '\0')
 
2073
        slen++;
 
2074
 
 
2075
    /* append fractional part, but only if we have enough characters. We
 
2076
     * expect string to be 21 chars (incl trailing \0) */
 
2077
    if (slen <= 17) {
 
2078
        string[slen++] = '.';
 
2079
        if (frac < 10)
 
2080
            string[slen++] = '0';
 
2081
 
 
2082
        FormatUInt64(frac, &string[slen]);
 
2083
    }
 
2084
}
 
2085
 
 
2086
 
 
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. */
 
2089
void
 
2090
FormatUInt64Hex(uint64_t num, char *string)
 
2091
{
 
2092
    uint64_t divisor;
 
2093
    int len;
 
2094
    int i;
 
2095
 
 
2096
    for (len = 1, divisor = 0x10;
 
2097
         len < 16 && num / divisor;
 
2098
         len++, divisor *= 0x10);
 
2099
 
 
2100
    for (i = len, divisor = 1; i > 0; i--, divisor *= 0x10) {
 
2101
        int val = (num / divisor) % 0x10;
 
2102
 
 
2103
        if (val < 10)
 
2104
            string[i - 1] = '0' + val;
 
2105
        else
 
2106
            string[i - 1] = 'a' + val - 10;
 
2107
    }
 
2108
 
 
2109
    string[len] = '\0';
 
2110
}
 
2111
 
 
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
 
2116
 */
 
2117
int
 
2118
os_move_fd(int fd)
 
2119
{
 
2120
    int newfd;
 
2121
 
 
2122
#ifdef F_DUPFD_CLOEXEC
 
2123
    newfd = fcntl(fd, F_DUPFD_CLOEXEC, MAXCLIENTS);
 
2124
#else
 
2125
    newfd = fcntl(fd, F_DUPFD, MAXCLIENTS);
 
2126
#endif
 
2127
    if (newfd < 0)
 
2128
        return fd;
 
2129
#ifndef F_DUPFD_CLOEXEC
 
2130
    fcntl(newfd, F_SETFD, FD_CLOEXEC);
 
2131
#endif
 
2132
    close(fd);
 
2133
    return newfd;
 
2134
}