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