summaryrefslogtreecommitdiff
path: root/xc/programs/Xserver/os/utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'xc/programs/Xserver/os/utils.c')
-rw-r--r--xc/programs/Xserver/os/utils.c677
1 files changed, 508 insertions, 169 deletions
diff --git a/xc/programs/Xserver/os/utils.c b/xc/programs/Xserver/os/utils.c
index de6d851c7..14015a91c 100644
--- a/xc/programs/Xserver/os/utils.c
+++ b/xc/programs/Xserver/os/utils.c
@@ -1,9 +1,13 @@
-/* $TOG: utils.c /main/138 1998/04/22 16:32:51 msr $ */
+/* $Xorg: utils.c,v 1.5 2001/02/09 02:05:24 xorgcvs Exp $ */
/*
Copyright 1987, 1998 The Open Group
-All Rights Reserved.
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
@@ -45,9 +49,14 @@ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $XFree86: xc/programs/Xserver/os/utils.c,v 3.52 1999/05/15 12:10:35 dawes Exp $ */
+/* $XFree86: xc/programs/Xserver/os/utils.c,v 3.81 2002/01/16 20:39:51 dawes Exp $ */
-#ifdef WIN32
+#ifdef __CYGWIN__
+#include <stdlib.h>
+#include <signal.h>
+#endif
+
+#if defined(WIN32) && !defined(__CYGWIN__)
#include <X11/Xwinsock.h>
#endif
#include "Xos.h"
@@ -55,6 +64,8 @@ OR PERFORMANCE OF THIS SOFTWARE.
#include "misc.h"
#include "X.h"
#include "input.h"
+#include "dixfont.h"
+#include "osdep.h"
#ifdef X_POSIX_C_SOURCE
#define _POSIX_C_SOURCE X_POSIX_C_SOURCE
#include <signal.h>
@@ -69,39 +80,20 @@ OR PERFORMANCE OF THIS SOFTWARE.
#endif
#endif
#include <sys/wait.h>
-#if !defined(SYSV) && !defined(AMOEBA) && !defined(_MINIX) && !defined(WIN32) && !defined(Lynx) && !defined(QNX)
+#if !defined(SYSV) && !defined(WIN32) && !defined(Lynx) && !defined(QNX4)
#include <sys/resource.h>
#endif
#include <time.h>
#include <sys/stat.h>
#include <ctype.h> /* for isspace */
-#if NeedVarargsPrototypes
#include <stdarg.h>
-#endif
#if defined(DGUX)
#include <sys/resource.h>
#include <netdb.h>
#endif
-#ifdef AMOEBA
-#include "osdep.h"
-#include <amoeba.h>
-#include <module/mutex.h>
-
-static mutex print_lock;
-#endif
-
-#if defined(__STDC__) || defined(AMOEBA)
-/* DHD: SVR4.0 has a prototype for abs() in stdlib.h */
-/* DHD: might be better to move this include higher up? */
-#ifdef abs
-#undef abs
-#endif
-#ifndef NOSTDHDRS
#include <stdlib.h> /* for malloc() */
-#endif
-#endif
#if defined(TCPCONN) || defined(STREAMSCONN)
# ifndef WIN32
@@ -111,14 +103,28 @@ static mutex print_lock;
#include "opaque.h"
+#ifdef SMART_SCHEDULE
+#include "dixstruct.h"
+#endif
+
+#ifdef XKB
+#include "XKBsrv.h"
+#endif
+#ifdef XCSECURITY
+#define _SECURITY_SERVER
+#include "security.h"
+#endif
+
+#define X_INCLUDE_NETDB_H
+#include <X11/Xos_r.h>
+
#include <errno.h>
-extern int errno;
Bool CoreDump;
Bool noTestExtensions;
-Bool noPanoramiXExtension = TRUE;
#ifdef PANORAMIX
+Bool noPanoramiXExtension = TRUE;
Bool PanoramiXVisibilityNotifySent = FALSE;
Bool PanoramiXMapped = FALSE;
Bool PanoramiXWindowExposureSent = FALSE;
@@ -147,10 +153,8 @@ extern int SelectWaitTime;
#ifdef MEMBUG
#define MEM_FAIL_SCALE 100000
long Memory_fail = 0;
-#ifdef linux
#include <stdlib.h> /* for random() */
#endif
-#endif
#ifdef sgi
int userdefinedfontpath = 0;
@@ -177,7 +181,7 @@ OsSignal(sig, handler)
return oact.sa_handler;
#endif
}
-
+
#ifdef SERVER_LOCK
/*
* Explicit support for a server lock file like the ones used for UUCP.
@@ -201,10 +205,6 @@ OsSignal(sig, handler)
#include <sys/param.h>
#endif
-#ifdef _MINIX
-#include <limits.h> /* For PATH_MAX */
-#endif
-
#ifdef __EMX__
#define link rename
#endif
@@ -226,6 +226,7 @@ OsSignal(sig, handler)
static Bool StillLocking = FALSE;
static char LockFile[PATH_MAX];
+static Bool nolock = FALSE;
/*
* LockServer --
@@ -236,7 +237,6 @@ static char LockFile[PATH_MAX];
void
LockServer()
{
-#ifndef AMOEBA
char tmp[PATH_MAX], pid_str[12];
int lfd, i, haslock, l_pid, t;
char *tmppath = NULL;
@@ -291,7 +291,7 @@ LockServer()
}
if (lfd < 0)
FatalError("Could not create lock file in %s\n", tmp);
- (void) sprintf(pid_str, "%10d\n", getpid());
+ (void) sprintf(pid_str, "%10ld\n", (long)getpid());
(void) write(lfd, pid_str, 11);
#ifndef __EMX__
#ifndef USE_CHMOD
@@ -365,7 +365,6 @@ LockServer()
if (!haslock)
FatalError("Could not create server lock file: %s\n", LockFile);
StillLocking = FALSE;
-#endif /* !AMOEBA */
}
/*
@@ -375,7 +374,6 @@ LockServer()
void
UnlockServer()
{
-#ifndef AMOEBA
if (nolock) return;
if (!StillLocking){
@@ -385,8 +383,6 @@ UnlockServer()
#endif /* __EMX__ */
(void) unlink(LockFile);
}
-#endif
-
}
#endif /* SERVER_LOCK */
@@ -397,6 +393,8 @@ SIGVAL
AutoResetServer (sig)
int sig;
{
+ int olderrno = errno;
+
dispatchException |= DE_RESET;
isItTimeToYield = TRUE;
#ifdef GPROF
@@ -406,9 +404,7 @@ AutoResetServer (sig)
#if defined(SYSV) && defined(X_NOT_POSIX)
OsSignal (SIGHUP, AutoResetServer);
#endif
-#ifdef AMOEBA
- WakeUpMainThread();
-#endif
+ errno = olderrno;
}
/* Force connections to close and then exit on SIGTERM, SIGINT */
@@ -418,15 +414,15 @@ SIGVAL
GiveUp(sig)
int sig;
{
+ int olderrno = errno;
+
dispatchException |= DE_TERMINATE;
isItTimeToYield = TRUE;
#if defined(SYSV) && defined(X_NOT_POSIX)
if (sig)
OsSignal(sig, SIG_IGN);
#endif
-#ifdef AMOEBA
- WakeUpMainThread();
-#endif
+ errno = olderrno;
}
#if __GNUC__
@@ -439,9 +435,6 @@ AbortServer()
OsCleanup();
AbortDDX();
fflush(stderr);
-#ifdef AMOEBA
- IOPCleanUp();
-#endif
if (CoreDump)
abort();
exit (1);
@@ -451,27 +444,17 @@ void
Error(str)
char *str;
{
-#ifdef AMOEBA
- mu_lock(&print_lock);
-#endif
perror(str);
-#ifdef AMOEBA
- mu_unlock(&print_lock);
-#endif
}
#ifndef DDXTIME
CARD32
GetTimeInMillis()
{
-#ifndef AMOEBA
struct timeval tp;
X_GETTIMEOFDAY(&tp);
return(tp.tv_sec * 1000) + (tp.tv_usec / 1000);
-#else
- return sys_milli();
-#endif
}
#endif
@@ -504,11 +487,7 @@ AdjustWaitForDelay (waitTime, newdelay)
void UseMsg()
{
#if !defined(AIXrt) && !defined(AIX386)
-#ifndef AMOEBA
ErrorF("use: X [:<display>] [option]\n");
-#else
- ErrorF("use: X [[<host>]:<display>] [option]\n");
-#endif
ErrorF("-a # mouse acceleration (pixels)\n");
ErrorF("-ac disable access control restrictions\n");
#ifdef MEMBUG
@@ -517,6 +496,7 @@ void UseMsg()
ErrorF("-audit int set audit trail level\n");
ErrorF("-auth file select authorization file\n");
ErrorF("bc enable bug compatibility\n");
+ ErrorF("-br create root window with black background\n");
ErrorF("+bs enable any backing store support\n");
ErrorF("-bs disable any backing store support\n");
ErrorF("-c turns off key-click\n");
@@ -567,9 +547,6 @@ void UseMsg()
#endif
ErrorF("-su disable any save under support\n");
ErrorF("-t # mouse threshold (pixels)\n");
-#ifdef AMOEBA
- ErrorF("-tcp capability specify TCP/IP server capability\n");
-#endif
ErrorF("-terminate terminate at server reset\n");
ErrorF("-to # connection time out\n");
ErrorF("-tst disable testing extensions\n");
@@ -623,10 +600,6 @@ char *argv[];
{
int i, skip;
-#ifdef AMOEBA
- mu_init(&print_lock);
-#endif
-
defaultKeyboardControl.autoRepeat = TRUE;
#ifdef PART_NET
@@ -651,27 +624,6 @@ char *argv[];
exit(1);
}
}
-#ifdef AMOEBA
- else if (strchr(argv[i], ':') != NULL) {
- char *p;
-
- XServerHostName = argv[i];
- if ((p = strchr(argv[i], ':')) != NULL) {
- *p++ = '\0';
- display = p;
- if( ! VerifyDisplayName( display ) ) {
- ErrorF("Bad display name: %s\n", display);
- UseMsg();
- exit(1);
- }
- }
- } else if (strcmp( argv[i], "-tcp") == 0) {
- if (++i < argc)
- XTcpServerName = argv[i];
- else
- UseMsg();
- }
-#endif /* AMOEBA */
else if ( strcmp( argv[i], "-a") == 0)
{
if(++i < argc)
@@ -708,6 +660,8 @@ char *argv[];
}
else if ( strcmp( argv[i], "bc") == 0)
permitOldBugs = TRUE;
+ else if ( strcmp( argv[i], "-br") == 0)
+ blackRoot = TRUE;
else if ( strcmp( argv[i], "+bs") == 0)
enableBackingStore = TRUE;
else if ( strcmp( argv[i], "-bs") == 0)
@@ -840,7 +794,7 @@ char *argv[];
#ifdef SERVER_LOCK
else if ( strcmp ( argv[i], "-nolock") == 0)
{
-#if !defined(WIN32) && !defined(__EMX__)
+#if !defined(WIN32) && !defined(__EMX__) && !defined(__CYGWIN__)
if (getuid() != 0)
ErrorF("Warning: the -nolock option can only be used by root\n");
else
@@ -984,6 +938,31 @@ char *argv[];
SyncOn++;
}
#endif
+#ifdef SMART_SCHEDULE
+ else if ( strcmp( argv[i], "-dumbSched") == 0)
+ {
+ SmartScheduleDisable = TRUE;
+ }
+ else if ( strcmp( argv[i], "-schedInterval") == 0)
+ {
+ if (++i < argc)
+ {
+ SmartScheduleInterval = atoi(argv[i]);
+ SmartScheduleSlice = SmartScheduleInterval;
+ }
+ else
+ UseMsg();
+ }
+ else if ( strcmp( argv[i], "-schedMax") == 0)
+ {
+ if (++i < argc)
+ {
+ SmartScheduleMaxSlice = atoi(argv[i]);
+ }
+ else
+ UseMsg();
+ }
+#endif
else
{
ErrorF("Unrecognized option: %s\n", argv[i]);
@@ -1092,7 +1071,7 @@ ExpandCommandLine(pargc, pargv)
{
int i;
-#if !defined(WIN32) && !defined(__EMX__)
+#if !defined(WIN32) && !defined(__EMX__) && !defined(__CYGWIN__)
if (getuid() != geteuid())
return;
#endif
@@ -1129,9 +1108,12 @@ pointer client;
char hname[1024], *hnameptr;
struct hostent *host;
int len;
+#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
+ _Xgethostbynameparams hparams;
+#endif
gethostname(hname, 1024);
- host = gethostbyname(hname);
+ host = _XGethostbyname(hname, hparams);
if (host == NULL)
hnameptr = hname;
else
@@ -1174,9 +1156,6 @@ void *
Xalloc (amount)
unsigned long amount;
{
-#if !defined(__STDC__) && !defined(AMOEBA)
- char *malloc();
-#endif
register pointer ptr;
if ((long)amount <= 0) {
@@ -1206,9 +1185,6 @@ void *
XNFalloc (amount)
unsigned long amount;
{
-#if !defined(__STDC__) && !defined(AMOEBA)
- char *malloc();
-#endif
register pointer ptr;
if ((long)amount <= 0)
@@ -1268,11 +1244,6 @@ Xrealloc (ptr, amount)
register pointer ptr;
unsigned long amount;
{
-#if !defined(__STDC__) && !defined(AMOEBA)
- char *malloc();
- char *realloc();
-#endif
-
#ifdef MEMBUG
if (!Must_have_memory && Memory_fail &&
((random() % MEM_FAIL_SCALE) < Memory_fail))
@@ -1374,13 +1345,9 @@ XNFstrdup(const char *s)
void
AuditPrefix(f)
- char *f;
+ const char *f;
{
-#ifdef X_NOT_STDC_ENV
- long tm;
-#else
time_t tm;
-#endif
char *autime, *s;
if (*f != ' ')
{
@@ -1396,59 +1363,32 @@ AuditPrefix(f)
}
}
-/*VARARGS1*/
void
-AuditF(
-#if NeedVarargsPrototypes
- const char * f, ...)
-#else
- f, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9) /* limit of ten args */
- char *f;
- char *s0, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9;
-#endif
+AuditF(const char * f, ...)
{
-#if NeedVarargsPrototypes
va_list args;
-#endif
AuditPrefix(f);
-#if NeedVarargsPrototypes
va_start(args, f);
VErrorF(f, args);
va_end(args);
-#else
- ErrorF(f, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9);
-#endif
}
-/*VARARGS1*/
void
-FatalError(
-#if NeedVarargsPrototypes
- const char *f, ...)
-#else
-f, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9) /* limit of ten args */
- const char *f;
- char *s0, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9;
-#endif
+FatalError(const char *f, ...)
{
-#if NeedVarargsPrototypes
va_list args;
-#endif
- static beenhere = 0;
+ static Bool beenhere = FALSE;
if (beenhere)
ErrorF("\nFatalError re-entered, aborting\n");
else
ErrorF("\nFatal server error:\n");
-#if NeedVarargsPrototypes
+
va_start(args, f);
VErrorF(f, args);
va_end(args);
-#else
- ErrorF(f, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9);
-#endif
ErrorF("\n");
#ifdef DDXOSFATALERROR
if (!beenhere)
@@ -1457,14 +1397,14 @@ f, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9) /* limit of ten args */
#ifdef ABORTONFATALERROR
abort();
#endif
- if (!beenhere)
+ if (!beenhere) {
+ beenhere = TRUE;
AbortServer();
- else
+ } else
abort();
/*NOTREACHED*/
}
-#if NeedVarargsPrototypes
void
VErrorF(f, args)
const char *f;
@@ -1496,37 +1436,160 @@ VFatalError(const char *msg, va_list args)
AbortServer();
/*NOTREACHED*/
}
-#endif /* NeedVarargsPrototypes */
-/*VARARGS1*/
void
-ErrorF(
-#if NeedVarargsPrototypes
- const char * f, ...)
-#else
- f, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9) /* limit of ten args */
- char *f;
- char *s0, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9;
-#endif
+ErrorF(const char * f, ...)
{
-#if NeedVarargsPrototypes
va_list args;
va_start(args, f);
VErrorF(f, args);
va_end(args);
+}
+
+#ifdef SMART_SCHEDULE
+
+unsigned long SmartScheduleIdleCount;
+Bool SmartScheduleIdle;
+Bool SmartScheduleTimerStopped;
+
+#ifdef SIGVTALRM
+#define SMART_SCHEDULE_POSSIBLE
+#endif
+
+#ifdef SMART_SCHEDULE_POSSIBLE
+#define SMART_SCHEDULE_SIGNAL SIGALRM
+#define SMART_SCHEDULE_TIMER ITIMER_REAL
+#endif
+
+void
+SmartScheduleStopTimer (void)
+{
+#ifdef SMART_SCHEDULE_POSSIBLE
+ struct itimerval timer;
+
+ timer.it_interval.tv_sec = 0;
+ timer.it_interval.tv_usec = 0;
+ timer.it_value.tv_sec = 0;
+ timer.it_value.tv_usec = 0;
+ (void) setitimer (ITIMER_REAL, &timer, 0);
+ SmartScheduleTimerStopped = TRUE;
+#endif
+}
+
+Bool
+SmartScheduleStartTimer (void)
+{
+#ifdef SMART_SCHEDULE_POSSIBLE
+ struct itimerval timer;
+
+ SmartScheduleTimerStopped = FALSE;
+ timer.it_interval.tv_sec = 0;
+ timer.it_interval.tv_usec = SmartScheduleInterval * 1000;
+ timer.it_value.tv_sec = 0;
+ timer.it_value.tv_usec = SmartScheduleInterval * 1000;
+ return setitimer (ITIMER_REAL, &timer, 0) >= 0;
+#endif
+ return FALSE;
+}
+
+#ifdef SMART_SCHEDULE_POSSIBLE
+void
+SmartScheduleTimer (int sig)
+{
+ int olderrno = errno;
+
+ SmartScheduleTime += SmartScheduleInterval;
+ if (SmartScheduleIdle)
+ {
+ SmartScheduleStopTimer ();
+ }
+ errno = olderrno;
+}
+#endif
+
+Bool
+SmartScheduleInit (void)
+{
+#ifdef SMART_SCHEDULE_POSSIBLE
+ struct sigaction act;
+
+ if (SmartScheduleDisable)
+ return TRUE;
+
+ bzero ((char *) &act, sizeof(struct sigaction));
+
+ /* Set up the timer signal function */
+ act.sa_handler = SmartScheduleTimer;
+ sigemptyset (&act.sa_mask);
+ sigaddset (&act.sa_mask, SMART_SCHEDULE_SIGNAL);
+ if (sigaction (SMART_SCHEDULE_SIGNAL, &act, 0) < 0)
+ {
+ perror ("sigaction for smart scheduler");
+ return FALSE;
+ }
+ /* Set up the virtual timer */
+ if (!SmartScheduleStartTimer ())
+ {
+ perror ("scheduling timer");
+ return FALSE;
+ }
+ /* stop the timer and wait for WaitForSomething to start it */
+ SmartScheduleStopTimer ();
+ return TRUE;
#else
-#ifdef AIXV3
- if (SyncOn)
- sync();
-#else /* not AIXV3 */
-#ifdef AMOEBA
- mu_lock(&print_lock);
+ return FALSE;
#endif
- fprintf( stderr, f, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9);
-#ifdef AMOEBA
- mu_unlock(&print_lock);
+}
#endif
-#endif /* AIXV3 */
+
+#ifdef SIG_BLOCK
+static sigset_t PreviousSignalMask;
+static int BlockedSignalCount;
+#endif
+
+void
+OsBlockSignals (void)
+{
+#ifdef SIG_BLOCK
+ if (BlockedSignalCount++ == 0)
+ {
+ sigset_t set;
+
+ sigemptyset (&set);
+#ifdef SIGALRM
+ sigaddset (&set, SIGALRM);
+#endif
+#ifdef SIGVTALRM
+ sigaddset (&set, SIGVTALRM);
+#endif
+#ifdef SIGWINCH
+ sigaddset (&set, SIGWINCH);
+#endif
+#ifdef SIGIO
+ sigaddset (&set, SIGIO);
+#endif
+#ifdef SIGTSTP
+ sigaddset (&set, SIGTSTP);
+#endif
+#ifdef SIGTTIN
+ sigaddset (&set, SIGTTIN);
+#endif
+#ifdef SIGTTOU
+ sigaddset (&set, SIGTTOU);
+#endif
+ sigprocmask (SIG_BLOCK, &set, &PreviousSignalMask);
+ }
+#endif
+}
+
+void
+OsReleaseSignals (void)
+{
+#ifdef SIG_BLOCK
+ if (--BlockedSignalCount == 0)
+ {
+ sigprocmask (SIG_SETMASK, &PreviousSignalMask, 0);
+ }
#endif
}
@@ -1536,6 +1599,9 @@ ErrorF(
* all privs before running a command.
*
* This is based on the code in FreeBSD 2.2 libc.
+ *
+ * XXX It'd be good to redirect stderr so that it ends up in the log file
+ * as well. As it is now, xkbcomp messages don't end up in the log file.
*/
int
@@ -1543,7 +1609,9 @@ System(command)
char *command;
{
int pid, p;
- void (*csig)();
+#ifdef SIGCHLD
+ void (*csig)(int);
+#endif
int status;
if (!command)
@@ -1553,7 +1621,9 @@ System(command)
csig = signal(SIGCHLD, SIG_DFL);
#endif
+#ifdef DEBUG
ErrorF("System: `%s'\n", command);
+#endif
switch (pid = fork()) {
case -1: /* error */
@@ -1591,7 +1661,6 @@ Popen(command, type)
struct pid *cur;
FILE *iop;
int pdes[2], pid;
- void (*csig)();
if (command == NULL || type == NULL)
return NULL;
@@ -1635,6 +1704,9 @@ Popen(command, type)
_exit(127);
}
+ /* Avoid EINTR during stdio calls */
+ OsBlockSignals ();
+
/* parent */
if (*type == 'r') {
iop = fdopen(pdes[0], type);
@@ -1649,7 +1721,7 @@ Popen(command, type)
cur->next = pidlist;
pidlist = cur;
-#if 0
+#ifdef DEBUG
ErrorF("Popen: `%s', fp = %p\n", command, iop);
#endif
@@ -1661,11 +1733,10 @@ Pclose(iop)
pointer iop;
{
struct pid *cur, *last;
- int omask;
int pstat;
int pid;
-#if 0
+#ifdef DEBUG
ErrorF("Pclose: fp = %p\n", iop);
#endif
@@ -1687,6 +1758,274 @@ Pclose(iop)
last->next = cur->next;
xfree(cur);
+ /* allow EINTR again */
+ OsReleaseSignals ();
+
return pid == -1 ? -1 : pstat;
}
#endif /* !WIN32 && !__EMX__ */
+
+
+/*
+ * CheckUserParameters: check for long command line arguments and long
+ * environment variables. By default, these checks are only done when
+ * the server's euid != ruid. In 3.3.x, these checks were done in an
+ * external wrapper utility.
+ */
+
+/* Consider LD* variables insecure? */
+#ifndef REMOVE_ENV_LD
+#define REMOVE_ENV_LD 1
+#endif
+
+/* Remove long environment variables? */
+#ifndef REMOVE_LONG_ENV
+#define REMOVE_LONG_ENV 1
+#endif
+
+/*
+ * Disallow stdout or stderr as pipes? It's possible to block the X server
+ * when piping stdout+stderr to a pipe.
+ *
+ * Don't enable this because it looks like it's going to cause problems.
+ */
+#ifndef NO_OUTPUT_PIPES
+#define NO_OUTPUT_PIPES 0
+#endif
+
+
+/* Check args and env only if running setuid (euid == 0 && euid != uid) ? */
+#ifndef CHECK_EUID
+#define CHECK_EUID 1
+#endif
+
+/*
+ * Maybe the locale can be faked to make isprint(3) report that everything
+ * is printable? Avoid it by default.
+ */
+#ifndef USE_ISPRINT
+#define USE_ISPRINT 0
+#endif
+
+#define MAX_ARG_LENGTH 128
+#define MAX_ENV_LENGTH 256
+#define MAX_ENV_PATH_LENGTH 2048 /* Limit for *PATH and TERMCAP */
+
+#if USE_ISPRINT
+#include <ctype.h>
+#define checkPrintable(c) isprint(c)
+#else
+#define checkPrintable(c) (((c) & 0x7f) >= 0x20 && ((c) & 0x7f) != 0x7f)
+#endif
+
+enum BadCode {
+ NotBad = 0,
+ UnsafeArg,
+ ArgTooLong,
+ UnprintableArg,
+ EnvTooLong,
+ OutputIsPipe,
+ InternalError
+};
+
+#define ARGMSG \
+ "\nIf the arguments used are valid, and have been rejected incorrectly\n" \
+ "please send details of the arguments and why they are valid to\n" \
+ "XFree86@XFree86.org. In the meantime, you can start the Xserver as\n" \
+ "the \"super user\" (root).\n"
+
+#define ENVMSG \
+ "\nIf the environment is valid, and have been rejected incorrectly\n" \
+ "please send details of the environment and why it is valid to\n" \
+ "XFree86@XFree86.org. In the meantime, you can start the Xserver as\n" \
+ "the \"super user\" (root).\n"
+
+void
+CheckUserParameters(int argc, char **argv, char **envp)
+{
+ enum BadCode bad = NotBad;
+ int i = 0, j;
+ char *a, *e = NULL;
+#if defined(__QNX__) && !defined(__QNXNTO__)
+ char cmd_name[64];
+#endif
+
+#if CHECK_EUID
+ if (geteuid() == 0 && getuid() != geteuid())
+#endif
+ {
+ /* Check each argv[] */
+ for (i = 1; i < argc; i++) {
+ if (strlen(argv[i]) > MAX_ARG_LENGTH) {
+ bad = ArgTooLong;
+ break;
+ }
+ a = argv[i];
+ while (*a) {
+ if (checkPrintable(*a) == 0) {
+ bad = UnprintableArg;
+ break;
+ }
+ a++;
+ }
+ if (bad)
+ break;
+ }
+ if (!bad) {
+ /* Check each envp[] */
+ for (i = 0; envp[i]; i++) {
+
+ /* Check for bad environment variables and values */
+#if REMOVE_ENV_LD
+ while (envp[i] && (strncmp(envp[i], "LD", 2) == 0)) {
+#ifdef ENVDEBUG
+ ErrorF("CheckUserParameters: removing %s from the "
+ "environment\n", strtok(envp[i], "="));
+#endif
+ for (j = i; envp[j]; j++) {
+ envp[j] = envp[j+1];
+ }
+ }
+#endif
+ if (envp[i] && (strlen(envp[i]) > MAX_ENV_LENGTH)) {
+#if REMOVE_LONG_ENV
+#ifdef ENVDEBUG
+ ErrorF("CheckUserParameters: removing %s from the "
+ "environment\n", strtok(envp[i], "="));
+#endif
+ for (j = i; envp[j]; j++) {
+ envp[j] = envp[j+1];
+ }
+ i--;
+#else
+ char *eq;
+ int len;
+
+ eq = strchr(envp[i], '=');
+ if (!eq)
+ continue;
+ len = eq - envp[i];
+ e = malloc(len + 1);
+ if (!e) {
+ bad = InternalError;
+ break;
+ }
+ strncpy(e, envp[i], len);
+ e[len] = 0;
+ if (len >= 4 &&
+ (strcmp(e + len - 4, "PATH") == 0 ||
+ strcmp(e, "TERMCAP") == 0)) {
+ if (strlen(envp[i]) > MAX_ENV_PATH_LENGTH) {
+ bad = EnvTooLong;
+ break;
+ } else {
+ free(e);
+ }
+ } else {
+ bad = EnvTooLong;
+ break;
+ }
+#endif
+ }
+ }
+ }
+#if NO_OUTPUT_PIPES
+ if (!bad) {
+ struct stat buf;
+
+ if (fstat(fileno(stdout), &buf) == 0 && S_ISFIFO(buf.st_mode))
+ bad = OutputIsPipe;
+ if (fstat(fileno(stderr), &buf) == 0 && S_ISFIFO(buf.st_mode))
+ bad = OutputIsPipe;
+ }
+#endif
+ }
+ switch (bad) {
+ case NotBad:
+ return;
+ case UnsafeArg:
+ ErrorF("Command line argument number %d is unsafe\n", i);
+ ErrorF(ARGMSG);
+ break;
+ case ArgTooLong:
+ ErrorF("Command line argument number %d is too long\n", i);
+ ErrorF(ARGMSG);
+ break;
+ case UnprintableArg:
+ ErrorF("Command line argument number %d contains unprintable"
+ " characters\n", i);
+ ErrorF(ARGMSG);
+ break;
+ case EnvTooLong:
+ ErrorF("Environment variable `%s' is too long\n", e);
+ ErrorF(ENVMSG);
+ break;
+ case OutputIsPipe:
+ ErrorF("Stdout and/or stderr is a pipe\n");
+ break;
+ case InternalError:
+ ErrorF("Internal Error\n");
+ break;
+ default:
+ ErrorF("Unknown error\n");
+ ErrorF(ARGMSG);
+ ErrorF(ENVMSG);
+ break;
+ }
+ FatalError("X server aborted because of unsafe environment\n");
+}
+
+/*
+ * CheckUserAuthorization: check if the user is allowed to start the
+ * X server. This usually means some sort of PAM checking, and it is
+ * usually only done for setuid servers (uid != euid).
+ */
+
+#ifdef USE_PAM
+#include <security/pam_appl.h>
+#include <security/pam_misc.h>
+#include <pwd.h>
+#endif /* USE_PAM */
+
+void
+CheckUserAuthorization()
+{
+#ifdef USE_PAM
+ static struct pam_conv conv = {
+ misc_conv,
+ NULL
+ };
+
+ pam_handle_t *pamh = NULL;
+ struct passwd *pw;
+ int retval;
+
+ if (getuid() != geteuid()) {
+ pw = getpwuid(getuid());
+ if (pw == NULL)
+ FatalError("getpwuid() failed for uid %d\n", getuid());
+
+ retval = pam_start("xserver", pw->pw_name, &conv, &pamh);
+ if (retval != PAM_SUCCESS)
+ FatalError("pam_start() failed.\n"
+ "\tMissing or mangled PAM config file or module?\n");
+
+ retval = pam_authenticate(pamh, 0);
+ if (retval != PAM_SUCCESS) {
+ pam_end(pamh, retval);
+ FatalError("PAM authentication failed, cannot start X server.\n"
+ "\tPerhaps you do not have console ownership?\n");
+ }
+
+ retval = pam_acct_mgmt(pamh, 0);
+ if (retval != PAM_SUCCESS) {
+ pam_end(pamh, retval);
+ FatalError("PAM authentication failed, cannot start X server.\n"
+ "\tPerhaps you do not have console ownership?\n");
+ }
+
+ /* this is not a session, so do not do session management */
+ pam_end(pamh, PAM_SUCCESS);
+ }
+#endif
+}