utils.c revision 05b261ec
105b261ecSmrg/*
205b261ecSmrg
305b261ecSmrgCopyright 1987, 1998  The Open Group
405b261ecSmrg
505b261ecSmrgPermission to use, copy, modify, distribute, and sell this software and its
605b261ecSmrgdocumentation for any purpose is hereby granted without fee, provided that
705b261ecSmrgthe above copyright notice appear in all copies and that both that
805b261ecSmrgcopyright notice and this permission notice appear in supporting
905b261ecSmrgdocumentation.
1005b261ecSmrg
1105b261ecSmrgThe above copyright notice and this permission notice shall be included
1205b261ecSmrgin all copies or substantial portions of the Software.
1305b261ecSmrg
1405b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1505b261ecSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1605b261ecSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
1705b261ecSmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
1805b261ecSmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
1905b261ecSmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2005b261ecSmrgOTHER DEALINGS IN THE SOFTWARE.
2105b261ecSmrg
2205b261ecSmrgExcept as contained in this notice, the name of The Open Group shall
2305b261ecSmrgnot be used in advertising or otherwise to promote the sale, use or
2405b261ecSmrgother dealings in this Software without prior written authorization
2505b261ecSmrgfrom The Open Group.
2605b261ecSmrg
2705b261ecSmrg
2805b261ecSmrgCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
2905b261ecSmrgCopyright 1994 Quarterdeck Office Systems.
3005b261ecSmrg
3105b261ecSmrg                        All Rights Reserved
3205b261ecSmrg
3305b261ecSmrgPermission to use, copy, modify, and distribute this software and its
3405b261ecSmrgdocumentation for any purpose and without fee is hereby granted,
3505b261ecSmrgprovided that the above copyright notice appear in all copies and that
3605b261ecSmrgboth that copyright notice and this permission notice appear in
3705b261ecSmrgsupporting documentation, and that the names of Digital and
3805b261ecSmrgQuarterdeck not be used in advertising or publicity pertaining to
3905b261ecSmrgdistribution of the software without specific, written prior
4005b261ecSmrgpermission.
4105b261ecSmrg
4205b261ecSmrgDIGITAL AND QUARTERDECK DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
4305b261ecSmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
4405b261ecSmrgFITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT
4505b261ecSmrgOR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
4605b261ecSmrgOF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
4705b261ecSmrgOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
4805b261ecSmrgOR PERFORMANCE OF THIS SOFTWARE.
4905b261ecSmrg
5005b261ecSmrg*/
5105b261ecSmrg
5205b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
5305b261ecSmrg#include <dix-config.h>
5405b261ecSmrg#endif
5505b261ecSmrg
5605b261ecSmrg#ifdef __CYGWIN__
5705b261ecSmrg#include <stdlib.h>
5805b261ecSmrg#include <signal.h>
5905b261ecSmrg#endif
6005b261ecSmrg
6105b261ecSmrg#if defined(WIN32) && !defined(__CYGWIN__)
6205b261ecSmrg#include <X11/Xwinsock.h>
6305b261ecSmrg#endif
6405b261ecSmrg#include <X11/Xos.h>
6505b261ecSmrg#include <stdio.h>
6605b261ecSmrg#include <time.h>
6705b261ecSmrg#if !defined(WIN32) || !defined(__MINGW32__)
6805b261ecSmrg#include <sys/time.h>
6905b261ecSmrg#include <sys/resource.h>
7005b261ecSmrg#endif
7105b261ecSmrg#include "misc.h"
7205b261ecSmrg#include <X11/X.h>
7305b261ecSmrg#define XSERV_t
7405b261ecSmrg#define TRANS_SERVER
7505b261ecSmrg#define TRANS_REOPEN
7605b261ecSmrg#include <X11/Xtrans/Xtrans.h>
7705b261ecSmrg#include "input.h"
7805b261ecSmrg#include "dixfont.h"
7905b261ecSmrg#include "osdep.h"
8005b261ecSmrg#include "extension.h"
8105b261ecSmrg#ifdef X_POSIX_C_SOURCE
8205b261ecSmrg#define _POSIX_C_SOURCE X_POSIX_C_SOURCE
8305b261ecSmrg#include <signal.h>
8405b261ecSmrg#undef _POSIX_C_SOURCE
8505b261ecSmrg#else
8605b261ecSmrg#if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE)
8705b261ecSmrg#include <signal.h>
8805b261ecSmrg#else
8905b261ecSmrg#define _POSIX_SOURCE
9005b261ecSmrg#include <signal.h>
9105b261ecSmrg#undef _POSIX_SOURCE
9205b261ecSmrg#endif
9305b261ecSmrg#endif
9405b261ecSmrg#ifndef WIN32
9505b261ecSmrg#include <sys/wait.h>
9605b261ecSmrg#endif
9705b261ecSmrg#if !defined(SYSV) && !defined(WIN32) && !defined(Lynx) && !defined(QNX4)
9805b261ecSmrg#include <sys/resource.h>
9905b261ecSmrg#endif
10005b261ecSmrg#include <sys/stat.h>
10105b261ecSmrg#include <ctype.h>    /* for isspace */
10205b261ecSmrg#include <stdarg.h>
10305b261ecSmrg
10405b261ecSmrg#if defined(DGUX)
10505b261ecSmrg#include <sys/resource.h>
10605b261ecSmrg#include <netdb.h>
10705b261ecSmrg#endif
10805b261ecSmrg
10905b261ecSmrg#include <stdlib.h>	/* for malloc() */
11005b261ecSmrg
11105b261ecSmrg#if defined(TCPCONN) || defined(STREAMSCONN)
11205b261ecSmrg# ifndef WIN32
11305b261ecSmrg#  include <netdb.h>
11405b261ecSmrg# endif
11505b261ecSmrg#endif
11605b261ecSmrg
11705b261ecSmrg#include "opaque.h"
11805b261ecSmrg
11905b261ecSmrg#ifdef SMART_SCHEDULE
12005b261ecSmrg#include "dixstruct.h"
12105b261ecSmrg#endif
12205b261ecSmrg
12305b261ecSmrg#ifdef XKB
12405b261ecSmrg#include <xkbsrv.h>
12505b261ecSmrg#endif
12605b261ecSmrg#ifdef XCSECURITY
12705b261ecSmrg#include "securitysrv.h"
12805b261ecSmrg#endif
12905b261ecSmrg
13005b261ecSmrg#ifdef RENDER
13105b261ecSmrg#include "picture.h"
13205b261ecSmrg#endif
13305b261ecSmrg
13405b261ecSmrg#ifdef XPRINT
13505b261ecSmrg#include "DiPrint.h"
13605b261ecSmrg#endif
13705b261ecSmrg
13805b261ecSmrg_X_EXPORT Bool noTestExtensions;
13905b261ecSmrg#ifdef BIGREQS
14005b261ecSmrg_X_EXPORT Bool noBigReqExtension = FALSE;
14105b261ecSmrg#endif
14205b261ecSmrg#ifdef COMPOSITE
14305b261ecSmrg_X_EXPORT Bool noCompositeExtension = FALSE;
14405b261ecSmrg#endif
14505b261ecSmrg
14605b261ecSmrg#ifdef DAMAGE
14705b261ecSmrg_X_EXPORT Bool noDamageExtension = FALSE;
14805b261ecSmrg#endif
14905b261ecSmrg#ifdef DBE
15005b261ecSmrg_X_EXPORT Bool noDbeExtension = FALSE;
15105b261ecSmrg#endif
15205b261ecSmrg#ifdef DPMSExtension
15305b261ecSmrg_X_EXPORT Bool noDPMSExtension = FALSE;
15405b261ecSmrg#endif
15505b261ecSmrg#ifdef EVI
15605b261ecSmrg_X_EXPORT Bool noEVIExtension = FALSE;
15705b261ecSmrg#endif
15805b261ecSmrg#ifdef FONTCACHE
15905b261ecSmrg_X_EXPORT Bool noFontCacheExtension = FALSE;
16005b261ecSmrg#endif
16105b261ecSmrg#ifdef GLXEXT
16205b261ecSmrg_X_EXPORT Bool noGlxExtension = FALSE;
16305b261ecSmrg#endif
16405b261ecSmrg#ifdef SCREENSAVER
16505b261ecSmrg_X_EXPORT Bool noScreenSaverExtension = FALSE;
16605b261ecSmrg#endif
16705b261ecSmrg#ifdef MITSHM
16805b261ecSmrg_X_EXPORT Bool noMITShmExtension = FALSE;
16905b261ecSmrg#endif
17005b261ecSmrg#ifdef MITMISC
17105b261ecSmrg_X_EXPORT Bool noMITMiscExtension = FALSE;
17205b261ecSmrg#endif
17305b261ecSmrg#ifdef MULTIBUFFER
17405b261ecSmrg_X_EXPORT Bool noMultibufferExtension = FALSE;
17505b261ecSmrg#endif
17605b261ecSmrg#ifdef RANDR
17705b261ecSmrg_X_EXPORT Bool noRRExtension = FALSE;
17805b261ecSmrg#endif
17905b261ecSmrg#ifdef RENDER
18005b261ecSmrg_X_EXPORT Bool noRenderExtension = FALSE;
18105b261ecSmrg#endif
18205b261ecSmrg#ifdef SHAPE
18305b261ecSmrg_X_EXPORT Bool noShapeExtension = FALSE;
18405b261ecSmrg#endif
18505b261ecSmrg#ifdef XCSECURITY
18605b261ecSmrg_X_EXPORT Bool noSecurityExtension = FALSE;
18705b261ecSmrg#endif
18805b261ecSmrg#ifdef XSYNC
18905b261ecSmrg_X_EXPORT Bool noSyncExtension = FALSE;
19005b261ecSmrg#endif
19105b261ecSmrg#ifdef TOGCUP
19205b261ecSmrg_X_EXPORT Bool noXcupExtension = FALSE;
19305b261ecSmrg#endif
19405b261ecSmrg#ifdef RES
19505b261ecSmrg_X_EXPORT Bool noResExtension = FALSE;
19605b261ecSmrg#endif
19705b261ecSmrg#ifdef XAPPGROUP
19805b261ecSmrg_X_EXPORT Bool noXagExtension = FALSE;
19905b261ecSmrg#endif
20005b261ecSmrg#ifdef XCMISC
20105b261ecSmrg_X_EXPORT Bool noXCMiscExtension = FALSE;
20205b261ecSmrg#endif
20305b261ecSmrg#ifdef XEVIE
20405b261ecSmrg/* Xevie is disabled by default for now until the
20505b261ecSmrg * interface is stable */
20605b261ecSmrg_X_EXPORT Bool noXevieExtension = TRUE;
20705b261ecSmrg#endif
20805b261ecSmrg#ifdef XF86BIGFONT
20905b261ecSmrg_X_EXPORT Bool noXFree86BigfontExtension = FALSE;
21005b261ecSmrg#endif
21105b261ecSmrg#ifdef XFreeXDGA
21205b261ecSmrg_X_EXPORT Bool noXFree86DGAExtension = FALSE;
21305b261ecSmrg#endif
21405b261ecSmrg#ifdef XF86DRI
21505b261ecSmrg_X_EXPORT Bool noXFree86DRIExtension = FALSE;
21605b261ecSmrg#endif
21705b261ecSmrg#ifdef XF86MISC
21805b261ecSmrg_X_EXPORT Bool noXFree86MiscExtension = FALSE;
21905b261ecSmrg#endif
22005b261ecSmrg#ifdef XF86VIDMODE
22105b261ecSmrg_X_EXPORT Bool noXFree86VidModeExtension = FALSE;
22205b261ecSmrg#endif
22305b261ecSmrg#ifdef XFIXES
22405b261ecSmrg_X_EXPORT Bool noXFixesExtension = FALSE;
22505b261ecSmrg#endif
22605b261ecSmrg/* |noXkbExtension| is defined in xc/programs/Xserver/xkb/xkbInit.c */
22705b261ecSmrg#ifdef PANORAMIX
22805b261ecSmrg/* Xinerama is disabled by default unless enabled via +xinerama */
22905b261ecSmrg_X_EXPORT Bool noPanoramiXExtension = TRUE;
23005b261ecSmrg#endif
23105b261ecSmrg#ifdef XINPUT
23205b261ecSmrg_X_EXPORT Bool noXInputExtension = FALSE;
23305b261ecSmrg#endif
23405b261ecSmrg#ifdef XIDLE
23505b261ecSmrg_X_EXPORT Bool noXIdleExtension = FALSE;
23605b261ecSmrg#endif
23705b261ecSmrg#ifdef XV
23805b261ecSmrg_X_EXPORT Bool noXvExtension = FALSE;
23905b261ecSmrg#endif
24005b261ecSmrg
24105b261ecSmrg#define X_INCLUDE_NETDB_H
24205b261ecSmrg#include <X11/Xos_r.h>
24305b261ecSmrg
24405b261ecSmrg#include <errno.h>
24505b261ecSmrg
24605b261ecSmrgBool CoreDump;
24705b261ecSmrg
24805b261ecSmrg#ifdef PANORAMIX
24905b261ecSmrgBool PanoramiXExtensionDisabledHack = FALSE;
25005b261ecSmrg#endif
25105b261ecSmrg
25205b261ecSmrgint auditTrailLevel = 1;
25305b261ecSmrg
25405b261ecSmrg_X_EXPORT Bool Must_have_memory = FALSE;
25505b261ecSmrg
25605b261ecSmrg#ifdef AIXV3
25705b261ecSmrgint SyncOn  = 0;
25805b261ecSmrgextern int SelectWaitTime;
25905b261ecSmrg#endif
26005b261ecSmrg
26105b261ecSmrg#if defined(SVR4) || defined(__linux__) || defined(CSRG_BASED)
26205b261ecSmrg#define HAS_SAVED_IDS_AND_SETEUID
26305b261ecSmrg#endif
26405b261ecSmrg
26505b261ecSmrg#ifdef MEMBUG
26605b261ecSmrg#define MEM_FAIL_SCALE 100000
26705b261ecSmrglong Memory_fail = 0;
26805b261ecSmrg#include <stdlib.h>  /* for random() */
26905b261ecSmrg#endif
27005b261ecSmrg
27105b261ecSmrgstatic char *dev_tty_from_init = NULL;	/* since we need to parse it anyway */
27205b261ecSmrg
27305b261ecSmrgOsSigHandlerPtr
27405b261ecSmrgOsSignal(sig, handler)
27505b261ecSmrg    int sig;
27605b261ecSmrg    OsSigHandlerPtr handler;
27705b261ecSmrg{
27805b261ecSmrg#ifdef X_NOT_POSIX
27905b261ecSmrg    return signal(sig, handler);
28005b261ecSmrg#else
28105b261ecSmrg    struct sigaction act, oact;
28205b261ecSmrg
28305b261ecSmrg    sigemptyset(&act.sa_mask);
28405b261ecSmrg    if (handler != SIG_IGN)
28505b261ecSmrg	sigaddset(&act.sa_mask, sig);
28605b261ecSmrg    act.sa_flags = 0;
28705b261ecSmrg    act.sa_handler = handler;
28805b261ecSmrg    if (sigaction(sig, &act, &oact))
28905b261ecSmrg      perror("sigaction");
29005b261ecSmrg    return oact.sa_handler;
29105b261ecSmrg#endif
29205b261ecSmrg}
29305b261ecSmrg
29405b261ecSmrg#ifdef SERVER_LOCK
29505b261ecSmrg/*
29605b261ecSmrg * Explicit support for a server lock file like the ones used for UUCP.
29705b261ecSmrg * For architectures with virtual terminals that can run more than one
29805b261ecSmrg * server at a time.  This keeps the servers from stomping on each other
29905b261ecSmrg * if the user forgets to give them different display numbers.
30005b261ecSmrg */
30105b261ecSmrg#define LOCK_DIR "/tmp"
30205b261ecSmrg#define LOCK_TMP_PREFIX "/.tX"
30305b261ecSmrg#define LOCK_PREFIX "/.X"
30405b261ecSmrg#define LOCK_SUFFIX "-lock"
30505b261ecSmrg
30605b261ecSmrg#if defined(DGUX)
30705b261ecSmrg#include <limits.h>
30805b261ecSmrg#include <sys/param.h>
30905b261ecSmrg#endif
31005b261ecSmrg
31105b261ecSmrg#ifndef PATH_MAX
31205b261ecSmrg#ifndef Lynx
31305b261ecSmrg#include <sys/param.h>
31405b261ecSmrg#else
31505b261ecSmrg#include <param.h>
31605b261ecSmrg#endif
31705b261ecSmrg#ifndef PATH_MAX
31805b261ecSmrg#ifdef MAXPATHLEN
31905b261ecSmrg#define PATH_MAX MAXPATHLEN
32005b261ecSmrg#else
32105b261ecSmrg#define PATH_MAX 1024
32205b261ecSmrg#endif
32305b261ecSmrg#endif
32405b261ecSmrg#endif
32505b261ecSmrg
32605b261ecSmrgstatic Bool StillLocking = FALSE;
32705b261ecSmrgstatic char LockFile[PATH_MAX];
32805b261ecSmrgstatic Bool nolock = FALSE;
32905b261ecSmrg
33005b261ecSmrg/*
33105b261ecSmrg * LockServer --
33205b261ecSmrg *      Check if the server lock file exists.  If so, check if the PID
33305b261ecSmrg *      contained inside is valid.  If so, then die.  Otherwise, create
33405b261ecSmrg *      the lock file containing the PID.
33505b261ecSmrg */
33605b261ecSmrgvoid
33705b261ecSmrgLockServer(void)
33805b261ecSmrg{
33905b261ecSmrg  char tmp[PATH_MAX], pid_str[12];
34005b261ecSmrg  int lfd, i, haslock, l_pid, t;
34105b261ecSmrg  char *tmppath = NULL;
34205b261ecSmrg  int len;
34305b261ecSmrg  char port[20];
34405b261ecSmrg
34505b261ecSmrg  if (nolock) return;
34605b261ecSmrg  /*
34705b261ecSmrg   * Path names
34805b261ecSmrg   */
34905b261ecSmrg  tmppath = LOCK_DIR;
35005b261ecSmrg
35105b261ecSmrg  sprintf(port, "%d", atoi(display));
35205b261ecSmrg  len = strlen(LOCK_PREFIX) > strlen(LOCK_TMP_PREFIX) ? strlen(LOCK_PREFIX) :
35305b261ecSmrg						strlen(LOCK_TMP_PREFIX);
35405b261ecSmrg  len += strlen(tmppath) + strlen(port) + strlen(LOCK_SUFFIX) + 1;
35505b261ecSmrg  if (len > sizeof(LockFile))
35605b261ecSmrg    FatalError("Display name `%s' is too long\n", port);
35705b261ecSmrg  (void)sprintf(tmp, "%s" LOCK_TMP_PREFIX "%s" LOCK_SUFFIX, tmppath, port);
35805b261ecSmrg  (void)sprintf(LockFile, "%s" LOCK_PREFIX "%s" LOCK_SUFFIX, tmppath, port);
35905b261ecSmrg
36005b261ecSmrg  /*
36105b261ecSmrg   * Create a temporary file containing our PID.  Attempt three times
36205b261ecSmrg   * to create the file.
36305b261ecSmrg   */
36405b261ecSmrg  StillLocking = TRUE;
36505b261ecSmrg  i = 0;
36605b261ecSmrg  do {
36705b261ecSmrg    i++;
36805b261ecSmrg    lfd = open(tmp, O_CREAT | O_EXCL | O_WRONLY, 0644);
36905b261ecSmrg    if (lfd < 0)
37005b261ecSmrg       sleep(2);
37105b261ecSmrg    else
37205b261ecSmrg       break;
37305b261ecSmrg  } while (i < 3);
37405b261ecSmrg  if (lfd < 0) {
37505b261ecSmrg    unlink(tmp);
37605b261ecSmrg    i = 0;
37705b261ecSmrg    do {
37805b261ecSmrg      i++;
37905b261ecSmrg      lfd = open(tmp, O_CREAT | O_EXCL | O_WRONLY, 0644);
38005b261ecSmrg      if (lfd < 0)
38105b261ecSmrg         sleep(2);
38205b261ecSmrg      else
38305b261ecSmrg         break;
38405b261ecSmrg    } while (i < 3);
38505b261ecSmrg  }
38605b261ecSmrg  if (lfd < 0)
38705b261ecSmrg    FatalError("Could not create lock file in %s\n", tmp);
38805b261ecSmrg  (void) sprintf(pid_str, "%10ld\n", (long)getpid());
38905b261ecSmrg  (void) write(lfd, pid_str, 11);
39005b261ecSmrg#ifndef USE_CHMOD
39105b261ecSmrg  (void) fchmod(lfd, 0444);
39205b261ecSmrg#else
39305b261ecSmrg  (void) chmod(tmp, 0444);
39405b261ecSmrg#endif
39505b261ecSmrg  (void) close(lfd);
39605b261ecSmrg
39705b261ecSmrg  /*
39805b261ecSmrg   * OK.  Now the tmp file exists.  Try three times to move it in place
39905b261ecSmrg   * for the lock.
40005b261ecSmrg   */
40105b261ecSmrg  i = 0;
40205b261ecSmrg  haslock = 0;
40305b261ecSmrg  while ((!haslock) && (i++ < 3)) {
40405b261ecSmrg    haslock = (link(tmp,LockFile) == 0);
40505b261ecSmrg    if (haslock) {
40605b261ecSmrg      /*
40705b261ecSmrg       * We're done.
40805b261ecSmrg       */
40905b261ecSmrg      break;
41005b261ecSmrg    }
41105b261ecSmrg    else {
41205b261ecSmrg      /*
41305b261ecSmrg       * Read the pid from the existing file
41405b261ecSmrg       */
41505b261ecSmrg      lfd = open(LockFile, O_RDONLY);
41605b261ecSmrg      if (lfd < 0) {
41705b261ecSmrg        unlink(tmp);
41805b261ecSmrg        FatalError("Can't read lock file %s\n", LockFile);
41905b261ecSmrg      }
42005b261ecSmrg      pid_str[0] = '\0';
42105b261ecSmrg      if (read(lfd, pid_str, 11) != 11) {
42205b261ecSmrg        /*
42305b261ecSmrg         * Bogus lock file.
42405b261ecSmrg         */
42505b261ecSmrg        unlink(LockFile);
42605b261ecSmrg        close(lfd);
42705b261ecSmrg        continue;
42805b261ecSmrg      }
42905b261ecSmrg      pid_str[11] = '\0';
43005b261ecSmrg      sscanf(pid_str, "%d", &l_pid);
43105b261ecSmrg      close(lfd);
43205b261ecSmrg
43305b261ecSmrg      /*
43405b261ecSmrg       * Now try to kill the PID to see if it exists.
43505b261ecSmrg       */
43605b261ecSmrg      errno = 0;
43705b261ecSmrg      t = kill(l_pid, 0);
43805b261ecSmrg      if ((t< 0) && (errno == ESRCH)) {
43905b261ecSmrg        /*
44005b261ecSmrg         * Stale lock file.
44105b261ecSmrg         */
44205b261ecSmrg        unlink(LockFile);
44305b261ecSmrg        continue;
44405b261ecSmrg      }
44505b261ecSmrg      else if (((t < 0) && (errno == EPERM)) || (t == 0)) {
44605b261ecSmrg        /*
44705b261ecSmrg         * Process is still active.
44805b261ecSmrg         */
44905b261ecSmrg        unlink(tmp);
45005b261ecSmrg	FatalError("Server is already active for display %s\n%s %s\n%s\n",
45105b261ecSmrg		   port, "\tIf this server is no longer running, remove",
45205b261ecSmrg		   LockFile, "\tand start again.");
45305b261ecSmrg      }
45405b261ecSmrg    }
45505b261ecSmrg  }
45605b261ecSmrg  unlink(tmp);
45705b261ecSmrg  if (!haslock)
45805b261ecSmrg    FatalError("Could not create server lock file: %s\n", LockFile);
45905b261ecSmrg  StillLocking = FALSE;
46005b261ecSmrg}
46105b261ecSmrg
46205b261ecSmrg/*
46305b261ecSmrg * UnlockServer --
46405b261ecSmrg *      Remove the server lock file.
46505b261ecSmrg */
46605b261ecSmrgvoid
46705b261ecSmrgUnlockServer(void)
46805b261ecSmrg{
46905b261ecSmrg  if (nolock) return;
47005b261ecSmrg
47105b261ecSmrg  if (!StillLocking){
47205b261ecSmrg
47305b261ecSmrg  (void) unlink(LockFile);
47405b261ecSmrg  }
47505b261ecSmrg}
47605b261ecSmrg#endif /* SERVER_LOCK */
47705b261ecSmrg
47805b261ecSmrg/* Force connections to close on SIGHUP from init */
47905b261ecSmrg
48005b261ecSmrg/*ARGSUSED*/
48105b261ecSmrgSIGVAL
48205b261ecSmrgAutoResetServer (int sig)
48305b261ecSmrg{
48405b261ecSmrg    int olderrno = errno;
48505b261ecSmrg
48605b261ecSmrg    dispatchException |= DE_RESET;
48705b261ecSmrg    isItTimeToYield = TRUE;
48805b261ecSmrg#ifdef GPROF
48905b261ecSmrg    chdir ("/tmp");
49005b261ecSmrg    exit (0);
49105b261ecSmrg#endif
49205b261ecSmrg#if defined(SYSV) && defined(X_NOT_POSIX)
49305b261ecSmrg    OsSignal (SIGHUP, AutoResetServer);
49405b261ecSmrg#endif
49505b261ecSmrg    errno = olderrno;
49605b261ecSmrg}
49705b261ecSmrg
49805b261ecSmrg/* Force connections to close and then exit on SIGTERM, SIGINT */
49905b261ecSmrg
50005b261ecSmrg/*ARGSUSED*/
50105b261ecSmrg_X_EXPORT SIGVAL
50205b261ecSmrgGiveUp(int sig)
50305b261ecSmrg{
50405b261ecSmrg    int olderrno = errno;
50505b261ecSmrg
50605b261ecSmrg    dispatchException |= DE_TERMINATE;
50705b261ecSmrg    isItTimeToYield = TRUE;
50805b261ecSmrg#if defined(SYSV) && defined(X_NOT_POSIX)
50905b261ecSmrg    if (sig)
51005b261ecSmrg	OsSignal(sig, SIG_IGN);
51105b261ecSmrg#endif
51205b261ecSmrg    errno = olderrno;
51305b261ecSmrg}
51405b261ecSmrg
51505b261ecSmrg#if defined WIN32 && defined __MINGW32__
51605b261ecSmrg_X_EXPORT CARD32
51705b261ecSmrgGetTimeInMillis (void)
51805b261ecSmrg{
51905b261ecSmrg  return GetTickCount ();
52005b261ecSmrg}
52105b261ecSmrg#else
52205b261ecSmrg_X_EXPORT CARD32
52305b261ecSmrgGetTimeInMillis(void)
52405b261ecSmrg{
52505b261ecSmrg    struct timeval tv;
52605b261ecSmrg
52705b261ecSmrg#ifdef MONOTONIC_CLOCK
52805b261ecSmrg    struct timespec tp;
52905b261ecSmrg    if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
53005b261ecSmrg        return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000L);
53105b261ecSmrg#endif
53205b261ecSmrg
53305b261ecSmrg    X_GETTIMEOFDAY(&tv);
53405b261ecSmrg    return(tv.tv_sec * 1000) + (tv.tv_usec / 1000);
53505b261ecSmrg}
53605b261ecSmrg#endif
53705b261ecSmrg
53805b261ecSmrg_X_EXPORT void
53905b261ecSmrgAdjustWaitForDelay (pointer waitTime, unsigned long newdelay)
54005b261ecSmrg{
54105b261ecSmrg    static struct timeval   delay_val;
54205b261ecSmrg    struct timeval	    **wt = (struct timeval **) waitTime;
54305b261ecSmrg    unsigned long	    olddelay;
54405b261ecSmrg
54505b261ecSmrg    if (*wt == NULL)
54605b261ecSmrg    {
54705b261ecSmrg	delay_val.tv_sec = newdelay / 1000;
54805b261ecSmrg	delay_val.tv_usec = 1000 * (newdelay % 1000);
54905b261ecSmrg	*wt = &delay_val;
55005b261ecSmrg    }
55105b261ecSmrg    else
55205b261ecSmrg    {
55305b261ecSmrg	olddelay = (*wt)->tv_sec * 1000 + (*wt)->tv_usec / 1000;
55405b261ecSmrg	if (newdelay < olddelay)
55505b261ecSmrg	{
55605b261ecSmrg	    (*wt)->tv_sec = newdelay / 1000;
55705b261ecSmrg	    (*wt)->tv_usec = 1000 * (newdelay % 1000);
55805b261ecSmrg	}
55905b261ecSmrg    }
56005b261ecSmrg}
56105b261ecSmrg
56205b261ecSmrgvoid UseMsg(void)
56305b261ecSmrg{
56405b261ecSmrg#if !defined(AIXrt) && !defined(AIX386)
56505b261ecSmrg    ErrorF("use: X [:<display>] [option]\n");
56605b261ecSmrg    ErrorF("-a #                   mouse acceleration (pixels)\n");
56705b261ecSmrg    ErrorF("-ac                    disable access control restrictions\n");
56805b261ecSmrg#ifdef MEMBUG
56905b261ecSmrg    ErrorF("-alloc int             chance alloc should fail\n");
57005b261ecSmrg#endif
57105b261ecSmrg    ErrorF("-audit int             set audit trail level\n");
57205b261ecSmrg    ErrorF("-auth file             select authorization file\n");
57305b261ecSmrg    ErrorF("-br                    create root window with black background\n");
57405b261ecSmrg    ErrorF("+bs                    enable any backing store support\n");
57505b261ecSmrg    ErrorF("-bs                    disable any backing store support\n");
57605b261ecSmrg    ErrorF("-c                     turns off key-click\n");
57705b261ecSmrg    ErrorF("c #                    key-click volume (0-100)\n");
57805b261ecSmrg    ErrorF("-cc int                default color visual class\n");
57905b261ecSmrg    ErrorF("-co file               color database file\n");
58005b261ecSmrg#ifdef COMMANDLINE_CHALLENGED_OPERATING_SYSTEMS
58105b261ecSmrg    ErrorF("-config file           read options from file\n");
58205b261ecSmrg#endif
58305b261ecSmrg    ErrorF("-core                  generate core dump on fatal error\n");
58405b261ecSmrg    ErrorF("-dpi int               screen resolution in dots per inch\n");
58505b261ecSmrg#ifdef DPMSExtension
58605b261ecSmrg    ErrorF("dpms                   enables VESA DPMS monitor control\n");
58705b261ecSmrg    ErrorF("-dpms                  disables VESA DPMS monitor control\n");
58805b261ecSmrg#endif
58905b261ecSmrg    ErrorF("-deferglyphs [none|all|16] defer loading of [no|all|16-bit] glyphs\n");
59005b261ecSmrg    ErrorF("-f #                   bell base (0-100)\n");
59105b261ecSmrg    ErrorF("-fc string             cursor font\n");
59205b261ecSmrg    ErrorF("-fn string             default font name\n");
59305b261ecSmrg    ErrorF("-fp string             default font path\n");
59405b261ecSmrg    ErrorF("-help                  prints message with these options\n");
59505b261ecSmrg    ErrorF("-I                     ignore all remaining arguments\n");
59605b261ecSmrg#ifdef RLIMIT_DATA
59705b261ecSmrg    ErrorF("-ld int                limit data space to N Kb\n");
59805b261ecSmrg#endif
59905b261ecSmrg#ifdef RLIMIT_NOFILE
60005b261ecSmrg    ErrorF("-lf int                limit number of open files to N\n");
60105b261ecSmrg#endif
60205b261ecSmrg#ifdef RLIMIT_STACK
60305b261ecSmrg    ErrorF("-ls int                limit stack space to N Kb\n");
60405b261ecSmrg#endif
60505b261ecSmrg#ifdef SERVER_LOCK
60605b261ecSmrg    ErrorF("-nolock                disable the locking mechanism\n");
60705b261ecSmrg#endif
60805b261ecSmrg#ifndef NOLOGOHACK
60905b261ecSmrg    ErrorF("-logo                  enable logo in screen saver\n");
61005b261ecSmrg    ErrorF("nologo                 disable logo in screen saver\n");
61105b261ecSmrg#endif
61205b261ecSmrg    ErrorF("-nolisten string       don't listen on protocol\n");
61305b261ecSmrg    ErrorF("-noreset               don't reset after last client exists\n");
61405b261ecSmrg    ErrorF("-reset                 reset after last client exists\n");
61505b261ecSmrg    ErrorF("-p #                   screen-saver pattern duration (minutes)\n");
61605b261ecSmrg    ErrorF("-pn                    accept failure to listen on all ports\n");
61705b261ecSmrg    ErrorF("-nopn                  reject failure to listen on all ports\n");
61805b261ecSmrg    ErrorF("-r                     turns off auto-repeat\n");
61905b261ecSmrg    ErrorF("r                      turns on auto-repeat \n");
62005b261ecSmrg#ifdef RENDER
62105b261ecSmrg    ErrorF("-render [default|mono|gray|color] set render color alloc policy\n");
62205b261ecSmrg#endif
62305b261ecSmrg    ErrorF("-s #                   screen-saver timeout (minutes)\n");
62405b261ecSmrg#ifdef XCSECURITY
62505b261ecSmrg    ErrorF("-sp file               security policy file\n");
62605b261ecSmrg#endif
62705b261ecSmrg#ifdef XPRINT
62805b261ecSmrg    PrinterUseMsg();
62905b261ecSmrg#endif
63005b261ecSmrg    ErrorF("-su                    disable any save under support\n");
63105b261ecSmrg    ErrorF("-t #                   mouse threshold (pixels)\n");
63205b261ecSmrg    ErrorF("-terminate             terminate at server reset\n");
63305b261ecSmrg    ErrorF("-to #                  connection time out\n");
63405b261ecSmrg    ErrorF("-tst                   disable testing extensions\n");
63505b261ecSmrg    ErrorF("ttyxx                  server started from init on /dev/ttyxx\n");
63605b261ecSmrg    ErrorF("v                      video blanking for screen-saver\n");
63705b261ecSmrg    ErrorF("-v                     screen-saver without video blanking\n");
63805b261ecSmrg    ErrorF("-wm                    WhenMapped default backing-store\n");
63905b261ecSmrg    ErrorF("-wr                    create root window with white background\n");
64005b261ecSmrg    ErrorF("-x string              loads named extension at init time \n");
64105b261ecSmrg    ErrorF("-maxbigreqsize         set maximal bigrequest size \n");
64205b261ecSmrg#ifdef PANORAMIX
64305b261ecSmrg    ErrorF("+xinerama              Enable XINERAMA extension\n");
64405b261ecSmrg    ErrorF("-xinerama              Disable XINERAMA extension\n");
64505b261ecSmrg#endif
64605b261ecSmrg#ifdef SMART_SCHEDULE
64705b261ecSmrg    ErrorF("-dumbSched             Disable smart scheduling, enable old behavior\n");
64805b261ecSmrg    ErrorF("-schedInterval int     Set scheduler interval in msec\n");
64905b261ecSmrg#endif
65005b261ecSmrg    ErrorF("+extension name        Enable extension\n");
65105b261ecSmrg    ErrorF("-extension name        Disable extension\n");
65205b261ecSmrg#ifdef XDMCP
65305b261ecSmrg    XdmcpUseMsg();
65405b261ecSmrg#endif
65505b261ecSmrg#endif /* !AIXrt && ! AIX386 */
65605b261ecSmrg#ifdef XKB
65705b261ecSmrg    XkbUseMsg();
65805b261ecSmrg#endif
65905b261ecSmrg    ddxUseMsg();
66005b261ecSmrg}
66105b261ecSmrg
66205b261ecSmrg/*  This function performs a rudimentary sanity check
66305b261ecSmrg *  on the display name passed in on the command-line,
66405b261ecSmrg *  since this string is used to generate filenames.
66505b261ecSmrg *  It is especially important that the display name
66605b261ecSmrg *  not contain a "/" and not start with a "-".
66705b261ecSmrg *                                            --kvajk
66805b261ecSmrg */
66905b261ecSmrgstatic int
67005b261ecSmrgVerifyDisplayName(const char *d)
67105b261ecSmrg{
67205b261ecSmrg    if ( d == (char *)0 ) return( 0 );  /*  null  */
67305b261ecSmrg    if ( *d == '\0' ) return( 0 );  /*  empty  */
67405b261ecSmrg    if ( *d == '-' ) return( 0 );  /*  could be confused for an option  */
67505b261ecSmrg    if ( *d == '.' ) return( 0 );  /*  must not equal "." or ".."  */
67605b261ecSmrg    if ( strchr(d, '/') != (char *)0 ) return( 0 );  /*  very important!!!  */
67705b261ecSmrg    return( 1 );
67805b261ecSmrg}
67905b261ecSmrg
68005b261ecSmrg/*
68105b261ecSmrg * This function is responsible for doing initalisation of any global
68205b261ecSmrg * variables at an very early point of server startup (even before
68305b261ecSmrg * |ProcessCommandLine()|.
68405b261ecSmrg */
68505b261ecSmrgvoid InitGlobals(void)
68605b261ecSmrg{
68705b261ecSmrg    ddxInitGlobals();
68805b261ecSmrg}
68905b261ecSmrg
69005b261ecSmrg
69105b261ecSmrg/*
69205b261ecSmrg * This function parses the command line. Handles device-independent fields
69305b261ecSmrg * and allows ddx to handle additional fields.  It is not allowed to modify
69405b261ecSmrg * argc or any of the strings pointed to by argv.
69505b261ecSmrg */
69605b261ecSmrgvoid
69705b261ecSmrgProcessCommandLine(int argc, char *argv[])
69805b261ecSmrg{
69905b261ecSmrg    int i, skip;
70005b261ecSmrg
70105b261ecSmrg    defaultKeyboardControl.autoRepeat = TRUE;
70205b261ecSmrg
70305b261ecSmrg#ifdef NO_PART_NET
70405b261ecSmrg    PartialNetwork = FALSE;
70505b261ecSmrg#else
70605b261ecSmrg    PartialNetwork = TRUE;
70705b261ecSmrg#endif
70805b261ecSmrg
70905b261ecSmrg    for ( i = 1; i < argc; i++ )
71005b261ecSmrg    {
71105b261ecSmrg	/* call ddx first, so it can peek/override if it wants */
71205b261ecSmrg        if((skip = ddxProcessArgument(argc, argv, i)))
71305b261ecSmrg	{
71405b261ecSmrg	    i += (skip - 1);
71505b261ecSmrg	}
71605b261ecSmrg	else if(argv[i][0] ==  ':')
71705b261ecSmrg	{
71805b261ecSmrg	    /* initialize display */
71905b261ecSmrg	    display = argv[i];
72005b261ecSmrg	    display++;
72105b261ecSmrg            if( ! VerifyDisplayName( display ) ) {
72205b261ecSmrg                ErrorF("Bad display name: %s\n", display);
72305b261ecSmrg                UseMsg();
72405b261ecSmrg		FatalError("Bad display name, exiting: %s\n", display);
72505b261ecSmrg            }
72605b261ecSmrg	}
72705b261ecSmrg	else if ( strcmp( argv[i], "-a") == 0)
72805b261ecSmrg	{
72905b261ecSmrg	    if(++i < argc)
73005b261ecSmrg	        defaultPointerControl.num = atoi(argv[i]);
73105b261ecSmrg	    else
73205b261ecSmrg		UseMsg();
73305b261ecSmrg	}
73405b261ecSmrg	else if ( strcmp( argv[i], "-ac") == 0)
73505b261ecSmrg	{
73605b261ecSmrg	    defeatAccessControl = TRUE;
73705b261ecSmrg	}
73805b261ecSmrg#ifdef MEMBUG
73905b261ecSmrg	else if ( strcmp( argv[i], "-alloc") == 0)
74005b261ecSmrg	{
74105b261ecSmrg	    if(++i < argc)
74205b261ecSmrg	        Memory_fail = atoi(argv[i]);
74305b261ecSmrg	    else
74405b261ecSmrg		UseMsg();
74505b261ecSmrg	}
74605b261ecSmrg#endif
74705b261ecSmrg	else if ( strcmp( argv[i], "-audit") == 0)
74805b261ecSmrg	{
74905b261ecSmrg	    if(++i < argc)
75005b261ecSmrg	        auditTrailLevel = atoi(argv[i]);
75105b261ecSmrg	    else
75205b261ecSmrg		UseMsg();
75305b261ecSmrg	}
75405b261ecSmrg	else if ( strcmp( argv[i], "-auth") == 0)
75505b261ecSmrg	{
75605b261ecSmrg	    if(++i < argc)
75705b261ecSmrg	        InitAuthorization (argv[i]);
75805b261ecSmrg	    else
75905b261ecSmrg		UseMsg();
76005b261ecSmrg	}
76105b261ecSmrg	else if ( strcmp( argv[i], "-br") == 0)
76205b261ecSmrg	    blackRoot = TRUE;
76305b261ecSmrg	else if ( strcmp( argv[i], "+bs") == 0)
76405b261ecSmrg	    enableBackingStore = TRUE;
76505b261ecSmrg	else if ( strcmp( argv[i], "-bs") == 0)
76605b261ecSmrg	    disableBackingStore = TRUE;
76705b261ecSmrg	else if ( strcmp( argv[i], "c") == 0)
76805b261ecSmrg	{
76905b261ecSmrg	    if(++i < argc)
77005b261ecSmrg	        defaultKeyboardControl.click = atoi(argv[i]);
77105b261ecSmrg	    else
77205b261ecSmrg		UseMsg();
77305b261ecSmrg	}
77405b261ecSmrg	else if ( strcmp( argv[i], "-c") == 0)
77505b261ecSmrg	{
77605b261ecSmrg	    defaultKeyboardControl.click = 0;
77705b261ecSmrg	}
77805b261ecSmrg	else if ( strcmp( argv[i], "-cc") == 0)
77905b261ecSmrg	{
78005b261ecSmrg	    if(++i < argc)
78105b261ecSmrg	        defaultColorVisualClass = atoi(argv[i]);
78205b261ecSmrg	    else
78305b261ecSmrg		UseMsg();
78405b261ecSmrg	}
78505b261ecSmrg	else if ( strcmp( argv[i], "-co") == 0)
78605b261ecSmrg	{
78705b261ecSmrg	    if(++i < argc)
78805b261ecSmrg	        rgbPath = argv[i];
78905b261ecSmrg	    else
79005b261ecSmrg		UseMsg();
79105b261ecSmrg	}
79205b261ecSmrg	else if ( strcmp( argv[i], "-core") == 0)
79305b261ecSmrg	{
79405b261ecSmrg	    CoreDump = TRUE;
79505b261ecSmrg#if !defined(WIN32) || !defined(__MINGW32__)
79605b261ecSmrg	    struct rlimit   core_limit;
79705b261ecSmrg	    getrlimit (RLIMIT_CORE, &core_limit);
79805b261ecSmrg	    core_limit.rlim_cur = core_limit.rlim_max;
79905b261ecSmrg	    setrlimit (RLIMIT_CORE, &core_limit);
80005b261ecSmrg#endif
80105b261ecSmrg	}
80205b261ecSmrg	else if ( strcmp( argv[i], "-dpi") == 0)
80305b261ecSmrg	{
80405b261ecSmrg	    if(++i < argc)
80505b261ecSmrg	        monitorResolution = atoi(argv[i]);
80605b261ecSmrg	    else
80705b261ecSmrg		UseMsg();
80805b261ecSmrg	}
80905b261ecSmrg#ifdef DPMSExtension
81005b261ecSmrg	else if ( strcmp( argv[i], "dpms") == 0)
81105b261ecSmrg	    DPMSEnabledSwitch = TRUE;
81205b261ecSmrg	else if ( strcmp( argv[i], "-dpms") == 0)
81305b261ecSmrg	    DPMSDisabledSwitch = TRUE;
81405b261ecSmrg#endif
81505b261ecSmrg	else if ( strcmp( argv[i], "-deferglyphs") == 0)
81605b261ecSmrg	{
81705b261ecSmrg	    if(++i >= argc || !ParseGlyphCachingMode(argv[i]))
81805b261ecSmrg		UseMsg();
81905b261ecSmrg	}
82005b261ecSmrg	else if ( strcmp( argv[i], "-f") == 0)
82105b261ecSmrg	{
82205b261ecSmrg	    if(++i < argc)
82305b261ecSmrg	        defaultKeyboardControl.bell = atoi(argv[i]);
82405b261ecSmrg	    else
82505b261ecSmrg		UseMsg();
82605b261ecSmrg	}
82705b261ecSmrg	else if ( strcmp( argv[i], "-fc") == 0)
82805b261ecSmrg	{
82905b261ecSmrg	    if(++i < argc)
83005b261ecSmrg	        defaultCursorFont = argv[i];
83105b261ecSmrg	    else
83205b261ecSmrg		UseMsg();
83305b261ecSmrg	}
83405b261ecSmrg	else if ( strcmp( argv[i], "-fn") == 0)
83505b261ecSmrg	{
83605b261ecSmrg	    if(++i < argc)
83705b261ecSmrg	        defaultTextFont = argv[i];
83805b261ecSmrg	    else
83905b261ecSmrg		UseMsg();
84005b261ecSmrg	}
84105b261ecSmrg	else if ( strcmp( argv[i], "-fp") == 0)
84205b261ecSmrg	{
84305b261ecSmrg	    if(++i < argc)
84405b261ecSmrg	    {
84505b261ecSmrg	        defaultFontPath = argv[i];
84605b261ecSmrg	    }
84705b261ecSmrg	    else
84805b261ecSmrg		UseMsg();
84905b261ecSmrg	}
85005b261ecSmrg	else if ( strcmp( argv[i], "-help") == 0)
85105b261ecSmrg	{
85205b261ecSmrg	    UseMsg();
85305b261ecSmrg	    exit(0);
85405b261ecSmrg	}
85505b261ecSmrg#ifdef XKB
85605b261ecSmrg        else if ( (skip=XkbProcessArguments(argc,argv,i))!=0 ) {
85705b261ecSmrg	    if (skip>0)
85805b261ecSmrg		 i+= skip-1;
85905b261ecSmrg	    else UseMsg();
86005b261ecSmrg	}
86105b261ecSmrg#endif
86205b261ecSmrg#ifdef RLIMIT_DATA
86305b261ecSmrg	else if ( strcmp( argv[i], "-ld") == 0)
86405b261ecSmrg	{
86505b261ecSmrg	    if(++i < argc)
86605b261ecSmrg	    {
86705b261ecSmrg	        limitDataSpace = atoi(argv[i]);
86805b261ecSmrg		if (limitDataSpace > 0)
86905b261ecSmrg		    limitDataSpace *= 1024;
87005b261ecSmrg	    }
87105b261ecSmrg	    else
87205b261ecSmrg		UseMsg();
87305b261ecSmrg	}
87405b261ecSmrg#endif
87505b261ecSmrg#ifdef RLIMIT_NOFILE
87605b261ecSmrg	else if ( strcmp( argv[i], "-lf") == 0)
87705b261ecSmrg	{
87805b261ecSmrg	    if(++i < argc)
87905b261ecSmrg	        limitNoFile = atoi(argv[i]);
88005b261ecSmrg	    else
88105b261ecSmrg		UseMsg();
88205b261ecSmrg	}
88305b261ecSmrg#endif
88405b261ecSmrg#ifdef RLIMIT_STACK
88505b261ecSmrg	else if ( strcmp( argv[i], "-ls") == 0)
88605b261ecSmrg	{
88705b261ecSmrg	    if(++i < argc)
88805b261ecSmrg	    {
88905b261ecSmrg	        limitStackSpace = atoi(argv[i]);
89005b261ecSmrg		if (limitStackSpace > 0)
89105b261ecSmrg		    limitStackSpace *= 1024;
89205b261ecSmrg	    }
89305b261ecSmrg	    else
89405b261ecSmrg		UseMsg();
89505b261ecSmrg	}
89605b261ecSmrg#endif
89705b261ecSmrg#ifdef SERVER_LOCK
89805b261ecSmrg	else if ( strcmp ( argv[i], "-nolock") == 0)
89905b261ecSmrg	{
90005b261ecSmrg#if !defined(WIN32) && !defined(__CYGWIN__)
90105b261ecSmrg	  if (getuid() != 0)
90205b261ecSmrg	    ErrorF("Warning: the -nolock option can only be used by root\n");
90305b261ecSmrg	  else
90405b261ecSmrg#endif
90505b261ecSmrg	    nolock = TRUE;
90605b261ecSmrg	}
90705b261ecSmrg#endif
90805b261ecSmrg#ifndef NOLOGOHACK
90905b261ecSmrg	else if ( strcmp( argv[i], "-logo") == 0)
91005b261ecSmrg	{
91105b261ecSmrg	    logoScreenSaver = 1;
91205b261ecSmrg	}
91305b261ecSmrg	else if ( strcmp( argv[i], "nologo") == 0)
91405b261ecSmrg	{
91505b261ecSmrg	    logoScreenSaver = 0;
91605b261ecSmrg	}
91705b261ecSmrg#endif
91805b261ecSmrg	else if ( strcmp( argv[i], "-nolisten") == 0)
91905b261ecSmrg	{
92005b261ecSmrg            if(++i < argc) {
92105b261ecSmrg		if (_XSERVTransNoListen(argv[i]))
92205b261ecSmrg		    FatalError ("Failed to disable listen for %s transport",
92305b261ecSmrg				argv[i]);
92405b261ecSmrg	   } else
92505b261ecSmrg		UseMsg();
92605b261ecSmrg	}
92705b261ecSmrg	else if ( strcmp( argv[i], "-noreset") == 0)
92805b261ecSmrg	{
92905b261ecSmrg	    dispatchExceptionAtReset = 0;
93005b261ecSmrg	}
93105b261ecSmrg	else if ( strcmp( argv[i], "-reset") == 0)
93205b261ecSmrg	{
93305b261ecSmrg	    dispatchExceptionAtReset = DE_RESET;
93405b261ecSmrg	}
93505b261ecSmrg	else if ( strcmp( argv[i], "-p") == 0)
93605b261ecSmrg	{
93705b261ecSmrg	    if(++i < argc)
93805b261ecSmrg	        defaultScreenSaverInterval = ((CARD32)atoi(argv[i])) *
93905b261ecSmrg					     MILLI_PER_MIN;
94005b261ecSmrg	    else
94105b261ecSmrg		UseMsg();
94205b261ecSmrg	}
94305b261ecSmrg	else if ( strcmp( argv[i], "-pn") == 0)
94405b261ecSmrg	    PartialNetwork = TRUE;
94505b261ecSmrg	else if ( strcmp( argv[i], "-nopn") == 0)
94605b261ecSmrg	    PartialNetwork = FALSE;
94705b261ecSmrg	else if ( strcmp( argv[i], "r") == 0)
94805b261ecSmrg	    defaultKeyboardControl.autoRepeat = TRUE;
94905b261ecSmrg	else if ( strcmp( argv[i], "-r") == 0)
95005b261ecSmrg	    defaultKeyboardControl.autoRepeat = FALSE;
95105b261ecSmrg	else if ( strcmp( argv[i], "-s") == 0)
95205b261ecSmrg	{
95305b261ecSmrg	    if(++i < argc)
95405b261ecSmrg	        defaultScreenSaverTime = ((CARD32)atoi(argv[i])) *
95505b261ecSmrg					 MILLI_PER_MIN;
95605b261ecSmrg	    else
95705b261ecSmrg		UseMsg();
95805b261ecSmrg	}
95905b261ecSmrg	else if ( strcmp( argv[i], "-su") == 0)
96005b261ecSmrg	    disableSaveUnders = TRUE;
96105b261ecSmrg	else if ( strcmp( argv[i], "-t") == 0)
96205b261ecSmrg	{
96305b261ecSmrg	    if(++i < argc)
96405b261ecSmrg	        defaultPointerControl.threshold = atoi(argv[i]);
96505b261ecSmrg	    else
96605b261ecSmrg		UseMsg();
96705b261ecSmrg	}
96805b261ecSmrg	else if ( strcmp( argv[i], "-terminate") == 0)
96905b261ecSmrg	{
97005b261ecSmrg	    dispatchExceptionAtReset = DE_TERMINATE;
97105b261ecSmrg	}
97205b261ecSmrg	else if ( strcmp( argv[i], "-to") == 0)
97305b261ecSmrg	{
97405b261ecSmrg	    if(++i < argc)
97505b261ecSmrg		TimeOutValue = ((CARD32)atoi(argv[i])) * MILLI_PER_SECOND;
97605b261ecSmrg	    else
97705b261ecSmrg		UseMsg();
97805b261ecSmrg	}
97905b261ecSmrg	else if ( strcmp( argv[i], "-tst") == 0)
98005b261ecSmrg	{
98105b261ecSmrg	    noTestExtensions = TRUE;
98205b261ecSmrg	}
98305b261ecSmrg	else if ( strcmp( argv[i], "v") == 0)
98405b261ecSmrg	    defaultScreenSaverBlanking = PreferBlanking;
98505b261ecSmrg	else if ( strcmp( argv[i], "-v") == 0)
98605b261ecSmrg	    defaultScreenSaverBlanking = DontPreferBlanking;
98705b261ecSmrg	else if ( strcmp( argv[i], "-wm") == 0)
98805b261ecSmrg	    defaultBackingStore = WhenMapped;
98905b261ecSmrg        else if ( strcmp( argv[i], "-wr") == 0)
99005b261ecSmrg            whiteRoot = TRUE;
99105b261ecSmrg        else if ( strcmp( argv[i], "-maxbigreqsize") == 0) {
99205b261ecSmrg             if(++i < argc) {
99305b261ecSmrg                 long reqSizeArg = atol(argv[i]);
99405b261ecSmrg
99505b261ecSmrg                 /* Request size > 128MB does not make much sense... */
99605b261ecSmrg                 if( reqSizeArg > 0L && reqSizeArg < 128L ) {
99705b261ecSmrg                     maxBigRequestSize = (reqSizeArg * 1048576L) - 1L;
99805b261ecSmrg                 }
99905b261ecSmrg                 else
100005b261ecSmrg                 {
100105b261ecSmrg                     UseMsg();
100205b261ecSmrg                 }
100305b261ecSmrg             }
100405b261ecSmrg             else
100505b261ecSmrg             {
100605b261ecSmrg                 UseMsg();
100705b261ecSmrg             }
100805b261ecSmrg         }
100905b261ecSmrg#ifdef PANORAMIX
101005b261ecSmrg	else if ( strcmp( argv[i], "+xinerama") == 0){
101105b261ecSmrg	    noPanoramiXExtension = FALSE;
101205b261ecSmrg	}
101305b261ecSmrg	else if ( strcmp( argv[i], "-xinerama") == 0){
101405b261ecSmrg	    noPanoramiXExtension = TRUE;
101505b261ecSmrg	}
101605b261ecSmrg	else if ( strcmp( argv[i], "-disablexineramaextension") == 0){
101705b261ecSmrg	    PanoramiXExtensionDisabledHack = TRUE;
101805b261ecSmrg	}
101905b261ecSmrg#endif
102005b261ecSmrg	else if ( strcmp( argv[i], "-x") == 0)
102105b261ecSmrg	{
102205b261ecSmrg	    if(++i >= argc)
102305b261ecSmrg		UseMsg();
102405b261ecSmrg	    /* For U**x, which doesn't support dynamic loading, there's nothing
102505b261ecSmrg	     * to do when we see a -x.  Either the extension is linked in or
102605b261ecSmrg	     * it isn't */
102705b261ecSmrg	}
102805b261ecSmrg	else if ( strcmp( argv[i], "-I") == 0)
102905b261ecSmrg	{
103005b261ecSmrg	    /* ignore all remaining arguments */
103105b261ecSmrg	    break;
103205b261ecSmrg	}
103305b261ecSmrg	else if (strncmp (argv[i], "tty", 3) == 0)
103405b261ecSmrg	{
103505b261ecSmrg	    /* just in case any body is interested */
103605b261ecSmrg	    dev_tty_from_init = argv[i];
103705b261ecSmrg	}
103805b261ecSmrg#ifdef XDMCP
103905b261ecSmrg	else if ((skip = XdmcpOptions(argc, argv, i)) != i)
104005b261ecSmrg	{
104105b261ecSmrg	    i = skip - 1;
104205b261ecSmrg	}
104305b261ecSmrg#endif
104405b261ecSmrg#ifdef XPRINT
104505b261ecSmrg	else if ((skip = PrinterOptions(argc, argv, i)) != i)
104605b261ecSmrg	{
104705b261ecSmrg	    i = skip - 1;
104805b261ecSmrg	}
104905b261ecSmrg#endif
105005b261ecSmrg#ifdef XCSECURITY
105105b261ecSmrg	else if ((skip = XSecurityOptions(argc, argv, i)) != i)
105205b261ecSmrg	{
105305b261ecSmrg	    i = skip - 1;
105405b261ecSmrg	}
105505b261ecSmrg#endif
105605b261ecSmrg#ifdef AIXV3
105705b261ecSmrg        else if ( strcmp( argv[i], "-timeout") == 0)
105805b261ecSmrg        {
105905b261ecSmrg            if(++i < argc)
106005b261ecSmrg                SelectWaitTime = atoi(argv[i]);
106105b261ecSmrg            else
106205b261ecSmrg                UseMsg();
106305b261ecSmrg        }
106405b261ecSmrg        else if ( strcmp( argv[i], "-sync") == 0)
106505b261ecSmrg        {
106605b261ecSmrg            SyncOn++;
106705b261ecSmrg        }
106805b261ecSmrg#endif
106905b261ecSmrg#ifdef SMART_SCHEDULE
107005b261ecSmrg	else if ( strcmp( argv[i], "-dumbSched") == 0)
107105b261ecSmrg	{
107205b261ecSmrg	    SmartScheduleDisable = TRUE;
107305b261ecSmrg	}
107405b261ecSmrg	else if ( strcmp( argv[i], "-schedInterval") == 0)
107505b261ecSmrg	{
107605b261ecSmrg	    if (++i < argc)
107705b261ecSmrg	    {
107805b261ecSmrg		SmartScheduleInterval = atoi(argv[i]);
107905b261ecSmrg		SmartScheduleSlice = SmartScheduleInterval;
108005b261ecSmrg	    }
108105b261ecSmrg	    else
108205b261ecSmrg		UseMsg();
108305b261ecSmrg	}
108405b261ecSmrg	else if ( strcmp( argv[i], "-schedMax") == 0)
108505b261ecSmrg	{
108605b261ecSmrg	    if (++i < argc)
108705b261ecSmrg	    {
108805b261ecSmrg		SmartScheduleMaxSlice = atoi(argv[i]);
108905b261ecSmrg	    }
109005b261ecSmrg	    else
109105b261ecSmrg		UseMsg();
109205b261ecSmrg	}
109305b261ecSmrg#endif
109405b261ecSmrg#ifdef RENDER
109505b261ecSmrg	else if ( strcmp( argv[i], "-render" ) == 0)
109605b261ecSmrg	{
109705b261ecSmrg	    if (++i < argc)
109805b261ecSmrg	    {
109905b261ecSmrg		int policy = PictureParseCmapPolicy (argv[i]);
110005b261ecSmrg
110105b261ecSmrg		if (policy != PictureCmapPolicyInvalid)
110205b261ecSmrg		    PictureCmapPolicy = policy;
110305b261ecSmrg		else
110405b261ecSmrg		    UseMsg ();
110505b261ecSmrg	    }
110605b261ecSmrg	    else
110705b261ecSmrg		UseMsg ();
110805b261ecSmrg	}
110905b261ecSmrg#endif
111005b261ecSmrg	else if ( strcmp( argv[i], "+extension") == 0)
111105b261ecSmrg	{
111205b261ecSmrg	    if (++i < argc)
111305b261ecSmrg	    {
111405b261ecSmrg		if (!EnableDisableExtension(argv[i], TRUE))
111505b261ecSmrg		    EnableDisableExtensionError(argv[i], TRUE);
111605b261ecSmrg	    }
111705b261ecSmrg	    else
111805b261ecSmrg		UseMsg();
111905b261ecSmrg	}
112005b261ecSmrg	else if ( strcmp( argv[i], "-extension") == 0)
112105b261ecSmrg	{
112205b261ecSmrg	    if (++i < argc)
112305b261ecSmrg	    {
112405b261ecSmrg		if (!EnableDisableExtension(argv[i], FALSE))
112505b261ecSmrg		    EnableDisableExtensionError(argv[i], FALSE);
112605b261ecSmrg	    }
112705b261ecSmrg	    else
112805b261ecSmrg		UseMsg();
112905b261ecSmrg	}
113005b261ecSmrg 	else
113105b261ecSmrg 	{
113205b261ecSmrg	    ErrorF("Unrecognized option: %s\n", argv[i]);
113305b261ecSmrg	    UseMsg();
113405b261ecSmrg	    FatalError("Unrecognized option: %s\n", argv[i]);
113505b261ecSmrg        }
113605b261ecSmrg    }
113705b261ecSmrg}
113805b261ecSmrg
113905b261ecSmrg#ifdef COMMANDLINE_CHALLENGED_OPERATING_SYSTEMS
114005b261ecSmrgstatic void
114105b261ecSmrgInsertFileIntoCommandLine(
114205b261ecSmrg    int *resargc, char ***resargv,
114305b261ecSmrg    int prefix_argc, char **prefix_argv,
114405b261ecSmrg    char *filename,
114505b261ecSmrg    int suffix_argc, char **suffix_argv)
114605b261ecSmrg{
114705b261ecSmrg    struct stat     st;
114805b261ecSmrg    FILE           *f;
114905b261ecSmrg    char           *p;
115005b261ecSmrg    char           *q;
115105b261ecSmrg    int             insert_argc;
115205b261ecSmrg    char           *buf;
115305b261ecSmrg    int             len;
115405b261ecSmrg    int             i;
115505b261ecSmrg
115605b261ecSmrg    f = fopen(filename, "r");
115705b261ecSmrg    if (!f)
115805b261ecSmrg	FatalError("Can't open option file %s\n", filename);
115905b261ecSmrg
116005b261ecSmrg    fstat(fileno(f), &st);
116105b261ecSmrg
116205b261ecSmrg    buf = (char *) xalloc((unsigned) st.st_size + 1);
116305b261ecSmrg    if (!buf)
116405b261ecSmrg	FatalError("Out of Memory\n");
116505b261ecSmrg
116605b261ecSmrg    len = fread(buf, 1, (unsigned) st.st_size, f);
116705b261ecSmrg
116805b261ecSmrg    fclose(f);
116905b261ecSmrg
117005b261ecSmrg    if (len < 0)
117105b261ecSmrg	FatalError("Error reading option file %s\n", filename);
117205b261ecSmrg
117305b261ecSmrg    buf[len] = '\0';
117405b261ecSmrg
117505b261ecSmrg    p = buf;
117605b261ecSmrg    q = buf;
117705b261ecSmrg    insert_argc = 0;
117805b261ecSmrg
117905b261ecSmrg    while (*p)
118005b261ecSmrg    {
118105b261ecSmrg	while (isspace(*p))
118205b261ecSmrg	    p++;
118305b261ecSmrg	if (!*p)
118405b261ecSmrg	    break;
118505b261ecSmrg	if (*p == '#')
118605b261ecSmrg	{
118705b261ecSmrg	    while (*p && *p != '\n')
118805b261ecSmrg		p++;
118905b261ecSmrg	} else
119005b261ecSmrg	{
119105b261ecSmrg	    while (*p && !isspace(*p))
119205b261ecSmrg		*q++ = *p++;
119305b261ecSmrg	    /* Since p and q might still be pointing at the same place, we	 */
119405b261ecSmrg	    /* need to step p over the whitespace now before we add the null.	 */
119505b261ecSmrg	    if (*p)
119605b261ecSmrg		p++;
119705b261ecSmrg	    *q++ = '\0';
119805b261ecSmrg	    insert_argc++;
119905b261ecSmrg	}
120005b261ecSmrg    }
120105b261ecSmrg
120205b261ecSmrg    buf = (char *) xrealloc(buf, q - buf);
120305b261ecSmrg    if (!buf)
120405b261ecSmrg	FatalError("Out of memory reallocing option buf\n");
120505b261ecSmrg
120605b261ecSmrg    *resargc = prefix_argc + insert_argc + suffix_argc;
120705b261ecSmrg    *resargv = (char **) xalloc((*resargc + 1) * sizeof(char *));
120805b261ecSmrg    if (!*resargv)
120905b261ecSmrg	FatalError("Out of Memory\n");
121005b261ecSmrg
121105b261ecSmrg    memcpy(*resargv, prefix_argv, prefix_argc * sizeof(char *));
121205b261ecSmrg
121305b261ecSmrg    p = buf;
121405b261ecSmrg    for (i = 0; i < insert_argc; i++)
121505b261ecSmrg    {
121605b261ecSmrg	(*resargv)[prefix_argc + i] = p;
121705b261ecSmrg	p += strlen(p) + 1;
121805b261ecSmrg    }
121905b261ecSmrg
122005b261ecSmrg    memcpy(*resargv + prefix_argc + insert_argc,
122105b261ecSmrg	   suffix_argv, suffix_argc * sizeof(char *));
122205b261ecSmrg
122305b261ecSmrg    (*resargv)[*resargc] = NULL;
122405b261ecSmrg} /* end InsertFileIntoCommandLine */
122505b261ecSmrg
122605b261ecSmrg
122705b261ecSmrgvoid
122805b261ecSmrgExpandCommandLine(int *pargc, char ***pargv)
122905b261ecSmrg{
123005b261ecSmrg    int i;
123105b261ecSmrg
123205b261ecSmrg#if !defined(WIN32) && !defined(__CYGWIN__)
123305b261ecSmrg    if (getuid() != geteuid())
123405b261ecSmrg	return;
123505b261ecSmrg#endif
123605b261ecSmrg
123705b261ecSmrg    for (i = 1; i < *pargc; i++)
123805b261ecSmrg    {
123905b261ecSmrg	if ( (0 == strcmp((*pargv)[i], "-config")) && (i < (*pargc - 1)) )
124005b261ecSmrg	{
124105b261ecSmrg	    InsertFileIntoCommandLine(pargc, pargv,
124205b261ecSmrg					  i, *pargv,
124305b261ecSmrg					  (*pargv)[i+1], /* filename */
124405b261ecSmrg					  *pargc - i - 2, *pargv + i + 2);
124505b261ecSmrg	    i--;
124605b261ecSmrg	}
124705b261ecSmrg    }
124805b261ecSmrg} /* end ExpandCommandLine */
124905b261ecSmrg#endif
125005b261ecSmrg
125105b261ecSmrg/* Implement a simple-minded font authorization scheme.  The authorization
125205b261ecSmrg   name is "hp-hostname-1", the contents are simply the host name. */
125305b261ecSmrgint
125405b261ecSmrgset_font_authorizations(char **authorizations, int *authlen, pointer client)
125505b261ecSmrg{
125605b261ecSmrg#define AUTHORIZATION_NAME "hp-hostname-1"
125705b261ecSmrg#if defined(TCPCONN) || defined(STREAMSCONN)
125805b261ecSmrg    static char *result = NULL;
125905b261ecSmrg    static char *p = NULL;
126005b261ecSmrg
126105b261ecSmrg    if (p == NULL)
126205b261ecSmrg    {
126305b261ecSmrg	char hname[1024], *hnameptr;
126405b261ecSmrg	unsigned int len;
126505b261ecSmrg#if defined(IPv6) && defined(AF_INET6)
126605b261ecSmrg	struct addrinfo hints, *ai = NULL;
126705b261ecSmrg#else
126805b261ecSmrg	struct hostent *host;
126905b261ecSmrg#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
127005b261ecSmrg	_Xgethostbynameparams hparams;
127105b261ecSmrg#endif
127205b261ecSmrg#endif
127305b261ecSmrg
127405b261ecSmrg	gethostname(hname, 1024);
127505b261ecSmrg#if defined(IPv6) && defined(AF_INET6)
127605b261ecSmrg	bzero(&hints, sizeof(hints));
127705b261ecSmrg	hints.ai_flags = AI_CANONNAME;
127805b261ecSmrg	if (getaddrinfo(hname, NULL, &hints, &ai) == 0) {
127905b261ecSmrg	    hnameptr = ai->ai_canonname;
128005b261ecSmrg	} else {
128105b261ecSmrg	    hnameptr = hname;
128205b261ecSmrg	}
128305b261ecSmrg#else
128405b261ecSmrg	host = _XGethostbyname(hname, hparams);
128505b261ecSmrg	if (host == NULL)
128605b261ecSmrg	    hnameptr = hname;
128705b261ecSmrg	else
128805b261ecSmrg	    hnameptr = host->h_name;
128905b261ecSmrg#endif
129005b261ecSmrg
129105b261ecSmrg	len = strlen(hnameptr) + 1;
129205b261ecSmrg	result = xalloc(len + sizeof(AUTHORIZATION_NAME) + 4);
129305b261ecSmrg
129405b261ecSmrg	p = result;
129505b261ecSmrg        *p++ = sizeof(AUTHORIZATION_NAME) >> 8;
129605b261ecSmrg        *p++ = sizeof(AUTHORIZATION_NAME) & 0xff;
129705b261ecSmrg        *p++ = (len) >> 8;
129805b261ecSmrg        *p++ = (len & 0xff);
129905b261ecSmrg
130005b261ecSmrg	memmove(p, AUTHORIZATION_NAME, sizeof(AUTHORIZATION_NAME));
130105b261ecSmrg	p += sizeof(AUTHORIZATION_NAME);
130205b261ecSmrg	memmove(p, hnameptr, len);
130305b261ecSmrg	p += len;
130405b261ecSmrg#if defined(IPv6) && defined(AF_INET6)
130505b261ecSmrg	if (ai) {
130605b261ecSmrg	    freeaddrinfo(ai);
130705b261ecSmrg	}
130805b261ecSmrg#endif
130905b261ecSmrg    }
131005b261ecSmrg    *authlen = p - result;
131105b261ecSmrg    *authorizations = result;
131205b261ecSmrg    return 1;
131305b261ecSmrg#else /* TCPCONN */
131405b261ecSmrg    return 0;
131505b261ecSmrg#endif /* TCPCONN */
131605b261ecSmrg}
131705b261ecSmrg
131805b261ecSmrg/* XALLOC -- X's internal memory allocator.  Why does it return unsigned
131905b261ecSmrg * long * instead of the more common char *?  Well, if you read K&R you'll
132005b261ecSmrg * see they say that alloc must return a pointer "suitable for conversion"
132105b261ecSmrg * to whatever type you really want.  In a full-blown generic allocator
132205b261ecSmrg * there's no way to solve the alignment problems without potentially
132305b261ecSmrg * wasting lots of space.  But we have a more limited problem. We know
132405b261ecSmrg * we're only ever returning pointers to structures which will have to
132505b261ecSmrg * be long word aligned.  So we are making a stronger guarantee.  It might
132605b261ecSmrg * have made sense to make Xalloc return char * to conform with people's
132705b261ecSmrg * expectations of malloc, but this makes lint happier.
132805b261ecSmrg */
132905b261ecSmrg
133005b261ecSmrg#ifndef INTERNAL_MALLOC
133105b261ecSmrg
133205b261ecSmrg_X_EXPORT void *
133305b261ecSmrgXalloc(unsigned long amount)
133405b261ecSmrg{
133505b261ecSmrg    register pointer  ptr;
133605b261ecSmrg
133705b261ecSmrg    if ((long)amount <= 0) {
133805b261ecSmrg	return (unsigned long *)NULL;
133905b261ecSmrg    }
134005b261ecSmrg    /* aligned extra on long word boundary */
134105b261ecSmrg    amount = (amount + (sizeof(long) - 1)) & ~(sizeof(long) - 1);
134205b261ecSmrg#ifdef MEMBUG
134305b261ecSmrg    if (!Must_have_memory && Memory_fail &&
134405b261ecSmrg	((random() % MEM_FAIL_SCALE) < Memory_fail))
134505b261ecSmrg	return (unsigned long *)NULL;
134605b261ecSmrg#endif
134705b261ecSmrg    if ((ptr = (pointer)malloc(amount))) {
134805b261ecSmrg	return (unsigned long *)ptr;
134905b261ecSmrg    }
135005b261ecSmrg    if (Must_have_memory)
135105b261ecSmrg	FatalError("Out of memory");
135205b261ecSmrg    return (unsigned long *)NULL;
135305b261ecSmrg}
135405b261ecSmrg
135505b261ecSmrg/*****************
135605b261ecSmrg * XNFalloc
135705b261ecSmrg * "no failure" realloc, alternate interface to Xalloc w/o Must_have_memory
135805b261ecSmrg *****************/
135905b261ecSmrg
136005b261ecSmrg_X_EXPORT void *
136105b261ecSmrgXNFalloc(unsigned long amount)
136205b261ecSmrg{
136305b261ecSmrg    register pointer ptr;
136405b261ecSmrg
136505b261ecSmrg    if ((long)amount <= 0)
136605b261ecSmrg    {
136705b261ecSmrg        return (unsigned long *)NULL;
136805b261ecSmrg    }
136905b261ecSmrg    /* aligned extra on long word boundary */
137005b261ecSmrg    amount = (amount + (sizeof(long) - 1)) & ~(sizeof(long) - 1);
137105b261ecSmrg    ptr = (pointer)malloc(amount);
137205b261ecSmrg    if (!ptr)
137305b261ecSmrg    {
137405b261ecSmrg        FatalError("Out of memory");
137505b261ecSmrg    }
137605b261ecSmrg    return ((unsigned long *)ptr);
137705b261ecSmrg}
137805b261ecSmrg
137905b261ecSmrg/*****************
138005b261ecSmrg * Xcalloc
138105b261ecSmrg *****************/
138205b261ecSmrg
138305b261ecSmrg_X_EXPORT void *
138405b261ecSmrgXcalloc(unsigned long amount)
138505b261ecSmrg{
138605b261ecSmrg    unsigned long   *ret;
138705b261ecSmrg
138805b261ecSmrg    ret = Xalloc (amount);
138905b261ecSmrg    if (ret)
139005b261ecSmrg	bzero ((char *) ret, (int) amount);
139105b261ecSmrg    return ret;
139205b261ecSmrg}
139305b261ecSmrg
139405b261ecSmrg/*****************
139505b261ecSmrg * XNFcalloc
139605b261ecSmrg *****************/
139705b261ecSmrg
139805b261ecSmrg_X_EXPORT void *
139905b261ecSmrgXNFcalloc(unsigned long amount)
140005b261ecSmrg{
140105b261ecSmrg    unsigned long   *ret;
140205b261ecSmrg
140305b261ecSmrg    ret = Xalloc (amount);
140405b261ecSmrg    if (ret)
140505b261ecSmrg	bzero ((char *) ret, (int) amount);
140605b261ecSmrg    else if ((long)amount > 0)
140705b261ecSmrg        FatalError("Out of memory");
140805b261ecSmrg    return ret;
140905b261ecSmrg}
141005b261ecSmrg
141105b261ecSmrg/*****************
141205b261ecSmrg * Xrealloc
141305b261ecSmrg *****************/
141405b261ecSmrg
141505b261ecSmrg_X_EXPORT void *
141605b261ecSmrgXrealloc(pointer ptr, unsigned long amount)
141705b261ecSmrg{
141805b261ecSmrg#ifdef MEMBUG
141905b261ecSmrg    if (!Must_have_memory && Memory_fail &&
142005b261ecSmrg	((random() % MEM_FAIL_SCALE) < Memory_fail))
142105b261ecSmrg	return (unsigned long *)NULL;
142205b261ecSmrg#endif
142305b261ecSmrg    if ((long)amount <= 0)
142405b261ecSmrg    {
142505b261ecSmrg	if (ptr && !amount)
142605b261ecSmrg	    free(ptr);
142705b261ecSmrg	return (unsigned long *)NULL;
142805b261ecSmrg    }
142905b261ecSmrg    amount = (amount + (sizeof(long) - 1)) & ~(sizeof(long) - 1);
143005b261ecSmrg    if (ptr)
143105b261ecSmrg        ptr = (pointer)realloc((char *)ptr, amount);
143205b261ecSmrg    else
143305b261ecSmrg	ptr = (pointer)malloc(amount);
143405b261ecSmrg    if (ptr)
143505b261ecSmrg        return (unsigned long *)ptr;
143605b261ecSmrg    if (Must_have_memory)
143705b261ecSmrg	FatalError("Out of memory");
143805b261ecSmrg    return (unsigned long *)NULL;
143905b261ecSmrg}
144005b261ecSmrg
144105b261ecSmrg/*****************
144205b261ecSmrg * XNFrealloc
144305b261ecSmrg * "no failure" realloc, alternate interface to Xrealloc w/o Must_have_memory
144405b261ecSmrg *****************/
144505b261ecSmrg
144605b261ecSmrg_X_EXPORT void *
144705b261ecSmrgXNFrealloc(pointer ptr, unsigned long amount)
144805b261ecSmrg{
144905b261ecSmrg    if (( ptr = (pointer)Xrealloc( ptr, amount ) ) == NULL)
145005b261ecSmrg    {
145105b261ecSmrg	if ((long)amount > 0)
145205b261ecSmrg            FatalError( "Out of memory" );
145305b261ecSmrg    }
145405b261ecSmrg    return ((unsigned long *)ptr);
145505b261ecSmrg}
145605b261ecSmrg
145705b261ecSmrg/*****************
145805b261ecSmrg *  Xfree
145905b261ecSmrg *    calls free
146005b261ecSmrg *****************/
146105b261ecSmrg
146205b261ecSmrg_X_EXPORT void
146305b261ecSmrgXfree(pointer ptr)
146405b261ecSmrg{
146505b261ecSmrg    if (ptr)
146605b261ecSmrg	free((char *)ptr);
146705b261ecSmrg}
146805b261ecSmrg
146905b261ecSmrgvoid
147005b261ecSmrgOsInitAllocator (void)
147105b261ecSmrg{
147205b261ecSmrg#ifdef MEMBUG
147305b261ecSmrg    static int	been_here;
147405b261ecSmrg
147505b261ecSmrg    /* Check the memory system after each generation */
147605b261ecSmrg    if (been_here)
147705b261ecSmrg	CheckMemory ();
147805b261ecSmrg    else
147905b261ecSmrg	been_here = 1;
148005b261ecSmrg#endif
148105b261ecSmrg}
148205b261ecSmrg#endif /* !INTERNAL_MALLOC */
148305b261ecSmrg
148405b261ecSmrg
148505b261ecSmrgchar *
148605b261ecSmrgXstrdup(const char *s)
148705b261ecSmrg{
148805b261ecSmrg    char *sd;
148905b261ecSmrg
149005b261ecSmrg    if (s == NULL)
149105b261ecSmrg	return NULL;
149205b261ecSmrg
149305b261ecSmrg    sd = (char *)Xalloc(strlen(s) + 1);
149405b261ecSmrg    if (sd != NULL)
149505b261ecSmrg	strcpy(sd, s);
149605b261ecSmrg    return sd;
149705b261ecSmrg}
149805b261ecSmrg
149905b261ecSmrg
150005b261ecSmrg_X_EXPORT char *
150105b261ecSmrgXNFstrdup(const char *s)
150205b261ecSmrg{
150305b261ecSmrg    char *sd;
150405b261ecSmrg
150505b261ecSmrg    if (s == NULL)
150605b261ecSmrg	return NULL;
150705b261ecSmrg
150805b261ecSmrg    sd = (char *)XNFalloc(strlen(s) + 1);
150905b261ecSmrg    strcpy(sd, s);
151005b261ecSmrg    return sd;
151105b261ecSmrg}
151205b261ecSmrg
151305b261ecSmrg#ifdef SMART_SCHEDULE
151405b261ecSmrg
151505b261ecSmrgunsigned long	SmartScheduleIdleCount;
151605b261ecSmrgBool		SmartScheduleIdle;
151705b261ecSmrgBool		SmartScheduleTimerStopped;
151805b261ecSmrg
151905b261ecSmrg#ifdef SIGVTALRM
152005b261ecSmrg#define SMART_SCHEDULE_POSSIBLE
152105b261ecSmrg#endif
152205b261ecSmrg
152305b261ecSmrg#ifdef SMART_SCHEDULE_POSSIBLE
152405b261ecSmrg#define SMART_SCHEDULE_SIGNAL		SIGALRM
152505b261ecSmrg#define SMART_SCHEDULE_TIMER		ITIMER_REAL
152605b261ecSmrg#endif
152705b261ecSmrg
152805b261ecSmrgstatic void
152905b261ecSmrgSmartScheduleStopTimer (void)
153005b261ecSmrg{
153105b261ecSmrg#ifdef SMART_SCHEDULE_POSSIBLE
153205b261ecSmrg    struct itimerval	timer;
153305b261ecSmrg
153405b261ecSmrg    timer.it_interval.tv_sec = 0;
153505b261ecSmrg    timer.it_interval.tv_usec = 0;
153605b261ecSmrg    timer.it_value.tv_sec = 0;
153705b261ecSmrg    timer.it_value.tv_usec = 0;
153805b261ecSmrg    (void) setitimer (ITIMER_REAL, &timer, 0);
153905b261ecSmrg    SmartScheduleTimerStopped = TRUE;
154005b261ecSmrg#endif
154105b261ecSmrg}
154205b261ecSmrg
154305b261ecSmrgBool
154405b261ecSmrgSmartScheduleStartTimer (void)
154505b261ecSmrg{
154605b261ecSmrg#ifdef SMART_SCHEDULE_POSSIBLE
154705b261ecSmrg    struct itimerval	timer;
154805b261ecSmrg
154905b261ecSmrg    SmartScheduleTimerStopped = FALSE;
155005b261ecSmrg    timer.it_interval.tv_sec = 0;
155105b261ecSmrg    timer.it_interval.tv_usec = SmartScheduleInterval * 1000;
155205b261ecSmrg    timer.it_value.tv_sec = 0;
155305b261ecSmrg    timer.it_value.tv_usec = SmartScheduleInterval * 1000;
155405b261ecSmrg    return setitimer (ITIMER_REAL, &timer, 0) >= 0;
155505b261ecSmrg#endif
155605b261ecSmrg    return FALSE;
155705b261ecSmrg}
155805b261ecSmrg
155905b261ecSmrg#ifdef SMART_SCHEDULE_POSSIBLE
156005b261ecSmrgstatic void
156105b261ecSmrgSmartScheduleTimer (int sig)
156205b261ecSmrg{
156305b261ecSmrg    int olderrno = errno;
156405b261ecSmrg
156505b261ecSmrg    SmartScheduleTime += SmartScheduleInterval;
156605b261ecSmrg    if (SmartScheduleIdle)
156705b261ecSmrg    {
156805b261ecSmrg	SmartScheduleStopTimer ();
156905b261ecSmrg    }
157005b261ecSmrg    errno = olderrno;
157105b261ecSmrg}
157205b261ecSmrg#endif
157305b261ecSmrg
157405b261ecSmrgBool
157505b261ecSmrgSmartScheduleInit (void)
157605b261ecSmrg{
157705b261ecSmrg#ifdef SMART_SCHEDULE_POSSIBLE
157805b261ecSmrg    struct sigaction	act;
157905b261ecSmrg
158005b261ecSmrg    if (SmartScheduleDisable)
158105b261ecSmrg	return TRUE;
158205b261ecSmrg
158305b261ecSmrg    bzero ((char *) &act, sizeof(struct sigaction));
158405b261ecSmrg
158505b261ecSmrg    /* Set up the timer signal function */
158605b261ecSmrg    act.sa_handler = SmartScheduleTimer;
158705b261ecSmrg    sigemptyset (&act.sa_mask);
158805b261ecSmrg    sigaddset (&act.sa_mask, SMART_SCHEDULE_SIGNAL);
158905b261ecSmrg    if (sigaction (SMART_SCHEDULE_SIGNAL, &act, 0) < 0)
159005b261ecSmrg    {
159105b261ecSmrg	perror ("sigaction for smart scheduler");
159205b261ecSmrg	return FALSE;
159305b261ecSmrg    }
159405b261ecSmrg    /* Set up the virtual timer */
159505b261ecSmrg    if (!SmartScheduleStartTimer ())
159605b261ecSmrg    {
159705b261ecSmrg	perror ("scheduling timer");
159805b261ecSmrg	return FALSE;
159905b261ecSmrg    }
160005b261ecSmrg    /* stop the timer and wait for WaitForSomething to start it */
160105b261ecSmrg    SmartScheduleStopTimer ();
160205b261ecSmrg    return TRUE;
160305b261ecSmrg#else
160405b261ecSmrg    return FALSE;
160505b261ecSmrg#endif
160605b261ecSmrg}
160705b261ecSmrg#endif
160805b261ecSmrg
160905b261ecSmrg#ifdef SIG_BLOCK
161005b261ecSmrgstatic sigset_t	PreviousSignalMask;
161105b261ecSmrgstatic int	BlockedSignalCount;
161205b261ecSmrg#endif
161305b261ecSmrg
161405b261ecSmrgvoid
161505b261ecSmrgOsBlockSignals (void)
161605b261ecSmrg{
161705b261ecSmrg#ifdef SIG_BLOCK
161805b261ecSmrg    if (BlockedSignalCount++ == 0)
161905b261ecSmrg    {
162005b261ecSmrg	sigset_t    set;
162105b261ecSmrg
162205b261ecSmrg	sigemptyset (&set);
162305b261ecSmrg#ifdef SIGALRM
162405b261ecSmrg	sigaddset (&set, SIGALRM);
162505b261ecSmrg#endif
162605b261ecSmrg#ifdef SIGVTALRM
162705b261ecSmrg	sigaddset (&set, SIGVTALRM);
162805b261ecSmrg#endif
162905b261ecSmrg#ifdef SIGWINCH
163005b261ecSmrg	sigaddset (&set, SIGWINCH);
163105b261ecSmrg#endif
163205b261ecSmrg#ifdef SIGIO
163305b261ecSmrg	sigaddset (&set, SIGIO);
163405b261ecSmrg#endif
163505b261ecSmrg#ifdef SIGTSTP
163605b261ecSmrg	sigaddset (&set, SIGTSTP);
163705b261ecSmrg#endif
163805b261ecSmrg#ifdef SIGTTIN
163905b261ecSmrg	sigaddset (&set, SIGTTIN);
164005b261ecSmrg#endif
164105b261ecSmrg#ifdef SIGTTOU
164205b261ecSmrg	sigaddset (&set, SIGTTOU);
164305b261ecSmrg#endif
164405b261ecSmrg#ifdef SIGCHLD
164505b261ecSmrg	sigaddset (&set, SIGCHLD);
164605b261ecSmrg#endif
164705b261ecSmrg	sigprocmask (SIG_BLOCK, &set, &PreviousSignalMask);
164805b261ecSmrg    }
164905b261ecSmrg#endif
165005b261ecSmrg}
165105b261ecSmrg
165205b261ecSmrgvoid
165305b261ecSmrgOsReleaseSignals (void)
165405b261ecSmrg{
165505b261ecSmrg#ifdef SIG_BLOCK
165605b261ecSmrg    if (--BlockedSignalCount == 0)
165705b261ecSmrg    {
165805b261ecSmrg	sigprocmask (SIG_SETMASK, &PreviousSignalMask, 0);
165905b261ecSmrg    }
166005b261ecSmrg#endif
166105b261ecSmrg}
166205b261ecSmrg
166305b261ecSmrg#if !defined(WIN32)
166405b261ecSmrg/*
166505b261ecSmrg * "safer" versions of system(3), popen(3) and pclose(3) which give up
166605b261ecSmrg * all privs before running a command.
166705b261ecSmrg *
166805b261ecSmrg * This is based on the code in FreeBSD 2.2 libc.
166905b261ecSmrg *
167005b261ecSmrg * XXX It'd be good to redirect stderr so that it ends up in the log file
167105b261ecSmrg * as well.  As it is now, xkbcomp messages don't end up in the log file.
167205b261ecSmrg */
167305b261ecSmrg
167405b261ecSmrgint
167505b261ecSmrgSystem(char *command)
167605b261ecSmrg{
167705b261ecSmrg    int pid, p;
167805b261ecSmrg#ifdef SIGCHLD
167905b261ecSmrg    void (*csig)(int);
168005b261ecSmrg#endif
168105b261ecSmrg    int status;
168205b261ecSmrg
168305b261ecSmrg    if (!command)
168405b261ecSmrg	return(1);
168505b261ecSmrg
168605b261ecSmrg#ifdef SIGCHLD
168705b261ecSmrg    csig = signal(SIGCHLD, SIG_DFL);
168805b261ecSmrg    if (csig == SIG_ERR) {
168905b261ecSmrg      perror("signal");
169005b261ecSmrg      return -1;
169105b261ecSmrg    }
169205b261ecSmrg#endif
169305b261ecSmrg
169405b261ecSmrg#ifdef DEBUG
169505b261ecSmrg    ErrorF("System: `%s'\n", command);
169605b261ecSmrg#endif
169705b261ecSmrg
169805b261ecSmrg    switch (pid = fork()) {
169905b261ecSmrg    case -1:	/* error */
170005b261ecSmrg	p = -1;
170105b261ecSmrg    case 0:	/* child */
170205b261ecSmrg	if (setgid(getgid()) == -1)
170305b261ecSmrg	    _exit(127);
170405b261ecSmrg	if (setuid(getuid()) == -1)
170505b261ecSmrg	    _exit(127);
170605b261ecSmrg	execl("/bin/sh", "sh", "-c", command, (char *)NULL);
170705b261ecSmrg	_exit(127);
170805b261ecSmrg    default:	/* parent */
170905b261ecSmrg	do {
171005b261ecSmrg	    p = waitpid(pid, &status, 0);
171105b261ecSmrg	} while (p == -1 && errno == EINTR);
171205b261ecSmrg
171305b261ecSmrg    }
171405b261ecSmrg
171505b261ecSmrg#ifdef SIGCHLD
171605b261ecSmrg    if (signal(SIGCHLD, csig) == SIG_ERR) {
171705b261ecSmrg      perror("signal");
171805b261ecSmrg      return -1;
171905b261ecSmrg    }
172005b261ecSmrg#endif
172105b261ecSmrg
172205b261ecSmrg    return p == -1 ? -1 : status;
172305b261ecSmrg}
172405b261ecSmrg
172505b261ecSmrgstatic struct pid {
172605b261ecSmrg    struct pid *next;
172705b261ecSmrg    FILE *fp;
172805b261ecSmrg    int pid;
172905b261ecSmrg} *pidlist;
173005b261ecSmrg
173105b261ecSmrgvoid (*old_alarm)(int) = NULL; /* XXX horrible awful hack */
173205b261ecSmrg
173305b261ecSmrgpointer
173405b261ecSmrgPopen(char *command, char *type)
173505b261ecSmrg{
173605b261ecSmrg    struct pid *cur;
173705b261ecSmrg    FILE *iop;
173805b261ecSmrg    int pdes[2], pid;
173905b261ecSmrg
174005b261ecSmrg    if (command == NULL || type == NULL)
174105b261ecSmrg	return NULL;
174205b261ecSmrg
174305b261ecSmrg    if ((*type != 'r' && *type != 'w') || type[1])
174405b261ecSmrg	return NULL;
174505b261ecSmrg
174605b261ecSmrg    if ((cur = (struct pid *)xalloc(sizeof(struct pid))) == NULL)
174705b261ecSmrg	return NULL;
174805b261ecSmrg
174905b261ecSmrg    if (pipe(pdes) < 0) {
175005b261ecSmrg	xfree(cur);
175105b261ecSmrg	return NULL;
175205b261ecSmrg    }
175305b261ecSmrg
175405b261ecSmrg    /* Ignore the smart scheduler while this is going on */
175505b261ecSmrg    old_alarm = signal(SIGALRM, SIG_IGN);
175605b261ecSmrg    if (old_alarm == SIG_ERR) {
175705b261ecSmrg      perror("signal");
175805b261ecSmrg      return NULL;
175905b261ecSmrg    }
176005b261ecSmrg
176105b261ecSmrg    switch (pid = fork()) {
176205b261ecSmrg    case -1: 	/* error */
176305b261ecSmrg	close(pdes[0]);
176405b261ecSmrg	close(pdes[1]);
176505b261ecSmrg	xfree(cur);
176605b261ecSmrg	if (signal(SIGALRM, old_alarm) == SIG_ERR)
176705b261ecSmrg	  perror("signal");
176805b261ecSmrg	return NULL;
176905b261ecSmrg    case 0:	/* child */
177005b261ecSmrg	if (setgid(getgid()) == -1)
177105b261ecSmrg	    _exit(127);
177205b261ecSmrg	if (setuid(getuid()) == -1)
177305b261ecSmrg	    _exit(127);
177405b261ecSmrg	if (*type == 'r') {
177505b261ecSmrg	    if (pdes[1] != 1) {
177605b261ecSmrg		/* stdout */
177705b261ecSmrg		dup2(pdes[1], 1);
177805b261ecSmrg		close(pdes[1]);
177905b261ecSmrg	    }
178005b261ecSmrg	    close(pdes[0]);
178105b261ecSmrg	} else {
178205b261ecSmrg	    if (pdes[0] != 0) {
178305b261ecSmrg		/* stdin */
178405b261ecSmrg		dup2(pdes[0], 0);
178505b261ecSmrg		close(pdes[0]);
178605b261ecSmrg	    }
178705b261ecSmrg	    close(pdes[1]);
178805b261ecSmrg	}
178905b261ecSmrg	execl("/bin/sh", "sh", "-c", command, (char *)NULL);
179005b261ecSmrg	_exit(127);
179105b261ecSmrg    }
179205b261ecSmrg
179305b261ecSmrg    /* Avoid EINTR during stdio calls */
179405b261ecSmrg    OsBlockSignals ();
179505b261ecSmrg
179605b261ecSmrg    /* parent */
179705b261ecSmrg    if (*type == 'r') {
179805b261ecSmrg	iop = fdopen(pdes[0], type);
179905b261ecSmrg	close(pdes[1]);
180005b261ecSmrg    } else {
180105b261ecSmrg	iop = fdopen(pdes[1], type);
180205b261ecSmrg	close(pdes[0]);
180305b261ecSmrg    }
180405b261ecSmrg
180505b261ecSmrg    cur->fp = iop;
180605b261ecSmrg    cur->pid = pid;
180705b261ecSmrg    cur->next = pidlist;
180805b261ecSmrg    pidlist = cur;
180905b261ecSmrg
181005b261ecSmrg#ifdef DEBUG
181105b261ecSmrg    ErrorF("Popen: `%s', fp = %p\n", command, iop);
181205b261ecSmrg#endif
181305b261ecSmrg
181405b261ecSmrg    return iop;
181505b261ecSmrg}
181605b261ecSmrg
181705b261ecSmrg/* fopen that drops privileges */
181805b261ecSmrgpointer
181905b261ecSmrgFopen(char *file, char *type)
182005b261ecSmrg{
182105b261ecSmrg    FILE *iop;
182205b261ecSmrg#ifndef HAS_SAVED_IDS_AND_SETEUID
182305b261ecSmrg    struct pid *cur;
182405b261ecSmrg    int pdes[2], pid;
182505b261ecSmrg
182605b261ecSmrg    if (file == NULL || type == NULL)
182705b261ecSmrg	return NULL;
182805b261ecSmrg
182905b261ecSmrg    if ((*type != 'r' && *type != 'w') || type[1])
183005b261ecSmrg	return NULL;
183105b261ecSmrg
183205b261ecSmrg    if ((cur = (struct pid *)xalloc(sizeof(struct pid))) == NULL)
183305b261ecSmrg	return NULL;
183405b261ecSmrg
183505b261ecSmrg    if (pipe(pdes) < 0) {
183605b261ecSmrg	xfree(cur);
183705b261ecSmrg	return NULL;
183805b261ecSmrg    }
183905b261ecSmrg
184005b261ecSmrg    switch (pid = fork()) {
184105b261ecSmrg    case -1: 	/* error */
184205b261ecSmrg	close(pdes[0]);
184305b261ecSmrg	close(pdes[1]);
184405b261ecSmrg	xfree(cur);
184505b261ecSmrg	return NULL;
184605b261ecSmrg    case 0:	/* child */
184705b261ecSmrg	if (setgid(getgid()) == -1)
184805b261ecSmrg	    _exit(127);
184905b261ecSmrg	if (setuid(getuid()) == -1)
185005b261ecSmrg	    _exit(127);
185105b261ecSmrg	if (*type == 'r') {
185205b261ecSmrg	    if (pdes[1] != 1) {
185305b261ecSmrg		/* stdout */
185405b261ecSmrg		dup2(pdes[1], 1);
185505b261ecSmrg		close(pdes[1]);
185605b261ecSmrg	    }
185705b261ecSmrg	    close(pdes[0]);
185805b261ecSmrg	} else {
185905b261ecSmrg	    if (pdes[0] != 0) {
186005b261ecSmrg		/* stdin */
186105b261ecSmrg		dup2(pdes[0], 0);
186205b261ecSmrg		close(pdes[0]);
186305b261ecSmrg	    }
186405b261ecSmrg	    close(pdes[1]);
186505b261ecSmrg	}
186605b261ecSmrg	execl("/bin/cat", "cat", file, (char *)NULL);
186705b261ecSmrg	_exit(127);
186805b261ecSmrg    }
186905b261ecSmrg
187005b261ecSmrg    /* Avoid EINTR during stdio calls */
187105b261ecSmrg    OsBlockSignals ();
187205b261ecSmrg
187305b261ecSmrg    /* parent */
187405b261ecSmrg    if (*type == 'r') {
187505b261ecSmrg	iop = fdopen(pdes[0], type);
187605b261ecSmrg	close(pdes[1]);
187705b261ecSmrg    } else {
187805b261ecSmrg	iop = fdopen(pdes[1], type);
187905b261ecSmrg	close(pdes[0]);
188005b261ecSmrg    }
188105b261ecSmrg
188205b261ecSmrg    cur->fp = iop;
188305b261ecSmrg    cur->pid = pid;
188405b261ecSmrg    cur->next = pidlist;
188505b261ecSmrg    pidlist = cur;
188605b261ecSmrg
188705b261ecSmrg#ifdef DEBUG
188805b261ecSmrg    ErrorF("Fopen(%s), fp = %p\n", file, iop);
188905b261ecSmrg#endif
189005b261ecSmrg
189105b261ecSmrg    return iop;
189205b261ecSmrg#else
189305b261ecSmrg    int ruid, euid;
189405b261ecSmrg
189505b261ecSmrg    ruid = getuid();
189605b261ecSmrg    euid = geteuid();
189705b261ecSmrg
189805b261ecSmrg    if (seteuid(ruid) == -1) {
189905b261ecSmrg	    return NULL;
190005b261ecSmrg    }
190105b261ecSmrg    iop = fopen(file, type);
190205b261ecSmrg
190305b261ecSmrg    if (seteuid(euid) == -1) {
190405b261ecSmrg	    fclose(iop);
190505b261ecSmrg	    return NULL;
190605b261ecSmrg    }
190705b261ecSmrg    return iop;
190805b261ecSmrg#endif /* HAS_SAVED_IDS_AND_SETEUID */
190905b261ecSmrg}
191005b261ecSmrg
191105b261ecSmrgint
191205b261ecSmrgPclose(pointer iop)
191305b261ecSmrg{
191405b261ecSmrg    struct pid *cur, *last;
191505b261ecSmrg    int pstat;
191605b261ecSmrg    int pid;
191705b261ecSmrg
191805b261ecSmrg#ifdef DEBUG
191905b261ecSmrg    ErrorF("Pclose: fp = %p\n", iop);
192005b261ecSmrg#endif
192105b261ecSmrg
192205b261ecSmrg    fclose(iop);
192305b261ecSmrg
192405b261ecSmrg    for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next)
192505b261ecSmrg	if (cur->fp == iop)
192605b261ecSmrg	    break;
192705b261ecSmrg    if (cur == NULL)
192805b261ecSmrg	return -1;
192905b261ecSmrg
193005b261ecSmrg    do {
193105b261ecSmrg	pid = waitpid(cur->pid, &pstat, 0);
193205b261ecSmrg    } while (pid == -1 && errno == EINTR);
193305b261ecSmrg
193405b261ecSmrg    if (last == NULL)
193505b261ecSmrg	pidlist = cur->next;
193605b261ecSmrg    else
193705b261ecSmrg	last->next = cur->next;
193805b261ecSmrg    xfree(cur);
193905b261ecSmrg
194005b261ecSmrg    /* allow EINTR again */
194105b261ecSmrg    OsReleaseSignals ();
194205b261ecSmrg
194305b261ecSmrg    if (old_alarm && signal(SIGALRM, old_alarm) == SIG_ERR) {
194405b261ecSmrg      perror("signal");
194505b261ecSmrg      return -1;
194605b261ecSmrg    }
194705b261ecSmrg
194805b261ecSmrg    return pid == -1 ? -1 : pstat;
194905b261ecSmrg}
195005b261ecSmrg
195105b261ecSmrgint
195205b261ecSmrgFclose(pointer iop)
195305b261ecSmrg{
195405b261ecSmrg#ifdef HAS_SAVED_IDS_AND_SETEUID
195505b261ecSmrg    return fclose(iop);
195605b261ecSmrg#else
195705b261ecSmrg    return Pclose(iop);
195805b261ecSmrg#endif
195905b261ecSmrg}
196005b261ecSmrg
196105b261ecSmrg#endif /* !WIN32 */
196205b261ecSmrg
196305b261ecSmrg
196405b261ecSmrg/*
196505b261ecSmrg * CheckUserParameters: check for long command line arguments and long
196605b261ecSmrg * environment variables.  By default, these checks are only done when
196705b261ecSmrg * the server's euid != ruid.  In 3.3.x, these checks were done in an
196805b261ecSmrg * external wrapper utility.
196905b261ecSmrg */
197005b261ecSmrg
197105b261ecSmrg/* Consider LD* variables insecure? */
197205b261ecSmrg#ifndef REMOVE_ENV_LD
197305b261ecSmrg#define REMOVE_ENV_LD 1
197405b261ecSmrg#endif
197505b261ecSmrg
197605b261ecSmrg/* Remove long environment variables? */
197705b261ecSmrg#ifndef REMOVE_LONG_ENV
197805b261ecSmrg#define REMOVE_LONG_ENV 1
197905b261ecSmrg#endif
198005b261ecSmrg
198105b261ecSmrg/*
198205b261ecSmrg * Disallow stdout or stderr as pipes?  It's possible to block the X server
198305b261ecSmrg * when piping stdout+stderr to a pipe.
198405b261ecSmrg *
198505b261ecSmrg * Don't enable this because it looks like it's going to cause problems.
198605b261ecSmrg */
198705b261ecSmrg#ifndef NO_OUTPUT_PIPES
198805b261ecSmrg#define NO_OUTPUT_PIPES 0
198905b261ecSmrg#endif
199005b261ecSmrg
199105b261ecSmrg
199205b261ecSmrg/* Check args and env only if running setuid (euid == 0 && euid != uid) ? */
199305b261ecSmrg#ifndef CHECK_EUID
199405b261ecSmrg#ifndef WIN32
199505b261ecSmrg#define CHECK_EUID 1
199605b261ecSmrg#else
199705b261ecSmrg#define CHECK_EUID 0
199805b261ecSmrg#endif
199905b261ecSmrg#endif
200005b261ecSmrg
200105b261ecSmrg/*
200205b261ecSmrg * Maybe the locale can be faked to make isprint(3) report that everything
200305b261ecSmrg * is printable?  Avoid it by default.
200405b261ecSmrg */
200505b261ecSmrg#ifndef USE_ISPRINT
200605b261ecSmrg#define USE_ISPRINT 0
200705b261ecSmrg#endif
200805b261ecSmrg
200905b261ecSmrg#define MAX_ARG_LENGTH          128
201005b261ecSmrg#define MAX_ENV_LENGTH          256
201105b261ecSmrg#define MAX_ENV_PATH_LENGTH     2048	/* Limit for *PATH and TERMCAP */
201205b261ecSmrg
201305b261ecSmrg#if USE_ISPRINT
201405b261ecSmrg#include <ctype.h>
201505b261ecSmrg#define checkPrintable(c) isprint(c)
201605b261ecSmrg#else
201705b261ecSmrg#define checkPrintable(c) (((c) & 0x7f) >= 0x20 && ((c) & 0x7f) != 0x7f)
201805b261ecSmrg#endif
201905b261ecSmrg
202005b261ecSmrgenum BadCode {
202105b261ecSmrg    NotBad = 0,
202205b261ecSmrg    UnsafeArg,
202305b261ecSmrg    ArgTooLong,
202405b261ecSmrg    UnprintableArg,
202505b261ecSmrg    EnvTooLong,
202605b261ecSmrg    OutputIsPipe,
202705b261ecSmrg    InternalError
202805b261ecSmrg};
202905b261ecSmrg
203005b261ecSmrg#if defined(VENDORSUPPORT)
203105b261ecSmrg#define BUGADDRESS VENDORSUPPORT
203205b261ecSmrg#elif defined(BUILDERADDR)
203305b261ecSmrg#define BUGADDRESS BUILDERADDR
203405b261ecSmrg#else
203505b261ecSmrg#define BUGADDRESS "xorg@freedesktop.org"
203605b261ecSmrg#endif
203705b261ecSmrg
203805b261ecSmrg#define ARGMSG \
203905b261ecSmrg    "\nIf the arguments used are valid, and have been rejected incorrectly\n" \
204005b261ecSmrg      "please send details of the arguments and why they are valid to\n" \
204105b261ecSmrg      "%s.  In the meantime, you can start the Xserver as\n" \
204205b261ecSmrg      "the \"super user\" (root).\n"
204305b261ecSmrg
204405b261ecSmrg#define ENVMSG \
204505b261ecSmrg    "\nIf the environment is valid, and have been rejected incorrectly\n" \
204605b261ecSmrg      "please send details of the environment and why it is valid to\n" \
204705b261ecSmrg      "%s.  In the meantime, you can start the Xserver as\n" \
204805b261ecSmrg      "the \"super user\" (root).\n"
204905b261ecSmrg
205005b261ecSmrgvoid
205105b261ecSmrgCheckUserParameters(int argc, char **argv, char **envp)
205205b261ecSmrg{
205305b261ecSmrg    enum BadCode bad = NotBad;
205405b261ecSmrg    int i = 0, j;
205505b261ecSmrg    char *a, *e = NULL;
205605b261ecSmrg#if defined(__QNX__) && !defined(__QNXNTO__)
205705b261ecSmrg    char cmd_name[64];
205805b261ecSmrg#endif
205905b261ecSmrg
206005b261ecSmrg#if CHECK_EUID
206105b261ecSmrg    if (geteuid() == 0 && getuid() != geteuid())
206205b261ecSmrg#endif
206305b261ecSmrg    {
206405b261ecSmrg	/* Check each argv[] */
206505b261ecSmrg	for (i = 1; i < argc; i++) {
206605b261ecSmrg	    if (strcmp(argv[i], "-fp") == 0)
206705b261ecSmrg	    {
206805b261ecSmrg		i++; /* continue with next argument. skip the length check */
206905b261ecSmrg		if (i >= argc)
207005b261ecSmrg		    break;
207105b261ecSmrg	    } else
207205b261ecSmrg	    {
207305b261ecSmrg		if (strlen(argv[i]) > MAX_ARG_LENGTH) {
207405b261ecSmrg		    bad = ArgTooLong;
207505b261ecSmrg		    break;
207605b261ecSmrg		}
207705b261ecSmrg	    }
207805b261ecSmrg	    a = argv[i];
207905b261ecSmrg	    while (*a) {
208005b261ecSmrg		if (checkPrintable(*a) == 0) {
208105b261ecSmrg		    bad = UnprintableArg;
208205b261ecSmrg		    break;
208305b261ecSmrg		}
208405b261ecSmrg		a++;
208505b261ecSmrg	    }
208605b261ecSmrg	    if (bad)
208705b261ecSmrg		break;
208805b261ecSmrg	}
208905b261ecSmrg	if (!bad) {
209005b261ecSmrg	    /* Check each envp[] */
209105b261ecSmrg	    for (i = 0; envp[i]; i++) {
209205b261ecSmrg
209305b261ecSmrg		/* Check for bad environment variables and values */
209405b261ecSmrg#if REMOVE_ENV_LD
209505b261ecSmrg		while (envp[i] && (strncmp(envp[i], "LD", 2) == 0)) {
209605b261ecSmrg#ifdef ENVDEBUG
209705b261ecSmrg		    ErrorF("CheckUserParameters: removing %s from the "
209805b261ecSmrg			   "environment\n", strtok(envp[i], "="));
209905b261ecSmrg#endif
210005b261ecSmrg		    for (j = i; envp[j]; j++) {
210105b261ecSmrg			envp[j] = envp[j+1];
210205b261ecSmrg		    }
210305b261ecSmrg		}
210405b261ecSmrg#endif
210505b261ecSmrg		if (envp[i] && (strlen(envp[i]) > MAX_ENV_LENGTH)) {
210605b261ecSmrg#if REMOVE_LONG_ENV
210705b261ecSmrg#ifdef ENVDEBUG
210805b261ecSmrg		    ErrorF("CheckUserParameters: removing %s from the "
210905b261ecSmrg			   "environment\n", strtok(envp[i], "="));
211005b261ecSmrg#endif
211105b261ecSmrg		    for (j = i; envp[j]; j++) {
211205b261ecSmrg			envp[j] = envp[j+1];
211305b261ecSmrg		    }
211405b261ecSmrg		    i--;
211505b261ecSmrg#else
211605b261ecSmrg		    char *eq;
211705b261ecSmrg		    int len;
211805b261ecSmrg
211905b261ecSmrg		    eq = strchr(envp[i], '=');
212005b261ecSmrg		    if (!eq)
212105b261ecSmrg			continue;
212205b261ecSmrg		    len = eq - envp[i];
212305b261ecSmrg		    e = malloc(len + 1);
212405b261ecSmrg		    if (!e) {
212505b261ecSmrg			bad = InternalError;
212605b261ecSmrg			break;
212705b261ecSmrg		    }
212805b261ecSmrg		    strncpy(e, envp[i], len);
212905b261ecSmrg		    e[len] = 0;
213005b261ecSmrg		    if (len >= 4 &&
213105b261ecSmrg			(strcmp(e + len - 4, "PATH") == 0 ||
213205b261ecSmrg			 strcmp(e, "TERMCAP") == 0)) {
213305b261ecSmrg			if (strlen(envp[i]) > MAX_ENV_PATH_LENGTH) {
213405b261ecSmrg			    bad = EnvTooLong;
213505b261ecSmrg			    break;
213605b261ecSmrg			} else {
213705b261ecSmrg			    free(e);
213805b261ecSmrg			}
213905b261ecSmrg		    } else {
214005b261ecSmrg			bad = EnvTooLong;
214105b261ecSmrg			break;
214205b261ecSmrg		    }
214305b261ecSmrg#endif
214405b261ecSmrg		}
214505b261ecSmrg	    }
214605b261ecSmrg	}
214705b261ecSmrg#if NO_OUTPUT_PIPES
214805b261ecSmrg	if (!bad) {
214905b261ecSmrg	    struct stat buf;
215005b261ecSmrg
215105b261ecSmrg	    if (fstat(fileno(stdout), &buf) == 0 && S_ISFIFO(buf.st_mode))
215205b261ecSmrg		bad = OutputIsPipe;
215305b261ecSmrg	    if (fstat(fileno(stderr), &buf) == 0 && S_ISFIFO(buf.st_mode))
215405b261ecSmrg		bad = OutputIsPipe;
215505b261ecSmrg	}
215605b261ecSmrg#endif
215705b261ecSmrg    }
215805b261ecSmrg    switch (bad) {
215905b261ecSmrg    case NotBad:
216005b261ecSmrg	return;
216105b261ecSmrg    case UnsafeArg:
216205b261ecSmrg	ErrorF("Command line argument number %d is unsafe\n", i);
216305b261ecSmrg	ErrorF(ARGMSG, BUGADDRESS);
216405b261ecSmrg	break;
216505b261ecSmrg    case ArgTooLong:
216605b261ecSmrg	ErrorF("Command line argument number %d is too long\n", i);
216705b261ecSmrg	ErrorF(ARGMSG, BUGADDRESS);
216805b261ecSmrg	break;
216905b261ecSmrg    case UnprintableArg:
217005b261ecSmrg	ErrorF("Command line argument number %d contains unprintable"
217105b261ecSmrg		" characters\n", i);
217205b261ecSmrg	ErrorF(ARGMSG, BUGADDRESS);
217305b261ecSmrg	break;
217405b261ecSmrg    case EnvTooLong:
217505b261ecSmrg	ErrorF("Environment variable `%s' is too long\n", e);
217605b261ecSmrg	ErrorF(ENVMSG, BUGADDRESS);
217705b261ecSmrg	break;
217805b261ecSmrg    case OutputIsPipe:
217905b261ecSmrg	ErrorF("Stdout and/or stderr is a pipe\n");
218005b261ecSmrg	break;
218105b261ecSmrg    case InternalError:
218205b261ecSmrg	ErrorF("Internal Error\n");
218305b261ecSmrg	break;
218405b261ecSmrg    default:
218505b261ecSmrg	ErrorF("Unknown error\n");
218605b261ecSmrg	ErrorF(ARGMSG, BUGADDRESS);
218705b261ecSmrg	ErrorF(ENVMSG, BUGADDRESS);
218805b261ecSmrg	break;
218905b261ecSmrg    }
219005b261ecSmrg    FatalError("X server aborted because of unsafe environment\n");
219105b261ecSmrg}
219205b261ecSmrg
219305b261ecSmrg/*
219405b261ecSmrg * CheckUserAuthorization: check if the user is allowed to start the
219505b261ecSmrg * X server.  This usually means some sort of PAM checking, and it is
219605b261ecSmrg * usually only done for setuid servers (uid != euid).
219705b261ecSmrg */
219805b261ecSmrg
219905b261ecSmrg#ifdef USE_PAM
220005b261ecSmrg#include <security/pam_appl.h>
220105b261ecSmrg#include <security/pam_misc.h>
220205b261ecSmrg#include <pwd.h>
220305b261ecSmrg#endif /* USE_PAM */
220405b261ecSmrg
220505b261ecSmrgvoid
220605b261ecSmrgCheckUserAuthorization(void)
220705b261ecSmrg{
220805b261ecSmrg#ifdef USE_PAM
220905b261ecSmrg    static struct pam_conv conv = {
221005b261ecSmrg	misc_conv,
221105b261ecSmrg	NULL
221205b261ecSmrg    };
221305b261ecSmrg
221405b261ecSmrg    pam_handle_t *pamh = NULL;
221505b261ecSmrg    struct passwd *pw;
221605b261ecSmrg    int retval;
221705b261ecSmrg
221805b261ecSmrg    if (getuid() != geteuid()) {
221905b261ecSmrg	pw = getpwuid(getuid());
222005b261ecSmrg	if (pw == NULL)
222105b261ecSmrg	    FatalError("getpwuid() failed for uid %d\n", getuid());
222205b261ecSmrg
222305b261ecSmrg	retval = pam_start("xserver", pw->pw_name, &conv, &pamh);
222405b261ecSmrg	if (retval != PAM_SUCCESS)
222505b261ecSmrg	    FatalError("pam_start() failed.\n"
222605b261ecSmrg			"\tMissing or mangled PAM config file or module?\n");
222705b261ecSmrg
222805b261ecSmrg	retval = pam_authenticate(pamh, 0);
222905b261ecSmrg	if (retval != PAM_SUCCESS) {
223005b261ecSmrg	    pam_end(pamh, retval);
223105b261ecSmrg	    FatalError("PAM authentication failed, cannot start X server.\n"
223205b261ecSmrg			"\tPerhaps you do not have console ownership?\n");
223305b261ecSmrg	}
223405b261ecSmrg
223505b261ecSmrg	retval = pam_acct_mgmt(pamh, 0);
223605b261ecSmrg	if (retval != PAM_SUCCESS) {
223705b261ecSmrg	    pam_end(pamh, retval);
223805b261ecSmrg	    FatalError("PAM authentication failed, cannot start X server.\n"
223905b261ecSmrg			"\tPerhaps you do not have console ownership?\n");
224005b261ecSmrg	}
224105b261ecSmrg
224205b261ecSmrg	/* this is not a session, so do not do session management */
224305b261ecSmrg	pam_end(pamh, PAM_SUCCESS);
224405b261ecSmrg    }
224505b261ecSmrg#endif
224605b261ecSmrg}
224705b261ecSmrg
224805b261ecSmrg#ifdef __SCO__
224905b261ecSmrg#include <fcntl.h>
225005b261ecSmrg
225105b261ecSmrgstatic void
225205b261ecSmrglockit (int fd, short what)
225305b261ecSmrg{
225405b261ecSmrg  struct flock lck;
225505b261ecSmrg
225605b261ecSmrg  lck.l_whence = 0;
225705b261ecSmrg  lck.l_start = 0;
225805b261ecSmrg  lck.l_len = 1;
225905b261ecSmrg  lck.l_type = what;
226005b261ecSmrg
226105b261ecSmrg  (void)fcntl (fd, F_SETLKW, &lck);
226205b261ecSmrg}
226305b261ecSmrg
226405b261ecSmrg/* SCO OpenServer 5 lacks pread/pwrite. Emulate them. */
226505b261ecSmrgssize_t
226605b261ecSmrgpread (int fd, void *buf, size_t nbytes, off_t offset)
226705b261ecSmrg{
226805b261ecSmrg  off_t saved;
226905b261ecSmrg  ssize_t ret;
227005b261ecSmrg
227105b261ecSmrg  lockit (fd, F_RDLCK);
227205b261ecSmrg  saved = lseek (fd, 0, SEEK_CUR);
227305b261ecSmrg  lseek (fd, offset, SEEK_SET);
227405b261ecSmrg  ret = read (fd, buf, nbytes);
227505b261ecSmrg  lseek (fd, saved, SEEK_SET);
227605b261ecSmrg  lockit (fd, F_UNLCK);
227705b261ecSmrg
227805b261ecSmrg  return ret;
227905b261ecSmrg}
228005b261ecSmrg
228105b261ecSmrgssize_t
228205b261ecSmrgpwrite (int fd, const void *buf, size_t nbytes, off_t offset)
228305b261ecSmrg{
228405b261ecSmrg  off_t saved;
228505b261ecSmrg  ssize_t ret;
228605b261ecSmrg
228705b261ecSmrg  lockit (fd, F_WRLCK);
228805b261ecSmrg  saved = lseek (fd, 0, SEEK_CUR);
228905b261ecSmrg  lseek (fd, offset, SEEK_SET);
229005b261ecSmrg  ret = write (fd, buf, nbytes);
229105b261ecSmrg  lseek (fd, saved, SEEK_SET);
229205b261ecSmrg  lockit (fd, F_UNLCK);
229305b261ecSmrg
229405b261ecSmrg  return ret;
229505b261ecSmrg}
229605b261ecSmrg#endif /* __SCO__ */
2297