1706f2543Smrg/* 2706f2543Smrg 3706f2543SmrgCopyright 1987, 1998 The Open Group 4706f2543Smrg 5706f2543SmrgPermission to use, copy, modify, distribute, and sell this software and its 6706f2543Smrgdocumentation for any purpose is hereby granted without fee, provided that 7706f2543Smrgthe above copyright notice appear in all copies and that both that 8706f2543Smrgcopyright notice and this permission notice appear in supporting 9706f2543Smrgdocumentation. 10706f2543Smrg 11706f2543SmrgThe above copyright notice and this permission notice shall be included 12706f2543Smrgin all copies or substantial portions of the Software. 13706f2543Smrg 14706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15706f2543SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16706f2543SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17706f2543SmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 18706f2543SmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19706f2543SmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20706f2543SmrgOTHER DEALINGS IN THE SOFTWARE. 21706f2543Smrg 22706f2543SmrgExcept as contained in this notice, the name of The Open Group shall 23706f2543Smrgnot be used in advertising or otherwise to promote the sale, use or 24706f2543Smrgother dealings in this Software without prior written authorization 25706f2543Smrgfrom The Open Group. 26706f2543Smrg 27706f2543Smrg 28706f2543SmrgCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, 29706f2543SmrgCopyright 1994 Quarterdeck Office Systems. 30706f2543Smrg 31706f2543Smrg All Rights Reserved 32706f2543Smrg 33706f2543SmrgPermission to use, copy, modify, and distribute this software and its 34706f2543Smrgdocumentation for any purpose and without fee is hereby granted, 35706f2543Smrgprovided that the above copyright notice appear in all copies and that 36706f2543Smrgboth that copyright notice and this permission notice appear in 37706f2543Smrgsupporting documentation, and that the names of Digital and 38706f2543SmrgQuarterdeck not be used in advertising or publicity pertaining to 39706f2543Smrgdistribution of the software without specific, written prior 40706f2543Smrgpermission. 41706f2543Smrg 42706f2543SmrgDIGITAL AND QUARTERDECK DISCLAIM ALL WARRANTIES WITH REGARD TO THIS 43706f2543SmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 44706f2543SmrgFITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT 45706f2543SmrgOR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 46706f2543SmrgOF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 47706f2543SmrgOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE 48706f2543SmrgOR PERFORMANCE OF THIS SOFTWARE. 49706f2543Smrg 50706f2543Smrg*/ 51706f2543Smrg 52706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 53706f2543Smrg#include <dix-config.h> 54706f2543Smrg#endif 55706f2543Smrg 56706f2543Smrg#ifdef __CYGWIN__ 57706f2543Smrg#include <stdlib.h> 58706f2543Smrg#include <signal.h> 59706f2543Smrg/* 60706f2543Smrg Sigh... We really need a prototype for this to know it is stdcall, 61706f2543Smrg but #include-ing <windows.h> here is not a good idea... 62706f2543Smrg*/ 63706f2543Smrg__stdcall unsigned long GetTickCount(void); 64706f2543Smrg#endif 65706f2543Smrg 66706f2543Smrg#if defined(WIN32) && !defined(__CYGWIN__) 67706f2543Smrg#include <X11/Xwinsock.h> 68706f2543Smrg#endif 69706f2543Smrg#include <X11/Xos.h> 70706f2543Smrg#include <stdio.h> 71706f2543Smrg#include <time.h> 72706f2543Smrg#if !defined(WIN32) || !defined(__MINGW32__) 73706f2543Smrg#include <sys/time.h> 74706f2543Smrg#include <sys/resource.h> 75706f2543Smrg#endif 76706f2543Smrg#include "misc.h" 77706f2543Smrg#include <X11/X.h> 78706f2543Smrg#define XSERV_t 79706f2543Smrg#define TRANS_SERVER 80706f2543Smrg#define TRANS_REOPEN 81706f2543Smrg#include <X11/Xtrans/Xtrans.h> 82706f2543Smrg#include "input.h" 83706f2543Smrg#include "dixfont.h" 84706f2543Smrg#include "osdep.h" 85706f2543Smrg#include "extension.h" 86706f2543Smrg#ifdef X_POSIX_C_SOURCE 87706f2543Smrg#define _POSIX_C_SOURCE X_POSIX_C_SOURCE 88706f2543Smrg#include <signal.h> 89706f2543Smrg#undef _POSIX_C_SOURCE 90706f2543Smrg#else 91706f2543Smrg#if defined(_POSIX_SOURCE) 92706f2543Smrg#include <signal.h> 93706f2543Smrg#else 94706f2543Smrg#define _POSIX_SOURCE 95706f2543Smrg#include <signal.h> 96706f2543Smrg#undef _POSIX_SOURCE 97706f2543Smrg#endif 98706f2543Smrg#endif 99706f2543Smrg#ifndef WIN32 100706f2543Smrg#include <sys/wait.h> 101706f2543Smrg#endif 102706f2543Smrg#if !defined(SYSV) && !defined(WIN32) 103706f2543Smrg#include <sys/resource.h> 104706f2543Smrg#endif 105706f2543Smrg#include <sys/stat.h> 106706f2543Smrg#include <ctype.h> /* for isspace */ 107706f2543Smrg#include <stdarg.h> 108706f2543Smrg 109706f2543Smrg#include <stdlib.h> /* for malloc() */ 110706f2543Smrg 111706f2543Smrg#if defined(TCPCONN) || defined(STREAMSCONN) 112706f2543Smrg# ifndef WIN32 113706f2543Smrg# include <netdb.h> 114706f2543Smrg# endif 115706f2543Smrg#endif 116706f2543Smrg 117706f2543Smrg#include "opaque.h" 118706f2543Smrg 119706f2543Smrg#include "dixstruct.h" 120706f2543Smrg 121706f2543Smrg#include "xkbsrv.h" 122706f2543Smrg 123706f2543Smrg#include "picture.h" 124706f2543Smrg 125706f2543SmrgBool noTestExtensions; 126706f2543Smrg#ifdef COMPOSITE 127706f2543SmrgBool noCompositeExtension = FALSE; 128706f2543Smrg#endif 129706f2543Smrg 130706f2543Smrg#ifdef DAMAGE 131706f2543SmrgBool noDamageExtension = FALSE; 132706f2543Smrg#endif 133706f2543Smrg#ifdef DBE 134706f2543SmrgBool noDbeExtension = FALSE; 135706f2543Smrg#endif 136706f2543Smrg#ifdef DPMSExtension 137706f2543SmrgBool noDPMSExtension = FALSE; 138706f2543Smrg#endif 139706f2543Smrg#ifdef GLXEXT 140706f2543SmrgBool noGlxExtension = FALSE; 141706f2543SmrgBool noGlxVisualInit = FALSE; 142706f2543Smrg#endif 143706f2543Smrg#ifdef SCREENSAVER 144706f2543SmrgBool noScreenSaverExtension = FALSE; 145706f2543Smrg#endif 146706f2543Smrg#ifdef MITSHM 147706f2543SmrgBool noMITShmExtension = FALSE; 148706f2543Smrg#endif 149706f2543Smrg#ifdef RANDR 150706f2543SmrgBool noRRExtension = FALSE; 151706f2543Smrg#endif 152706f2543SmrgBool noRenderExtension = FALSE; 153706f2543Smrg#ifdef XCSECURITY 154706f2543SmrgBool noSecurityExtension = FALSE; 155706f2543Smrg#endif 156706f2543Smrg#ifdef RES 157706f2543SmrgBool noResExtension = FALSE; 158706f2543Smrg#endif 159706f2543Smrg#ifdef XF86BIGFONT 160706f2543SmrgBool noXFree86BigfontExtension = FALSE; 161706f2543Smrg#endif 162706f2543Smrg#ifdef XFreeXDGA 163706f2543SmrgBool noXFree86DGAExtension = FALSE; 164706f2543Smrg#endif 165706f2543Smrg#ifdef XF86DRI 166706f2543SmrgBool noXFree86DRIExtension = FALSE; 167706f2543Smrg#endif 168706f2543Smrg#ifdef XF86VIDMODE 169706f2543SmrgBool noXFree86VidModeExtension = FALSE; 170706f2543Smrg#endif 171706f2543Smrg#ifdef XFIXES 172706f2543SmrgBool noXFixesExtension = FALSE; 173706f2543Smrg#endif 174706f2543Smrg#ifdef PANORAMIX 175706f2543Smrg/* Xinerama is disabled by default unless enabled via +xinerama */ 176706f2543SmrgBool noPanoramiXExtension = TRUE; 177706f2543Smrg#endif 178706f2543Smrg#ifdef XSELINUX 179706f2543SmrgBool noSELinuxExtension = FALSE; 180706f2543Smrgint selinuxEnforcingState = SELINUX_MODE_DEFAULT; 181706f2543Smrg#endif 182706f2543Smrg#ifdef XV 183706f2543SmrgBool noXvExtension = FALSE; 184706f2543Smrg#endif 185706f2543Smrg#ifdef DRI2 186706f2543SmrgBool noDRI2Extension = FALSE; 187706f2543Smrg#endif 188706f2543Smrg 189706f2543SmrgBool noGEExtension = FALSE; 190706f2543Smrg 191706f2543Smrg#define X_INCLUDE_NETDB_H 192706f2543Smrg#include <X11/Xos_r.h> 193706f2543Smrg 194706f2543Smrg#include <errno.h> 195706f2543Smrg 196706f2543SmrgBool CoreDump; 197706f2543Smrg 198706f2543Smrg#ifdef PANORAMIX 199706f2543SmrgBool PanoramiXExtensionDisabledHack = FALSE; 200706f2543Smrg#endif 201706f2543Smrg 202706f2543Smrgint auditTrailLevel = 1; 203706f2543Smrg 204706f2543Smrg#if defined(SVR4) || defined(__linux__) || defined(CSRG_BASED) 205706f2543Smrg#define HAS_SAVED_IDS_AND_SETEUID 206706f2543Smrg#endif 207706f2543Smrg 208706f2543SmrgOsSigHandlerPtr 209706f2543SmrgOsSignal(int sig, OsSigHandlerPtr handler) 210706f2543Smrg{ 211706f2543Smrg struct sigaction act, oact; 212706f2543Smrg 213706f2543Smrg sigemptyset(&act.sa_mask); 214706f2543Smrg if (handler != SIG_IGN) 215706f2543Smrg sigaddset(&act.sa_mask, sig); 216706f2543Smrg act.sa_flags = 0; 217706f2543Smrg act.sa_handler = handler; 218706f2543Smrg if (sigaction(sig, &act, &oact)) 219706f2543Smrg perror("sigaction"); 220706f2543Smrg return oact.sa_handler; 221706f2543Smrg} 222706f2543Smrg 223706f2543Smrg/* 224706f2543Smrg * Explicit support for a server lock file like the ones used for UUCP. 225706f2543Smrg * For architectures with virtual terminals that can run more than one 226706f2543Smrg * server at a time. This keeps the servers from stomping on each other 227706f2543Smrg * if the user forgets to give them different display numbers. 228706f2543Smrg */ 229706f2543Smrg#define LOCK_DIR "/tmp" 230706f2543Smrg#define LOCK_TMP_PREFIX "/.tX" 231706f2543Smrg#define LOCK_PREFIX "/.X" 232706f2543Smrg#define LOCK_SUFFIX "-lock" 233706f2543Smrg 234706f2543Smrg#ifndef PATH_MAX 235706f2543Smrg#include <sys/param.h> 236706f2543Smrg#ifndef PATH_MAX 237706f2543Smrg#ifdef MAXPATHLEN 238706f2543Smrg#define PATH_MAX MAXPATHLEN 239706f2543Smrg#else 240706f2543Smrg#define PATH_MAX 1024 241706f2543Smrg#endif 242706f2543Smrg#endif 243706f2543Smrg#endif 244706f2543Smrg 245706f2543Smrgstatic Bool StillLocking = FALSE; 246706f2543Smrgstatic char LockFile[PATH_MAX]; 247706f2543Smrgstatic Bool nolock = FALSE; 248706f2543Smrg 249706f2543Smrg/* 250706f2543Smrg * LockServer -- 251706f2543Smrg * Check if the server lock file exists. If so, check if the PID 252706f2543Smrg * contained inside is valid. If so, then die. Otherwise, create 253706f2543Smrg * the lock file containing the PID. 254706f2543Smrg */ 255706f2543Smrgvoid 256706f2543SmrgLockServer(void) 257706f2543Smrg{ 258706f2543Smrg char tmp[PATH_MAX], pid_str[12]; 259706f2543Smrg int lfd, i, haslock, l_pid, t; 260706f2543Smrg char *tmppath = NULL; 261706f2543Smrg int len; 262706f2543Smrg char port[20]; 263706f2543Smrg 264706f2543Smrg if (nolock) return; 265706f2543Smrg /* 266706f2543Smrg * Path names 267706f2543Smrg */ 268706f2543Smrg tmppath = LOCK_DIR; 269706f2543Smrg 270706f2543Smrg sprintf(port, "%d", atoi(display)); 271706f2543Smrg len = strlen(LOCK_PREFIX) > strlen(LOCK_TMP_PREFIX) ? strlen(LOCK_PREFIX) : 272706f2543Smrg strlen(LOCK_TMP_PREFIX); 273706f2543Smrg len += strlen(tmppath) + strlen(port) + strlen(LOCK_SUFFIX) + 1; 274706f2543Smrg if (len > sizeof(LockFile)) 275706f2543Smrg FatalError("Display name `%s' is too long\n", port); 276706f2543Smrg (void)sprintf(tmp, "%s" LOCK_TMP_PREFIX "%s" LOCK_SUFFIX, tmppath, port); 277706f2543Smrg (void)sprintf(LockFile, "%s" LOCK_PREFIX "%s" LOCK_SUFFIX, tmppath, port); 278706f2543Smrg 279706f2543Smrg /* 280706f2543Smrg * Create a temporary file containing our PID. Attempt three times 281706f2543Smrg * to create the file. 282706f2543Smrg */ 283706f2543Smrg StillLocking = TRUE; 284706f2543Smrg i = 0; 285706f2543Smrg do { 286706f2543Smrg i++; 287706f2543Smrg lfd = open(tmp, O_CREAT | O_EXCL | O_WRONLY, 0644); 288706f2543Smrg if (lfd < 0) 289706f2543Smrg sleep(2); 290706f2543Smrg else 291706f2543Smrg break; 292706f2543Smrg } while (i < 3); 293706f2543Smrg if (lfd < 0) { 294706f2543Smrg unlink(tmp); 295706f2543Smrg i = 0; 296706f2543Smrg do { 297706f2543Smrg i++; 298706f2543Smrg lfd = open(tmp, O_CREAT | O_EXCL | O_WRONLY, 0644); 299706f2543Smrg if (lfd < 0) 300706f2543Smrg sleep(2); 301706f2543Smrg else 302706f2543Smrg break; 303706f2543Smrg } while (i < 3); 304706f2543Smrg } 305706f2543Smrg if (lfd < 0) 306706f2543Smrg FatalError("Could not create lock file in %s\n", tmp); 307706f2543Smrg (void) sprintf(pid_str, "%10ld\n", (long)getpid()); 308706f2543Smrg (void) write(lfd, pid_str, 11); 309706f2543Smrg (void) fchmod(lfd, 0444); 310706f2543Smrg (void) close(lfd); 311706f2543Smrg 312706f2543Smrg /* 313706f2543Smrg * OK. Now the tmp file exists. Try three times to move it in place 314706f2543Smrg * for the lock. 315706f2543Smrg */ 316706f2543Smrg i = 0; 317706f2543Smrg haslock = 0; 318706f2543Smrg while ((!haslock) && (i++ < 3)) { 319706f2543Smrg haslock = (link(tmp,LockFile) == 0); 320706f2543Smrg if (haslock) { 321706f2543Smrg /* 322706f2543Smrg * We're done. 323706f2543Smrg */ 324706f2543Smrg break; 325706f2543Smrg } 326706f2543Smrg else { 327706f2543Smrg /* 328706f2543Smrg * Read the pid from the existing file 329706f2543Smrg */ 330706f2543Smrg lfd = open(LockFile, O_RDONLY|O_NOFOLLOW); 331706f2543Smrg if (lfd < 0) { 332706f2543Smrg unlink(tmp); 333706f2543Smrg FatalError("Can't read lock file %s\n", LockFile); 334706f2543Smrg } 335706f2543Smrg pid_str[0] = '\0'; 336706f2543Smrg if (read(lfd, pid_str, 11) != 11) { 337706f2543Smrg /* 338706f2543Smrg * Bogus lock file. 339706f2543Smrg */ 340706f2543Smrg unlink(LockFile); 341706f2543Smrg close(lfd); 342706f2543Smrg continue; 343706f2543Smrg } 344706f2543Smrg pid_str[11] = '\0'; 345706f2543Smrg sscanf(pid_str, "%d", &l_pid); 346706f2543Smrg close(lfd); 347706f2543Smrg 348706f2543Smrg /* 349706f2543Smrg * Now try to kill the PID to see if it exists. 350706f2543Smrg */ 351706f2543Smrg errno = 0; 352706f2543Smrg t = kill(l_pid, 0); 353706f2543Smrg if ((t< 0) && (errno == ESRCH)) { 354706f2543Smrg /* 355706f2543Smrg * Stale lock file. 356706f2543Smrg */ 357706f2543Smrg unlink(LockFile); 358706f2543Smrg continue; 359706f2543Smrg } 360706f2543Smrg else if (((t < 0) && (errno == EPERM)) || (t == 0)) { 361706f2543Smrg /* 362706f2543Smrg * Process is still active. 363706f2543Smrg */ 364706f2543Smrg unlink(tmp); 365706f2543Smrg FatalError("Server is already active for display %s\n%s %s\n%s\n", 366706f2543Smrg port, "\tIf this server is no longer running, remove", 367706f2543Smrg LockFile, "\tand start again."); 368706f2543Smrg } 369706f2543Smrg } 370706f2543Smrg } 371706f2543Smrg unlink(tmp); 372706f2543Smrg if (!haslock) 373706f2543Smrg FatalError("Could not create server lock file: %s\n", LockFile); 374706f2543Smrg StillLocking = FALSE; 375706f2543Smrg} 376706f2543Smrg 377706f2543Smrg/* 378706f2543Smrg * UnlockServer -- 379706f2543Smrg * Remove the server lock file. 380706f2543Smrg */ 381706f2543Smrgvoid 382706f2543SmrgUnlockServer(void) 383706f2543Smrg{ 384706f2543Smrg if (nolock) return; 385706f2543Smrg 386706f2543Smrg if (!StillLocking){ 387706f2543Smrg 388706f2543Smrg (void) unlink(LockFile); 389706f2543Smrg } 390706f2543Smrg} 391706f2543Smrg 392706f2543Smrg/* Force connections to close on SIGHUP from init */ 393706f2543Smrg 394706f2543Smrgvoid 395706f2543SmrgAutoResetServer (int sig) 396706f2543Smrg{ 397706f2543Smrg int olderrno = errno; 398706f2543Smrg 399706f2543Smrg dispatchException |= DE_RESET; 400706f2543Smrg isItTimeToYield = TRUE; 401706f2543Smrg errno = olderrno; 402706f2543Smrg} 403706f2543Smrg 404706f2543Smrg/* Force connections to close and then exit on SIGTERM, SIGINT */ 405706f2543Smrg 406706f2543Smrgvoid 407706f2543SmrgGiveUp(int sig) 408706f2543Smrg{ 409706f2543Smrg int olderrno = errno; 410706f2543Smrg 411706f2543Smrg dispatchException |= DE_TERMINATE; 412706f2543Smrg isItTimeToYield = TRUE; 413706f2543Smrg errno = olderrno; 414706f2543Smrg} 415706f2543Smrg 416706f2543Smrg#if (defined WIN32 && defined __MINGW32__) || defined(__CYGWIN__) 417706f2543SmrgCARD32 418706f2543SmrgGetTimeInMillis (void) 419706f2543Smrg{ 420706f2543Smrg return GetTickCount (); 421706f2543Smrg} 422706f2543Smrg#else 423706f2543SmrgCARD32 424706f2543SmrgGetTimeInMillis(void) 425706f2543Smrg{ 426706f2543Smrg struct timeval tv; 427706f2543Smrg 428706f2543Smrg#ifdef MONOTONIC_CLOCK 429706f2543Smrg struct timespec tp; 430706f2543Smrg static clockid_t clockid; 431706f2543Smrg if (!clockid) { 432706f2543Smrg#ifdef CLOCK_MONOTONIC_COARSE 433706f2543Smrg if (clock_getres(CLOCK_MONOTONIC_COARSE, &tp) == 0 && 434706f2543Smrg (tp.tv_nsec / 1000) <= 1000 && 435706f2543Smrg clock_gettime(CLOCK_MONOTONIC_COARSE, &tp) == 0) 436706f2543Smrg clockid = CLOCK_MONOTONIC_COARSE; 437706f2543Smrg else 438706f2543Smrg#endif 439706f2543Smrg if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) 440706f2543Smrg clockid = CLOCK_MONOTONIC; 441706f2543Smrg else 442706f2543Smrg clockid = ~0L; 443706f2543Smrg } 444706f2543Smrg if (clockid != ~0L && clock_gettime(clockid, &tp) == 0) 445706f2543Smrg return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000L); 446706f2543Smrg#endif 447706f2543Smrg 448706f2543Smrg X_GETTIMEOFDAY(&tv); 449706f2543Smrg return(tv.tv_sec * 1000) + (tv.tv_usec / 1000); 450706f2543Smrg} 451706f2543Smrg#endif 452706f2543Smrg 453706f2543Smrgvoid 454706f2543SmrgAdjustWaitForDelay (pointer waitTime, unsigned long newdelay) 455706f2543Smrg{ 456706f2543Smrg static struct timeval delay_val; 457706f2543Smrg struct timeval **wt = (struct timeval **) waitTime; 458706f2543Smrg unsigned long olddelay; 459706f2543Smrg 460706f2543Smrg if (*wt == NULL) 461706f2543Smrg { 462706f2543Smrg delay_val.tv_sec = newdelay / 1000; 463706f2543Smrg delay_val.tv_usec = 1000 * (newdelay % 1000); 464706f2543Smrg *wt = &delay_val; 465706f2543Smrg } 466706f2543Smrg else 467706f2543Smrg { 468706f2543Smrg olddelay = (*wt)->tv_sec * 1000 + (*wt)->tv_usec / 1000; 469706f2543Smrg if (newdelay < olddelay) 470706f2543Smrg { 471706f2543Smrg (*wt)->tv_sec = newdelay / 1000; 472706f2543Smrg (*wt)->tv_usec = 1000 * (newdelay % 1000); 473706f2543Smrg } 474706f2543Smrg } 475706f2543Smrg} 476706f2543Smrg 477706f2543Smrgvoid UseMsg(void) 478706f2543Smrg{ 479706f2543Smrg ErrorF("use: X [:<display>] [option]\n"); 480706f2543Smrg ErrorF("-a # default pointer acceleration (factor)\n"); 481706f2543Smrg ErrorF("-ac disable access control restrictions\n"); 482706f2543Smrg ErrorF("-audit int set audit trail level\n"); 483706f2543Smrg ErrorF("-auth file select authorization file\n"); 484706f2543Smrg ErrorF("-br create root window with black background\n"); 485706f2543Smrg ErrorF("+bs enable any backing store support\n"); 486706f2543Smrg ErrorF("-bs disable any backing store support\n"); 487706f2543Smrg ErrorF("-c turns off key-click\n"); 488706f2543Smrg ErrorF("c # key-click volume (0-100)\n"); 489706f2543Smrg ErrorF("-cc int default color visual class\n"); 490706f2543Smrg ErrorF("-nocursor disable the cursor\n"); 491706f2543Smrg ErrorF("-core generate core dump on fatal error\n"); 492706f2543Smrg ErrorF("-dpi int screen resolution in dots per inch\n"); 493706f2543Smrg#ifdef DPMSExtension 494706f2543Smrg ErrorF("-dpms disables VESA DPMS monitor control\n"); 495706f2543Smrg#endif 496706f2543Smrg ErrorF("-deferglyphs [none|all|16] defer loading of [no|all|16-bit] glyphs\n"); 497706f2543Smrg ErrorF("-f # bell base (0-100)\n"); 498706f2543Smrg ErrorF("-fc string cursor font\n"); 499706f2543Smrg ErrorF("-fn string default font name\n"); 500706f2543Smrg ErrorF("-fp string default font path\n"); 501706f2543Smrg ErrorF("-help prints message with these options\n"); 502706f2543Smrg ErrorF("-I ignore all remaining arguments\n"); 503706f2543Smrg#ifdef RLIMIT_DATA 504706f2543Smrg ErrorF("-ld int limit data space to N Kb\n"); 505706f2543Smrg#endif 506706f2543Smrg#ifdef RLIMIT_NOFILE 507706f2543Smrg ErrorF("-lf int limit number of open files to N\n"); 508706f2543Smrg#endif 509706f2543Smrg#ifdef RLIMIT_STACK 510706f2543Smrg ErrorF("-ls int limit stack space to N Kb\n"); 511706f2543Smrg#endif 512706f2543Smrg ErrorF("-nolock disable the locking mechanism\n"); 513706f2543Smrg ErrorF("-nolisten string don't listen on protocol\n"); 514706f2543Smrg ErrorF("-noreset don't reset after last client exists\n"); 515706f2543Smrg ErrorF("-background [none] create root window with no background\n"); 516706f2543Smrg ErrorF("-reset reset after last client exists\n"); 517706f2543Smrg ErrorF("-p # screen-saver pattern duration (minutes)\n"); 518706f2543Smrg ErrorF("-pn accept failure to listen on all ports\n"); 519706f2543Smrg ErrorF("-nopn reject failure to listen on all ports\n"); 520706f2543Smrg ErrorF("-r turns off auto-repeat\n"); 521706f2543Smrg ErrorF("r turns on auto-repeat \n"); 522706f2543Smrg ErrorF("-render [default|mono|gray|color] set render color alloc policy\n"); 523706f2543Smrg ErrorF("-retro start with classic stipple and cursor\n"); 524706f2543Smrg ErrorF("-noretro start with black background and no cursor\n"); 525706f2543Smrg ErrorF("-s # screen-saver timeout (minutes)\n"); 526706f2543Smrg ErrorF("-t # default pointer threshold (pixels/t)\n"); 527706f2543Smrg ErrorF("-terminate terminate at server reset\n"); 528706f2543Smrg ErrorF("-to # connection time out\n"); 529706f2543Smrg ErrorF("-tst disable testing extensions\n"); 530706f2543Smrg ErrorF("ttyxx server started from init on /dev/ttyxx\n"); 531706f2543Smrg ErrorF("v video blanking for screen-saver\n"); 532706f2543Smrg ErrorF("-v screen-saver without video blanking\n"); 533706f2543Smrg ErrorF("-wm WhenMapped default backing-store\n"); 534706f2543Smrg ErrorF("-wr create root window with white background\n"); 535706f2543Smrg ErrorF("-maxbigreqsize set maximal bigrequest size \n"); 536706f2543Smrg#ifdef PANORAMIX 537706f2543Smrg ErrorF("+xinerama Enable XINERAMA extension\n"); 538706f2543Smrg ErrorF("-xinerama Disable XINERAMA extension\n"); 539706f2543Smrg#endif 540706f2543Smrg ErrorF("-dumbSched Disable smart scheduling, enable old behavior\n"); 541706f2543Smrg ErrorF("-schedInterval int Set scheduler interval in msec\n"); 542706f2543Smrg ErrorF("-sigstop Enable SIGSTOP based startup\n"); 543706f2543Smrg ErrorF("+extension name Enable extension\n"); 544706f2543Smrg ErrorF("-extension name Disable extension\n"); 545706f2543Smrg#ifdef XDMCP 546706f2543Smrg XdmcpUseMsg(); 547706f2543Smrg#endif 548706f2543Smrg XkbUseMsg(); 549706f2543Smrg ddxUseMsg(); 550706f2543Smrg} 551706f2543Smrg 552706f2543Smrg/* This function performs a rudimentary sanity check 553706f2543Smrg * on the display name passed in on the command-line, 554706f2543Smrg * since this string is used to generate filenames. 555706f2543Smrg * It is especially important that the display name 556706f2543Smrg * not contain a "/" and not start with a "-". 557706f2543Smrg * --kvajk 558706f2543Smrg */ 559706f2543Smrgstatic int 560706f2543SmrgVerifyDisplayName(const char *d) 561706f2543Smrg{ 562706f2543Smrg if ( d == (char *)0 ) return 0; /* null */ 563706f2543Smrg if ( *d == '\0' ) return 0; /* empty */ 564706f2543Smrg if ( *d == '-' ) return 0; /* could be confused for an option */ 565706f2543Smrg if ( *d == '.' ) return 0; /* must not equal "." or ".." */ 566706f2543Smrg if ( strchr(d, '/') != (char *)0 ) return 0; /* very important!!! */ 567706f2543Smrg return 1; 568706f2543Smrg} 569706f2543Smrg 570706f2543Smrg/* 571706f2543Smrg * This function parses the command line. Handles device-independent fields 572706f2543Smrg * and allows ddx to handle additional fields. It is not allowed to modify 573706f2543Smrg * argc or any of the strings pointed to by argv. 574706f2543Smrg */ 575706f2543Smrgvoid 576706f2543SmrgProcessCommandLine(int argc, char *argv[]) 577706f2543Smrg{ 578706f2543Smrg int i, skip; 579706f2543Smrg 580706f2543Smrg defaultKeyboardControl.autoRepeat = TRUE; 581706f2543Smrg 582706f2543Smrg#ifdef NO_PART_NET 583706f2543Smrg PartialNetwork = FALSE; 584706f2543Smrg#else 585706f2543Smrg PartialNetwork = TRUE; 586706f2543Smrg#endif 587706f2543Smrg 588706f2543Smrg for ( i = 1; i < argc; i++ ) 589706f2543Smrg { 590706f2543Smrg /* call ddx first, so it can peek/override if it wants */ 591706f2543Smrg if((skip = ddxProcessArgument(argc, argv, i))) 592706f2543Smrg { 593706f2543Smrg i += (skip - 1); 594706f2543Smrg } 595706f2543Smrg else if(argv[i][0] == ':') 596706f2543Smrg { 597706f2543Smrg /* initialize display */ 598706f2543Smrg display = argv[i]; 599706f2543Smrg display++; 600706f2543Smrg if( ! VerifyDisplayName( display ) ) { 601706f2543Smrg ErrorF("Bad display name: %s\n", display); 602706f2543Smrg UseMsg(); 603706f2543Smrg FatalError("Bad display name, exiting: %s\n", display); 604706f2543Smrg } 605706f2543Smrg } 606706f2543Smrg else if ( strcmp( argv[i], "-a") == 0) 607706f2543Smrg { 608706f2543Smrg if(++i < argc) 609706f2543Smrg defaultPointerControl.num = atoi(argv[i]); 610706f2543Smrg else 611706f2543Smrg UseMsg(); 612706f2543Smrg } 613706f2543Smrg else if ( strcmp( argv[i], "-ac") == 0) 614706f2543Smrg { 615706f2543Smrg defeatAccessControl = TRUE; 616706f2543Smrg } 617706f2543Smrg else if ( strcmp( argv[i], "-audit") == 0) 618706f2543Smrg { 619706f2543Smrg if(++i < argc) 620706f2543Smrg auditTrailLevel = atoi(argv[i]); 621706f2543Smrg else 622706f2543Smrg UseMsg(); 623706f2543Smrg } 624706f2543Smrg else if ( strcmp( argv[i], "-auth") == 0) 625706f2543Smrg { 626706f2543Smrg if(++i < argc) 627706f2543Smrg InitAuthorization (argv[i]); 628706f2543Smrg else 629706f2543Smrg UseMsg(); 630706f2543Smrg } 631706f2543Smrg else if ( strcmp( argv[i], "-br") == 0) ; /* default */ 632706f2543Smrg else if ( strcmp( argv[i], "+bs") == 0) 633706f2543Smrg enableBackingStore = TRUE; 634706f2543Smrg else if ( strcmp( argv[i], "-bs") == 0) 635706f2543Smrg disableBackingStore = TRUE; 636706f2543Smrg else if ( strcmp( argv[i], "c") == 0) 637706f2543Smrg { 638706f2543Smrg if(++i < argc) 639706f2543Smrg defaultKeyboardControl.click = atoi(argv[i]); 640706f2543Smrg else 641706f2543Smrg UseMsg(); 642706f2543Smrg } 643706f2543Smrg else if ( strcmp( argv[i], "-c") == 0) 644706f2543Smrg { 645706f2543Smrg defaultKeyboardControl.click = 0; 646706f2543Smrg } 647706f2543Smrg else if ( strcmp( argv[i], "-cc") == 0) 648706f2543Smrg { 649706f2543Smrg if(++i < argc) 650706f2543Smrg defaultColorVisualClass = atoi(argv[i]); 651706f2543Smrg else 652706f2543Smrg UseMsg(); 653706f2543Smrg } 654706f2543Smrg else if ( strcmp( argv[i], "-core") == 0) 655706f2543Smrg { 656706f2543Smrg#if !defined(WIN32) || !defined(__MINGW32__) 657706f2543Smrg struct rlimit core_limit; 658706f2543Smrg if (getrlimit (RLIMIT_CORE, &core_limit) != -1) { 659706f2543Smrg core_limit.rlim_cur = core_limit.rlim_max; 660706f2543Smrg setrlimit (RLIMIT_CORE, &core_limit); 661706f2543Smrg } 662706f2543Smrg#endif 663706f2543Smrg CoreDump = TRUE; 664706f2543Smrg } 665706f2543Smrg else if ( strcmp( argv[i], "-nocursor") == 0) 666706f2543Smrg { 667706f2543Smrg EnableCursor = FALSE; 668706f2543Smrg } 669706f2543Smrg else if ( strcmp( argv[i], "-dpi") == 0) 670706f2543Smrg { 671706f2543Smrg if(++i < argc) 672706f2543Smrg monitorResolution = atoi(argv[i]); 673706f2543Smrg else 674706f2543Smrg UseMsg(); 675706f2543Smrg } 676706f2543Smrg#ifdef DPMSExtension 677706f2543Smrg else if ( strcmp( argv[i], "dpms") == 0) 678706f2543Smrg /* ignored for compatibility */ ; 679706f2543Smrg else if ( strcmp( argv[i], "-dpms") == 0) 680706f2543Smrg DPMSDisabledSwitch = TRUE; 681706f2543Smrg#endif 682706f2543Smrg else if ( strcmp( argv[i], "-deferglyphs") == 0) 683706f2543Smrg { 684706f2543Smrg if(++i >= argc || !ParseGlyphCachingMode(argv[i])) 685706f2543Smrg UseMsg(); 686706f2543Smrg } 687706f2543Smrg else if ( strcmp( argv[i], "-f") == 0) 688706f2543Smrg { 689706f2543Smrg if(++i < argc) 690706f2543Smrg defaultKeyboardControl.bell = atoi(argv[i]); 691706f2543Smrg else 692706f2543Smrg UseMsg(); 693706f2543Smrg } 694706f2543Smrg else if ( strcmp( argv[i], "-fc") == 0) 695706f2543Smrg { 696706f2543Smrg if(++i < argc) 697706f2543Smrg defaultCursorFont = argv[i]; 698706f2543Smrg else 699706f2543Smrg UseMsg(); 700706f2543Smrg } 701706f2543Smrg else if ( strcmp( argv[i], "-fn") == 0) 702706f2543Smrg { 703706f2543Smrg if(++i < argc) 704706f2543Smrg defaultTextFont = argv[i]; 705706f2543Smrg else 706706f2543Smrg UseMsg(); 707706f2543Smrg } 708706f2543Smrg else if ( strcmp( argv[i], "-fp") == 0) 709706f2543Smrg { 710706f2543Smrg if(++i < argc) 711706f2543Smrg { 712706f2543Smrg defaultFontPath = argv[i]; 713706f2543Smrg } 714706f2543Smrg else 715706f2543Smrg UseMsg(); 716706f2543Smrg } 717706f2543Smrg else if ( strcmp( argv[i], "-help") == 0) 718706f2543Smrg { 719706f2543Smrg UseMsg(); 720706f2543Smrg exit(0); 721706f2543Smrg } 722706f2543Smrg else if ( (skip=XkbProcessArguments(argc,argv,i))!=0 ) { 723706f2543Smrg if (skip>0) 724706f2543Smrg i+= skip-1; 725706f2543Smrg else UseMsg(); 726706f2543Smrg } 727706f2543Smrg#ifdef RLIMIT_DATA 728706f2543Smrg else if ( strcmp( argv[i], "-ld") == 0) 729706f2543Smrg { 730706f2543Smrg if(++i < argc) 731706f2543Smrg { 732706f2543Smrg limitDataSpace = atoi(argv[i]); 733706f2543Smrg if (limitDataSpace > 0) 734706f2543Smrg limitDataSpace *= 1024; 735706f2543Smrg } 736706f2543Smrg else 737706f2543Smrg UseMsg(); 738706f2543Smrg } 739706f2543Smrg#endif 740706f2543Smrg#ifdef RLIMIT_NOFILE 741706f2543Smrg else if ( strcmp( argv[i], "-lf") == 0) 742706f2543Smrg { 743706f2543Smrg if(++i < argc) 744706f2543Smrg limitNoFile = atoi(argv[i]); 745706f2543Smrg else 746706f2543Smrg UseMsg(); 747706f2543Smrg } 748706f2543Smrg#endif 749706f2543Smrg#ifdef RLIMIT_STACK 750706f2543Smrg else if ( strcmp( argv[i], "-ls") == 0) 751706f2543Smrg { 752706f2543Smrg if(++i < argc) 753706f2543Smrg { 754706f2543Smrg limitStackSpace = atoi(argv[i]); 755706f2543Smrg if (limitStackSpace > 0) 756706f2543Smrg limitStackSpace *= 1024; 757706f2543Smrg } 758706f2543Smrg else 759706f2543Smrg UseMsg(); 760706f2543Smrg } 761706f2543Smrg#endif 762706f2543Smrg else if ( strcmp ( argv[i], "-nolock") == 0) 763706f2543Smrg { 764706f2543Smrg#if !defined(WIN32) && !defined(__CYGWIN__) 765706f2543Smrg if (getuid() != 0) 766706f2543Smrg ErrorF("Warning: the -nolock option can only be used by root\n"); 767706f2543Smrg else 768706f2543Smrg#endif 769706f2543Smrg nolock = TRUE; 770706f2543Smrg } 771706f2543Smrg else if ( strcmp( argv[i], "-nolisten") == 0) 772706f2543Smrg { 773706f2543Smrg if(++i < argc) { 774706f2543Smrg if (_XSERVTransNoListen(argv[i])) 775706f2543Smrg FatalError ("Failed to disable listen for %s transport", 776706f2543Smrg argv[i]); 777706f2543Smrg } else 778706f2543Smrg UseMsg(); 779706f2543Smrg } 780706f2543Smrg else if ( strcmp( argv[i], "-noreset") == 0) 781706f2543Smrg { 782706f2543Smrg dispatchExceptionAtReset = 0; 783706f2543Smrg } 784706f2543Smrg else if ( strcmp( argv[i], "-reset") == 0) 785706f2543Smrg { 786706f2543Smrg dispatchExceptionAtReset = DE_RESET; 787706f2543Smrg } 788706f2543Smrg else if ( strcmp( argv[i], "-p") == 0) 789706f2543Smrg { 790706f2543Smrg if(++i < argc) 791706f2543Smrg defaultScreenSaverInterval = ((CARD32)atoi(argv[i])) * 792706f2543Smrg MILLI_PER_MIN; 793706f2543Smrg else 794706f2543Smrg UseMsg(); 795706f2543Smrg } 796706f2543Smrg else if (strcmp(argv[i], "-pogo") == 0) 797706f2543Smrg { 798706f2543Smrg dispatchException = DE_TERMINATE; 799706f2543Smrg } 800706f2543Smrg else if ( strcmp( argv[i], "-pn") == 0) 801706f2543Smrg PartialNetwork = TRUE; 802706f2543Smrg else if ( strcmp( argv[i], "-nopn") == 0) 803706f2543Smrg PartialNetwork = FALSE; 804706f2543Smrg else if ( strcmp( argv[i], "r") == 0) 805706f2543Smrg defaultKeyboardControl.autoRepeat = TRUE; 806706f2543Smrg else if ( strcmp( argv[i], "-r") == 0) 807706f2543Smrg defaultKeyboardControl.autoRepeat = FALSE; 808706f2543Smrg else if ( strcmp( argv[i], "-retro") == 0) 809706f2543Smrg party_like_its_1989 = TRUE; 810706f2543Smrg else if ( strcmp( argv[i], "-noretro") == 0) 811706f2543Smrg party_like_its_1989 = FALSE; 812706f2543Smrg else if ( strcmp( argv[i], "-s") == 0) 813706f2543Smrg { 814706f2543Smrg if(++i < argc) 815706f2543Smrg defaultScreenSaverTime = ((CARD32)atoi(argv[i])) * 816706f2543Smrg MILLI_PER_MIN; 817706f2543Smrg else 818706f2543Smrg UseMsg(); 819706f2543Smrg } 820706f2543Smrg else if ( strcmp( argv[i], "-t") == 0) 821706f2543Smrg { 822706f2543Smrg if(++i < argc) 823706f2543Smrg defaultPointerControl.threshold = atoi(argv[i]); 824706f2543Smrg else 825706f2543Smrg UseMsg(); 826706f2543Smrg } 827706f2543Smrg else if ( strcmp( argv[i], "-terminate") == 0) 828706f2543Smrg { 829706f2543Smrg dispatchExceptionAtReset = DE_TERMINATE; 830706f2543Smrg } 831706f2543Smrg else if ( strcmp( argv[i], "-to") == 0) 832706f2543Smrg { 833706f2543Smrg if(++i < argc) 834706f2543Smrg TimeOutValue = ((CARD32)atoi(argv[i])) * MILLI_PER_SECOND; 835706f2543Smrg else 836706f2543Smrg UseMsg(); 837706f2543Smrg } 838706f2543Smrg else if ( strcmp( argv[i], "-tst") == 0) 839706f2543Smrg { 840706f2543Smrg noTestExtensions = TRUE; 841706f2543Smrg } 842706f2543Smrg else if ( strcmp( argv[i], "v") == 0) 843706f2543Smrg defaultScreenSaverBlanking = PreferBlanking; 844706f2543Smrg else if ( strcmp( argv[i], "-v") == 0) 845706f2543Smrg defaultScreenSaverBlanking = DontPreferBlanking; 846706f2543Smrg else if ( strcmp( argv[i], "-wm") == 0) 847706f2543Smrg defaultBackingStore = WhenMapped; 848706f2543Smrg else if ( strcmp( argv[i], "-wr") == 0) 849706f2543Smrg whiteRoot = TRUE; 850706f2543Smrg else if ( strcmp( argv[i], "-background") == 0) { 851706f2543Smrg if(++i < argc) { 852706f2543Smrg if (!strcmp ( argv[i], "none")) 853706f2543Smrg bgNoneRoot = TRUE; 854706f2543Smrg else 855706f2543Smrg UseMsg(); 856706f2543Smrg } 857706f2543Smrg } 858706f2543Smrg else if ( strcmp( argv[i], "-maxbigreqsize") == 0) { 859706f2543Smrg if(++i < argc) { 860706f2543Smrg long reqSizeArg = atol(argv[i]); 861706f2543Smrg 862706f2543Smrg /* Request size > 128MB does not make much sense... */ 863706f2543Smrg if( reqSizeArg > 0L && reqSizeArg < 128L ) { 864706f2543Smrg maxBigRequestSize = (reqSizeArg * 1048576L) - 1L; 865706f2543Smrg } 866706f2543Smrg else 867706f2543Smrg { 868706f2543Smrg UseMsg(); 869706f2543Smrg } 870706f2543Smrg } 871706f2543Smrg else 872706f2543Smrg { 873706f2543Smrg UseMsg(); 874706f2543Smrg } 875706f2543Smrg } 876706f2543Smrg#ifdef PANORAMIX 877706f2543Smrg else if ( strcmp( argv[i], "+xinerama") == 0){ 878706f2543Smrg noPanoramiXExtension = FALSE; 879706f2543Smrg } 880706f2543Smrg else if ( strcmp( argv[i], "-xinerama") == 0){ 881706f2543Smrg noPanoramiXExtension = TRUE; 882706f2543Smrg } 883706f2543Smrg else if ( strcmp( argv[i], "-disablexineramaextension") == 0){ 884706f2543Smrg PanoramiXExtensionDisabledHack = TRUE; 885706f2543Smrg } 886706f2543Smrg#endif 887706f2543Smrg else if ( strcmp( argv[i], "-I") == 0) 888706f2543Smrg { 889706f2543Smrg /* ignore all remaining arguments */ 890706f2543Smrg break; 891706f2543Smrg } 892706f2543Smrg else if (strncmp (argv[i], "tty", 3) == 0) 893706f2543Smrg { 894706f2543Smrg /* init supplies us with this useless information */ 895706f2543Smrg } 896706f2543Smrg#ifdef XDMCP 897706f2543Smrg else if ((skip = XdmcpOptions(argc, argv, i)) != i) 898706f2543Smrg { 899706f2543Smrg i = skip - 1; 900706f2543Smrg } 901706f2543Smrg#endif 902706f2543Smrg else if ( strcmp( argv[i], "-dumbSched") == 0) 903706f2543Smrg { 904706f2543Smrg SmartScheduleDisable = TRUE; 905706f2543Smrg } 906706f2543Smrg else if ( strcmp( argv[i], "-schedInterval") == 0) 907706f2543Smrg { 908706f2543Smrg if (++i < argc) 909706f2543Smrg { 910706f2543Smrg SmartScheduleInterval = atoi(argv[i]); 911706f2543Smrg SmartScheduleSlice = SmartScheduleInterval; 912706f2543Smrg } 913706f2543Smrg else 914706f2543Smrg UseMsg(); 915706f2543Smrg } 916706f2543Smrg else if ( strcmp( argv[i], "-schedMax") == 0) 917706f2543Smrg { 918706f2543Smrg if (++i < argc) 919706f2543Smrg { 920706f2543Smrg SmartScheduleMaxSlice = atoi(argv[i]); 921706f2543Smrg } 922706f2543Smrg else 923706f2543Smrg UseMsg(); 924706f2543Smrg } 925706f2543Smrg else if ( strcmp( argv[i], "-render" ) == 0) 926706f2543Smrg { 927706f2543Smrg if (++i < argc) 928706f2543Smrg { 929706f2543Smrg int policy = PictureParseCmapPolicy (argv[i]); 930706f2543Smrg 931706f2543Smrg if (policy != PictureCmapPolicyInvalid) 932706f2543Smrg PictureCmapPolicy = policy; 933706f2543Smrg else 934706f2543Smrg UseMsg (); 935706f2543Smrg } 936706f2543Smrg else 937706f2543Smrg UseMsg (); 938706f2543Smrg } 939706f2543Smrg else if ( strcmp( argv[i], "-sigstop") == 0) 940706f2543Smrg { 941706f2543Smrg RunFromSigStopParent = TRUE; 942706f2543Smrg } 943706f2543Smrg else if ( strcmp( argv[i], "+extension") == 0) 944706f2543Smrg { 945706f2543Smrg if (++i < argc) 946706f2543Smrg { 947706f2543Smrg if (!EnableDisableExtension(argv[i], TRUE)) 948706f2543Smrg EnableDisableExtensionError(argv[i], TRUE); 949706f2543Smrg } 950706f2543Smrg else 951706f2543Smrg UseMsg(); 952706f2543Smrg } 953706f2543Smrg else if ( strcmp( argv[i], "-extension") == 0) 954706f2543Smrg { 955706f2543Smrg if (++i < argc) 956706f2543Smrg { 957706f2543Smrg if (!EnableDisableExtension(argv[i], FALSE)) 958706f2543Smrg EnableDisableExtensionError(argv[i], FALSE); 959706f2543Smrg } 960706f2543Smrg else 961706f2543Smrg UseMsg(); 962706f2543Smrg } 963706f2543Smrg else 964706f2543Smrg { 965706f2543Smrg ErrorF("Unrecognized option: %s\n", argv[i]); 966706f2543Smrg UseMsg(); 967706f2543Smrg FatalError("Unrecognized option: %s\n", argv[i]); 968706f2543Smrg } 969706f2543Smrg } 970706f2543Smrg} 971706f2543Smrg 972706f2543Smrg/* Implement a simple-minded font authorization scheme. The authorization 973706f2543Smrg name is "hp-hostname-1", the contents are simply the host name. */ 974706f2543Smrgint 975706f2543Smrgset_font_authorizations(char **authorizations, int *authlen, pointer client) 976706f2543Smrg{ 977706f2543Smrg#define AUTHORIZATION_NAME "hp-hostname-1" 978706f2543Smrg#if defined(TCPCONN) || defined(STREAMSCONN) 979706f2543Smrg static char *result = NULL; 980706f2543Smrg static char *p = NULL; 981706f2543Smrg 982706f2543Smrg if (p == NULL) 983706f2543Smrg { 984706f2543Smrg char hname[1024], *hnameptr; 985706f2543Smrg unsigned int len; 986706f2543Smrg#if defined(IPv6) && defined(AF_INET6) 987706f2543Smrg struct addrinfo hints, *ai = NULL; 988706f2543Smrg#else 989706f2543Smrg struct hostent *host; 990706f2543Smrg#ifdef XTHREADS_NEEDS_BYNAMEPARAMS 991706f2543Smrg _Xgethostbynameparams hparams; 992706f2543Smrg#endif 993706f2543Smrg#endif 994706f2543Smrg 995706f2543Smrg gethostname(hname, 1024); 996706f2543Smrg#if defined(IPv6) && defined(AF_INET6) 997706f2543Smrg memset(&hints, 0, sizeof(hints)); 998706f2543Smrg hints.ai_flags = AI_CANONNAME; 999706f2543Smrg if (getaddrinfo(hname, NULL, &hints, &ai) == 0) { 1000706f2543Smrg hnameptr = ai->ai_canonname; 1001706f2543Smrg } else { 1002706f2543Smrg hnameptr = hname; 1003706f2543Smrg } 1004706f2543Smrg#else 1005706f2543Smrg host = _XGethostbyname(hname, hparams); 1006706f2543Smrg if (host == NULL) 1007706f2543Smrg hnameptr = hname; 1008706f2543Smrg else 1009706f2543Smrg hnameptr = host->h_name; 1010706f2543Smrg#endif 1011706f2543Smrg 1012706f2543Smrg len = strlen(hnameptr) + 1; 1013706f2543Smrg result = malloc(len + sizeof(AUTHORIZATION_NAME) + 4); 1014706f2543Smrg 1015706f2543Smrg p = result; 1016706f2543Smrg *p++ = sizeof(AUTHORIZATION_NAME) >> 8; 1017706f2543Smrg *p++ = sizeof(AUTHORIZATION_NAME) & 0xff; 1018706f2543Smrg *p++ = (len) >> 8; 1019706f2543Smrg *p++ = (len & 0xff); 1020706f2543Smrg 1021706f2543Smrg memmove(p, AUTHORIZATION_NAME, sizeof(AUTHORIZATION_NAME)); 1022706f2543Smrg p += sizeof(AUTHORIZATION_NAME); 1023706f2543Smrg memmove(p, hnameptr, len); 1024706f2543Smrg p += len; 1025706f2543Smrg#if defined(IPv6) && defined(AF_INET6) 1026706f2543Smrg if (ai) { 1027706f2543Smrg freeaddrinfo(ai); 1028706f2543Smrg } 1029706f2543Smrg#endif 1030706f2543Smrg } 1031706f2543Smrg *authlen = p - result; 1032706f2543Smrg *authorizations = result; 1033706f2543Smrg return 1; 1034706f2543Smrg#else /* TCPCONN */ 1035706f2543Smrg return 0; 1036706f2543Smrg#endif /* TCPCONN */ 1037706f2543Smrg} 1038706f2543Smrg 1039706f2543Smrgvoid * 1040706f2543SmrgXalloc(unsigned long amount) 1041706f2543Smrg{ 1042706f2543Smrg /* 1043706f2543Smrg * Xalloc used to return NULL when large amount of memory is requested. In 1044706f2543Smrg * order to catch the buggy callers this warning has been added, slated to 1045706f2543Smrg * removal by anyone who touches this code (or just looks at it) in 2011. 1046706f2543Smrg * 1047706f2543Smrg * -- Mikhail Gusarov 1048706f2543Smrg */ 1049706f2543Smrg if ((long)amount <= 0) 1050706f2543Smrg ErrorF("Warning: Xalloc: " 1051706f2543Smrg "requesting unpleasantly large amount of memory: %lu bytes.\n", 1052706f2543Smrg amount); 1053706f2543Smrg 1054706f2543Smrg return malloc(amount); 1055706f2543Smrg} 1056706f2543Smrg 1057706f2543Smrgvoid * 1058706f2543SmrgXNFalloc(unsigned long amount) 1059706f2543Smrg{ 1060706f2543Smrg void *ptr = malloc(amount); 1061706f2543Smrg if (!ptr) 1062706f2543Smrg FatalError("Out of memory"); 1063706f2543Smrg return ptr; 1064706f2543Smrg} 1065706f2543Smrg 1066706f2543Smrgvoid * 1067706f2543SmrgXcalloc(unsigned long amount) 1068706f2543Smrg{ 1069706f2543Smrg return calloc(1, amount); 1070706f2543Smrg} 1071706f2543Smrg 1072706f2543Smrgvoid * 1073706f2543SmrgXNFcalloc(unsigned long amount) 1074706f2543Smrg{ 1075706f2543Smrg void *ret = calloc(1, amount); 1076706f2543Smrg if (!ret) 1077706f2543Smrg FatalError("XNFcalloc: Out of memory"); 1078706f2543Smrg return ret; 1079706f2543Smrg} 1080706f2543Smrg 1081706f2543Smrgvoid * 1082706f2543SmrgXrealloc(void *ptr, unsigned long amount) 1083706f2543Smrg{ 1084706f2543Smrg /* 1085706f2543Smrg * Xrealloc used to return NULL when large amount of memory is requested. In 1086706f2543Smrg * order to catch the buggy callers this warning has been added, slated to 1087706f2543Smrg * removal by anyone who touches this code (or just looks at it) in 2011. 1088706f2543Smrg * 1089706f2543Smrg * -- Mikhail Gusarov 1090706f2543Smrg */ 1091706f2543Smrg if ((long)amount <= 0) 1092706f2543Smrg ErrorF("Warning: Xrealloc: " 1093706f2543Smrg "requesting unpleasantly large amount of memory: %lu bytes.\n", 1094706f2543Smrg amount); 1095706f2543Smrg 1096706f2543Smrg return realloc(ptr, amount); 1097706f2543Smrg} 1098706f2543Smrg 1099706f2543Smrgvoid * 1100706f2543SmrgXNFrealloc(void *ptr, unsigned long amount) 1101706f2543Smrg{ 1102706f2543Smrg void *ret = realloc(ptr, amount); 1103706f2543Smrg if (!ret) 1104706f2543Smrg FatalError("XNFrealloc: Out of memory"); 1105706f2543Smrg return ret; 1106706f2543Smrg} 1107706f2543Smrg 1108706f2543Smrgvoid 1109706f2543SmrgXfree(void *ptr) 1110706f2543Smrg{ 1111706f2543Smrg free(ptr); 1112706f2543Smrg} 1113706f2543Smrg 1114706f2543Smrg 1115706f2543Smrgchar * 1116706f2543SmrgXstrdup(const char *s) 1117706f2543Smrg{ 1118706f2543Smrg if (s == NULL) 1119706f2543Smrg return NULL; 1120706f2543Smrg return strdup(s); 1121706f2543Smrg} 1122706f2543Smrg 1123706f2543Smrgchar * 1124706f2543SmrgXNFstrdup(const char *s) 1125706f2543Smrg{ 1126706f2543Smrg char *ret; 1127706f2543Smrg 1128706f2543Smrg if (s == NULL) 1129706f2543Smrg return NULL; 1130706f2543Smrg 1131706f2543Smrg ret = strdup(s); 1132706f2543Smrg if (!ret) 1133706f2543Smrg FatalError("XNFstrdup: Out of memory"); 1134706f2543Smrg return ret; 1135706f2543Smrg} 1136706f2543Smrg 1137706f2543Smrgvoid 1138706f2543SmrgSmartScheduleStopTimer (void) 1139706f2543Smrg{ 1140706f2543Smrg struct itimerval timer; 1141706f2543Smrg 1142706f2543Smrg if (SmartScheduleDisable) 1143706f2543Smrg return; 1144706f2543Smrg timer.it_interval.tv_sec = 0; 1145706f2543Smrg timer.it_interval.tv_usec = 0; 1146706f2543Smrg timer.it_value.tv_sec = 0; 1147706f2543Smrg timer.it_value.tv_usec = 0; 1148706f2543Smrg (void) setitimer (ITIMER_REAL, &timer, 0); 1149706f2543Smrg} 1150706f2543Smrg 1151706f2543Smrgvoid 1152706f2543SmrgSmartScheduleStartTimer (void) 1153706f2543Smrg{ 1154706f2543Smrg struct itimerval timer; 1155706f2543Smrg 1156706f2543Smrg if (SmartScheduleDisable) 1157706f2543Smrg return; 1158706f2543Smrg timer.it_interval.tv_sec = 0; 1159706f2543Smrg timer.it_interval.tv_usec = SmartScheduleInterval * 1000; 1160706f2543Smrg timer.it_value.tv_sec = 0; 1161706f2543Smrg timer.it_value.tv_usec = SmartScheduleInterval * 1000; 1162706f2543Smrg setitimer (ITIMER_REAL, &timer, 0); 1163706f2543Smrg} 1164706f2543Smrg 1165706f2543Smrgstatic void 1166706f2543SmrgSmartScheduleTimer (int sig) 1167706f2543Smrg{ 1168706f2543Smrg SmartScheduleTime += SmartScheduleInterval; 1169706f2543Smrg} 1170706f2543Smrg 1171706f2543Smrgvoid 1172706f2543SmrgSmartScheduleInit (void) 1173706f2543Smrg{ 1174706f2543Smrg struct sigaction act; 1175706f2543Smrg 1176706f2543Smrg if (SmartScheduleDisable) 1177706f2543Smrg return; 1178706f2543Smrg 1179706f2543Smrg memset((char *) &act, 0, sizeof(struct sigaction)); 1180706f2543Smrg 1181706f2543Smrg /* Set up the timer signal function */ 1182706f2543Smrg act.sa_handler = SmartScheduleTimer; 1183706f2543Smrg sigemptyset (&act.sa_mask); 1184706f2543Smrg sigaddset (&act.sa_mask, SIGALRM); 1185706f2543Smrg if (sigaction (SIGALRM, &act, 0) < 0) 1186706f2543Smrg { 1187706f2543Smrg perror ("sigaction for smart scheduler"); 1188706f2543Smrg SmartScheduleDisable = TRUE; 1189706f2543Smrg } 1190706f2543Smrg} 1191706f2543Smrg 1192706f2543Smrg#ifdef SIG_BLOCK 1193706f2543Smrgstatic sigset_t PreviousSignalMask; 1194706f2543Smrgstatic int BlockedSignalCount; 1195706f2543Smrg#endif 1196706f2543Smrg 1197706f2543Smrgvoid 1198706f2543SmrgOsBlockSignals (void) 1199706f2543Smrg{ 1200706f2543Smrg#ifdef SIG_BLOCK 1201706f2543Smrg if (BlockedSignalCount++ == 0) 1202706f2543Smrg { 1203706f2543Smrg sigset_t set; 1204706f2543Smrg 1205706f2543Smrg sigemptyset (&set); 1206706f2543Smrg sigaddset (&set, SIGALRM); 1207706f2543Smrg sigaddset (&set, SIGVTALRM); 1208706f2543Smrg#ifdef SIGWINCH 1209706f2543Smrg sigaddset (&set, SIGWINCH); 1210706f2543Smrg#endif 1211706f2543Smrg#ifdef SIGIO 1212706f2543Smrg sigaddset (&set, SIGIO); 1213706f2543Smrg#endif 1214706f2543Smrg sigaddset (&set, SIGTSTP); 1215706f2543Smrg sigaddset (&set, SIGTTIN); 1216706f2543Smrg sigaddset (&set, SIGTTOU); 1217706f2543Smrg sigaddset (&set, SIGCHLD); 1218706f2543Smrg sigprocmask (SIG_BLOCK, &set, &PreviousSignalMask); 1219706f2543Smrg } 1220706f2543Smrg#endif 1221706f2543Smrg} 1222706f2543Smrg 1223706f2543Smrgvoid 1224706f2543SmrgOsReleaseSignals (void) 1225706f2543Smrg{ 1226706f2543Smrg#ifdef SIG_BLOCK 1227706f2543Smrg if (--BlockedSignalCount == 0) 1228706f2543Smrg { 1229706f2543Smrg sigprocmask (SIG_SETMASK, &PreviousSignalMask, 0); 1230706f2543Smrg } 1231706f2543Smrg#endif 1232706f2543Smrg} 1233706f2543Smrg 1234706f2543Smrg/* 1235706f2543Smrg * Pending signals may interfere with core dumping. Provide a 1236706f2543Smrg * mechanism to block signals when aborting. 1237706f2543Smrg */ 1238706f2543Smrg 1239706f2543Smrgvoid 1240706f2543SmrgOsAbort (void) 1241706f2543Smrg{ 1242706f2543Smrg#ifndef __APPLE__ 1243706f2543Smrg OsBlockSignals(); 1244706f2543Smrg#endif 1245706f2543Smrg abort(); 1246706f2543Smrg} 1247706f2543Smrg 1248706f2543Smrg#if !defined(WIN32) 1249706f2543Smrg/* 1250706f2543Smrg * "safer" versions of system(3), popen(3) and pclose(3) which give up 1251706f2543Smrg * all privs before running a command. 1252706f2543Smrg * 1253706f2543Smrg * This is based on the code in FreeBSD 2.2 libc. 1254706f2543Smrg * 1255706f2543Smrg * XXX It'd be good to redirect stderr so that it ends up in the log file 1256706f2543Smrg * as well. As it is now, xkbcomp messages don't end up in the log file. 1257706f2543Smrg */ 1258706f2543Smrg 1259706f2543Smrgint 1260706f2543SmrgSystem(char *command) 1261706f2543Smrg{ 1262706f2543Smrg int pid, p; 1263706f2543Smrg void (*csig)(int); 1264706f2543Smrg int status; 1265706f2543Smrg 1266706f2543Smrg if (!command) 1267706f2543Smrg return 1; 1268706f2543Smrg 1269706f2543Smrg csig = signal(SIGCHLD, SIG_DFL); 1270706f2543Smrg if (csig == SIG_ERR) { 1271706f2543Smrg perror("signal"); 1272706f2543Smrg return -1; 1273706f2543Smrg } 1274706f2543Smrg DebugF("System: `%s'\n", command); 1275706f2543Smrg 1276706f2543Smrg switch (pid = fork()) { 1277706f2543Smrg case -1: /* error */ 1278706f2543Smrg p = -1; 1279706f2543Smrg case 0: /* child */ 1280706f2543Smrg if (setgid(getgid()) == -1) 1281706f2543Smrg _exit(127); 1282706f2543Smrg if (setuid(getuid()) == -1) 1283706f2543Smrg _exit(127); 1284706f2543Smrg execl("/bin/sh", "sh", "-c", command, (char *)NULL); 1285706f2543Smrg _exit(127); 1286706f2543Smrg default: /* parent */ 1287706f2543Smrg do { 1288706f2543Smrg p = waitpid(pid, &status, 0); 1289706f2543Smrg } while (p == -1 && errno == EINTR); 1290706f2543Smrg 1291706f2543Smrg } 1292706f2543Smrg 1293706f2543Smrg if (signal(SIGCHLD, csig) == SIG_ERR) { 1294706f2543Smrg perror("signal"); 1295706f2543Smrg return -1; 1296706f2543Smrg } 1297706f2543Smrg 1298706f2543Smrg return p == -1 ? -1 : status; 1299706f2543Smrg} 1300706f2543Smrg 1301706f2543Smrgstatic struct pid { 1302706f2543Smrg struct pid *next; 1303706f2543Smrg FILE *fp; 1304706f2543Smrg int pid; 1305706f2543Smrg} *pidlist; 1306706f2543Smrg 1307706f2543SmrgOsSigHandlerPtr old_alarm = NULL; /* XXX horrible awful hack */ 1308706f2543Smrg 1309706f2543Smrgpointer 1310706f2543SmrgPopen(char *command, char *type) 1311706f2543Smrg{ 1312706f2543Smrg struct pid *cur; 1313706f2543Smrg FILE *iop; 1314706f2543Smrg int pdes[2], pid; 1315706f2543Smrg 1316706f2543Smrg if (command == NULL || type == NULL) 1317706f2543Smrg return NULL; 1318706f2543Smrg 1319706f2543Smrg if ((*type != 'r' && *type != 'w') || type[1]) 1320706f2543Smrg return NULL; 1321706f2543Smrg 1322706f2543Smrg if ((cur = malloc(sizeof(struct pid))) == NULL) 1323706f2543Smrg return NULL; 1324706f2543Smrg 1325706f2543Smrg if (pipe(pdes) < 0) { 1326706f2543Smrg free(cur); 1327706f2543Smrg return NULL; 1328706f2543Smrg } 1329706f2543Smrg 1330706f2543Smrg /* Ignore the smart scheduler while this is going on */ 1331706f2543Smrg old_alarm = OsSignal(SIGALRM, SIG_IGN); 1332706f2543Smrg if (old_alarm == SIG_ERR) { 1333706f2543Smrg close(pdes[0]); 1334706f2543Smrg close(pdes[1]); 1335706f2543Smrg free(cur); 1336706f2543Smrg perror("signal"); 1337706f2543Smrg return NULL; 1338706f2543Smrg } 1339706f2543Smrg 1340706f2543Smrg switch (pid = fork()) { 1341706f2543Smrg case -1: /* error */ 1342706f2543Smrg close(pdes[0]); 1343706f2543Smrg close(pdes[1]); 1344706f2543Smrg free(cur); 1345706f2543Smrg if (OsSignal(SIGALRM, old_alarm) == SIG_ERR) 1346706f2543Smrg perror("signal"); 1347706f2543Smrg return NULL; 1348706f2543Smrg case 0: /* child */ 1349706f2543Smrg if (setgid(getgid()) == -1) 1350706f2543Smrg _exit(127); 1351706f2543Smrg if (setuid(getuid()) == -1) 1352706f2543Smrg _exit(127); 1353706f2543Smrg if (*type == 'r') { 1354706f2543Smrg if (pdes[1] != 1) { 1355706f2543Smrg /* stdout */ 1356706f2543Smrg dup2(pdes[1], 1); 1357706f2543Smrg close(pdes[1]); 1358706f2543Smrg } 1359706f2543Smrg close(pdes[0]); 1360706f2543Smrg } else { 1361706f2543Smrg if (pdes[0] != 0) { 1362706f2543Smrg /* stdin */ 1363706f2543Smrg dup2(pdes[0], 0); 1364706f2543Smrg close(pdes[0]); 1365706f2543Smrg } 1366706f2543Smrg close(pdes[1]); 1367706f2543Smrg } 1368706f2543Smrg execl("/bin/sh", "sh", "-c", command, (char *)NULL); 1369706f2543Smrg _exit(127); 1370706f2543Smrg } 1371706f2543Smrg 1372706f2543Smrg /* Avoid EINTR during stdio calls */ 1373706f2543Smrg OsBlockSignals (); 1374706f2543Smrg 1375706f2543Smrg /* parent */ 1376706f2543Smrg if (*type == 'r') { 1377706f2543Smrg iop = fdopen(pdes[0], type); 1378706f2543Smrg close(pdes[1]); 1379706f2543Smrg } else { 1380706f2543Smrg iop = fdopen(pdes[1], type); 1381706f2543Smrg close(pdes[0]); 1382706f2543Smrg } 1383706f2543Smrg 1384706f2543Smrg cur->fp = iop; 1385706f2543Smrg cur->pid = pid; 1386706f2543Smrg cur->next = pidlist; 1387706f2543Smrg pidlist = cur; 1388706f2543Smrg 1389706f2543Smrg DebugF("Popen: `%s', fp = %p\n", command, iop); 1390706f2543Smrg 1391706f2543Smrg return iop; 1392706f2543Smrg} 1393706f2543Smrg 1394706f2543Smrg/* fopen that drops privileges */ 1395706f2543Smrgpointer 1396706f2543SmrgFopen(char *file, char *type) 1397706f2543Smrg{ 1398706f2543Smrg FILE *iop; 1399706f2543Smrg#ifndef HAS_SAVED_IDS_AND_SETEUID 1400706f2543Smrg struct pid *cur; 1401706f2543Smrg int pdes[2], pid; 1402706f2543Smrg 1403706f2543Smrg if (file == NULL || type == NULL) 1404706f2543Smrg return NULL; 1405706f2543Smrg 1406706f2543Smrg if ((*type != 'r' && *type != 'w') || type[1]) 1407706f2543Smrg return NULL; 1408706f2543Smrg 1409706f2543Smrg if ((cur = malloc(sizeof(struct pid))) == NULL) 1410706f2543Smrg return NULL; 1411706f2543Smrg 1412706f2543Smrg if (pipe(pdes) < 0) { 1413706f2543Smrg free(cur); 1414706f2543Smrg return NULL; 1415706f2543Smrg } 1416706f2543Smrg 1417706f2543Smrg switch (pid = fork()) { 1418706f2543Smrg case -1: /* error */ 1419706f2543Smrg close(pdes[0]); 1420706f2543Smrg close(pdes[1]); 1421706f2543Smrg free(cur); 1422706f2543Smrg return NULL; 1423706f2543Smrg case 0: /* child */ 1424706f2543Smrg if (setgid(getgid()) == -1) 1425706f2543Smrg _exit(127); 1426706f2543Smrg if (setuid(getuid()) == -1) 1427706f2543Smrg _exit(127); 1428706f2543Smrg if (*type == 'r') { 1429706f2543Smrg if (pdes[1] != 1) { 1430706f2543Smrg /* stdout */ 1431706f2543Smrg dup2(pdes[1], 1); 1432706f2543Smrg close(pdes[1]); 1433706f2543Smrg } 1434706f2543Smrg close(pdes[0]); 1435706f2543Smrg } else { 1436706f2543Smrg if (pdes[0] != 0) { 1437706f2543Smrg /* stdin */ 1438706f2543Smrg dup2(pdes[0], 0); 1439706f2543Smrg close(pdes[0]); 1440706f2543Smrg } 1441706f2543Smrg close(pdes[1]); 1442706f2543Smrg } 1443706f2543Smrg execl("/bin/cat", "cat", file, (char *)NULL); 1444706f2543Smrg _exit(127); 1445706f2543Smrg } 1446706f2543Smrg 1447706f2543Smrg /* Avoid EINTR during stdio calls */ 1448706f2543Smrg OsBlockSignals (); 1449706f2543Smrg 1450706f2543Smrg /* parent */ 1451706f2543Smrg if (*type == 'r') { 1452706f2543Smrg iop = fdopen(pdes[0], type); 1453706f2543Smrg close(pdes[1]); 1454706f2543Smrg } else { 1455706f2543Smrg iop = fdopen(pdes[1], type); 1456706f2543Smrg close(pdes[0]); 1457706f2543Smrg } 1458706f2543Smrg 1459706f2543Smrg cur->fp = iop; 1460706f2543Smrg cur->pid = pid; 1461706f2543Smrg cur->next = pidlist; 1462706f2543Smrg pidlist = cur; 1463706f2543Smrg 1464706f2543Smrg DebugF("Fopen(%s), fp = %p\n", file, iop); 1465706f2543Smrg 1466706f2543Smrg return iop; 1467706f2543Smrg#else 1468706f2543Smrg int ruid, euid; 1469706f2543Smrg 1470706f2543Smrg ruid = getuid(); 1471706f2543Smrg euid = geteuid(); 1472706f2543Smrg 1473706f2543Smrg if (seteuid(ruid) == -1) { 1474706f2543Smrg return NULL; 1475706f2543Smrg } 1476706f2543Smrg iop = fopen(file, type); 1477706f2543Smrg 1478706f2543Smrg if (seteuid(euid) == -1) { 1479706f2543Smrg fclose(iop); 1480706f2543Smrg return NULL; 1481706f2543Smrg } 1482706f2543Smrg return iop; 1483706f2543Smrg#endif /* HAS_SAVED_IDS_AND_SETEUID */ 1484706f2543Smrg} 1485706f2543Smrg 1486706f2543Smrgint 1487706f2543SmrgPclose(pointer iop) 1488706f2543Smrg{ 1489706f2543Smrg struct pid *cur, *last; 1490706f2543Smrg int pstat; 1491706f2543Smrg int pid; 1492706f2543Smrg 1493706f2543Smrg DebugF("Pclose: fp = %p\n", iop); 1494706f2543Smrg fclose(iop); 1495706f2543Smrg 1496706f2543Smrg for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next) 1497706f2543Smrg if (cur->fp == iop) 1498706f2543Smrg break; 1499706f2543Smrg if (cur == NULL) 1500706f2543Smrg return -1; 1501706f2543Smrg 1502706f2543Smrg do { 1503706f2543Smrg pid = waitpid(cur->pid, &pstat, 0); 1504706f2543Smrg } while (pid == -1 && errno == EINTR); 1505706f2543Smrg 1506706f2543Smrg if (last == NULL) 1507706f2543Smrg pidlist = cur->next; 1508706f2543Smrg else 1509706f2543Smrg last->next = cur->next; 1510706f2543Smrg free(cur); 1511706f2543Smrg 1512706f2543Smrg /* allow EINTR again */ 1513706f2543Smrg OsReleaseSignals (); 1514706f2543Smrg 1515706f2543Smrg if (old_alarm && OsSignal(SIGALRM, old_alarm) == SIG_ERR) { 1516706f2543Smrg perror("signal"); 1517706f2543Smrg return -1; 1518706f2543Smrg } 1519706f2543Smrg 1520706f2543Smrg return pid == -1 ? -1 : pstat; 1521706f2543Smrg} 1522706f2543Smrg 1523706f2543Smrgint 1524706f2543SmrgFclose(pointer iop) 1525706f2543Smrg{ 1526706f2543Smrg#ifdef HAS_SAVED_IDS_AND_SETEUID 1527706f2543Smrg return fclose(iop); 1528706f2543Smrg#else 1529706f2543Smrg return Pclose(iop); 1530706f2543Smrg#endif 1531706f2543Smrg} 1532706f2543Smrg 1533706f2543Smrg#endif /* !WIN32 */ 1534706f2543Smrg 1535706f2543Smrg 1536706f2543Smrg/* 1537706f2543Smrg * CheckUserParameters: check for long command line arguments and long 1538706f2543Smrg * environment variables. By default, these checks are only done when 1539706f2543Smrg * the server's euid != ruid. In 3.3.x, these checks were done in an 1540706f2543Smrg * external wrapper utility. 1541706f2543Smrg */ 1542706f2543Smrg 1543706f2543Smrg/* Consider LD* variables insecure? */ 1544706f2543Smrg#ifndef REMOVE_ENV_LD 1545706f2543Smrg#define REMOVE_ENV_LD 1 1546706f2543Smrg#endif 1547706f2543Smrg 1548706f2543Smrg/* Remove long environment variables? */ 1549706f2543Smrg#ifndef REMOVE_LONG_ENV 1550706f2543Smrg#define REMOVE_LONG_ENV 1 1551706f2543Smrg#endif 1552706f2543Smrg 1553706f2543Smrg/* 1554706f2543Smrg * Disallow stdout or stderr as pipes? It's possible to block the X server 1555706f2543Smrg * when piping stdout+stderr to a pipe. 1556706f2543Smrg * 1557706f2543Smrg * Don't enable this because it looks like it's going to cause problems. 1558706f2543Smrg */ 1559706f2543Smrg#ifndef NO_OUTPUT_PIPES 1560706f2543Smrg#define NO_OUTPUT_PIPES 0 1561706f2543Smrg#endif 1562706f2543Smrg 1563706f2543Smrg 1564706f2543Smrg/* Check args and env only if running setuid (euid == 0 && euid != uid) ? */ 1565706f2543Smrg#ifndef CHECK_EUID 1566706f2543Smrg#ifndef WIN32 1567706f2543Smrg#define CHECK_EUID 1 1568706f2543Smrg#else 1569706f2543Smrg#define CHECK_EUID 0 1570706f2543Smrg#endif 1571706f2543Smrg#endif 1572706f2543Smrg 1573706f2543Smrg/* 1574706f2543Smrg * Maybe the locale can be faked to make isprint(3) report that everything 1575706f2543Smrg * is printable? Avoid it by default. 1576706f2543Smrg */ 1577706f2543Smrg#ifndef USE_ISPRINT 1578706f2543Smrg#define USE_ISPRINT 0 1579706f2543Smrg#endif 1580706f2543Smrg 1581706f2543Smrg#define MAX_ARG_LENGTH 128 1582706f2543Smrg#define MAX_ENV_LENGTH 256 1583706f2543Smrg#define MAX_ENV_PATH_LENGTH 2048 /* Limit for *PATH and TERMCAP */ 1584706f2543Smrg 1585706f2543Smrg#if USE_ISPRINT 1586706f2543Smrg#include <ctype.h> 1587706f2543Smrg#define checkPrintable(c) isprint(c) 1588706f2543Smrg#else 1589706f2543Smrg#define checkPrintable(c) (((c) & 0x7f) >= 0x20 && ((c) & 0x7f) != 0x7f) 1590706f2543Smrg#endif 1591706f2543Smrg 1592706f2543Smrgenum BadCode { 1593706f2543Smrg NotBad = 0, 1594706f2543Smrg UnsafeArg, 1595706f2543Smrg ArgTooLong, 1596706f2543Smrg UnprintableArg, 1597706f2543Smrg EnvTooLong, 1598706f2543Smrg OutputIsPipe, 1599706f2543Smrg InternalError 1600706f2543Smrg}; 1601706f2543Smrg 1602706f2543Smrg#if defined(VENDORSUPPORT) 1603706f2543Smrg#define BUGADDRESS VENDORSUPPORT 1604706f2543Smrg#elif defined(BUILDERADDR) 1605706f2543Smrg#define BUGADDRESS BUILDERADDR 1606706f2543Smrg#else 1607706f2543Smrg#define BUGADDRESS "xorg@freedesktop.org" 1608706f2543Smrg#endif 1609706f2543Smrg 1610706f2543Smrgvoid 1611706f2543SmrgCheckUserParameters(int argc, char **argv, char **envp) 1612706f2543Smrg{ 1613706f2543Smrg enum BadCode bad = NotBad; 1614706f2543Smrg int i = 0, j; 1615706f2543Smrg char *a, *e = NULL; 1616706f2543Smrg 1617706f2543Smrg#if CHECK_EUID 1618706f2543Smrg if (geteuid() == 0 && getuid() != geteuid()) 1619706f2543Smrg#endif 1620706f2543Smrg { 1621706f2543Smrg /* Check each argv[] */ 1622706f2543Smrg for (i = 1; i < argc; i++) { 1623706f2543Smrg if (strcmp(argv[i], "-fp") == 0) 1624706f2543Smrg { 1625706f2543Smrg i++; /* continue with next argument. skip the length check */ 1626706f2543Smrg if (i >= argc) 1627706f2543Smrg break; 1628706f2543Smrg } else 1629706f2543Smrg { 1630706f2543Smrg if (strlen(argv[i]) > MAX_ARG_LENGTH) { 1631706f2543Smrg bad = ArgTooLong; 1632706f2543Smrg break; 1633706f2543Smrg } 1634706f2543Smrg } 1635706f2543Smrg a = argv[i]; 1636706f2543Smrg while (*a) { 1637706f2543Smrg if (checkPrintable(*a) == 0) { 1638706f2543Smrg bad = UnprintableArg; 1639706f2543Smrg break; 1640706f2543Smrg } 1641706f2543Smrg a++; 1642706f2543Smrg } 1643706f2543Smrg if (bad) 1644706f2543Smrg break; 1645706f2543Smrg } 1646706f2543Smrg if (!bad) { 1647706f2543Smrg /* Check each envp[] */ 1648706f2543Smrg for (i = 0; envp[i]; i++) { 1649706f2543Smrg 1650706f2543Smrg /* Check for bad environment variables and values */ 1651706f2543Smrg#if REMOVE_ENV_LD 1652706f2543Smrg while (envp[i] && (strncmp(envp[i], "LD", 2) == 0)) { 1653706f2543Smrg for (j = i; envp[j]; j++) { 1654706f2543Smrg envp[j] = envp[j+1]; 1655706f2543Smrg } 1656706f2543Smrg } 1657706f2543Smrg#endif 1658706f2543Smrg if (envp[i] && (strlen(envp[i]) > MAX_ENV_LENGTH)) { 1659706f2543Smrg#if REMOVE_LONG_ENV 1660706f2543Smrg for (j = i; envp[j]; j++) { 1661706f2543Smrg envp[j] = envp[j+1]; 1662706f2543Smrg } 1663706f2543Smrg i--; 1664706f2543Smrg#else 1665706f2543Smrg char *eq; 1666706f2543Smrg int len; 1667706f2543Smrg 1668706f2543Smrg eq = strchr(envp[i], '='); 1669706f2543Smrg if (!eq) 1670706f2543Smrg continue; 1671706f2543Smrg len = eq - envp[i]; 1672706f2543Smrg e = malloc(len + 1); 1673706f2543Smrg if (!e) { 1674706f2543Smrg bad = InternalError; 1675706f2543Smrg break; 1676706f2543Smrg } 1677706f2543Smrg strncpy(e, envp[i], len); 1678706f2543Smrg e[len] = 0; 1679706f2543Smrg if (len >= 4 && 1680706f2543Smrg (strcmp(e + len - 4, "PATH") == 0 || 1681706f2543Smrg strcmp(e, "TERMCAP") == 0)) { 1682706f2543Smrg if (strlen(envp[i]) > MAX_ENV_PATH_LENGTH) { 1683706f2543Smrg bad = EnvTooLong; 1684706f2543Smrg break; 1685706f2543Smrg } else { 1686706f2543Smrg free(e); 1687706f2543Smrg } 1688706f2543Smrg } else { 1689706f2543Smrg bad = EnvTooLong; 1690706f2543Smrg break; 1691706f2543Smrg } 1692706f2543Smrg#endif 1693706f2543Smrg } 1694706f2543Smrg } 1695706f2543Smrg } 1696706f2543Smrg#if NO_OUTPUT_PIPES 1697706f2543Smrg if (!bad) { 1698706f2543Smrg struct stat buf; 1699706f2543Smrg 1700706f2543Smrg if (fstat(fileno(stdout), &buf) == 0 && S_ISFIFO(buf.st_mode)) 1701706f2543Smrg bad = OutputIsPipe; 1702706f2543Smrg if (fstat(fileno(stderr), &buf) == 0 && S_ISFIFO(buf.st_mode)) 1703706f2543Smrg bad = OutputIsPipe; 1704706f2543Smrg } 1705706f2543Smrg#endif 1706706f2543Smrg } 1707706f2543Smrg switch (bad) { 1708706f2543Smrg case NotBad: 1709706f2543Smrg return; 1710706f2543Smrg case UnsafeArg: 1711706f2543Smrg ErrorF("Command line argument number %d is unsafe\n", i); 1712706f2543Smrg break; 1713706f2543Smrg case ArgTooLong: 1714706f2543Smrg ErrorF("Command line argument number %d is too long\n", i); 1715706f2543Smrg break; 1716706f2543Smrg case UnprintableArg: 1717706f2543Smrg ErrorF("Command line argument number %d contains unprintable" 1718706f2543Smrg " characters\n", i); 1719706f2543Smrg break; 1720706f2543Smrg case EnvTooLong: 1721706f2543Smrg ErrorF("Environment variable `%s' is too long\n", e); 1722706f2543Smrg break; 1723706f2543Smrg case OutputIsPipe: 1724706f2543Smrg ErrorF("Stdout and/or stderr is a pipe\n"); 1725706f2543Smrg break; 1726706f2543Smrg case InternalError: 1727706f2543Smrg ErrorF("Internal Error\n"); 1728706f2543Smrg break; 1729706f2543Smrg default: 1730706f2543Smrg ErrorF("Unknown error\n"); 1731706f2543Smrg break; 1732706f2543Smrg } 1733706f2543Smrg FatalError("X server aborted because of unsafe environment\n"); 1734706f2543Smrg} 1735706f2543Smrg 1736706f2543Smrg/* 1737706f2543Smrg * CheckUserAuthorization: check if the user is allowed to start the 1738706f2543Smrg * X server. This usually means some sort of PAM checking, and it is 1739706f2543Smrg * usually only done for setuid servers (uid != euid). 1740706f2543Smrg */ 1741706f2543Smrg 1742706f2543Smrg#ifdef USE_PAM 1743706f2543Smrg#include <security/pam_appl.h> 1744706f2543Smrg#include <security/pam_misc.h> 1745706f2543Smrg#include <pwd.h> 1746706f2543Smrg#endif /* USE_PAM */ 1747706f2543Smrg 1748706f2543Smrgvoid 1749706f2543SmrgCheckUserAuthorization(void) 1750706f2543Smrg{ 1751706f2543Smrg#ifdef USE_PAM 1752706f2543Smrg static struct pam_conv conv = { 1753706f2543Smrg misc_conv, 1754706f2543Smrg NULL 1755706f2543Smrg }; 1756706f2543Smrg 1757706f2543Smrg pam_handle_t *pamh = NULL; 1758706f2543Smrg struct passwd *pw; 1759706f2543Smrg int retval; 1760706f2543Smrg 1761706f2543Smrg if (getuid() != geteuid()) { 1762706f2543Smrg pw = getpwuid(getuid()); 1763706f2543Smrg if (pw == NULL) 1764706f2543Smrg FatalError("getpwuid() failed for uid %d\n", getuid()); 1765706f2543Smrg 1766706f2543Smrg retval = pam_start("xserver", pw->pw_name, &conv, &pamh); 1767706f2543Smrg if (retval != PAM_SUCCESS) 1768706f2543Smrg FatalError("pam_start() failed.\n" 1769706f2543Smrg "\tMissing or mangled PAM config file or module?\n"); 1770706f2543Smrg 1771706f2543Smrg retval = pam_authenticate(pamh, 0); 1772706f2543Smrg if (retval != PAM_SUCCESS) { 1773706f2543Smrg pam_end(pamh, retval); 1774706f2543Smrg FatalError("PAM authentication failed, cannot start X server.\n" 1775706f2543Smrg "\tPerhaps you do not have console ownership?\n"); 1776706f2543Smrg } 1777706f2543Smrg 1778706f2543Smrg retval = pam_acct_mgmt(pamh, 0); 1779706f2543Smrg if (retval != PAM_SUCCESS) { 1780706f2543Smrg pam_end(pamh, retval); 1781706f2543Smrg FatalError("PAM authentication failed, cannot start X server.\n" 1782706f2543Smrg "\tPerhaps you do not have console ownership?\n"); 1783706f2543Smrg } 1784706f2543Smrg 1785706f2543Smrg /* this is not a session, so do not do session management */ 1786706f2543Smrg pam_end(pamh, PAM_SUCCESS); 1787706f2543Smrg } 1788706f2543Smrg#endif 1789706f2543Smrg} 1790706f2543Smrg 1791706f2543Smrg/* 1792706f2543Smrg * Tokenize a string into a NULL terminated array of strings. Always returns 1793706f2543Smrg * an allocated array unless an error occurs. 1794706f2543Smrg */ 1795706f2543Smrgchar** 1796706f2543Smrgxstrtokenize(const char *str, const char *separators) 1797706f2543Smrg{ 1798706f2543Smrg char **list, **nlist; 1799706f2543Smrg char *tok, *tmp; 1800706f2543Smrg unsigned num = 0, n; 1801706f2543Smrg 1802706f2543Smrg if (!str) 1803706f2543Smrg return NULL; 1804706f2543Smrg list = calloc(1, sizeof(*list)); 1805706f2543Smrg if (!list) 1806706f2543Smrg return NULL; 1807706f2543Smrg tmp = strdup(str); 1808706f2543Smrg if (!tmp) 1809706f2543Smrg goto error; 1810706f2543Smrg for (tok = strtok(tmp, separators); tok; tok = strtok(NULL, separators)) { 1811706f2543Smrg nlist = realloc(list, (num + 2) * sizeof(*list)); 1812706f2543Smrg if (!nlist) 1813706f2543Smrg goto error; 1814706f2543Smrg list = nlist; 1815706f2543Smrg list[num] = strdup(tok); 1816706f2543Smrg if (!list[num]) 1817706f2543Smrg goto error; 1818706f2543Smrg list[++num] = NULL; 1819706f2543Smrg } 1820706f2543Smrg free(tmp); 1821706f2543Smrg return list; 1822706f2543Smrg 1823706f2543Smrgerror: 1824706f2543Smrg free(tmp); 1825706f2543Smrg for (n = 0; n < num; n++) 1826706f2543Smrg free(list[n]); 1827706f2543Smrg free(list); 1828706f2543Smrg return NULL; 1829706f2543Smrg} 1830