From 1c94119ae26b94a60bb2c2b33494ed43c3b8a52f Mon Sep 17 00:00:00 2001 From: marha Date: Sun, 16 May 2010 20:50:58 +0000 Subject: svn merge -r588:HEAD ^/branches/released . --- xorg-server/os/WaitFor.c | 1374 +++++++-------- xorg-server/os/access.c | 37 +- xorg-server/os/connection.c | 2656 ++++++++++++++--------------- xorg-server/os/io.c | 2216 ++++++++++++------------ xorg-server/os/log.c | 1235 +++++++------- xorg-server/os/mitauth.c | 14 +- xorg-server/os/osinit.c | 659 ++++---- xorg-server/os/rpcauth.c | 6 +- xorg-server/os/utils.c | 3897 +++++++++++++++++++++---------------------- xorg-server/os/xdmauth.c | 44 +- xorg-server/os/xdmcp.c | 14 +- xorg-server/os/xprintf.c | 232 +-- xorg-server/os/xsha1.c | 336 ++-- 13 files changed, 6335 insertions(+), 6385 deletions(-) (limited to 'xorg-server/os') diff --git a/xorg-server/os/WaitFor.c b/xorg-server/os/WaitFor.c index 7199680cd..025f2a2a4 100644 --- a/xorg-server/os/WaitFor.c +++ b/xorg-server/os/WaitFor.c @@ -1,687 +1,687 @@ -/*********************************************************** - -Copyright 1987, 1998 The Open Group - -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. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. - - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -******************************************************************/ - - -/***************************************************************** - * OS Dependent input routines: - * - * WaitForSomething - * TimerForce, TimerSet, TimerCheck, TimerFree - * - *****************************************************************/ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#ifdef WIN32 -#include -#endif -#include /* for strings, fcntl, time */ -#include -#include -#include -#include "misc.h" - -#include "osdep.h" -#include -#include "dixstruct.h" -#include "opaque.h" -#ifdef DPMSExtension -#include "dpmsproc.h" -#endif - -#ifdef WIN32 -/* Error codes from windows sockets differ from fileio error codes */ -#undef EINTR -#define EINTR WSAEINTR -#undef EINVAL -#define EINVAL WSAEINVAL -#undef EBADF -#define EBADF WSAENOTSOCK -/* Windows select does not set errno. Use GetErrno as wrapper for - WSAGetLastError */ -#define GetErrno WSAGetLastError -#else -/* This is just a fallback to errno to hide the differences between unix and - Windows in the code */ -#define GetErrno() errno -#endif - -/* like ffs, but uses fd_mask instead of int as argument, so it works - when fd_mask is longer than an int, such as common 64-bit platforms */ -/* modifications by raphael */ -int -mffs(fd_mask mask) -{ - int i; - - if (!mask) return 0; - i = 1; - while (!(mask & 1)) - { - i++; - mask >>= 1; - } - return i; -} - -#ifdef DPMSExtension -#include -#endif - -struct _OsTimerRec { - OsTimerPtr next; - CARD32 expires; - CARD32 delta; - OsTimerCallback callback; - pointer arg; -}; - -static void DoTimer(OsTimerPtr timer, CARD32 now, OsTimerPtr *prev); -static void CheckAllTimers(void); -static OsTimerPtr timers = NULL; - -/***************** - * WaitForSomething: - * Make the server suspend until there is - * 1. data from clients or - * 2. input events available or - * 3. ddx notices something of interest (graphics - * queue ready, etc.) or - * 4. clients that have buffered replies/events are ready - * - * If the time between INPUT events is - * greater than ScreenSaverTime, the display is turned off (or - * saved, depending on the hardware). So, WaitForSomething() - * has to handle this also (that's why the select() has a timeout. - * For more info on ClientsWithInput, see ReadRequestFromClient(). - * pClientsReady is an array to store ready client->index values into. - *****************/ - -int -WaitForSomething(int *pClientsReady) -{ - int i; - struct timeval waittime, *wt; - INT32 timeout = 0; - fd_set clientsReadable; - fd_set clientsWritable; - int curclient; - int selecterr; - int nready; - fd_set devicesReadable; - CARD32 now = 0; - Bool someReady = FALSE; - - FD_ZERO(&clientsReadable); - - /* We need a while loop here to handle - crashed connections and the screen saver timeout */ - while (1) - { - /* deal with any blocked jobs */ - if (workQueue) - ProcessWorkQueue(); - if (XFD_ANYSET (&ClientsWithInput)) - { - if (!SmartScheduleDisable) - { - someReady = TRUE; - waittime.tv_sec = 0; - waittime.tv_usec = 0; - wt = &waittime; - } - else - { - XFD_COPYSET (&ClientsWithInput, &clientsReadable); - break; - } - } - if (someReady) - { - XFD_COPYSET(&AllSockets, &LastSelectMask); - XFD_UNSET(&LastSelectMask, &ClientsWithInput); - } - else - { - wt = NULL; - if (timers) - { - now = GetTimeInMillis(); - timeout = timers->expires - now; - if (timeout > 0 && timeout > timers->delta + 250) { - /* time has rewound. reset the timers. */ - CheckAllTimers(); - } - - if (timers) { - timeout = timers->expires - now; - if (timeout < 0) - timeout = 0; - waittime.tv_sec = timeout / MILLI_PER_SECOND; - waittime.tv_usec = (timeout % MILLI_PER_SECOND) * - (1000000 / MILLI_PER_SECOND); - wt = &waittime; - } - } - if (!wt) - { - wt = &waittime; - waittime.tv_sec = 0; - waittime.tv_usec = 100; - } - XFD_COPYSET(&AllSockets, &LastSelectMask); - } - SmartScheduleStopTimer (); - - BlockHandler((pointer)&wt, (pointer)&LastSelectMask); - if (NewOutputPending) - FlushAllOutput(); - /* keep this check close to select() call to minimize race */ - if (dispatchException) - i = -1; - else if (AnyClientsWriteBlocked) - { - XFD_COPYSET(&ClientsWriteBlocked, &clientsWritable); - i = Select (MaxClients, &LastSelectMask, &clientsWritable, NULL, wt); - } - else - { - i = Select (MaxClients, &LastSelectMask, NULL, NULL, wt); - } - selecterr = GetErrno(); - WakeupHandler(i, (pointer)&LastSelectMask); - SmartScheduleStartTimer (); - if (i <= 0) /* An error or timeout occurred */ - { - if (dispatchException) - return 0; - if (i < 0) - { - if (selecterr == EBADF) /* Some client disconnected */ - { - CheckConnections (); - if (! XFD_ANYSET (&AllClients)) - return 0; - } - else if (selecterr == EINVAL) - { - FatalError("WaitForSomething(): select: %s\n", - strerror(selecterr)); - } - else if (selecterr != EINTR && selecterr != EAGAIN) - { - ErrorF("WaitForSomething(): select: %s\n", - strerror(selecterr)); - } - } - else if (someReady) - { - /* - * If no-one else is home, bail quickly - */ - XFD_COPYSET(&ClientsWithInput, &LastSelectMask); - XFD_COPYSET(&ClientsWithInput, &clientsReadable); - break; - } - if (*checkForInput[0] != *checkForInput[1]) - return 0; - - if (timers) - { - int expired = 0; - now = GetTimeInMillis(); - if ((int) (timers->expires - now) <= 0) - expired = 1; - - while (timers && (int) (timers->expires - now) <= 0) - DoTimer(timers, now, &timers); - - if (expired) - return 0; - } - } - else - { - fd_set tmp_set; - - if (*checkForInput[0] == *checkForInput[1]) { - if (timers) - { - int expired = 0; - now = GetTimeInMillis(); - if ((int) (timers->expires - now) <= 0) - expired = 1; - - while (timers && (int) (timers->expires - now) <= 0) - DoTimer(timers, now, &timers); - - if (expired) - return 0; - } - } - if (someReady) - XFD_ORSET(&LastSelectMask, &ClientsWithInput, &LastSelectMask); - if (AnyClientsWriteBlocked && XFD_ANYSET (&clientsWritable)) - { - NewOutputPending = TRUE; - XFD_ORSET(&OutputPending, &clientsWritable, &OutputPending); - XFD_UNSET(&ClientsWriteBlocked, &clientsWritable); - if (! XFD_ANYSET(&ClientsWriteBlocked)) - AnyClientsWriteBlocked = FALSE; - } - - XFD_ANDSET(&devicesReadable, &LastSelectMask, &EnabledDevices); - XFD_ANDSET(&clientsReadable, &LastSelectMask, &AllClients); - XFD_ANDSET(&tmp_set, &LastSelectMask, &WellKnownConnections); - if (XFD_ANYSET(&tmp_set)) - QueueWorkProc(EstablishNewConnections, NULL, - (pointer)&LastSelectMask); - - if (XFD_ANYSET (&devicesReadable) || XFD_ANYSET (&clientsReadable)) - break; - /* check here for DDXes that queue events during Block/Wakeup */ - if (*checkForInput[0] != *checkForInput[1]) - return 0; - } - } - - nready = 0; - if (XFD_ANYSET (&clientsReadable)) - { -#ifndef WIN32 - for (i=0; ipriority; - if (nready == 0 || client_priority > highest_priority) - { - /* Either we found the first client, or we found - * a client whose priority is greater than all others - * that have been found so far. Either way, we want - * to initialize the list of clients to contain just - * this client. - */ - pClientsReady[0] = client_index; - highest_priority = client_priority; - nready = 1; - } - /* the following if makes sure that multiple same-priority - * clients get batched together - */ - else if (client_priority == highest_priority) - { - pClientsReady[nready++] = client_index; - } -#ifndef WIN32 - clientsReadable.fds_bits[i] &= ~(((fd_mask)1L) << curclient); - } -#else - FD_CLR(curclient, &clientsReadable); -#endif - } - } - return nready; -} - -/* If time has rewound, re-run every affected timer. - * Timers might drop out of the list, so we have to restart every time. */ -static void -CheckAllTimers(void) -{ - OsTimerPtr timer; - CARD32 now; - -start: - now = GetTimeInMillis(); - - for (timer = timers; timer; timer = timer->next) { - if (timer->expires - now > timer->delta + 250) { - TimerForce(timer); - goto start; - } - } -} - -static void -DoTimer(OsTimerPtr timer, CARD32 now, OsTimerPtr *prev) -{ - CARD32 newTime; - - *prev = timer->next; - timer->next = NULL; - newTime = (*timer->callback)(timer, now, timer->arg); - if (newTime) - TimerSet(timer, 0, newTime, timer->callback, timer->arg); -} - -OsTimerPtr -TimerSet(OsTimerPtr timer, int flags, CARD32 millis, - OsTimerCallback func, pointer arg) -{ - register OsTimerPtr *prev; - CARD32 now = GetTimeInMillis(); - - if (!timer) - { - timer = xalloc(sizeof(struct _OsTimerRec)); - if (!timer) - return NULL; - } - else - { - for (prev = &timers; *prev; prev = &(*prev)->next) - { - if (*prev == timer) - { - *prev = timer->next; - if (flags & TimerForceOld) - (void)(*timer->callback)(timer, now, timer->arg); - break; - } - } - } - if (!millis) - return timer; - if (flags & TimerAbsolute) { - timer->delta = millis - now; - } - else { - timer->delta = millis; - millis += now; - } - timer->expires = millis; - timer->callback = func; - timer->arg = arg; - if ((int) (millis - now) <= 0) - { - timer->next = NULL; - millis = (*timer->callback)(timer, now, timer->arg); - if (!millis) - return timer; - } - for (prev = &timers; - *prev && (int) ((*prev)->expires - millis) <= 0; - prev = &(*prev)->next) - ; - timer->next = *prev; - *prev = timer; - return timer; -} - -Bool -TimerForce(OsTimerPtr timer) -{ - OsTimerPtr *prev; - - for (prev = &timers; *prev; prev = &(*prev)->next) - { - if (*prev == timer) - { - DoTimer(timer, GetTimeInMillis(), prev); - return TRUE; - } - } - return FALSE; -} - - -void -TimerCancel(OsTimerPtr timer) -{ - OsTimerPtr *prev; - - if (!timer) - return; - for (prev = &timers; *prev; prev = &(*prev)->next) - { - if (*prev == timer) - { - *prev = timer->next; - break; - } - } -} - -void -TimerFree(OsTimerPtr timer) -{ - if (!timer) - return; - TimerCancel(timer); - xfree(timer); -} - -void -TimerCheck(void) -{ - CARD32 now = GetTimeInMillis(); - - while (timers && (int) (timers->expires - now) <= 0) - DoTimer(timers, now, &timers); -} - -void -TimerInit(void) -{ - OsTimerPtr timer; - - while ((timer = timers)) - { - timers = timer->next; - xfree(timer); - } -} - -#ifdef DPMSExtension - -#define DPMS_CHECK_MODE(mode,time)\ - if (time > 0 && DPMSPowerLevel < mode && timeout >= time)\ - DPMSSet(serverClient, mode); - -#define DPMS_CHECK_TIMEOUT(time)\ - if (time > 0 && (time - timeout) > 0)\ - return time - timeout; - -static CARD32 -NextDPMSTimeout(INT32 timeout) -{ - /* - * Return the amount of time remaining until we should set - * the next power level. Fallthroughs are intentional. - */ - switch (DPMSPowerLevel) - { - case DPMSModeOn: - DPMS_CHECK_TIMEOUT(DPMSStandbyTime) - - case DPMSModeStandby: - DPMS_CHECK_TIMEOUT(DPMSSuspendTime) - - case DPMSModeSuspend: - DPMS_CHECK_TIMEOUT(DPMSOffTime) - - default: /* DPMSModeOff */ - return 0; - } -} -#endif /* DPMSExtension */ - -static CARD32 -ScreenSaverTimeoutExpire(OsTimerPtr timer,CARD32 now,pointer arg) -{ - INT32 timeout = now - lastDeviceEventTime.milliseconds; - CARD32 nextTimeout = 0; - -#ifdef DPMSExtension - /* - * Check each mode lowest to highest, since a lower mode can - * have the same timeout as a higher one. - */ - if (DPMSEnabled) - { - DPMS_CHECK_MODE(DPMSModeOff, DPMSOffTime) - DPMS_CHECK_MODE(DPMSModeSuspend, DPMSSuspendTime) - DPMS_CHECK_MODE(DPMSModeStandby, DPMSStandbyTime) - - nextTimeout = NextDPMSTimeout(timeout); - } - - /* - * Only do the screensaver checks if we're not in a DPMS - * power saving mode - */ - if (DPMSPowerLevel != DPMSModeOn) - return nextTimeout; -#endif /* DPMSExtension */ - - if (!ScreenSaverTime) - return nextTimeout; - - if (timeout < ScreenSaverTime) - { - return nextTimeout > 0 ? - min(ScreenSaverTime - timeout, nextTimeout) : - ScreenSaverTime - timeout; - } - - ResetOsBuffers(); /* not ideal, but better than nothing */ - dixSaveScreens(serverClient, SCREEN_SAVER_ON, ScreenSaverActive); - - if (ScreenSaverInterval > 0) - { - nextTimeout = nextTimeout > 0 ? - min(ScreenSaverInterval, nextTimeout) : - ScreenSaverInterval; - } - - return nextTimeout; -} - -static OsTimerPtr ScreenSaverTimer = NULL; - -void -FreeScreenSaverTimer(void) -{ - if (ScreenSaverTimer) { - TimerFree(ScreenSaverTimer); - ScreenSaverTimer = NULL; - } -} - -void -SetScreenSaverTimer(void) -{ - CARD32 timeout = 0; - -#ifdef DPMSExtension - if (DPMSEnabled) - { - /* - * A higher DPMS level has a timeout that's either less - * than or equal to that of a lower DPMS level. - */ - if (DPMSStandbyTime > 0) - timeout = DPMSStandbyTime; - - else if (DPMSSuspendTime > 0) - timeout = DPMSSuspendTime; - - else if (DPMSOffTime > 0) - timeout = DPMSOffTime; - } -#endif - - if (ScreenSaverTime > 0) - { - timeout = timeout > 0 ? - min(ScreenSaverTime, timeout) : - ScreenSaverTime; - } - -#ifdef SCREENSAVER - if (timeout && !screenSaverSuspended) { -#else - if (timeout) { -#endif - ScreenSaverTimer = TimerSet(ScreenSaverTimer, 0, timeout, - ScreenSaverTimeoutExpire, NULL); - } - else if (ScreenSaverTimer) { - FreeScreenSaverTimer(); - } -} - +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +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. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + + +/***************************************************************** + * OS Dependent input routines: + * + * WaitForSomething + * TimerForce, TimerSet, TimerCheck, TimerFree + * + *****************************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#ifdef WIN32 +#include +#endif +#include /* for strings, fcntl, time */ +#include +#include +#include +#include "misc.h" + +#include "osdep.h" +#include +#include "dixstruct.h" +#include "opaque.h" +#ifdef DPMSExtension +#include "dpmsproc.h" +#endif + +#ifdef WIN32 +/* Error codes from windows sockets differ from fileio error codes */ +#undef EINTR +#define EINTR WSAEINTR +#undef EINVAL +#define EINVAL WSAEINVAL +#undef EBADF +#define EBADF WSAENOTSOCK +/* Windows select does not set errno. Use GetErrno as wrapper for + WSAGetLastError */ +#define GetErrno WSAGetLastError +#else +/* This is just a fallback to errno to hide the differences between unix and + Windows in the code */ +#define GetErrno() errno +#endif + +/* like ffs, but uses fd_mask instead of int as argument, so it works + when fd_mask is longer than an int, such as common 64-bit platforms */ +/* modifications by raphael */ +int +mffs(fd_mask mask) +{ + int i; + + if (!mask) return 0; + i = 1; + while (!(mask & 1)) + { + i++; + mask >>= 1; + } + return i; +} + +#ifdef DPMSExtension +#include +#endif + +struct _OsTimerRec { + OsTimerPtr next; + CARD32 expires; + CARD32 delta; + OsTimerCallback callback; + pointer arg; +}; + +static void DoTimer(OsTimerPtr timer, CARD32 now, OsTimerPtr *prev); +static void CheckAllTimers(void); +static OsTimerPtr timers = NULL; + +/***************** + * WaitForSomething: + * Make the server suspend until there is + * 1. data from clients or + * 2. input events available or + * 3. ddx notices something of interest (graphics + * queue ready, etc.) or + * 4. clients that have buffered replies/events are ready + * + * If the time between INPUT events is + * greater than ScreenSaverTime, the display is turned off (or + * saved, depending on the hardware). So, WaitForSomething() + * has to handle this also (that's why the select() has a timeout. + * For more info on ClientsWithInput, see ReadRequestFromClient(). + * pClientsReady is an array to store ready client->index values into. + *****************/ + +int +WaitForSomething(int *pClientsReady) +{ + int i; + struct timeval waittime, *wt; + INT32 timeout = 0; + fd_set clientsReadable; + fd_set clientsWritable; + int curclient; + int selecterr; + int nready; + fd_set devicesReadable; + CARD32 now = 0; + Bool someReady = FALSE; + + FD_ZERO(&clientsReadable); + + /* We need a while loop here to handle + crashed connections and the screen saver timeout */ + while (1) + { + /* deal with any blocked jobs */ + if (workQueue) + ProcessWorkQueue(); + if (XFD_ANYSET (&ClientsWithInput)) + { + if (!SmartScheduleDisable) + { + someReady = TRUE; + waittime.tv_sec = 0; + waittime.tv_usec = 0; + wt = &waittime; + } + else + { + XFD_COPYSET (&ClientsWithInput, &clientsReadable); + break; + } + } + if (someReady) + { + XFD_COPYSET(&AllSockets, &LastSelectMask); + XFD_UNSET(&LastSelectMask, &ClientsWithInput); + } + else + { + wt = NULL; + if (timers) + { + now = GetTimeInMillis(); + timeout = timers->expires - now; + if (timeout > 0 && timeout > timers->delta + 250) { + /* time has rewound. reset the timers. */ + CheckAllTimers(); + } + + if (timers) { + timeout = timers->expires - now; + if (timeout < 0) + timeout = 0; + waittime.tv_sec = timeout / MILLI_PER_SECOND; + waittime.tv_usec = (timeout % MILLI_PER_SECOND) * + (1000000 / MILLI_PER_SECOND); + wt = &waittime; + } + } + if (!wt) + { + wt = &waittime; + waittime.tv_sec = 0; + waittime.tv_usec = 100; + } + XFD_COPYSET(&AllSockets, &LastSelectMask); + } + SmartScheduleStopTimer (); + + BlockHandler((pointer)&wt, (pointer)&LastSelectMask); + if (NewOutputPending) + FlushAllOutput(); + /* keep this check close to select() call to minimize race */ + if (dispatchException) + i = -1; + else if (AnyClientsWriteBlocked) + { + XFD_COPYSET(&ClientsWriteBlocked, &clientsWritable); + i = Select (MaxClients, &LastSelectMask, &clientsWritable, NULL, wt); + } + else + { + i = Select (MaxClients, &LastSelectMask, NULL, NULL, wt); + } + selecterr = GetErrno(); + WakeupHandler(i, (pointer)&LastSelectMask); + SmartScheduleStartTimer (); + if (i <= 0) /* An error or timeout occurred */ + { + if (dispatchException) + return 0; + if (i < 0) + { + if (selecterr == EBADF) /* Some client disconnected */ + { + CheckConnections (); + if (! XFD_ANYSET (&AllClients)) + return 0; + } + else if (selecterr == EINVAL) + { + FatalError("WaitForSomething(): select: %s\n", + strerror(selecterr)); + } + else if (selecterr != EINTR && selecterr != EAGAIN) + { + ErrorF("WaitForSomething(): select: %s\n", + strerror(selecterr)); + } + } + else if (someReady) + { + /* + * If no-one else is home, bail quickly + */ + XFD_COPYSET(&ClientsWithInput, &LastSelectMask); + XFD_COPYSET(&ClientsWithInput, &clientsReadable); + break; + } + if (*checkForInput[0] != *checkForInput[1]) + return 0; + + if (timers) + { + int expired = 0; + now = GetTimeInMillis(); + if ((int) (timers->expires - now) <= 0) + expired = 1; + + while (timers && (int) (timers->expires - now) <= 0) + DoTimer(timers, now, &timers); + + if (expired) + return 0; + } + } + else + { + fd_set tmp_set; + + if (*checkForInput[0] == *checkForInput[1]) { + if (timers) + { + int expired = 0; + now = GetTimeInMillis(); + if ((int) (timers->expires - now) <= 0) + expired = 1; + + while (timers && (int) (timers->expires - now) <= 0) + DoTimer(timers, now, &timers); + + if (expired) + return 0; + } + } + if (someReady) + XFD_ORSET(&LastSelectMask, &ClientsWithInput, &LastSelectMask); + if (AnyClientsWriteBlocked && XFD_ANYSET (&clientsWritable)) + { + NewOutputPending = TRUE; + XFD_ORSET(&OutputPending, &clientsWritable, &OutputPending); + XFD_UNSET(&ClientsWriteBlocked, &clientsWritable); + if (! XFD_ANYSET(&ClientsWriteBlocked)) + AnyClientsWriteBlocked = FALSE; + } + + XFD_ANDSET(&devicesReadable, &LastSelectMask, &EnabledDevices); + XFD_ANDSET(&clientsReadable, &LastSelectMask, &AllClients); + XFD_ANDSET(&tmp_set, &LastSelectMask, &WellKnownConnections); + if (XFD_ANYSET(&tmp_set)) + QueueWorkProc(EstablishNewConnections, NULL, + (pointer)&LastSelectMask); + + if (XFD_ANYSET (&devicesReadable) || XFD_ANYSET (&clientsReadable)) + break; + /* check here for DDXes that queue events during Block/Wakeup */ + if (*checkForInput[0] != *checkForInput[1]) + return 0; + } + } + + nready = 0; + if (XFD_ANYSET (&clientsReadable)) + { +#ifndef WIN32 + for (i=0; ipriority; + if (nready == 0 || client_priority > highest_priority) + { + /* Either we found the first client, or we found + * a client whose priority is greater than all others + * that have been found so far. Either way, we want + * to initialize the list of clients to contain just + * this client. + */ + pClientsReady[0] = client_index; + highest_priority = client_priority; + nready = 1; + } + /* the following if makes sure that multiple same-priority + * clients get batched together + */ + else if (client_priority == highest_priority) + { + pClientsReady[nready++] = client_index; + } +#ifndef WIN32 + clientsReadable.fds_bits[i] &= ~(((fd_mask)1L) << curclient); + } +#else + FD_CLR(curclient, &clientsReadable); +#endif + } + } + return nready; +} + +/* If time has rewound, re-run every affected timer. + * Timers might drop out of the list, so we have to restart every time. */ +static void +CheckAllTimers(void) +{ + OsTimerPtr timer; + CARD32 now; + +start: + now = GetTimeInMillis(); + + for (timer = timers; timer; timer = timer->next) { + if (timer->expires - now > timer->delta + 250) { + TimerForce(timer); + goto start; + } + } +} + +static void +DoTimer(OsTimerPtr timer, CARD32 now, OsTimerPtr *prev) +{ + CARD32 newTime; + + *prev = timer->next; + timer->next = NULL; + newTime = (*timer->callback)(timer, now, timer->arg); + if (newTime) + TimerSet(timer, 0, newTime, timer->callback, timer->arg); +} + +OsTimerPtr +TimerSet(OsTimerPtr timer, int flags, CARD32 millis, + OsTimerCallback func, pointer arg) +{ + register OsTimerPtr *prev; + CARD32 now = GetTimeInMillis(); + + if (!timer) + { + timer = malloc(sizeof(struct _OsTimerRec)); + if (!timer) + return NULL; + } + else + { + for (prev = &timers; *prev; prev = &(*prev)->next) + { + if (*prev == timer) + { + *prev = timer->next; + if (flags & TimerForceOld) + (void)(*timer->callback)(timer, now, timer->arg); + break; + } + } + } + if (!millis) + return timer; + if (flags & TimerAbsolute) { + timer->delta = millis - now; + } + else { + timer->delta = millis; + millis += now; + } + timer->expires = millis; + timer->callback = func; + timer->arg = arg; + if ((int) (millis - now) <= 0) + { + timer->next = NULL; + millis = (*timer->callback)(timer, now, timer->arg); + if (!millis) + return timer; + } + for (prev = &timers; + *prev && (int) ((*prev)->expires - millis) <= 0; + prev = &(*prev)->next) + ; + timer->next = *prev; + *prev = timer; + return timer; +} + +Bool +TimerForce(OsTimerPtr timer) +{ + OsTimerPtr *prev; + + for (prev = &timers; *prev; prev = &(*prev)->next) + { + if (*prev == timer) + { + DoTimer(timer, GetTimeInMillis(), prev); + return TRUE; + } + } + return FALSE; +} + + +void +TimerCancel(OsTimerPtr timer) +{ + OsTimerPtr *prev; + + if (!timer) + return; + for (prev = &timers; *prev; prev = &(*prev)->next) + { + if (*prev == timer) + { + *prev = timer->next; + break; + } + } +} + +void +TimerFree(OsTimerPtr timer) +{ + if (!timer) + return; + TimerCancel(timer); + free(timer); +} + +void +TimerCheck(void) +{ + CARD32 now = GetTimeInMillis(); + + while (timers && (int) (timers->expires - now) <= 0) + DoTimer(timers, now, &timers); +} + +void +TimerInit(void) +{ + OsTimerPtr timer; + + while ((timer = timers)) + { + timers = timer->next; + free(timer); + } +} + +#ifdef DPMSExtension + +#define DPMS_CHECK_MODE(mode,time)\ + if (time > 0 && DPMSPowerLevel < mode && timeout >= time)\ + DPMSSet(serverClient, mode); + +#define DPMS_CHECK_TIMEOUT(time)\ + if (time > 0 && (time - timeout) > 0)\ + return time - timeout; + +static CARD32 +NextDPMSTimeout(INT32 timeout) +{ + /* + * Return the amount of time remaining until we should set + * the next power level. Fallthroughs are intentional. + */ + switch (DPMSPowerLevel) + { + case DPMSModeOn: + DPMS_CHECK_TIMEOUT(DPMSStandbyTime) + + case DPMSModeStandby: + DPMS_CHECK_TIMEOUT(DPMSSuspendTime) + + case DPMSModeSuspend: + DPMS_CHECK_TIMEOUT(DPMSOffTime) + + default: /* DPMSModeOff */ + return 0; + } +} +#endif /* DPMSExtension */ + +static CARD32 +ScreenSaverTimeoutExpire(OsTimerPtr timer,CARD32 now,pointer arg) +{ + INT32 timeout = now - lastDeviceEventTime.milliseconds; + CARD32 nextTimeout = 0; + +#ifdef DPMSExtension + /* + * Check each mode lowest to highest, since a lower mode can + * have the same timeout as a higher one. + */ + if (DPMSEnabled) + { + DPMS_CHECK_MODE(DPMSModeOff, DPMSOffTime) + DPMS_CHECK_MODE(DPMSModeSuspend, DPMSSuspendTime) + DPMS_CHECK_MODE(DPMSModeStandby, DPMSStandbyTime) + + nextTimeout = NextDPMSTimeout(timeout); + } + + /* + * Only do the screensaver checks if we're not in a DPMS + * power saving mode + */ + if (DPMSPowerLevel != DPMSModeOn) + return nextTimeout; +#endif /* DPMSExtension */ + + if (!ScreenSaverTime) + return nextTimeout; + + if (timeout < ScreenSaverTime) + { + return nextTimeout > 0 ? + min(ScreenSaverTime - timeout, nextTimeout) : + ScreenSaverTime - timeout; + } + + ResetOsBuffers(); /* not ideal, but better than nothing */ + dixSaveScreens(serverClient, SCREEN_SAVER_ON, ScreenSaverActive); + + if (ScreenSaverInterval > 0) + { + nextTimeout = nextTimeout > 0 ? + min(ScreenSaverInterval, nextTimeout) : + ScreenSaverInterval; + } + + return nextTimeout; +} + +static OsTimerPtr ScreenSaverTimer = NULL; + +void +FreeScreenSaverTimer(void) +{ + if (ScreenSaverTimer) { + TimerFree(ScreenSaverTimer); + ScreenSaverTimer = NULL; + } +} + +void +SetScreenSaverTimer(void) +{ + CARD32 timeout = 0; + +#ifdef DPMSExtension + if (DPMSEnabled) + { + /* + * A higher DPMS level has a timeout that's either less + * than or equal to that of a lower DPMS level. + */ + if (DPMSStandbyTime > 0) + timeout = DPMSStandbyTime; + + else if (DPMSSuspendTime > 0) + timeout = DPMSSuspendTime; + + else if (DPMSOffTime > 0) + timeout = DPMSOffTime; + } +#endif + + if (ScreenSaverTime > 0) + { + timeout = timeout > 0 ? + min(ScreenSaverTime, timeout) : + ScreenSaverTime; + } + +#ifdef SCREENSAVER + if (timeout && !screenSaverSuspended) { +#else + if (timeout) { +#endif + ScreenSaverTimer = TimerSet(ScreenSaverTimer, 0, timeout, + ScreenSaverTimeoutExpire, NULL); + } + else if (ScreenSaverTimer) { + FreeScreenSaverTimer(); + } +} + diff --git a/xorg-server/os/access.c b/xorg-server/os/access.c index 603210f85..2a0ea01cd 100644 --- a/xorg-server/os/access.c +++ b/xorg-server/os/access.c @@ -238,12 +238,12 @@ typedef struct _host { int requested; } HOST; -#define MakeHost(h,l) (h)=xalloc(sizeof *(h)+(l));\ +#define MakeHost(h,l) (h)=malloc(sizeof *(h)+(l));\ if (h) { \ (h)->addr=(unsigned char *) ((h) + 1);\ (h)->requested = FALSE; \ } -#define FreeHost(h) xfree(h) +#define FreeHost(h) free(h) static HOST *selfhosts = NULL; static HOST *validhosts = NULL; static int AccessEnabled = DEFAULT_ACCESS_CONTROL; @@ -587,7 +587,7 @@ DefineSelf (int fd) Error ("Getting interface count"); if (len < (ifn.lifn_count * sizeof(struct lifreq))) { len = ifn.lifn_count * sizeof(struct lifreq); - bufptr = xalloc(len); + bufptr = malloc(len); } #endif @@ -765,7 +765,8 @@ DefineSelf (int fd) continue; #endif /* DNETCONN */ len = sizeof(*(ifr->ifa_addr)); - family = ConvertAddr(ifr->ifa_addr, &len, (pointer *)&addr); + family = ConvertAddr((struct sockaddr *) ifr->ifa_addr, &len, + (pointer *)&addr); if (family == -1 || family == FamilyLocal) continue; #if defined(IPv6) && defined(AF_INET6) @@ -789,7 +790,6 @@ DefineSelf (int fd) } #ifdef XDMCP { - struct sockaddr broad_addr; /* * If this isn't an Internet Address, don't register it. */ @@ -835,11 +835,10 @@ DefineSelf (int fd) if ((ifr->ifa_flags & IFF_BROADCAST) && (ifr->ifa_flags & IFF_UP) && ifr->ifa_broadaddr) - broad_addr = *ifr->ifa_broadaddr; + XdmcpRegisterBroadcastAddress( + (struct sockaddr_in *) ifr->ifa_broadaddr); else continue; - XdmcpRegisterBroadcastAddress((struct sockaddr_in *) - &broad_addr); } #endif /* XDMCP */ @@ -1131,12 +1130,12 @@ Bool LocalClient(ClientPtr client) &alen, (pointer *)&addr); if (family == -1) { - xfree (from); + free(from); return FALSE; } if (family == FamilyLocal) { - xfree (from); + free(from); return TRUE; } for (host = selfhosts; host; host = host->next) @@ -1144,7 +1143,7 @@ Bool LocalClient(ClientPtr client) if (addrEqual (family, addr, alen, host)) return TRUE; } - xfree (from); + free(from); } return FALSE; } @@ -1214,7 +1213,7 @@ GetLocalClientCreds(ClientPtr client, LocalClientCredRec **lccp) } #endif - *lccp = Xcalloc(sizeof(LocalClientCredRec)); + *lccp = calloc(1, sizeof(LocalClientCredRec)); if (*lccp == NULL) return -1; lcc = *lccp; @@ -1250,7 +1249,7 @@ GetLocalClientCreds(ClientPtr client, LocalClientCredRec **lccp) #endif lcc->nSuppGids = ucred_getgroups(peercred, &gids); if (lcc->nSuppGids > 0) { - lcc->pSuppGids = Xcalloc((lcc->nSuppGids) * sizeof(int)); + lcc->pSuppGids = calloc(lcc->nSuppGids, sizeof(int)); if (lcc->pSuppGids == NULL) { lcc->nSuppGids = 0; } else { @@ -1287,9 +1286,9 @@ FreeLocalClientCreds(LocalClientCredRec *lcc) { if (lcc != NULL) { if (lcc->nSuppGids > 0) { - Xfree(lcc->pSuppGids); + free(lcc->pSuppGids); } - Xfree(lcc); + free(lcc); } } @@ -1484,7 +1483,7 @@ GetHosts ( } if (n) { - *data = ptr = xalloc (n); + *data = ptr = malloc(n); if (!ptr) { return(BadAlloc); @@ -1743,7 +1742,7 @@ siTypeAdd(const char *typeName, siAddrMatchFunc addrMatch, } } - s = xalloc(sizeof(struct siType)); + s = malloc(sizeof(struct siType)); if (s == NULL) return BadAlloc; @@ -2085,7 +2084,7 @@ static Bool siLocalCredGetId(const char *addr, int len, siLocalCredPrivPtr lcPriv, int *id) { Bool parsedOK = FALSE; - char *addrbuf = xalloc(len + 1); + char *addrbuf = malloc(len + 1); if (addrbuf == NULL) { return FALSE; @@ -2119,7 +2118,7 @@ siLocalCredGetId(const char *addr, int len, siLocalCredPrivPtr lcPriv, int *id) } } - xfree(addrbuf); + free(addrbuf); return parsedOK; } diff --git a/xorg-server/os/connection.c b/xorg-server/os/connection.c index 73a37df49..f35a2f66a 100644 --- a/xorg-server/os/connection.c +++ b/xorg-server/os/connection.c @@ -1,1328 +1,1328 @@ -/*********************************************************** - -Copyright 1987, 1989, 1998 The Open Group - -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. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. - - -Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -******************************************************************/ -/***************************************************************** - * Stuff to create connections --- OS dependent - * - * EstablishNewConnections, CreateWellKnownSockets, ResetWellKnownSockets, - * CloseDownConnection, CheckConnections, AddEnabledDevice, - * RemoveEnabledDevice, OnlyListToOneClient, - * ListenToAllClients, - * - * (WaitForSomething is in its own file) - * - * In this implementation, a client socket table is not kept. - * Instead, what would be the index into the table is just the - * file descriptor of the socket. This won't work for if the - * socket ids aren't small nums (0 - 2^8) - * - *****************************************************************/ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#ifdef WIN32 -#include -#ifdef _DEBUG -#define DEBUG -#endif -#endif -#include -#include -#define XSERV_t -#define TRANS_SERVER -#define TRANS_REOPEN -#include -#include -#include -#include -#include -#include - -#ifndef WIN32 -#include - - - -#if defined(TCPCONN) || defined(STREAMSCONN) -# include -# include -# ifdef apollo -# ifndef NO_TCP_H -# include -# endif -# else -# ifdef CSRG_BASED -# include -# endif -# include -# endif -# include -#endif - -#include - -#endif /* WIN32 */ -#include "misc.h" /* for typedef of pointer */ -#include "osdep.h" -#include -#include "opaque.h" -#include "dixstruct.h" -#include "xace.h" - -#ifdef _MSC_VER -typedef int pid_t; -#endif - -#define Pid_t pid_t - -#ifdef DNETCONN -#include -#endif /* DNETCONN */ - -#ifdef HAS_GETPEERUCRED -# include -# include -#endif - -#ifdef XSERVER_DTRACE -# include -typedef const char *string; -# ifndef HAS_GETPEERUCRED -# define zoneid_t int -# endif -# include "../dix/Xserver-dtrace.h" -#endif - -static int lastfdesc; /* maximum file descriptor */ - -fd_set WellKnownConnections; /* Listener mask */ -fd_set EnabledDevices; /* mask for input devices that are on */ -fd_set AllSockets; /* select on this */ -fd_set AllClients; /* available clients */ -fd_set LastSelectMask; /* mask returned from last select call */ -fd_set ClientsWithInput; /* clients with FULL requests in buffer */ -fd_set ClientsWriteBlocked; /* clients who cannot receive output */ -fd_set OutputPending; /* clients with reply/event data ready to go */ -int MaxClients = 0; -Bool NewOutputPending; /* not yet attempted to write some new output */ -Bool AnyClientsWriteBlocked; /* true if some client blocked on write */ - -static Bool RunFromSmartParent; /* send SIGUSR1 to parent process */ -Bool PartialNetwork; /* continue even if unable to bind all addrs */ -static Pid_t ParentProcess; - -static Bool debug_conns = FALSE; - -fd_set IgnoredClientsWithInput; -static fd_set GrabImperviousClients; -static fd_set SavedAllClients; -static fd_set SavedAllSockets; -static fd_set SavedClientsWithInput; -int GrabInProgress = 0; - -#if !defined(WIN32) -int *ConnectionTranslation = NULL; -#else -/* - * On NT fds are not between 0 and MAXSOCKS, they are unrelated, and there is - * not even a known maximum value, so use something quite arbitrary for now. - * Do storage is a hash table of size 256. Collisions are handled in a linked - * list. - */ - -#undef MAXSOCKS -#define MAXSOCKS 500 -#undef MAXSELECT -#define MAXSELECT 500 - -struct _ct_node { - struct _ct_node *next; - int key; - int value; -}; - -struct _ct_node *ct_head[256]; - -void InitConnectionTranslation(void) -{ - bzero(ct_head, sizeof(ct_head)); -} - -int GetConnectionTranslation(int conn) -{ - struct _ct_node *node = ct_head[conn & 0xff]; - while (node != NULL) - { - if (node->key == conn) - return node->value; - node = node->next; - } - return 0; -} - -void SetConnectionTranslation(int conn, int client) -{ - struct _ct_node **node = ct_head + (conn & 0xff); - if (client == 0) /* remove entry */ - { - while (*node != NULL) - { - if ((*node)->key == conn) - { - struct _ct_node *temp = *node; - *node = (*node)->next; - free(temp); - return; - } - node = &((*node)->next); - } - return; - } else - { - while (*node != NULL) - { - if ((*node)->key == conn) - { - (*node)->value = client; - return; - } - node = &((*node)->next); - } - *node = xalloc(sizeof(struct _ct_node)); - (*node)->next = NULL; - (*node)->key = conn; - (*node)->value = client; - return; - } -} - -void ClearConnectionTranslation(void) -{ - unsigned i; - for (i = 0; i < 256; i++) - { - struct _ct_node *node = ct_head[i]; - while (node != NULL) - { - struct _ct_node *temp = node; - node = node->next; - xfree(temp); - } - } -} -#endif - -static XtransConnInfo *ListenTransConns = NULL; -static int *ListenTransFds = NULL; -static int ListenTransCount; - -static void ErrorConnMax(XtransConnInfo /* trans_conn */); - -static XtransConnInfo -lookup_trans_conn (int fd) -{ - if (ListenTransFds) - { - int i; - for (i = 0; i < ListenTransCount; i++) - if (ListenTransFds[i] == fd) - return ListenTransConns[i]; - } - - return (NULL); -} - -int -TransIsListening(char *protocol) -{ - /* look for this transport in the list of listeners */ - int i; - for (i = 0; i < ListenTransCount; i++) - { - if (!strcmp(protocol, ListenTransConns[i]->transptr->TransName)) - { - return 1; - } - } - - return 0; -} - - -/* Set MaxClients and lastfdesc, and allocate ConnectionTranslation */ - -void -InitConnectionLimits(void) -{ - lastfdesc = -1; - -#ifndef __CYGWIN__ - -#if !defined(XNO_SYSCONF) && defined(_SC_OPEN_MAX) - lastfdesc = sysconf(_SC_OPEN_MAX) - 1; -#endif - -#ifdef HAS_GETDTABLESIZE - if (lastfdesc < 0) - lastfdesc = getdtablesize() - 1; -#endif - -#ifdef _NFILE - if (lastfdesc < 0) - lastfdesc = _NFILE - 1; -#endif - -#endif /* __CYGWIN__ */ - - /* This is the fallback */ - if (lastfdesc < 0) - lastfdesc = MAXSOCKS; - - if (lastfdesc > MAXSELECT) - lastfdesc = MAXSELECT; - - if (lastfdesc > MAXCLIENTS) - { - lastfdesc = MAXCLIENTS; - if (debug_conns) - ErrorF( "REACHED MAXIMUM CLIENTS LIMIT %d\n", MAXCLIENTS); - } - MaxClients = lastfdesc; - -#ifdef DEBUG - ErrorF("InitConnectionLimits: MaxClients = %d\n", MaxClients); -#endif - -#if !defined(WIN32) - if (!ConnectionTranslation) - ConnectionTranslation = (int *)xnfalloc(sizeof(int)*(lastfdesc + 1)); -#else - InitConnectionTranslation(); -#endif -} - -/* - * If SIGUSR1 was set to SIG_IGN when the server started, assume that either - * - * a- The parent process is ignoring SIGUSR1 - * - * or - * - * b- The parent process is expecting a SIGUSR1 - * when the server is ready to accept connections - * - * In the first case, the signal will be harmless, in the second case, - * the signal will be quite useful. - */ -static void -InitParentProcess(void) -{ -#if !defined(WIN32) - OsSigHandlerPtr handler; - handler = OsSignal (SIGUSR1, SIG_IGN); - if ( handler == SIG_IGN) - RunFromSmartParent = TRUE; - OsSignal(SIGUSR1, handler); - ParentProcess = getppid (); -#endif -} - -void -NotifyParentProcess(void) -{ -#if !defined(WIN32) - if (RunFromSmartParent) { - if (ParentProcess > 1) { - kill (ParentProcess, SIGUSR1); - } - } -#endif -} - -/***************** - * CreateWellKnownSockets - * At initialization, create the sockets to listen on for new clients. - *****************/ - -void -CreateWellKnownSockets(void) -{ - int i; - int partial; - char port[20]; - - FD_ZERO(&AllSockets); - FD_ZERO(&AllClients); - FD_ZERO(&LastSelectMask); - FD_ZERO(&ClientsWithInput); - -#if !defined(WIN32) - for (i=0; i= 0) && - (ListenTransCount >= 1)) - { - if (!PartialNetwork && partial) - { - FatalError ("Failed to establish all listening sockets"); - } - else - { - ListenTransFds = xalloc (ListenTransCount * sizeof (int)); - - for (i = 0; i < ListenTransCount; i++) - { - int fd = _XSERVTransGetConnectionNumber (ListenTransConns[i]); - - ListenTransFds[i] = fd; - FD_SET (fd, &WellKnownConnections); - - if (!_XSERVTransIsLocal (ListenTransConns[i])) - { - DefineSelf (fd); - } - } - } - } - - if (!XFD_ANYSET (&WellKnownConnections)) - FatalError ("Cannot establish any listening sockets - Make sure an X server isn't already running"); -#if !defined(WIN32) - OsSignal (SIGPIPE, SIG_IGN); - OsSignal (SIGHUP, AutoResetServer); -#endif - OsSignal (SIGINT, GiveUp); - OsSignal (SIGTERM, GiveUp); - XFD_COPYSET (&WellKnownConnections, &AllSockets); - ResetHosts(display); - - InitParentProcess(); - -#ifdef XDMCP - XdmcpInit (); -#endif -} - -void -ResetWellKnownSockets (void) -{ - int i; - - ResetOsBuffers(); - - for (i = 0; i < ListenTransCount; i++) - { - int status = _XSERVTransResetListener (ListenTransConns[i]); - - if (status != TRANS_RESET_NOOP) - { - if (status == TRANS_RESET_FAILURE) - { - /* - * ListenTransConns[i] freed by xtrans. - * Remove it from out list. - */ - - FD_CLR (ListenTransFds[i], &WellKnownConnections); - ListenTransFds[i] = ListenTransFds[ListenTransCount - 1]; - ListenTransConns[i] = ListenTransConns[ListenTransCount - 1]; - ListenTransCount -= 1; - i -= 1; - } - else if (status == TRANS_RESET_NEW_FD) - { - /* - * A new file descriptor was allocated (the old one was closed) - */ - - int newfd = _XSERVTransGetConnectionNumber (ListenTransConns[i]); - - FD_CLR (ListenTransFds[i], &WellKnownConnections); - ListenTransFds[i] = newfd; - FD_SET(newfd, &WellKnownConnections); - } - } - } - - ResetAuthorization (); - ResetHosts(display); - /* - * restart XDMCP - */ -#ifdef XDMCP - XdmcpReset (); -#endif -} - -void -CloseWellKnownConnections(void) -{ - int i; - - for (i = 0; i < ListenTransCount; i++) - _XSERVTransClose (ListenTransConns[i]); -} - -static void -AuthAudit (ClientPtr client, Bool letin, - struct sockaddr *saddr, int len, - unsigned int proto_n, char *auth_proto, int auth_id) -{ - char addr[128]; - char *out = addr; - char client_uid_string[64]; - LocalClientCredRec *lcc; -#ifdef XSERVER_DTRACE - pid_t client_pid = -1; - zoneid_t client_zid = -1; -#endif - - if (!len) - strcpy(out, "local host"); - else - switch (saddr->sa_family) - { - case AF_UNSPEC: -#if defined(UNIXCONN) || defined(LOCALCONN) - case AF_UNIX: -#endif - strcpy(out, "local host"); - break; -#if defined(TCPCONN) || defined(STREAMSCONN) || defined(MNX_TCPCONN) - case AF_INET: - sprintf(out, "IP %s", - inet_ntoa(((struct sockaddr_in *) saddr)->sin_addr)); - break; -#if defined(IPv6) && defined(AF_INET6) - case AF_INET6: { - char ipaddr[INET6_ADDRSTRLEN]; - inet_ntop(AF_INET6, &((struct sockaddr_in6 *) saddr)->sin6_addr, - ipaddr, sizeof(ipaddr)); - sprintf(out, "IP %s", ipaddr); - } - break; -#endif -#endif -#ifdef DNETCONN - case AF_DECnet: - sprintf(out, "DN %s", - dnet_ntoa(&((struct sockaddr_dn *) saddr)->sdn_add)); - break; -#endif - default: - strcpy(out, "unknown address"); - } - - if (GetLocalClientCreds(client, &lcc) != -1) { - int slen; /* length written to client_uid_string */ - - strcpy(client_uid_string, " ( "); - slen = 3; - - if (lcc->fieldsSet & LCC_UID_SET) { - snprintf(client_uid_string + slen, - sizeof(client_uid_string) - slen, - "uid=%ld ", (long) lcc->euid); - slen = strlen(client_uid_string); - } - - if (lcc->fieldsSet & LCC_GID_SET) { - snprintf(client_uid_string + slen, - sizeof(client_uid_string) - slen, - "gid=%ld ", (long) lcc->egid); - slen = strlen(client_uid_string); - } - - if (lcc->fieldsSet & LCC_PID_SET) { -#ifdef XSERVER_DTRACE - client_pid = lcc->pid; -#endif - snprintf(client_uid_string + slen, - sizeof(client_uid_string) - slen, - "pid=%ld ", (long) lcc->pid); - slen = strlen(client_uid_string); - } - - if (lcc->fieldsSet & LCC_ZID_SET) { -#ifdef XSERVER_DTRACE - client_zid = lcc->zoneid; -#endif - snprintf(client_uid_string + slen, - sizeof(client_uid_string) - slen, - "zoneid=%ld ", (long) lcc->zoneid); - slen = strlen(client_uid_string); - } - - snprintf(client_uid_string + slen, sizeof(client_uid_string) - slen, - ")"); - FreeLocalClientCreds(lcc); - } - else { - client_uid_string[0] = '\0'; - } - -#ifdef XSERVER_DTRACE - XSERVER_CLIENT_AUTH(client->index, addr, client_pid, client_zid); -#endif - if (auditTrailLevel > 1) { - if (proto_n) - AuditF("client %d %s from %s%s\n Auth name: %.*s ID: %d\n", - client->index, letin ? "connected" : "rejected", addr, - client_uid_string, (int)proto_n, auth_proto, auth_id); - else - AuditF("client %d %s from %s%s\n", - client->index, letin ? "connected" : "rejected", addr, - client_uid_string); - - } -} - -XID -AuthorizationIDOfClient(ClientPtr client) -{ - if (client->osPrivate) - return ((OsCommPtr)client->osPrivate)->auth_id; - else - return None; -} - - -/***************************************************************** - * ClientAuthorized - * - * Sent by the client at connection setup: - * typedef struct _xConnClientPrefix { - * CARD8 byteOrder; - * BYTE pad; - * CARD16 majorVersion, minorVersion; - * CARD16 nbytesAuthProto; - * CARD16 nbytesAuthString; - * } xConnClientPrefix; - * - * It is hoped that eventually one protocol will be agreed upon. In the - * mean time, a server that implements a different protocol than the - * client expects, or a server that only implements the host-based - * mechanism, will simply ignore this information. - * - *****************************************************************/ - -char * -ClientAuthorized(ClientPtr client, - unsigned int proto_n, char *auth_proto, - unsigned int string_n, char *auth_string) -{ - OsCommPtr priv; - Xtransaddr *from = NULL; - int family; - int fromlen; - XID auth_id; - char *reason = NULL; - XtransConnInfo trans_conn; - - priv = (OsCommPtr)client->osPrivate; - trans_conn = priv->trans_conn; - - /* Allow any client to connect without authorization on a launchd socket, - because it is securely created -- this prevents a race condition on launch */ - if(trans_conn->flags & TRANS_NOXAUTH) { - auth_id = (XID) 0L; - } else { - auth_id = CheckAuthorization (proto_n, auth_proto, string_n, auth_string, client, &reason); - } - - if (auth_id == (XID) ~0L) - { - if (_XSERVTransGetPeerAddr(trans_conn, &family, &fromlen, &from) != -1) - { - if (InvalidHost ((struct sockaddr *) from, fromlen, client)) - AuthAudit(client, FALSE, (struct sockaddr *) from, - fromlen, proto_n, auth_proto, auth_id); - else - { - auth_id = (XID) 0; -#ifdef XSERVER_DTRACE - if ((auditTrailLevel > 1) || XSERVER_CLIENT_AUTH_ENABLED()) -#else - if (auditTrailLevel > 1) -#endif - AuthAudit(client, TRUE, - (struct sockaddr *) from, fromlen, - proto_n, auth_proto, auth_id); - } - - xfree (from); - } - - if (auth_id == (XID) ~0L) { - if (reason) - return reason; - else - return "Client is not authorized to connect to Server"; - } - } -#ifdef XSERVER_DTRACE - else if ((auditTrailLevel > 1) || XSERVER_CLIENT_AUTH_ENABLED()) -#else - else if (auditTrailLevel > 1) -#endif - { - if (_XSERVTransGetPeerAddr (trans_conn, - &family, &fromlen, &from) != -1) - { - AuthAudit(client, TRUE, (struct sockaddr *) from, fromlen, - proto_n, auth_proto, auth_id); - - xfree (from); - } - } - priv->auth_id = auth_id; - priv->conn_time = 0; - -#ifdef XDMCP - /* indicate to Xdmcp protocol that we've opened new client */ - XdmcpOpenDisplay(priv->fd); -#endif /* XDMCP */ - - XaceHook(XACE_AUTH_AVAIL, client, auth_id); - - /* At this point, if the client is authorized to change the access control - * list, we should getpeername() information, and add the client to - * the selfhosts list. It's not really the host machine, but the - * true purpose of the selfhosts list is to see who may change the - * access control list. - */ - return((char *)NULL); -} - -static ClientPtr -AllocNewConnection (XtransConnInfo trans_conn, int fd, CARD32 conn_time) -{ - OsCommPtr oc; - ClientPtr client; - - if ( -#ifndef WIN32 - fd >= lastfdesc -#else - XFD_SETCOUNT(&AllClients) >= MaxClients -#endif - ) - return NullClient; - oc = xalloc(sizeof(OsCommRec)); - if (!oc) - return NullClient; - oc->trans_conn = trans_conn; - oc->fd = fd; - oc->input = (ConnectionInputPtr)NULL; - oc->output = (ConnectionOutputPtr)NULL; - oc->auth_id = None; - oc->conn_time = conn_time; - if (!(client = NextAvailableClient((pointer)oc))) - { - xfree (oc); - return NullClient; - } -#if !defined(WIN32) - ConnectionTranslation[fd] = client->index; -#else - SetConnectionTranslation(fd, client->index); -#endif - if (GrabInProgress) - { - FD_SET(fd, &SavedAllClients); - FD_SET(fd, &SavedAllSockets); - } - else - { - FD_SET(fd, &AllClients); - FD_SET(fd, &AllSockets); - } - -#ifdef DEBUG - ErrorF("AllocNewConnection: client index = %d, socket fd = %d\n", - client->index, fd); -#endif -#ifdef XSERVER_DTRACE - XSERVER_CLIENT_CONNECT(client->index, fd); -#endif - - return client; -} - -/***************** - * EstablishNewConnections - * If anyone is waiting on listened sockets, accept them. - * Returns a mask with indices of new clients. Updates AllClients - * and AllSockets. - *****************/ - -/*ARGSUSED*/ -Bool -EstablishNewConnections(ClientPtr clientUnused, pointer closure) -{ - fd_set readyconnections; /* set of listeners that are ready */ - int curconn; /* fd of listener that's ready */ - register int newconn; /* fd of new client */ - CARD32 connect_time; - register int i; - register ClientPtr client; - register OsCommPtr oc; - fd_set tmask; - - XFD_ANDSET (&tmask, (fd_set*)closure, &WellKnownConnections); - XFD_COPYSET(&tmask, &readyconnections); - if (!XFD_ANYSET(&readyconnections)) - return TRUE; - connect_time = GetTimeInMillis(); - /* kill off stragglers */ - for (i=1; iosPrivate); - if ((oc && (oc->conn_time != 0) && - (connect_time - oc->conn_time) >= TimeOutValue) || - (client->noClientException != Success && !client->clientGone)) - CloseDownClient(client); - } - } -#ifndef WIN32 - for (i = 0; i < howmany(XFD_SETSIZE, NFDBITS); i++) - { - while (readyconnections.fds_bits[i]) -#else - for (i = 0; i < XFD_SETCOUNT(&readyconnections); i++) -#endif - { - XtransConnInfo trans_conn, new_trans_conn; - int status; - -#ifndef WIN32 - curconn = mffs (readyconnections.fds_bits[i]) - 1; - readyconnections.fds_bits[i] &= ~((fd_mask)1 << curconn); - curconn += (i * (sizeof(fd_mask)*8)); -#else - curconn = XFD_FD(&readyconnections, i); -#endif - - if ((trans_conn = lookup_trans_conn (curconn)) == NULL) - continue; - - if ((new_trans_conn = _XSERVTransAccept (trans_conn, &status)) == NULL) - continue; - - newconn = _XSERVTransGetConnectionNumber (new_trans_conn); - - if (newconn < lastfdesc) - { - int clientid; -#if !defined(WIN32) - clientid = ConnectionTranslation[newconn]; -#else - clientid = GetConnectionTranslation(newconn); -#endif - if(clientid && (client = clients[clientid])) - CloseDownClient(client); - } - - _XSERVTransSetOption(new_trans_conn, TRANS_NONBLOCKING, 1); - - if (!AllocNewConnection (new_trans_conn, newconn, connect_time)) - { - ErrorConnMax(new_trans_conn); - _XSERVTransClose(new_trans_conn); - } - - if(trans_conn->flags & TRANS_NOXAUTH) - new_trans_conn->flags = new_trans_conn->flags | TRANS_NOXAUTH; - - } -#ifndef WIN32 - } -#endif - return TRUE; -} - -#define NOROOM "Maximum number of clients reached" - -/************ - * ErrorConnMax - * Fail a connection due to lack of client or file descriptor space - ************/ - -static void -ErrorConnMax(XtransConnInfo trans_conn) -{ - int fd = _XSERVTransGetConnectionNumber (trans_conn); - xConnSetupPrefix csp; - char pad[3]; - struct iovec iov[3]; - char byteOrder = 0; - int whichbyte = 1; - struct timeval waittime; - fd_set mask; - - /* if these seems like a lot of trouble to go to, it probably is */ - waittime.tv_sec = BOTIMEOUT / MILLI_PER_SECOND; - waittime.tv_usec = (BOTIMEOUT % MILLI_PER_SECOND) * - (1000000 / MILLI_PER_SECOND); - FD_ZERO(&mask); - FD_SET(fd, &mask); - (void)Select(fd + 1, &mask, NULL, NULL, &waittime); - /* try to read the byte-order of the connection */ - (void)_XSERVTransRead(trans_conn, &byteOrder, 1); - if ((byteOrder == 'l') || (byteOrder == 'B')) - { - csp.success = xFalse; - csp.lengthReason = sizeof(NOROOM) - 1; - csp.length = (sizeof(NOROOM) + 2) >> 2; - csp.majorVersion = X_PROTOCOL; - csp.minorVersion = X_PROTOCOL_REVISION; - if (((*(char *) &whichbyte) && (byteOrder == 'B')) || - (!(*(char *) &whichbyte) && (byteOrder == 'l'))) - { - swaps(&csp.majorVersion, whichbyte); - swaps(&csp.minorVersion, whichbyte); - swaps(&csp.length, whichbyte); - } - iov[0].iov_len = sz_xConnSetupPrefix; - iov[0].iov_base = (char *) &csp; - iov[1].iov_len = csp.lengthReason; - iov[1].iov_base = NOROOM; - iov[2].iov_len = (4 - (csp.lengthReason & 3)) & 3; - iov[2].iov_base = pad; - (void)_XSERVTransWritev(trans_conn, iov, 3); - } -} - -/************ - * CloseDownFileDescriptor: - * Remove this file descriptor and it's I/O buffers, etc. - ************/ - -static void -CloseDownFileDescriptor(OsCommPtr oc) -{ - int connection = oc->fd; - - if (oc->trans_conn) { - _XSERVTransDisconnect(oc->trans_conn); - _XSERVTransClose(oc->trans_conn); - } -#ifndef WIN32 - ConnectionTranslation[connection] = 0; -#else - SetConnectionTranslation(connection, 0); -#endif - FD_CLR(connection, &AllSockets); - FD_CLR(connection, &AllClients); - FD_CLR(connection, &ClientsWithInput); - FD_CLR(connection, &GrabImperviousClients); - if (GrabInProgress) - { - FD_CLR(connection, &SavedAllSockets); - FD_CLR(connection, &SavedAllClients); - FD_CLR(connection, &SavedClientsWithInput); - } - FD_CLR(connection, &ClientsWriteBlocked); - if (!XFD_ANYSET(&ClientsWriteBlocked)) - AnyClientsWriteBlocked = FALSE; - FD_CLR(connection, &OutputPending); -} - -/***************** - * CheckConnections - * Some connection has died, go find which one and shut it down - * The file descriptor has been closed, but is still in AllClients. - * If would truly be wonderful if select() would put the bogus - * file descriptors in the exception mask, but nooooo. So we have - * to check each and every socket individually. - *****************/ - -void -CheckConnections(void) -{ -#ifndef WIN32 - fd_mask mask; -#endif - fd_set tmask; - int curclient, curoff; - int i; - struct timeval notime; - int r; -#ifdef WIN32 - fd_set savedAllClients; -#endif - - notime.tv_sec = 0; - notime.tv_usec = 0; - -#ifndef WIN32 - for (i=0; i 0) - CloseDownClient(clients[ConnectionTranslation[curclient]]); - mask &= ~((fd_mask)1 << curoff); - } - } -#else - XFD_COPYSET(&AllClients, &savedAllClients); - for (i = 0; i < XFD_SETCOUNT(&savedAllClients); i++) - { - curclient = XFD_FD(&savedAllClients, i); - FD_ZERO(&tmask); - FD_SET(curclient, &tmask); - do { - r = Select (curclient + 1, &tmask, NULL, NULL, ¬ime); - } while (r < 0 && (errno == EINTR || errno == EAGAIN)); - if (r < 0) - if (GetConnectionTranslation(curclient) > 0) - CloseDownClient(clients[GetConnectionTranslation(curclient)]); - } -#endif -} - - -/***************** - * CloseDownConnection - * Delete client from AllClients and free resources - *****************/ - -void -CloseDownConnection(ClientPtr client) -{ - OsCommPtr oc = (OsCommPtr)client->osPrivate; - -#ifdef DEBUG - ErrorF("CloseDownConnection: client index = %d, socket fd = %d\n", - client->index, oc->fd); -#endif - if (oc->output && oc->output->count) - FlushClient(client, oc, (char *)NULL, 0); -#ifdef XDMCP - XdmcpCloseDisplay(oc->fd); -#endif - CloseDownFileDescriptor(oc); - FreeOsBuffers(oc); - xfree(client->osPrivate); - client->osPrivate = (pointer)NULL; - if (auditTrailLevel > 1) - AuditF("client %d disconnected\n", client->index); -} - -void -AddGeneralSocket(int fd) -{ - FD_SET(fd, &AllSockets); - if (GrabInProgress) - FD_SET(fd, &SavedAllSockets); -} - -void -AddEnabledDevice(int fd) -{ - FD_SET(fd, &EnabledDevices); - AddGeneralSocket(fd); -} - -void -RemoveGeneralSocket(int fd) -{ - FD_CLR(fd, &AllSockets); - if (GrabInProgress) - FD_CLR(fd, &SavedAllSockets); -} - -void -RemoveEnabledDevice(int fd) -{ - FD_CLR(fd, &EnabledDevices); - RemoveGeneralSocket(fd); -} - -/***************** - * OnlyListenToOneClient: - * Only accept requests from one client. Continue to handle new - * connections, but don't take any protocol requests from the new - * ones. Note that if GrabInProgress is set, EstablishNewConnections - * needs to put new clients into SavedAllSockets and SavedAllClients. - * Note also that there is no timeout for this in the protocol. - * This routine is "undone" by ListenToAllClients() - *****************/ - -int -OnlyListenToOneClient(ClientPtr client) -{ - OsCommPtr oc = (OsCommPtr)client->osPrivate; - int rc, connection = oc->fd; - - rc = XaceHook(XACE_SERVER_ACCESS, client, DixGrabAccess); - if (rc != Success) - return rc; - - if (! GrabInProgress) - { - XFD_COPYSET(&ClientsWithInput, &SavedClientsWithInput); - XFD_ANDSET(&ClientsWithInput, - &ClientsWithInput, &GrabImperviousClients); - if (FD_ISSET(connection, &SavedClientsWithInput)) - { - FD_CLR(connection, &SavedClientsWithInput); - FD_SET(connection, &ClientsWithInput); - } - XFD_UNSET(&SavedClientsWithInput, &GrabImperviousClients); - XFD_COPYSET(&AllSockets, &SavedAllSockets); - XFD_COPYSET(&AllClients, &SavedAllClients); - XFD_UNSET(&AllSockets, &AllClients); - XFD_ANDSET(&AllClients, &AllClients, &GrabImperviousClients); - FD_SET(connection, &AllClients); - XFD_ORSET(&AllSockets, &AllSockets, &AllClients); - GrabInProgress = client->index; - } - return rc; -} - -/**************** - * ListenToAllClients: - * Undoes OnlyListentToOneClient() - ****************/ - -void -ListenToAllClients(void) -{ - if (GrabInProgress) - { - XFD_ORSET(&AllSockets, &AllSockets, &SavedAllSockets); - XFD_ORSET(&AllClients, &AllClients, &SavedAllClients); - XFD_ORSET(&ClientsWithInput, &ClientsWithInput, &SavedClientsWithInput); - GrabInProgress = 0; - } -} - -/**************** - * IgnoreClient - * Removes one client from input masks. - * Must have cooresponding call to AttendClient. - ****************/ - -void -IgnoreClient (ClientPtr client) -{ - OsCommPtr oc = (OsCommPtr)client->osPrivate; - int connection = oc->fd; - - isItTimeToYield = TRUE; - if (!GrabInProgress || FD_ISSET(connection, &AllClients)) - { - if (FD_ISSET (connection, &ClientsWithInput)) - FD_SET(connection, &IgnoredClientsWithInput); - else - FD_CLR(connection, &IgnoredClientsWithInput); - FD_CLR(connection, &ClientsWithInput); - FD_CLR(connection, &AllSockets); - FD_CLR(connection, &AllClients); - FD_CLR(connection, &LastSelectMask); - } - else - { - if (FD_ISSET (connection, &SavedClientsWithInput)) - FD_SET(connection, &IgnoredClientsWithInput); - else - FD_CLR(connection, &IgnoredClientsWithInput); - FD_CLR(connection, &SavedClientsWithInput); - FD_CLR(connection, &SavedAllSockets); - FD_CLR(connection, &SavedAllClients); - } -} - -/**************** - * AttendClient - * Adds one client back into the input masks. - ****************/ - -void -AttendClient (ClientPtr client) -{ - OsCommPtr oc = (OsCommPtr)client->osPrivate; - int connection = oc->fd; - if (!GrabInProgress || GrabInProgress == client->index || - FD_ISSET(connection, &GrabImperviousClients)) - { - FD_SET(connection, &AllClients); - FD_SET(connection, &AllSockets); - FD_SET(connection, &LastSelectMask); - if (FD_ISSET (connection, &IgnoredClientsWithInput)) - FD_SET(connection, &ClientsWithInput); - } - else - { - FD_SET(connection, &SavedAllClients); - FD_SET(connection, &SavedAllSockets); - if (FD_ISSET(connection, &IgnoredClientsWithInput)) - FD_SET(connection, &SavedClientsWithInput); - } -} - -/* make client impervious to grabs; assume only executing client calls this */ - -void -MakeClientGrabImpervious(ClientPtr client) -{ - OsCommPtr oc = (OsCommPtr)client->osPrivate; - int connection = oc->fd; - - FD_SET(connection, &GrabImperviousClients); - - if (ServerGrabCallback) - { - ServerGrabInfoRec grabinfo; - grabinfo.client = client; - grabinfo.grabstate = CLIENT_IMPERVIOUS; - CallCallbacks(&ServerGrabCallback, &grabinfo); - } -} - -/* make client pervious to grabs; assume only executing client calls this */ - -void -MakeClientGrabPervious(ClientPtr client) -{ - OsCommPtr oc = (OsCommPtr)client->osPrivate; - int connection = oc->fd; - - FD_CLR(connection, &GrabImperviousClients); - if (GrabInProgress && (GrabInProgress != client->index)) - { - if (FD_ISSET(connection, &ClientsWithInput)) - { - FD_SET(connection, &SavedClientsWithInput); - FD_CLR(connection, &ClientsWithInput); - } - FD_CLR(connection, &AllSockets); - FD_CLR(connection, &AllClients); - isItTimeToYield = TRUE; - } - - if (ServerGrabCallback) - { - ServerGrabInfoRec grabinfo; - grabinfo.client = client; - grabinfo.grabstate = CLIENT_PERVIOUS; - CallCallbacks(&ServerGrabCallback, &grabinfo); - } -} - -#ifdef XQUARTZ -/* Add a fd (from launchd) to our listeners */ -void ListenOnOpenFD(int fd, int noxauth) { - char port[256]; - XtransConnInfo ciptr; - const char *display_env = getenv("DISPLAY"); - - if(display_env && (strncmp(display_env, "/tmp/launch", 11) == 0)) { - /* Make the path the launchd socket if our DISPLAY is set right */ - strcpy(port, display_env); - } else { - /* Just some default so things don't break and die. */ - sprintf(port, ":%d", atoi(display)); - } - - /* Make our XtransConnInfo - * TRANS_SOCKET_LOCAL_INDEX = 5 from Xtrans.c - */ - ciptr = _XSERVTransReopenCOTSServer(5, fd, port); - if(ciptr == NULL) { - ErrorF("Got NULL while trying to Reopen launchd port.\n"); - return; - } - - if(noxauth) - ciptr->flags = ciptr->flags | TRANS_NOXAUTH; - - /* Allocate space to store it */ - ListenTransFds = (int *) xrealloc(ListenTransFds, (ListenTransCount + 1) * sizeof (int)); - ListenTransConns = (XtransConnInfo *) xrealloc(ListenTransConns, (ListenTransCount + 1) * sizeof (XtransConnInfo)); - - /* Store it */ - ListenTransConns[ListenTransCount] = ciptr; - ListenTransFds[ListenTransCount] = fd; - - FD_SET(fd, &WellKnownConnections); - FD_SET(fd, &AllSockets); - - /* Increment the count */ - ListenTransCount++; - - /* This *might* not be needed... /shrug */ - ResetAuthorization(); - ResetHosts(display); -#ifdef XDMCP - XdmcpReset(); -#endif -} - -#endif +/*********************************************************** + +Copyright 1987, 1989, 1998 The Open Group + +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. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/***************************************************************** + * Stuff to create connections --- OS dependent + * + * EstablishNewConnections, CreateWellKnownSockets, ResetWellKnownSockets, + * CloseDownConnection, CheckConnections, AddEnabledDevice, + * RemoveEnabledDevice, OnlyListToOneClient, + * ListenToAllClients, + * + * (WaitForSomething is in its own file) + * + * In this implementation, a client socket table is not kept. + * Instead, what would be the index into the table is just the + * file descriptor of the socket. This won't work for if the + * socket ids aren't small nums (0 - 2^8) + * + *****************************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#ifdef WIN32 +#include +#ifdef _DEBUG +#define DEBUG +#endif +#endif +#include +#include +#define XSERV_t +#define TRANS_SERVER +#define TRANS_REOPEN +#include +#include +#include +#include +#include +#include + +#ifndef WIN32 +#include + + + +#if defined(TCPCONN) || defined(STREAMSCONN) +# include +# include +# ifdef apollo +# ifndef NO_TCP_H +# include +# endif +# else +# ifdef CSRG_BASED +# include +# endif +# include +# endif +# include +#endif + +#include + +#endif /* WIN32 */ +#include "misc.h" /* for typedef of pointer */ +#include "osdep.h" +#include +#include "opaque.h" +#include "dixstruct.h" +#include "xace.h" + +#ifdef _MSC_VER +typedef int pid_t; +#endif + +#define Pid_t pid_t + +#ifdef DNETCONN +#include +#endif /* DNETCONN */ + +#ifdef HAS_GETPEERUCRED +# include +# include +#endif + +#ifdef XSERVER_DTRACE +# include +typedef const char *string; +# ifndef HAS_GETPEERUCRED +# define zoneid_t int +# endif +# include "../dix/Xserver-dtrace.h" +#endif + +static int lastfdesc; /* maximum file descriptor */ + +fd_set WellKnownConnections; /* Listener mask */ +fd_set EnabledDevices; /* mask for input devices that are on */ +fd_set AllSockets; /* select on this */ +fd_set AllClients; /* available clients */ +fd_set LastSelectMask; /* mask returned from last select call */ +fd_set ClientsWithInput; /* clients with FULL requests in buffer */ +fd_set ClientsWriteBlocked; /* clients who cannot receive output */ +fd_set OutputPending; /* clients with reply/event data ready to go */ +int MaxClients = 0; +Bool NewOutputPending; /* not yet attempted to write some new output */ +Bool AnyClientsWriteBlocked; /* true if some client blocked on write */ + +static Bool RunFromSmartParent; /* send SIGUSR1 to parent process */ +Bool PartialNetwork; /* continue even if unable to bind all addrs */ +static Pid_t ParentProcess; + +static Bool debug_conns = FALSE; + +fd_set IgnoredClientsWithInput; +static fd_set GrabImperviousClients; +static fd_set SavedAllClients; +static fd_set SavedAllSockets; +static fd_set SavedClientsWithInput; +int GrabInProgress = 0; + +#if !defined(WIN32) +int *ConnectionTranslation = NULL; +#else +/* + * On NT fds are not between 0 and MAXSOCKS, they are unrelated, and there is + * not even a known maximum value, so use something quite arbitrary for now. + * Do storage is a hash table of size 256. Collisions are handled in a linked + * list. + */ + +#undef MAXSOCKS +#define MAXSOCKS 500 +#undef MAXSELECT +#define MAXSELECT 500 + +struct _ct_node { + struct _ct_node *next; + int key; + int value; +}; + +struct _ct_node *ct_head[256]; + +void InitConnectionTranslation(void) +{ + bzero(ct_head, sizeof(ct_head)); +} + +int GetConnectionTranslation(int conn) +{ + struct _ct_node *node = ct_head[conn & 0xff]; + while (node != NULL) + { + if (node->key == conn) + return node->value; + node = node->next; + } + return 0; +} + +void SetConnectionTranslation(int conn, int client) +{ + struct _ct_node **node = ct_head + (conn & 0xff); + if (client == 0) /* remove entry */ + { + while (*node != NULL) + { + if ((*node)->key == conn) + { + struct _ct_node *temp = *node; + *node = (*node)->next; + free(temp); + return; + } + node = &((*node)->next); + } + return; + } else + { + while (*node != NULL) + { + if ((*node)->key == conn) + { + (*node)->value = client; + return; + } + node = &((*node)->next); + } + *node = malloc(sizeof(struct _ct_node)); + (*node)->next = NULL; + (*node)->key = conn; + (*node)->value = client; + return; + } +} + +void ClearConnectionTranslation(void) +{ + unsigned i; + for (i = 0; i < 256; i++) + { + struct _ct_node *node = ct_head[i]; + while (node != NULL) + { + struct _ct_node *temp = node; + node = node->next; + free(temp); + } + } +} +#endif + +static XtransConnInfo *ListenTransConns = NULL; +static int *ListenTransFds = NULL; +static int ListenTransCount; + +static void ErrorConnMax(XtransConnInfo /* trans_conn */); + +static XtransConnInfo +lookup_trans_conn (int fd) +{ + if (ListenTransFds) + { + int i; + for (i = 0; i < ListenTransCount; i++) + if (ListenTransFds[i] == fd) + return ListenTransConns[i]; + } + + return (NULL); +} + +int +TransIsListening(char *protocol) +{ + /* look for this transport in the list of listeners */ + int i; + for (i = 0; i < ListenTransCount; i++) + { + if (!strcmp(protocol, ListenTransConns[i]->transptr->TransName)) + { + return 1; + } + } + + return 0; +} + + +/* Set MaxClients and lastfdesc, and allocate ConnectionTranslation */ + +void +InitConnectionLimits(void) +{ + lastfdesc = -1; + +#ifndef __CYGWIN__ + +#if !defined(XNO_SYSCONF) && defined(_SC_OPEN_MAX) + lastfdesc = sysconf(_SC_OPEN_MAX) - 1; +#endif + +#ifdef HAS_GETDTABLESIZE + if (lastfdesc < 0) + lastfdesc = getdtablesize() - 1; +#endif + +#ifdef _NFILE + if (lastfdesc < 0) + lastfdesc = _NFILE - 1; +#endif + +#endif /* __CYGWIN__ */ + + /* This is the fallback */ + if (lastfdesc < 0) + lastfdesc = MAXSOCKS; + + if (lastfdesc > MAXSELECT) + lastfdesc = MAXSELECT; + + if (lastfdesc > MAXCLIENTS) + { + lastfdesc = MAXCLIENTS; + if (debug_conns) + ErrorF( "REACHED MAXIMUM CLIENTS LIMIT %d\n", MAXCLIENTS); + } + MaxClients = lastfdesc; + +#ifdef DEBUG + ErrorF("InitConnectionLimits: MaxClients = %d\n", MaxClients); +#endif + +#if !defined(WIN32) + if (!ConnectionTranslation) + ConnectionTranslation = (int *)xnfalloc(sizeof(int)*(lastfdesc + 1)); +#else + InitConnectionTranslation(); +#endif +} + +/* + * If SIGUSR1 was set to SIG_IGN when the server started, assume that either + * + * a- The parent process is ignoring SIGUSR1 + * + * or + * + * b- The parent process is expecting a SIGUSR1 + * when the server is ready to accept connections + * + * In the first case, the signal will be harmless, in the second case, + * the signal will be quite useful. + */ +static void +InitParentProcess(void) +{ +#if !defined(WIN32) + OsSigHandlerPtr handler; + handler = OsSignal (SIGUSR1, SIG_IGN); + if ( handler == SIG_IGN) + RunFromSmartParent = TRUE; + OsSignal(SIGUSR1, handler); + ParentProcess = getppid (); +#endif +} + +void +NotifyParentProcess(void) +{ +#if !defined(WIN32) + if (RunFromSmartParent) { + if (ParentProcess > 1) { + kill (ParentProcess, SIGUSR1); + } + } +#endif +} + +/***************** + * CreateWellKnownSockets + * At initialization, create the sockets to listen on for new clients. + *****************/ + +void +CreateWellKnownSockets(void) +{ + int i; + int partial; + char port[20]; + + FD_ZERO(&AllSockets); + FD_ZERO(&AllClients); + FD_ZERO(&LastSelectMask); + FD_ZERO(&ClientsWithInput); + +#if !defined(WIN32) + for (i=0; i= 0) && + (ListenTransCount >= 1)) + { + if (!PartialNetwork && partial) + { + FatalError ("Failed to establish all listening sockets"); + } + else + { + ListenTransFds = malloc(ListenTransCount * sizeof (int)); + + for (i = 0; i < ListenTransCount; i++) + { + int fd = _XSERVTransGetConnectionNumber (ListenTransConns[i]); + + ListenTransFds[i] = fd; + FD_SET (fd, &WellKnownConnections); + + if (!_XSERVTransIsLocal (ListenTransConns[i])) + { + DefineSelf (fd); + } + } + } + } + + if (!XFD_ANYSET (&WellKnownConnections)) + FatalError ("Cannot establish any listening sockets - Make sure an X server isn't already running"); +#if !defined(WIN32) + OsSignal (SIGPIPE, SIG_IGN); + OsSignal (SIGHUP, AutoResetServer); +#endif + OsSignal (SIGINT, GiveUp); + OsSignal (SIGTERM, GiveUp); + XFD_COPYSET (&WellKnownConnections, &AllSockets); + ResetHosts(display); + + InitParentProcess(); + +#ifdef XDMCP + XdmcpInit (); +#endif +} + +void +ResetWellKnownSockets (void) +{ + int i; + + ResetOsBuffers(); + + for (i = 0; i < ListenTransCount; i++) + { + int status = _XSERVTransResetListener (ListenTransConns[i]); + + if (status != TRANS_RESET_NOOP) + { + if (status == TRANS_RESET_FAILURE) + { + /* + * ListenTransConns[i] freed by xtrans. + * Remove it from out list. + */ + + FD_CLR (ListenTransFds[i], &WellKnownConnections); + ListenTransFds[i] = ListenTransFds[ListenTransCount - 1]; + ListenTransConns[i] = ListenTransConns[ListenTransCount - 1]; + ListenTransCount -= 1; + i -= 1; + } + else if (status == TRANS_RESET_NEW_FD) + { + /* + * A new file descriptor was allocated (the old one was closed) + */ + + int newfd = _XSERVTransGetConnectionNumber (ListenTransConns[i]); + + FD_CLR (ListenTransFds[i], &WellKnownConnections); + ListenTransFds[i] = newfd; + FD_SET(newfd, &WellKnownConnections); + } + } + } + + ResetAuthorization (); + ResetHosts(display); + /* + * restart XDMCP + */ +#ifdef XDMCP + XdmcpReset (); +#endif +} + +void +CloseWellKnownConnections(void) +{ + int i; + + for (i = 0; i < ListenTransCount; i++) + _XSERVTransClose (ListenTransConns[i]); +} + +static void +AuthAudit (ClientPtr client, Bool letin, + struct sockaddr *saddr, int len, + unsigned int proto_n, char *auth_proto, int auth_id) +{ + char addr[128]; + char *out = addr; + char client_uid_string[64]; + LocalClientCredRec *lcc; +#ifdef XSERVER_DTRACE + pid_t client_pid = -1; + zoneid_t client_zid = -1; +#endif + + if (!len) + strcpy(out, "local host"); + else + switch (saddr->sa_family) + { + case AF_UNSPEC: +#if defined(UNIXCONN) || defined(LOCALCONN) + case AF_UNIX: +#endif + strcpy(out, "local host"); + break; +#if defined(TCPCONN) || defined(STREAMSCONN) || defined(MNX_TCPCONN) + case AF_INET: + sprintf(out, "IP %s", + inet_ntoa(((struct sockaddr_in *) saddr)->sin_addr)); + break; +#if defined(IPv6) && defined(AF_INET6) + case AF_INET6: { + char ipaddr[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET6, &((struct sockaddr_in6 *) saddr)->sin6_addr, + ipaddr, sizeof(ipaddr)); + sprintf(out, "IP %s", ipaddr); + } + break; +#endif +#endif +#ifdef DNETCONN + case AF_DECnet: + sprintf(out, "DN %s", + dnet_ntoa(&((struct sockaddr_dn *) saddr)->sdn_add)); + break; +#endif + default: + strcpy(out, "unknown address"); + } + + if (GetLocalClientCreds(client, &lcc) != -1) { + int slen; /* length written to client_uid_string */ + + strcpy(client_uid_string, " ( "); + slen = 3; + + if (lcc->fieldsSet & LCC_UID_SET) { + snprintf(client_uid_string + slen, + sizeof(client_uid_string) - slen, + "uid=%ld ", (long) lcc->euid); + slen = strlen(client_uid_string); + } + + if (lcc->fieldsSet & LCC_GID_SET) { + snprintf(client_uid_string + slen, + sizeof(client_uid_string) - slen, + "gid=%ld ", (long) lcc->egid); + slen = strlen(client_uid_string); + } + + if (lcc->fieldsSet & LCC_PID_SET) { +#ifdef XSERVER_DTRACE + client_pid = lcc->pid; +#endif + snprintf(client_uid_string + slen, + sizeof(client_uid_string) - slen, + "pid=%ld ", (long) lcc->pid); + slen = strlen(client_uid_string); + } + + if (lcc->fieldsSet & LCC_ZID_SET) { +#ifdef XSERVER_DTRACE + client_zid = lcc->zoneid; +#endif + snprintf(client_uid_string + slen, + sizeof(client_uid_string) - slen, + "zoneid=%ld ", (long) lcc->zoneid); + slen = strlen(client_uid_string); + } + + snprintf(client_uid_string + slen, sizeof(client_uid_string) - slen, + ")"); + FreeLocalClientCreds(lcc); + } + else { + client_uid_string[0] = '\0'; + } + +#ifdef XSERVER_DTRACE + XSERVER_CLIENT_AUTH(client->index, addr, client_pid, client_zid); +#endif + if (auditTrailLevel > 1) { + if (proto_n) + AuditF("client %d %s from %s%s\n Auth name: %.*s ID: %d\n", + client->index, letin ? "connected" : "rejected", addr, + client_uid_string, (int)proto_n, auth_proto, auth_id); + else + AuditF("client %d %s from %s%s\n", + client->index, letin ? "connected" : "rejected", addr, + client_uid_string); + + } +} + +XID +AuthorizationIDOfClient(ClientPtr client) +{ + if (client->osPrivate) + return ((OsCommPtr)client->osPrivate)->auth_id; + else + return None; +} + + +/***************************************************************** + * ClientAuthorized + * + * Sent by the client at connection setup: + * typedef struct _xConnClientPrefix { + * CARD8 byteOrder; + * BYTE pad; + * CARD16 majorVersion, minorVersion; + * CARD16 nbytesAuthProto; + * CARD16 nbytesAuthString; + * } xConnClientPrefix; + * + * It is hoped that eventually one protocol will be agreed upon. In the + * mean time, a server that implements a different protocol than the + * client expects, or a server that only implements the host-based + * mechanism, will simply ignore this information. + * + *****************************************************************/ + +char * +ClientAuthorized(ClientPtr client, + unsigned int proto_n, char *auth_proto, + unsigned int string_n, char *auth_string) +{ + OsCommPtr priv; + Xtransaddr *from = NULL; + int family; + int fromlen; + XID auth_id; + char *reason = NULL; + XtransConnInfo trans_conn; + + priv = (OsCommPtr)client->osPrivate; + trans_conn = priv->trans_conn; + + /* Allow any client to connect without authorization on a launchd socket, + because it is securely created -- this prevents a race condition on launch */ + if(trans_conn->flags & TRANS_NOXAUTH) { + auth_id = (XID) 0L; + } else { + auth_id = CheckAuthorization (proto_n, auth_proto, string_n, auth_string, client, &reason); + } + + if (auth_id == (XID) ~0L) + { + if (_XSERVTransGetPeerAddr(trans_conn, &family, &fromlen, &from) != -1) + { + if (InvalidHost ((struct sockaddr *) from, fromlen, client)) + AuthAudit(client, FALSE, (struct sockaddr *) from, + fromlen, proto_n, auth_proto, auth_id); + else + { + auth_id = (XID) 0; +#ifdef XSERVER_DTRACE + if ((auditTrailLevel > 1) || XSERVER_CLIENT_AUTH_ENABLED()) +#else + if (auditTrailLevel > 1) +#endif + AuthAudit(client, TRUE, + (struct sockaddr *) from, fromlen, + proto_n, auth_proto, auth_id); + } + + free(from); + } + + if (auth_id == (XID) ~0L) { + if (reason) + return reason; + else + return "Client is not authorized to connect to Server"; + } + } +#ifdef XSERVER_DTRACE + else if ((auditTrailLevel > 1) || XSERVER_CLIENT_AUTH_ENABLED()) +#else + else if (auditTrailLevel > 1) +#endif + { + if (_XSERVTransGetPeerAddr (trans_conn, + &family, &fromlen, &from) != -1) + { + AuthAudit(client, TRUE, (struct sockaddr *) from, fromlen, + proto_n, auth_proto, auth_id); + + free(from); + } + } + priv->auth_id = auth_id; + priv->conn_time = 0; + +#ifdef XDMCP + /* indicate to Xdmcp protocol that we've opened new client */ + XdmcpOpenDisplay(priv->fd); +#endif /* XDMCP */ + + XaceHook(XACE_AUTH_AVAIL, client, auth_id); + + /* At this point, if the client is authorized to change the access control + * list, we should getpeername() information, and add the client to + * the selfhosts list. It's not really the host machine, but the + * true purpose of the selfhosts list is to see who may change the + * access control list. + */ + return((char *)NULL); +} + +static ClientPtr +AllocNewConnection (XtransConnInfo trans_conn, int fd, CARD32 conn_time) +{ + OsCommPtr oc; + ClientPtr client; + + if ( +#ifndef WIN32 + fd >= lastfdesc +#else + XFD_SETCOUNT(&AllClients) >= MaxClients +#endif + ) + return NullClient; + oc = malloc(sizeof(OsCommRec)); + if (!oc) + return NullClient; + oc->trans_conn = trans_conn; + oc->fd = fd; + oc->input = (ConnectionInputPtr)NULL; + oc->output = (ConnectionOutputPtr)NULL; + oc->auth_id = None; + oc->conn_time = conn_time; + if (!(client = NextAvailableClient((pointer)oc))) + { + free(oc); + return NullClient; + } +#if !defined(WIN32) + ConnectionTranslation[fd] = client->index; +#else + SetConnectionTranslation(fd, client->index); +#endif + if (GrabInProgress) + { + FD_SET(fd, &SavedAllClients); + FD_SET(fd, &SavedAllSockets); + } + else + { + FD_SET(fd, &AllClients); + FD_SET(fd, &AllSockets); + } + +#ifdef DEBUG + ErrorF("AllocNewConnection: client index = %d, socket fd = %d\n", + client->index, fd); +#endif +#ifdef XSERVER_DTRACE + XSERVER_CLIENT_CONNECT(client->index, fd); +#endif + + return client; +} + +/***************** + * EstablishNewConnections + * If anyone is waiting on listened sockets, accept them. + * Returns a mask with indices of new clients. Updates AllClients + * and AllSockets. + *****************/ + +/*ARGSUSED*/ +Bool +EstablishNewConnections(ClientPtr clientUnused, pointer closure) +{ + fd_set readyconnections; /* set of listeners that are ready */ + int curconn; /* fd of listener that's ready */ + register int newconn; /* fd of new client */ + CARD32 connect_time; + register int i; + register ClientPtr client; + register OsCommPtr oc; + fd_set tmask; + + XFD_ANDSET (&tmask, (fd_set*)closure, &WellKnownConnections); + XFD_COPYSET(&tmask, &readyconnections); + if (!XFD_ANYSET(&readyconnections)) + return TRUE; + connect_time = GetTimeInMillis(); + /* kill off stragglers */ + for (i=1; iosPrivate); + if ((oc && (oc->conn_time != 0) && + (connect_time - oc->conn_time) >= TimeOutValue) || + (client->noClientException != Success && !client->clientGone)) + CloseDownClient(client); + } + } +#ifndef WIN32 + for (i = 0; i < howmany(XFD_SETSIZE, NFDBITS); i++) + { + while (readyconnections.fds_bits[i]) +#else + for (i = 0; i < XFD_SETCOUNT(&readyconnections); i++) +#endif + { + XtransConnInfo trans_conn, new_trans_conn; + int status; + +#ifndef WIN32 + curconn = mffs (readyconnections.fds_bits[i]) - 1; + readyconnections.fds_bits[i] &= ~((fd_mask)1 << curconn); + curconn += (i * (sizeof(fd_mask)*8)); +#else + curconn = XFD_FD(&readyconnections, i); +#endif + + if ((trans_conn = lookup_trans_conn (curconn)) == NULL) + continue; + + if ((new_trans_conn = _XSERVTransAccept (trans_conn, &status)) == NULL) + continue; + + newconn = _XSERVTransGetConnectionNumber (new_trans_conn); + + if (newconn < lastfdesc) + { + int clientid; +#if !defined(WIN32) + clientid = ConnectionTranslation[newconn]; +#else + clientid = GetConnectionTranslation(newconn); +#endif + if(clientid && (client = clients[clientid])) + CloseDownClient(client); + } + + _XSERVTransSetOption(new_trans_conn, TRANS_NONBLOCKING, 1); + + if (!AllocNewConnection (new_trans_conn, newconn, connect_time)) + { + ErrorConnMax(new_trans_conn); + _XSERVTransClose(new_trans_conn); + } + + if(trans_conn->flags & TRANS_NOXAUTH) + new_trans_conn->flags = new_trans_conn->flags | TRANS_NOXAUTH; + + } +#ifndef WIN32 + } +#endif + return TRUE; +} + +#define NOROOM "Maximum number of clients reached" + +/************ + * ErrorConnMax + * Fail a connection due to lack of client or file descriptor space + ************/ + +static void +ErrorConnMax(XtransConnInfo trans_conn) +{ + int fd = _XSERVTransGetConnectionNumber (trans_conn); + xConnSetupPrefix csp; + char pad[3]; + struct iovec iov[3]; + char byteOrder = 0; + int whichbyte = 1; + struct timeval waittime; + fd_set mask; + + /* if these seems like a lot of trouble to go to, it probably is */ + waittime.tv_sec = BOTIMEOUT / MILLI_PER_SECOND; + waittime.tv_usec = (BOTIMEOUT % MILLI_PER_SECOND) * + (1000000 / MILLI_PER_SECOND); + FD_ZERO(&mask); + FD_SET(fd, &mask); + (void)Select(fd + 1, &mask, NULL, NULL, &waittime); + /* try to read the byte-order of the connection */ + (void)_XSERVTransRead(trans_conn, &byteOrder, 1); + if ((byteOrder == 'l') || (byteOrder == 'B')) + { + csp.success = xFalse; + csp.lengthReason = sizeof(NOROOM) - 1; + csp.length = (sizeof(NOROOM) + 2) >> 2; + csp.majorVersion = X_PROTOCOL; + csp.minorVersion = X_PROTOCOL_REVISION; + if (((*(char *) &whichbyte) && (byteOrder == 'B')) || + (!(*(char *) &whichbyte) && (byteOrder == 'l'))) + { + swaps(&csp.majorVersion, whichbyte); + swaps(&csp.minorVersion, whichbyte); + swaps(&csp.length, whichbyte); + } + iov[0].iov_len = sz_xConnSetupPrefix; + iov[0].iov_base = (char *) &csp; + iov[1].iov_len = csp.lengthReason; + iov[1].iov_base = NOROOM; + iov[2].iov_len = (4 - (csp.lengthReason & 3)) & 3; + iov[2].iov_base = pad; + (void)_XSERVTransWritev(trans_conn, iov, 3); + } +} + +/************ + * CloseDownFileDescriptor: + * Remove this file descriptor and it's I/O buffers, etc. + ************/ + +static void +CloseDownFileDescriptor(OsCommPtr oc) +{ + int connection = oc->fd; + + if (oc->trans_conn) { + _XSERVTransDisconnect(oc->trans_conn); + _XSERVTransClose(oc->trans_conn); + } +#ifndef WIN32 + ConnectionTranslation[connection] = 0; +#else + SetConnectionTranslation(connection, 0); +#endif + FD_CLR(connection, &AllSockets); + FD_CLR(connection, &AllClients); + FD_CLR(connection, &ClientsWithInput); + FD_CLR(connection, &GrabImperviousClients); + if (GrabInProgress) + { + FD_CLR(connection, &SavedAllSockets); + FD_CLR(connection, &SavedAllClients); + FD_CLR(connection, &SavedClientsWithInput); + } + FD_CLR(connection, &ClientsWriteBlocked); + if (!XFD_ANYSET(&ClientsWriteBlocked)) + AnyClientsWriteBlocked = FALSE; + FD_CLR(connection, &OutputPending); +} + +/***************** + * CheckConnections + * Some connection has died, go find which one and shut it down + * The file descriptor has been closed, but is still in AllClients. + * If would truly be wonderful if select() would put the bogus + * file descriptors in the exception mask, but nooooo. So we have + * to check each and every socket individually. + *****************/ + +void +CheckConnections(void) +{ +#ifndef WIN32 + fd_mask mask; +#endif + fd_set tmask; + int curclient, curoff; + int i; + struct timeval notime; + int r; +#ifdef WIN32 + fd_set savedAllClients; +#endif + + notime.tv_sec = 0; + notime.tv_usec = 0; + +#ifndef WIN32 + for (i=0; i 0) + CloseDownClient(clients[ConnectionTranslation[curclient]]); + mask &= ~((fd_mask)1 << curoff); + } + } +#else + XFD_COPYSET(&AllClients, &savedAllClients); + for (i = 0; i < XFD_SETCOUNT(&savedAllClients); i++) + { + curclient = XFD_FD(&savedAllClients, i); + FD_ZERO(&tmask); + FD_SET(curclient, &tmask); + do { + r = Select (curclient + 1, &tmask, NULL, NULL, ¬ime); + } while (r < 0 && (errno == EINTR || errno == EAGAIN)); + if (r < 0) + if (GetConnectionTranslation(curclient) > 0) + CloseDownClient(clients[GetConnectionTranslation(curclient)]); + } +#endif +} + + +/***************** + * CloseDownConnection + * Delete client from AllClients and free resources + *****************/ + +void +CloseDownConnection(ClientPtr client) +{ + OsCommPtr oc = (OsCommPtr)client->osPrivate; + +#ifdef DEBUG + ErrorF("CloseDownConnection: client index = %d, socket fd = %d\n", + client->index, oc->fd); +#endif + if (oc->output && oc->output->count) + FlushClient(client, oc, (char *)NULL, 0); +#ifdef XDMCP + XdmcpCloseDisplay(oc->fd); +#endif + CloseDownFileDescriptor(oc); + FreeOsBuffers(oc); + free(client->osPrivate); + client->osPrivate = (pointer)NULL; + if (auditTrailLevel > 1) + AuditF("client %d disconnected\n", client->index); +} + +void +AddGeneralSocket(int fd) +{ + FD_SET(fd, &AllSockets); + if (GrabInProgress) + FD_SET(fd, &SavedAllSockets); +} + +void +AddEnabledDevice(int fd) +{ + FD_SET(fd, &EnabledDevices); + AddGeneralSocket(fd); +} + +void +RemoveGeneralSocket(int fd) +{ + FD_CLR(fd, &AllSockets); + if (GrabInProgress) + FD_CLR(fd, &SavedAllSockets); +} + +void +RemoveEnabledDevice(int fd) +{ + FD_CLR(fd, &EnabledDevices); + RemoveGeneralSocket(fd); +} + +/***************** + * OnlyListenToOneClient: + * Only accept requests from one client. Continue to handle new + * connections, but don't take any protocol requests from the new + * ones. Note that if GrabInProgress is set, EstablishNewConnections + * needs to put new clients into SavedAllSockets and SavedAllClients. + * Note also that there is no timeout for this in the protocol. + * This routine is "undone" by ListenToAllClients() + *****************/ + +int +OnlyListenToOneClient(ClientPtr client) +{ + OsCommPtr oc = (OsCommPtr)client->osPrivate; + int rc, connection = oc->fd; + + rc = XaceHook(XACE_SERVER_ACCESS, client, DixGrabAccess); + if (rc != Success) + return rc; + + if (! GrabInProgress) + { + XFD_COPYSET(&ClientsWithInput, &SavedClientsWithInput); + XFD_ANDSET(&ClientsWithInput, + &ClientsWithInput, &GrabImperviousClients); + if (FD_ISSET(connection, &SavedClientsWithInput)) + { + FD_CLR(connection, &SavedClientsWithInput); + FD_SET(connection, &ClientsWithInput); + } + XFD_UNSET(&SavedClientsWithInput, &GrabImperviousClients); + XFD_COPYSET(&AllSockets, &SavedAllSockets); + XFD_COPYSET(&AllClients, &SavedAllClients); + XFD_UNSET(&AllSockets, &AllClients); + XFD_ANDSET(&AllClients, &AllClients, &GrabImperviousClients); + FD_SET(connection, &AllClients); + XFD_ORSET(&AllSockets, &AllSockets, &AllClients); + GrabInProgress = client->index; + } + return rc; +} + +/**************** + * ListenToAllClients: + * Undoes OnlyListentToOneClient() + ****************/ + +void +ListenToAllClients(void) +{ + if (GrabInProgress) + { + XFD_ORSET(&AllSockets, &AllSockets, &SavedAllSockets); + XFD_ORSET(&AllClients, &AllClients, &SavedAllClients); + XFD_ORSET(&ClientsWithInput, &ClientsWithInput, &SavedClientsWithInput); + GrabInProgress = 0; + } +} + +/**************** + * IgnoreClient + * Removes one client from input masks. + * Must have cooresponding call to AttendClient. + ****************/ + +void +IgnoreClient (ClientPtr client) +{ + OsCommPtr oc = (OsCommPtr)client->osPrivate; + int connection = oc->fd; + + isItTimeToYield = TRUE; + if (!GrabInProgress || FD_ISSET(connection, &AllClients)) + { + if (FD_ISSET (connection, &ClientsWithInput)) + FD_SET(connection, &IgnoredClientsWithInput); + else + FD_CLR(connection, &IgnoredClientsWithInput); + FD_CLR(connection, &ClientsWithInput); + FD_CLR(connection, &AllSockets); + FD_CLR(connection, &AllClients); + FD_CLR(connection, &LastSelectMask); + } + else + { + if (FD_ISSET (connection, &SavedClientsWithInput)) + FD_SET(connection, &IgnoredClientsWithInput); + else + FD_CLR(connection, &IgnoredClientsWithInput); + FD_CLR(connection, &SavedClientsWithInput); + FD_CLR(connection, &SavedAllSockets); + FD_CLR(connection, &SavedAllClients); + } +} + +/**************** + * AttendClient + * Adds one client back into the input masks. + ****************/ + +void +AttendClient (ClientPtr client) +{ + OsCommPtr oc = (OsCommPtr)client->osPrivate; + int connection = oc->fd; + if (!GrabInProgress || GrabInProgress == client->index || + FD_ISSET(connection, &GrabImperviousClients)) + { + FD_SET(connection, &AllClients); + FD_SET(connection, &AllSockets); + FD_SET(connection, &LastSelectMask); + if (FD_ISSET (connection, &IgnoredClientsWithInput)) + FD_SET(connection, &ClientsWithInput); + } + else + { + FD_SET(connection, &SavedAllClients); + FD_SET(connection, &SavedAllSockets); + if (FD_ISSET(connection, &IgnoredClientsWithInput)) + FD_SET(connection, &SavedClientsWithInput); + } +} + +/* make client impervious to grabs; assume only executing client calls this */ + +void +MakeClientGrabImpervious(ClientPtr client) +{ + OsCommPtr oc = (OsCommPtr)client->osPrivate; + int connection = oc->fd; + + FD_SET(connection, &GrabImperviousClients); + + if (ServerGrabCallback) + { + ServerGrabInfoRec grabinfo; + grabinfo.client = client; + grabinfo.grabstate = CLIENT_IMPERVIOUS; + CallCallbacks(&ServerGrabCallback, &grabinfo); + } +} + +/* make client pervious to grabs; assume only executing client calls this */ + +void +MakeClientGrabPervious(ClientPtr client) +{ + OsCommPtr oc = (OsCommPtr)client->osPrivate; + int connection = oc->fd; + + FD_CLR(connection, &GrabImperviousClients); + if (GrabInProgress && (GrabInProgress != client->index)) + { + if (FD_ISSET(connection, &ClientsWithInput)) + { + FD_SET(connection, &SavedClientsWithInput); + FD_CLR(connection, &ClientsWithInput); + } + FD_CLR(connection, &AllSockets); + FD_CLR(connection, &AllClients); + isItTimeToYield = TRUE; + } + + if (ServerGrabCallback) + { + ServerGrabInfoRec grabinfo; + grabinfo.client = client; + grabinfo.grabstate = CLIENT_PERVIOUS; + CallCallbacks(&ServerGrabCallback, &grabinfo); + } +} + +#ifdef XQUARTZ +/* Add a fd (from launchd) to our listeners */ +void ListenOnOpenFD(int fd, int noxauth) { + char port[256]; + XtransConnInfo ciptr; + const char *display_env = getenv("DISPLAY"); + + if(display_env && (strncmp(display_env, "/tmp/launch", 11) == 0)) { + /* Make the path the launchd socket if our DISPLAY is set right */ + strcpy(port, display_env); + } else { + /* Just some default so things don't break and die. */ + sprintf(port, ":%d", atoi(display)); + } + + /* Make our XtransConnInfo + * TRANS_SOCKET_LOCAL_INDEX = 5 from Xtrans.c + */ + ciptr = _XSERVTransReopenCOTSServer(5, fd, port); + if(ciptr == NULL) { + ErrorF("Got NULL while trying to Reopen launchd port.\n"); + return; + } + + if(noxauth) + ciptr->flags = ciptr->flags | TRANS_NOXAUTH; + + /* Allocate space to store it */ + ListenTransFds = (int *) realloc(ListenTransFds, (ListenTransCount + 1) * sizeof (int)); + ListenTransConns = (XtransConnInfo *) realloc(ListenTransConns, (ListenTransCount + 1) * sizeof (XtransConnInfo)); + + /* Store it */ + ListenTransConns[ListenTransCount] = ciptr; + ListenTransFds[ListenTransCount] = fd; + + FD_SET(fd, &WellKnownConnections); + FD_SET(fd, &AllSockets); + + /* Increment the count */ + ListenTransCount++; + + /* This *might* not be needed... /shrug */ + ResetAuthorization(); + ResetHosts(display); +#ifdef XDMCP + XdmcpReset(); +#endif +} + +#endif diff --git a/xorg-server/os/io.c b/xorg-server/os/io.c index beccdf5b1..edcaa654c 100644 --- a/xorg-server/os/io.c +++ b/xorg-server/os/io.c @@ -1,1108 +1,1108 @@ -/*********************************************************** - -Copyright 1987, 1989, 1998 The Open Group - -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. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. - - -Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - - -******************************************************************/ -/***************************************************************** - * i/o functions - * - * WriteToClient, ReadRequestFromClient - * InsertFakeRequest, ResetCurrentRequest - * - *****************************************************************/ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#undef DEBUG_COMMUNICATION - -#ifdef WIN32 -#include -#endif -#include -#define XSERV_t -#define TRANS_SERVER -#define TRANS_REOPEN -#include -#include -#include -#if !defined(WIN32) -#include -#endif -#include -#include -#include "os.h" -#include "osdep.h" -#include -#include "opaque.h" -#include "dixstruct.h" -#include "misc.h" - -CallbackListPtr ReplyCallback; -CallbackListPtr FlushCallback; - -static ConnectionInputPtr AllocateInputBuffer(void); -static ConnectionOutputPtr AllocateOutputBuffer(void); - -/* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX - * systems are broken and return EWOULDBLOCK when they should return EAGAIN - */ -#ifndef WIN32 -#define ETEST(err) (err == EAGAIN || err == EWOULDBLOCK) -#else /* WIN32 The socket errorcodes differ from the normal errors*/ -#define ETEST(err) (err == EAGAIN || err == WSAEWOULDBLOCK) -#endif - -static Bool CriticalOutputPending; -static int timesThisConnection = 0; -static ConnectionInputPtr FreeInputs = (ConnectionInputPtr)NULL; -static ConnectionOutputPtr FreeOutputs = (ConnectionOutputPtr)NULL; -static OsCommPtr AvailableInput = (OsCommPtr)NULL; - -#define get_req_len(req,cli) ((cli)->swapped ? \ - lswaps((req)->length) : (req)->length) - -#include - -#define get_big_req_len(req,cli) ((cli)->swapped ? \ - lswapl(((xBigReq *)(req))->length) : \ - ((xBigReq *)(req))->length) - -#define MAX_TIMES_PER 10 - -/* - * A lot of the code in this file manipulates a ConnectionInputPtr: - * - * ----------------------------------------------- - * |------- bufcnt ------->| | | - * | |- gotnow ->| | | - * | |-------- needed ------>| | - * |-----------+--------- size --------+---------->| - * ----------------------------------------------- - * ^ ^ - * | | - * buffer bufptr - * - * buffer is a pointer to the start of the buffer. - * bufptr points to the start of the current request. - * bufcnt counts how many bytes are in the buffer. - * size is the size of the buffer in bytes. - * - * In several of the functions, gotnow and needed are local variables - * that do the following: - * - * gotnow is the number of bytes of the request that we're - * trying to read that are currently in the buffer. - * Typically, gotnow = (buffer + bufcnt) - bufptr - * - * needed = the length of the request that we're trying to - * read. Watch out: needed sometimes counts bytes and sometimes - * counts CARD32's. - */ - - -/***************************************************************** - * ReadRequestFromClient - * Returns one request in client->requestBuffer. The request - * length will be in client->req_len. Return status is: - * - * > 0 if successful, specifies length in bytes of the request - * = 0 if entire request is not yet available - * < 0 if client should be terminated - * - * The request returned must be contiguous so that it can be - * cast in the dispatcher to the correct request type. Because requests - * are variable length, ReadRequestFromClient() must look at the first 4 - * or 8 bytes of a request to determine the length (the request length is - * in the 3rd and 4th bytes of the request unless it is a Big Request - * (see the Big Request Extension), in which case the 3rd and 4th bytes - * are zero and the following 4 bytes are the request length. - * - * Note: in order to make the server scheduler (WaitForSomething()) - * "fair", the ClientsWithInput mask is used. This mask tells which - * clients have FULL requests left in their buffers. Clients with - * partial requests require a read. Basically, client buffers - * are drained before select() is called again. But, we can't keep - * reading from a client that is sending buckets of data (or has - * a partial request) because others clients need to be scheduled. - *****************************************************************/ - -static void -YieldControl(void) -{ - isItTimeToYield = TRUE; - timesThisConnection = 0; -} - -static void -YieldControlNoInput(int fd) -{ - YieldControl(); - FD_CLR(fd, &ClientsWithInput); -} - -static void -YieldControlDeath(void) -{ - timesThisConnection = 0; -} - -int -ReadRequestFromClient(ClientPtr client) -{ - OsCommPtr oc = (OsCommPtr)client->osPrivate; - ConnectionInputPtr oci = oc->input; - int fd = oc->fd; - unsigned int gotnow, needed; - int result; - register xReq *request; - Bool need_header; - Bool move_header; - - /* If an input buffer was empty, either free it if it is too big - * or link it into our list of free input buffers. This means that - * different clients can share the same input buffer (at different - * times). This was done to save memory. - */ - - if (AvailableInput) - { - if (AvailableInput != oc) - { - register ConnectionInputPtr aci = AvailableInput->input; - if (aci->size > BUFWATERMARK) - { - xfree(aci->buffer); - xfree(aci); - } - else - { - aci->next = FreeInputs; - FreeInputs = aci; - } - AvailableInput->input = (ConnectionInputPtr)NULL; - } - AvailableInput = (OsCommPtr)NULL; - } - - /* make sure we have an input buffer */ - - if (!oci) - { - if ((oci = FreeInputs)) - { - FreeInputs = oci->next; - } - else if (!(oci = AllocateInputBuffer())) - { - YieldControlDeath(); - return -1; - } - oc->input = oci; - } - - /* advance to start of next request */ - - oci->bufptr += oci->lenLastReq; - - need_header = FALSE; - move_header = FALSE; - gotnow = oci->bufcnt + oci->buffer - oci->bufptr; - if (gotnow < sizeof(xReq)) - { - /* We don't have an entire xReq yet. Can't tell how big - * the request will be until we get the whole xReq. - */ - needed = sizeof(xReq); - need_header = TRUE; - } - else - { - /* We have a whole xReq. We can tell how big the whole - * request will be unless it is a Big Request. - */ - request = (xReq *)oci->bufptr; - needed = get_req_len(request, client); - if (!needed && client->big_requests) - { - /* It's a Big Request. */ - move_header = TRUE; - if (gotnow < sizeof(xBigReq)) - { - /* Still need more data to tell just how big. */ - needed = bytes_to_int32(sizeof(xBigReq)); /* needed is in CARD32s now */ - need_header = TRUE; - } - else - needed = get_big_req_len(request, client); - } - client->req_len = needed; - needed <<= 2; /* needed is in bytes now */ - } - if (gotnow < needed) - { - /* Need to read more data, either so that we can get a - * complete xReq (if need_header is TRUE), a complete - * xBigReq (if move_header is TRUE), or the rest of the - * request (if need_header and move_header are both FALSE). - */ - - oci->lenLastReq = 0; - if (needed > maxBigRequestSize << 2) - { - /* request is too big for us to handle */ - YieldControlDeath(); - return -1; - } - if ((gotnow == 0) || - ((oci->bufptr - oci->buffer + needed) > oci->size)) - { - /* no data, or the request is too big to fit in the buffer */ - - if ((gotnow > 0) && (oci->bufptr != oci->buffer)) - /* save the data we've already read */ - memmove(oci->buffer, oci->bufptr, gotnow); - if (needed > oci->size) - { - /* make buffer bigger to accomodate request */ - char *ibuf; - - ibuf = (char *)xrealloc(oci->buffer, needed); - if (!ibuf) - { - YieldControlDeath(); - return -1; - } - oci->size = needed; - oci->buffer = ibuf; - } - oci->bufptr = oci->buffer; - oci->bufcnt = gotnow; - } - /* XXX this is a workaround. This function is sometimes called - * after the trans_conn has been freed. In this case trans_conn - * will be null. Really ought to restructure things so that we - * never get here in those circumstances. - */ - if (!oc->trans_conn) - { - /* treat as if an error occured on the read, which is what - * used to happen - */ - YieldControlDeath(); - return -1; - } - result = _XSERVTransRead(oc->trans_conn, oci->buffer + oci->bufcnt, - oci->size - oci->bufcnt); - if (result <= 0) - { - if ((result < 0) && ETEST(errno)) - { -#if defined(SVR4) && defined(__i386__) && !defined(sun) - if (0) -#endif - { - YieldControlNoInput(fd); - return 0; - } - } - YieldControlDeath(); - return -1; - } - oci->bufcnt += result; - gotnow += result; - /* free up some space after huge requests */ - if ((oci->size > BUFWATERMARK) && - (oci->bufcnt < BUFSIZE) && (needed < BUFSIZE)) - { - char *ibuf; - - ibuf = (char *)xrealloc(oci->buffer, BUFSIZE); - if (ibuf) - { - oci->size = BUFSIZE; - oci->buffer = ibuf; - oci->bufptr = ibuf + oci->bufcnt - gotnow; - } - } - if (need_header && gotnow >= needed) - { - /* We wanted an xReq, now we've gotten it. */ - request = (xReq *)oci->bufptr; - needed = get_req_len(request, client); - if (!needed && client->big_requests) - { - move_header = TRUE; - if (gotnow < sizeof(xBigReq)) - needed = bytes_to_int32(sizeof(xBigReq)); - else - needed = get_big_req_len(request, client); - } - client->req_len = needed; - needed <<= 2; - } - if (gotnow < needed) - { - /* Still don't have enough; punt. */ - YieldControlNoInput(fd); - return 0; - } - } - if (needed == 0) - { - if (client->big_requests) - needed = sizeof(xBigReq); - else - needed = sizeof(xReq); - } - oci->lenLastReq = needed; - - /* - * Check to see if client has at least one whole request in the - * buffer beyond the request we're returning to the caller. - * If there is only a partial request, treat like buffer - * is empty so that select() will be called again and other clients - * can get into the queue. - */ - - gotnow -= needed; - if (gotnow >= sizeof(xReq)) - { - request = (xReq *)(oci->bufptr + needed); - if (gotnow >= (result = (get_req_len(request, client) << 2)) - && (result || - (client->big_requests && - (gotnow >= sizeof(xBigReq) && - gotnow >= (get_big_req_len(request, client) << 2)))) - ) - FD_SET(fd, &ClientsWithInput); - else - { - if (!SmartScheduleDisable) - FD_CLR(fd, &ClientsWithInput); - else - YieldControlNoInput(fd); - } - } - else - { - if (!gotnow) - AvailableInput = oc; - if (!SmartScheduleDisable) - FD_CLR(fd, &ClientsWithInput); - else - YieldControlNoInput(fd); - } - if (SmartScheduleDisable) - if (++timesThisConnection >= MAX_TIMES_PER) - YieldControl(); - if (move_header) - { - request = (xReq *)oci->bufptr; - oci->bufptr += (sizeof(xBigReq) - sizeof(xReq)); - *(xReq *)oci->bufptr = *request; - oci->lenLastReq -= (sizeof(xBigReq) - sizeof(xReq)); - client->req_len -= bytes_to_int32(sizeof(xBigReq) - sizeof(xReq)); - } - client->requestBuffer = (pointer)oci->bufptr; -#ifdef DEBUG_COMMUNICATION - { - xReq *req = client->requestBuffer; - ErrorF("REQUEST: ClientIDX: %i, type: 0x%x data: 0x%x len: %i\n", - client->index,req->reqType,req->data,req->length); - } -#endif - return needed; -} - -/***************************************************************** - * InsertFakeRequest - * Splice a consed up (possibly partial) request in as the next request. - * - **********************/ - -Bool -InsertFakeRequest(ClientPtr client, char *data, int count) -{ - OsCommPtr oc = (OsCommPtr)client->osPrivate; - ConnectionInputPtr oci = oc->input; - int fd = oc->fd; - int gotnow, moveup; - - if (AvailableInput) - { - if (AvailableInput != oc) - { - ConnectionInputPtr aci = AvailableInput->input; - if (aci->size > BUFWATERMARK) - { - xfree(aci->buffer); - xfree(aci); - } - else - { - aci->next = FreeInputs; - FreeInputs = aci; - } - AvailableInput->input = (ConnectionInputPtr)NULL; - } - AvailableInput = (OsCommPtr)NULL; - } - if (!oci) - { - if ((oci = FreeInputs)) - FreeInputs = oci->next; - else if (!(oci = AllocateInputBuffer())) - return FALSE; - oc->input = oci; - } - oci->bufptr += oci->lenLastReq; - oci->lenLastReq = 0; - gotnow = oci->bufcnt + oci->buffer - oci->bufptr; - if ((gotnow + count) > oci->size) - { - char *ibuf; - - ibuf = (char *)xrealloc(oci->buffer, gotnow + count); - if (!ibuf) - return(FALSE); - oci->size = gotnow + count; - oci->buffer = ibuf; - oci->bufptr = ibuf + oci->bufcnt - gotnow; - } - moveup = count - (oci->bufptr - oci->buffer); - if (moveup > 0) - { - if (gotnow > 0) - memmove(oci->bufptr + moveup, oci->bufptr, gotnow); - oci->bufptr += moveup; - oci->bufcnt += moveup; - } - memmove(oci->bufptr - count, data, count); - oci->bufptr -= count; - gotnow += count; - if ((gotnow >= sizeof(xReq)) && - (gotnow >= (int)(get_req_len((xReq *)oci->bufptr, client) << 2))) - FD_SET(fd, &ClientsWithInput); - else - YieldControlNoInput(fd); - return(TRUE); -} - -/***************************************************************** - * ResetRequestFromClient - * Reset to reexecute the current request, and yield. - * - **********************/ - -void -ResetCurrentRequest(ClientPtr client) -{ - OsCommPtr oc = (OsCommPtr)client->osPrivate; - register ConnectionInputPtr oci = oc->input; - int fd = oc->fd; - register xReq *request; - int gotnow, needed; - if (AvailableInput == oc) - AvailableInput = (OsCommPtr)NULL; - oci->lenLastReq = 0; - gotnow = oci->bufcnt + oci->buffer - oci->bufptr; - if (gotnow < sizeof(xReq)) - { - YieldControlNoInput(fd); - } - else - { - request = (xReq *)oci->bufptr; - needed = get_req_len(request, client); - if (!needed && client->big_requests) - { - oci->bufptr -= sizeof(xBigReq) - sizeof(xReq); - *(xReq *)oci->bufptr = *request; - ((xBigReq *)oci->bufptr)->length = client->req_len; - if (client->swapped) - { - char n; - swapl(&((xBigReq *)oci->bufptr)->length, n); - } - } - if (gotnow >= (needed << 2)) - { - if (FD_ISSET(fd, &AllClients)) - { - FD_SET(fd, &ClientsWithInput); - } - else - { - FD_SET(fd, &IgnoredClientsWithInput); - } - YieldControl(); - } - else - YieldControlNoInput(fd); - } -} - -static const int padlength[4] = {0, 3, 2, 1}; - - /******************** - * FlushAllOutput() - * Flush all clients with output. However, if some client still - * has input in the queue (more requests), then don't flush. This - * will prevent the output queue from being flushed every time around - * the round robin queue. Now, some say that it SHOULD be flushed - * every time around, but... - * - **********************/ - -void -FlushAllOutput(void) -{ - register int index, base; - register fd_mask mask; /* raphael */ - OsCommPtr oc; - register ClientPtr client; - Bool newoutput = NewOutputPending; -#if defined(WIN32) - fd_set newOutputPending; -#endif - - if (FlushCallback) - CallCallbacks(&FlushCallback, NULL); - - if (!newoutput) - return; - - /* - * It may be that some client still has critical output pending, - * but he is not yet ready to receive it anyway, so we will - * simply wait for the select to tell us when he's ready to receive. - */ - CriticalOutputPending = FALSE; - NewOutputPending = FALSE; - -#ifndef WIN32 - for (base = 0; base < howmany(XFD_SETSIZE, NFDBITS); base++) - { - mask = OutputPending.fds_bits[ base ]; - OutputPending.fds_bits[ base ] = 0; - while (mask) - { - index = ffs(mask) - 1; - mask &= ~lowbit(mask); - if ((index = ConnectionTranslation[(base * (sizeof(fd_mask)*8)) + index]) == 0) - continue; - client = clients[index]; - if (client->clientGone) - continue; - oc = (OsCommPtr)client->osPrivate; - if (FD_ISSET(oc->fd, &ClientsWithInput)) - { - FD_SET(oc->fd, &OutputPending); /* set the bit again */ - NewOutputPending = TRUE; - } - else - (void)FlushClient(client, oc, (char *)NULL, 0); - } - } -#else /* WIN32 */ - FD_ZERO(&newOutputPending); - for (base = 0; base < XFD_SETCOUNT(&OutputPending); base++) - { - index = XFD_FD(&OutputPending, base); - if ((index = GetConnectionTranslation(index)) == 0) - continue; - client = clients[index]; - if (client->clientGone) - continue; - oc = (OsCommPtr)client->osPrivate; - if (FD_ISSET(oc->fd, &ClientsWithInput)) - { - FD_SET(oc->fd, &newOutputPending); /* set the bit again */ - NewOutputPending = TRUE; - } - else - (void)FlushClient(client, oc, (char *)NULL, 0); - } - XFD_COPYSET(&newOutputPending, &OutputPending); -#endif /* WIN32 */ -} - -void -FlushIfCriticalOutputPending(void) -{ - if (CriticalOutputPending) - FlushAllOutput(); -} - -void -SetCriticalOutputPending(void) -{ - CriticalOutputPending = TRUE; -} - -/***************** - * WriteToClient - * Copies buf into ClientPtr.buf if it fits (with padding), else - * flushes ClientPtr.buf and buf to client. As of this writing, - * every use of WriteToClient is cast to void, and the result - * is ignored. Potentially, this could be used by requests - * that are sending several chunks of data and want to break - * out of a loop on error. Thus, we will leave the type of - * this routine as int. - *****************/ - -int -WriteToClient (ClientPtr who, int count, const void *__buf) -{ - OsCommPtr oc = (OsCommPtr)who->osPrivate; - ConnectionOutputPtr oco = oc->output; - int padBytes; - const char *buf = __buf; -#ifdef DEBUG_COMMUNICATION - Bool multicount = FALSE; -#endif - if (!count) - return(0); -#ifdef DEBUG_COMMUNICATION - { - char info[128]; - xError *err; - xGenericReply *rep; - xEvent *ev; - - if (!who->replyBytesRemaining) { - switch(buf[0]) { - case X_Reply: - rep = (xGenericReply*)buf; - if (rep->sequenceNumber == who->sequence) { - snprintf(info,127,"Xreply: type: 0x%x data: 0x%x " - "len: %i seq#: 0x%x", rep->type, rep->data1, - rep->length, rep->sequenceNumber); - multicount = TRUE; - } - break; - case X_Error: - err = (xError*)buf; - snprintf(info,127,"Xerror: Code: 0x%x resID: 0x%x maj: 0x%x " - "min: %x", err->errorCode,err->resourceID, - err->minorCode,err->majorCode); - break; - default: - if ((buf[0] & 0x7f) == KeymapNotify) - snprintf(info,127,"KeymapNotifyEvent: %i",buf[0]); - else { - ev = (xEvent*)buf; - snprintf(info,127,"XEvent: type: 0x%x detail: 0x%x " - "seq#: 0x%x", ev->u.u.type, ev->u.u.detail, - ev->u.u.sequenceNumber); - } - } - ErrorF("REPLY: ClientIDX: %i %s\n",who->index, info); - } else - multicount = TRUE; - } -#endif - - if (!oco) - { - if ((oco = FreeOutputs)) - { - FreeOutputs = oco->next; - } - else if (!(oco = AllocateOutputBuffer())) - { - if (oc->trans_conn) { - _XSERVTransDisconnect(oc->trans_conn); - _XSERVTransClose(oc->trans_conn); - oc->trans_conn = NULL; - } - MarkClientException(who); - return -1; - } - oc->output = oco; - } - - padBytes = padlength[count & 3]; - - if(ReplyCallback) - { - ReplyInfoRec replyinfo; - - replyinfo.client = who; - replyinfo.replyData = buf; - replyinfo.dataLenBytes = count + padBytes; - if (who->replyBytesRemaining) - { /* still sending data of an earlier reply */ - who->replyBytesRemaining -= count + padBytes; - replyinfo.startOfReply = FALSE; - replyinfo.bytesRemaining = who->replyBytesRemaining; - CallCallbacks((&ReplyCallback), (pointer)&replyinfo); - } - else if (who->clientState == ClientStateRunning - && buf[0] == X_Reply) - { /* start of new reply */ - CARD32 replylen; - unsigned long bytesleft; - char n; - - replylen = ((xGenericReply *)buf)->length; - if (who->swapped) - swapl(&replylen, n); - bytesleft = (replylen * 4) + SIZEOF(xReply) - count - padBytes; - replyinfo.startOfReply = TRUE; - replyinfo.bytesRemaining = who->replyBytesRemaining = bytesleft; - CallCallbacks((&ReplyCallback), (pointer)&replyinfo); - } - } -#ifdef DEBUG_COMMUNICATION - else if (multicount) { - if (who->replyBytesRemaining) { - who->replyBytesRemaining -= (count + padBytes); - } else { - CARD32 replylen; - replylen = ((xGenericReply *)buf)->length; - who->replyBytesRemaining = - (replylen * 4) + SIZEOF(xReply) - count - padBytes; - } - } -#endif - if (oco->count + count + padBytes > oco->size) - { - FD_CLR(oc->fd, &OutputPending); - if(!XFD_ANYSET(&OutputPending)) { - CriticalOutputPending = FALSE; - NewOutputPending = FALSE; - } - return FlushClient(who, oc, buf, count); - } - - NewOutputPending = TRUE; - FD_SET(oc->fd, &OutputPending); - memmove((char *)oco->buf + oco->count, buf, count); - oco->count += count + padBytes; - return(count); -} - - /******************** - * FlushClient() - * If the client isn't keeping up with us, then we try to continue - * buffering the data and set the apropriate bit in ClientsWritable - * (which is used by WaitFor in the select). If the connection yields - * a permanent error, or we can't allocate any more space, we then - * close the connection. - * - **********************/ - -int -FlushClient(ClientPtr who, OsCommPtr oc, const void *__extraBuf, int extraCount) -{ - ConnectionOutputPtr oco = oc->output; - int connection = oc->fd; - XtransConnInfo trans_conn = oc->trans_conn; - struct iovec iov[3]; - static char padBuffer[3]; - const char *extraBuf = __extraBuf; - long written; - long padsize; - long notWritten; - long todo; - - if (!oco) - return 0; - written = 0; - padsize = padlength[extraCount & 3]; - notWritten = oco->count + extraCount + padsize; - todo = notWritten; - while (notWritten) { - long before = written; /* amount of whole thing written */ - long remain = todo; /* amount to try this time, <= notWritten */ - int i = 0; - long len; - - /* You could be very general here and have "in" and "out" iovecs - * and write a loop without using a macro, but what the heck. This - * translates to: - * - * how much of this piece is new? - * if more new then we are trying this time, clamp - * if nothing new - * then bump down amount already written, for next piece - * else put new stuff in iovec, will need all of next piece - * - * Note that todo had better be at least 1 or else we'll end up - * writing 0 iovecs. - */ -#define InsertIOV(pointer, length) \ - len = (length) - before; \ - if (len > remain) \ - len = remain; \ - if (len <= 0) { \ - before = (-len); \ - } else { \ - iov[i].iov_len = len; \ - iov[i].iov_base = (pointer) + before; \ - i++; \ - remain -= len; \ - before = 0; \ - } - - InsertIOV ((char *)oco->buf, oco->count) - InsertIOV ((char *)extraBuf, extraCount) - InsertIOV (padBuffer, padsize) - - errno = 0; - if (trans_conn && (len = _XSERVTransWritev(trans_conn, iov, i)) >= 0) - { - written += len; - notWritten -= len; - todo = notWritten; - } - else if (ETEST(errno) -#ifdef SUNSYSV /* check for another brain-damaged OS bug */ - || (errno == 0) -#endif -#ifdef EMSGSIZE /* check for another brain-damaged OS bug */ - || ((errno == EMSGSIZE) && (todo == 1)) -#endif - ) - { - /* If we've arrived here, then the client is stuffed to the gills - and not ready to accept more. Make a note of it and buffer - the rest. */ - errno=0; - FD_SET(connection, &ClientsWriteBlocked); - AnyClientsWriteBlocked = TRUE; - - if (written < oco->count) - { - if (written > 0) - { - oco->count -= written; - memmove((char *)oco->buf, - (char *)oco->buf + written, - oco->count); - written = 0; - } - } - else - { - written -= oco->count; - oco->count = 0; - } - - if (notWritten > oco->size) - { - unsigned char *obuf; - - obuf = (unsigned char *)xrealloc(oco->buf, - notWritten + BUFSIZE); - if (!obuf) - { - _XSERVTransDisconnect(oc->trans_conn); - _XSERVTransClose(oc->trans_conn); - oc->trans_conn = NULL; - MarkClientException(who); - oco->count = 0; - return(-1); - } - oco->size = notWritten + BUFSIZE; - oco->buf = obuf; - } - - /* If the amount written extended into the padBuffer, then the - difference "extraCount - written" may be less than 0 */ - if ((len = extraCount - written) > 0) - memmove ((char *)oco->buf + oco->count, - extraBuf + written, - len); - - oco->count = notWritten; /* this will include the pad */ - /* return only the amount explicitly requested */ - return extraCount; - } -#ifdef EMSGSIZE /* check for another brain-damaged OS bug */ - else if (errno == EMSGSIZE) - { - todo >>= 1; - } -#endif - else - { - if (oc->trans_conn) - { - _XSERVTransDisconnect(oc->trans_conn); - _XSERVTransClose(oc->trans_conn); - oc->trans_conn = NULL; - } - MarkClientException(who); - oco->count = 0; - return(-1); - } - } - - /* everything was flushed out */ - oco->count = 0; - /* check to see if this client was write blocked */ - if (AnyClientsWriteBlocked) - { - FD_CLR(oc->fd, &ClientsWriteBlocked); - if (! XFD_ANYSET(&ClientsWriteBlocked)) - AnyClientsWriteBlocked = FALSE; - } - if (oco->size > BUFWATERMARK) - { - xfree(oco->buf); - xfree(oco); - } - else - { - oco->next = FreeOutputs; - FreeOutputs = oco; - } - oc->output = (ConnectionOutputPtr)NULL; - return extraCount; /* return only the amount explicitly requested */ -} - -static ConnectionInputPtr -AllocateInputBuffer(void) -{ - ConnectionInputPtr oci; - - oci = xalloc(sizeof(ConnectionInput)); - if (!oci) - return NULL; - oci->buffer = xalloc(BUFSIZE); - if (!oci->buffer) - { - xfree(oci); - return NULL; - } - oci->size = BUFSIZE; - oci->bufptr = oci->buffer; - oci->bufcnt = 0; - oci->lenLastReq = 0; - return oci; -} - -static ConnectionOutputPtr -AllocateOutputBuffer(void) -{ - ConnectionOutputPtr oco; - - oco = xalloc(sizeof(ConnectionOutput)); - if (!oco) - return NULL; - oco->buf = xcalloc(1, BUFSIZE); - if (!oco->buf) - { - xfree(oco); - return NULL; - } - oco->size = BUFSIZE; - oco->count = 0; - return oco; -} - -void -FreeOsBuffers(OsCommPtr oc) -{ - ConnectionInputPtr oci; - ConnectionOutputPtr oco; - - if (AvailableInput == oc) - AvailableInput = (OsCommPtr)NULL; - if ((oci = oc->input)) - { - if (FreeInputs) - { - xfree(oci->buffer); - xfree(oci); - } - else - { - FreeInputs = oci; - oci->next = (ConnectionInputPtr)NULL; - oci->bufptr = oci->buffer; - oci->bufcnt = 0; - oci->lenLastReq = 0; - } - } - if ((oco = oc->output)) - { - if (FreeOutputs) - { - xfree(oco->buf); - xfree(oco); - } - else - { - FreeOutputs = oco; - oco->next = (ConnectionOutputPtr)NULL; - oco->count = 0; - } - } -} - -void -ResetOsBuffers(void) -{ - ConnectionInputPtr oci; - ConnectionOutputPtr oco; - - while ((oci = FreeInputs)) - { - FreeInputs = oci->next; - xfree(oci->buffer); - xfree(oci); - } - while ((oco = FreeOutputs)) - { - FreeOutputs = oco->next; - xfree(oco->buf); - xfree(oco); - } -} +/*********************************************************** + +Copyright 1987, 1989, 1998 The Open Group + +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. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + + +******************************************************************/ +/***************************************************************** + * i/o functions + * + * WriteToClient, ReadRequestFromClient + * InsertFakeRequest, ResetCurrentRequest + * + *****************************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#undef DEBUG_COMMUNICATION + +#ifdef WIN32 +#include +#endif +#include +#define XSERV_t +#define TRANS_SERVER +#define TRANS_REOPEN +#include +#include +#include +#if !defined(WIN32) +#include +#endif +#include +#include +#include "os.h" +#include "osdep.h" +#include +#include "opaque.h" +#include "dixstruct.h" +#include "misc.h" + +CallbackListPtr ReplyCallback; +CallbackListPtr FlushCallback; + +static ConnectionInputPtr AllocateInputBuffer(void); +static ConnectionOutputPtr AllocateOutputBuffer(void); + +/* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX + * systems are broken and return EWOULDBLOCK when they should return EAGAIN + */ +#ifndef WIN32 +#define ETEST(err) (err == EAGAIN || err == EWOULDBLOCK) +#else /* WIN32 The socket errorcodes differ from the normal errors*/ +#define ETEST(err) (err == EAGAIN || err == WSAEWOULDBLOCK) +#endif + +static Bool CriticalOutputPending; +static int timesThisConnection = 0; +static ConnectionInputPtr FreeInputs = (ConnectionInputPtr)NULL; +static ConnectionOutputPtr FreeOutputs = (ConnectionOutputPtr)NULL; +static OsCommPtr AvailableInput = (OsCommPtr)NULL; + +#define get_req_len(req,cli) ((cli)->swapped ? \ + lswaps((req)->length) : (req)->length) + +#include + +#define get_big_req_len(req,cli) ((cli)->swapped ? \ + lswapl(((xBigReq *)(req))->length) : \ + ((xBigReq *)(req))->length) + +#define MAX_TIMES_PER 10 + +/* + * A lot of the code in this file manipulates a ConnectionInputPtr: + * + * ----------------------------------------------- + * |------- bufcnt ------->| | | + * | |- gotnow ->| | | + * | |-------- needed ------>| | + * |-----------+--------- size --------+---------->| + * ----------------------------------------------- + * ^ ^ + * | | + * buffer bufptr + * + * buffer is a pointer to the start of the buffer. + * bufptr points to the start of the current request. + * bufcnt counts how many bytes are in the buffer. + * size is the size of the buffer in bytes. + * + * In several of the functions, gotnow and needed are local variables + * that do the following: + * + * gotnow is the number of bytes of the request that we're + * trying to read that are currently in the buffer. + * Typically, gotnow = (buffer + bufcnt) - bufptr + * + * needed = the length of the request that we're trying to + * read. Watch out: needed sometimes counts bytes and sometimes + * counts CARD32's. + */ + + +/***************************************************************** + * ReadRequestFromClient + * Returns one request in client->requestBuffer. The request + * length will be in client->req_len. Return status is: + * + * > 0 if successful, specifies length in bytes of the request + * = 0 if entire request is not yet available + * < 0 if client should be terminated + * + * The request returned must be contiguous so that it can be + * cast in the dispatcher to the correct request type. Because requests + * are variable length, ReadRequestFromClient() must look at the first 4 + * or 8 bytes of a request to determine the length (the request length is + * in the 3rd and 4th bytes of the request unless it is a Big Request + * (see the Big Request Extension), in which case the 3rd and 4th bytes + * are zero and the following 4 bytes are the request length. + * + * Note: in order to make the server scheduler (WaitForSomething()) + * "fair", the ClientsWithInput mask is used. This mask tells which + * clients have FULL requests left in their buffers. Clients with + * partial requests require a read. Basically, client buffers + * are drained before select() is called again. But, we can't keep + * reading from a client that is sending buckets of data (or has + * a partial request) because others clients need to be scheduled. + *****************************************************************/ + +static void +YieldControl(void) +{ + isItTimeToYield = TRUE; + timesThisConnection = 0; +} + +static void +YieldControlNoInput(int fd) +{ + YieldControl(); + FD_CLR(fd, &ClientsWithInput); +} + +static void +YieldControlDeath(void) +{ + timesThisConnection = 0; +} + +int +ReadRequestFromClient(ClientPtr client) +{ + OsCommPtr oc = (OsCommPtr)client->osPrivate; + ConnectionInputPtr oci = oc->input; + int fd = oc->fd; + unsigned int gotnow, needed; + int result; + register xReq *request; + Bool need_header; + Bool move_header; + + /* If an input buffer was empty, either free it if it is too big + * or link it into our list of free input buffers. This means that + * different clients can share the same input buffer (at different + * times). This was done to save memory. + */ + + if (AvailableInput) + { + if (AvailableInput != oc) + { + register ConnectionInputPtr aci = AvailableInput->input; + if (aci->size > BUFWATERMARK) + { + free(aci->buffer); + free(aci); + } + else + { + aci->next = FreeInputs; + FreeInputs = aci; + } + AvailableInput->input = (ConnectionInputPtr)NULL; + } + AvailableInput = (OsCommPtr)NULL; + } + + /* make sure we have an input buffer */ + + if (!oci) + { + if ((oci = FreeInputs)) + { + FreeInputs = oci->next; + } + else if (!(oci = AllocateInputBuffer())) + { + YieldControlDeath(); + return -1; + } + oc->input = oci; + } + + /* advance to start of next request */ + + oci->bufptr += oci->lenLastReq; + + need_header = FALSE; + move_header = FALSE; + gotnow = oci->bufcnt + oci->buffer - oci->bufptr; + if (gotnow < sizeof(xReq)) + { + /* We don't have an entire xReq yet. Can't tell how big + * the request will be until we get the whole xReq. + */ + needed = sizeof(xReq); + need_header = TRUE; + } + else + { + /* We have a whole xReq. We can tell how big the whole + * request will be unless it is a Big Request. + */ + request = (xReq *)oci->bufptr; + needed = get_req_len(request, client); + if (!needed && client->big_requests) + { + /* It's a Big Request. */ + move_header = TRUE; + if (gotnow < sizeof(xBigReq)) + { + /* Still need more data to tell just how big. */ + needed = bytes_to_int32(sizeof(xBigReq)); /* needed is in CARD32s now */ + need_header = TRUE; + } + else + needed = get_big_req_len(request, client); + } + client->req_len = needed; + needed <<= 2; /* needed is in bytes now */ + } + if (gotnow < needed) + { + /* Need to read more data, either so that we can get a + * complete xReq (if need_header is TRUE), a complete + * xBigReq (if move_header is TRUE), or the rest of the + * request (if need_header and move_header are both FALSE). + */ + + oci->lenLastReq = 0; + if (needed > maxBigRequestSize << 2) + { + /* request is too big for us to handle */ + YieldControlDeath(); + return -1; + } + if ((gotnow == 0) || + ((oci->bufptr - oci->buffer + needed) > oci->size)) + { + /* no data, or the request is too big to fit in the buffer */ + + if ((gotnow > 0) && (oci->bufptr != oci->buffer)) + /* save the data we've already read */ + memmove(oci->buffer, oci->bufptr, gotnow); + if (needed > oci->size) + { + /* make buffer bigger to accomodate request */ + char *ibuf; + + ibuf = (char *)realloc(oci->buffer, needed); + if (!ibuf) + { + YieldControlDeath(); + return -1; + } + oci->size = needed; + oci->buffer = ibuf; + } + oci->bufptr = oci->buffer; + oci->bufcnt = gotnow; + } + /* XXX this is a workaround. This function is sometimes called + * after the trans_conn has been freed. In this case trans_conn + * will be null. Really ought to restructure things so that we + * never get here in those circumstances. + */ + if (!oc->trans_conn) + { + /* treat as if an error occured on the read, which is what + * used to happen + */ + YieldControlDeath(); + return -1; + } + result = _XSERVTransRead(oc->trans_conn, oci->buffer + oci->bufcnt, + oci->size - oci->bufcnt); + if (result <= 0) + { + if ((result < 0) && ETEST(errno)) + { +#if defined(SVR4) && defined(__i386__) && !defined(sun) + if (0) +#endif + { + YieldControlNoInput(fd); + return 0; + } + } + YieldControlDeath(); + return -1; + } + oci->bufcnt += result; + gotnow += result; + /* free up some space after huge requests */ + if ((oci->size > BUFWATERMARK) && + (oci->bufcnt < BUFSIZE) && (needed < BUFSIZE)) + { + char *ibuf; + + ibuf = (char *)realloc(oci->buffer, BUFSIZE); + if (ibuf) + { + oci->size = BUFSIZE; + oci->buffer = ibuf; + oci->bufptr = ibuf + oci->bufcnt - gotnow; + } + } + if (need_header && gotnow >= needed) + { + /* We wanted an xReq, now we've gotten it. */ + request = (xReq *)oci->bufptr; + needed = get_req_len(request, client); + if (!needed && client->big_requests) + { + move_header = TRUE; + if (gotnow < sizeof(xBigReq)) + needed = bytes_to_int32(sizeof(xBigReq)); + else + needed = get_big_req_len(request, client); + } + client->req_len = needed; + needed <<= 2; + } + if (gotnow < needed) + { + /* Still don't have enough; punt. */ + YieldControlNoInput(fd); + return 0; + } + } + if (needed == 0) + { + if (client->big_requests) + needed = sizeof(xBigReq); + else + needed = sizeof(xReq); + } + oci->lenLastReq = needed; + + /* + * Check to see if client has at least one whole request in the + * buffer beyond the request we're returning to the caller. + * If there is only a partial request, treat like buffer + * is empty so that select() will be called again and other clients + * can get into the queue. + */ + + gotnow -= needed; + if (gotnow >= sizeof(xReq)) + { + request = (xReq *)(oci->bufptr + needed); + if (gotnow >= (result = (get_req_len(request, client) << 2)) + && (result || + (client->big_requests && + (gotnow >= sizeof(xBigReq) && + gotnow >= (get_big_req_len(request, client) << 2)))) + ) + FD_SET(fd, &ClientsWithInput); + else + { + if (!SmartScheduleDisable) + FD_CLR(fd, &ClientsWithInput); + else + YieldControlNoInput(fd); + } + } + else + { + if (!gotnow) + AvailableInput = oc; + if (!SmartScheduleDisable) + FD_CLR(fd, &ClientsWithInput); + else + YieldControlNoInput(fd); + } + if (SmartScheduleDisable) + if (++timesThisConnection >= MAX_TIMES_PER) + YieldControl(); + if (move_header) + { + request = (xReq *)oci->bufptr; + oci->bufptr += (sizeof(xBigReq) - sizeof(xReq)); + *(xReq *)oci->bufptr = *request; + oci->lenLastReq -= (sizeof(xBigReq) - sizeof(xReq)); + client->req_len -= bytes_to_int32(sizeof(xBigReq) - sizeof(xReq)); + } + client->requestBuffer = (pointer)oci->bufptr; +#ifdef DEBUG_COMMUNICATION + { + xReq *req = client->requestBuffer; + ErrorF("REQUEST: ClientIDX: %i, type: 0x%x data: 0x%x len: %i\n", + client->index,req->reqType,req->data,req->length); + } +#endif + return needed; +} + +/***************************************************************** + * InsertFakeRequest + * Splice a consed up (possibly partial) request in as the next request. + * + **********************/ + +Bool +InsertFakeRequest(ClientPtr client, char *data, int count) +{ + OsCommPtr oc = (OsCommPtr)client->osPrivate; + ConnectionInputPtr oci = oc->input; + int fd = oc->fd; + int gotnow, moveup; + + if (AvailableInput) + { + if (AvailableInput != oc) + { + ConnectionInputPtr aci = AvailableInput->input; + if (aci->size > BUFWATERMARK) + { + free(aci->buffer); + free(aci); + } + else + { + aci->next = FreeInputs; + FreeInputs = aci; + } + AvailableInput->input = (ConnectionInputPtr)NULL; + } + AvailableInput = (OsCommPtr)NULL; + } + if (!oci) + { + if ((oci = FreeInputs)) + FreeInputs = oci->next; + else if (!(oci = AllocateInputBuffer())) + return FALSE; + oc->input = oci; + } + oci->bufptr += oci->lenLastReq; + oci->lenLastReq = 0; + gotnow = oci->bufcnt + oci->buffer - oci->bufptr; + if ((gotnow + count) > oci->size) + { + char *ibuf; + + ibuf = (char *)realloc(oci->buffer, gotnow + count); + if (!ibuf) + return(FALSE); + oci->size = gotnow + count; + oci->buffer = ibuf; + oci->bufptr = ibuf + oci->bufcnt - gotnow; + } + moveup = count - (oci->bufptr - oci->buffer); + if (moveup > 0) + { + if (gotnow > 0) + memmove(oci->bufptr + moveup, oci->bufptr, gotnow); + oci->bufptr += moveup; + oci->bufcnt += moveup; + } + memmove(oci->bufptr - count, data, count); + oci->bufptr -= count; + gotnow += count; + if ((gotnow >= sizeof(xReq)) && + (gotnow >= (int)(get_req_len((xReq *)oci->bufptr, client) << 2))) + FD_SET(fd, &ClientsWithInput); + else + YieldControlNoInput(fd); + return(TRUE); +} + +/***************************************************************** + * ResetRequestFromClient + * Reset to reexecute the current request, and yield. + * + **********************/ + +void +ResetCurrentRequest(ClientPtr client) +{ + OsCommPtr oc = (OsCommPtr)client->osPrivate; + register ConnectionInputPtr oci = oc->input; + int fd = oc->fd; + register xReq *request; + int gotnow, needed; + if (AvailableInput == oc) + AvailableInput = (OsCommPtr)NULL; + oci->lenLastReq = 0; + gotnow = oci->bufcnt + oci->buffer - oci->bufptr; + if (gotnow < sizeof(xReq)) + { + YieldControlNoInput(fd); + } + else + { + request = (xReq *)oci->bufptr; + needed = get_req_len(request, client); + if (!needed && client->big_requests) + { + oci->bufptr -= sizeof(xBigReq) - sizeof(xReq); + *(xReq *)oci->bufptr = *request; + ((xBigReq *)oci->bufptr)->length = client->req_len; + if (client->swapped) + { + char n; + swapl(&((xBigReq *)oci->bufptr)->length, n); + } + } + if (gotnow >= (needed << 2)) + { + if (FD_ISSET(fd, &AllClients)) + { + FD_SET(fd, &ClientsWithInput); + } + else + { + FD_SET(fd, &IgnoredClientsWithInput); + } + YieldControl(); + } + else + YieldControlNoInput(fd); + } +} + +static const int padlength[4] = {0, 3, 2, 1}; + + /******************** + * FlushAllOutput() + * Flush all clients with output. However, if some client still + * has input in the queue (more requests), then don't flush. This + * will prevent the output queue from being flushed every time around + * the round robin queue. Now, some say that it SHOULD be flushed + * every time around, but... + * + **********************/ + +void +FlushAllOutput(void) +{ + register int index, base; + register fd_mask mask; /* raphael */ + OsCommPtr oc; + register ClientPtr client; + Bool newoutput = NewOutputPending; +#if defined(WIN32) + fd_set newOutputPending; +#endif + + if (FlushCallback) + CallCallbacks(&FlushCallback, NULL); + + if (!newoutput) + return; + + /* + * It may be that some client still has critical output pending, + * but he is not yet ready to receive it anyway, so we will + * simply wait for the select to tell us when he's ready to receive. + */ + CriticalOutputPending = FALSE; + NewOutputPending = FALSE; + +#ifndef WIN32 + for (base = 0; base < howmany(XFD_SETSIZE, NFDBITS); base++) + { + mask = OutputPending.fds_bits[ base ]; + OutputPending.fds_bits[ base ] = 0; + while (mask) + { + index = ffs(mask) - 1; + mask &= ~lowbit(mask); + if ((index = ConnectionTranslation[(base * (sizeof(fd_mask)*8)) + index]) == 0) + continue; + client = clients[index]; + if (client->clientGone) + continue; + oc = (OsCommPtr)client->osPrivate; + if (FD_ISSET(oc->fd, &ClientsWithInput)) + { + FD_SET(oc->fd, &OutputPending); /* set the bit again */ + NewOutputPending = TRUE; + } + else + (void)FlushClient(client, oc, (char *)NULL, 0); + } + } +#else /* WIN32 */ + FD_ZERO(&newOutputPending); + for (base = 0; base < XFD_SETCOUNT(&OutputPending); base++) + { + index = XFD_FD(&OutputPending, base); + if ((index = GetConnectionTranslation(index)) == 0) + continue; + client = clients[index]; + if (client->clientGone) + continue; + oc = (OsCommPtr)client->osPrivate; + if (FD_ISSET(oc->fd, &ClientsWithInput)) + { + FD_SET(oc->fd, &newOutputPending); /* set the bit again */ + NewOutputPending = TRUE; + } + else + (void)FlushClient(client, oc, (char *)NULL, 0); + } + XFD_COPYSET(&newOutputPending, &OutputPending); +#endif /* WIN32 */ +} + +void +FlushIfCriticalOutputPending(void) +{ + if (CriticalOutputPending) + FlushAllOutput(); +} + +void +SetCriticalOutputPending(void) +{ + CriticalOutputPending = TRUE; +} + +/***************** + * WriteToClient + * Copies buf into ClientPtr.buf if it fits (with padding), else + * flushes ClientPtr.buf and buf to client. As of this writing, + * every use of WriteToClient is cast to void, and the result + * is ignored. Potentially, this could be used by requests + * that are sending several chunks of data and want to break + * out of a loop on error. Thus, we will leave the type of + * this routine as int. + *****************/ + +int +WriteToClient (ClientPtr who, int count, const void *__buf) +{ + OsCommPtr oc = (OsCommPtr)who->osPrivate; + ConnectionOutputPtr oco = oc->output; + int padBytes; + const char *buf = __buf; +#ifdef DEBUG_COMMUNICATION + Bool multicount = FALSE; +#endif + if (!count) + return(0); +#ifdef DEBUG_COMMUNICATION + { + char info[128]; + xError *err; + xGenericReply *rep; + xEvent *ev; + + if (!who->replyBytesRemaining) { + switch(buf[0]) { + case X_Reply: + rep = (xGenericReply*)buf; + if (rep->sequenceNumber == who->sequence) { + snprintf(info,127,"Xreply: type: 0x%x data: 0x%x " + "len: %i seq#: 0x%x", rep->type, rep->data1, + rep->length, rep->sequenceNumber); + multicount = TRUE; + } + break; + case X_Error: + err = (xError*)buf; + snprintf(info,127,"Xerror: Code: 0x%x resID: 0x%x maj: 0x%x " + "min: %x", err->errorCode,err->resourceID, + err->minorCode,err->majorCode); + break; + default: + if ((buf[0] & 0x7f) == KeymapNotify) + snprintf(info,127,"KeymapNotifyEvent: %i",buf[0]); + else { + ev = (xEvent*)buf; + snprintf(info,127,"XEvent: type: 0x%x detail: 0x%x " + "seq#: 0x%x", ev->u.u.type, ev->u.u.detail, + ev->u.u.sequenceNumber); + } + } + ErrorF("REPLY: ClientIDX: %i %s\n",who->index, info); + } else + multicount = TRUE; + } +#endif + + if (!oco) + { + if ((oco = FreeOutputs)) + { + FreeOutputs = oco->next; + } + else if (!(oco = AllocateOutputBuffer())) + { + if (oc->trans_conn) { + _XSERVTransDisconnect(oc->trans_conn); + _XSERVTransClose(oc->trans_conn); + oc->trans_conn = NULL; + } + MarkClientException(who); + return -1; + } + oc->output = oco; + } + + padBytes = padlength[count & 3]; + + if(ReplyCallback) + { + ReplyInfoRec replyinfo; + + replyinfo.client = who; + replyinfo.replyData = buf; + replyinfo.dataLenBytes = count + padBytes; + if (who->replyBytesRemaining) + { /* still sending data of an earlier reply */ + who->replyBytesRemaining -= count + padBytes; + replyinfo.startOfReply = FALSE; + replyinfo.bytesRemaining = who->replyBytesRemaining; + CallCallbacks((&ReplyCallback), (pointer)&replyinfo); + } + else if (who->clientState == ClientStateRunning + && buf[0] == X_Reply) + { /* start of new reply */ + CARD32 replylen; + unsigned long bytesleft; + char n; + + replylen = ((xGenericReply *)buf)->length; + if (who->swapped) + swapl(&replylen, n); + bytesleft = (replylen * 4) + SIZEOF(xReply) - count - padBytes; + replyinfo.startOfReply = TRUE; + replyinfo.bytesRemaining = who->replyBytesRemaining = bytesleft; + CallCallbacks((&ReplyCallback), (pointer)&replyinfo); + } + } +#ifdef DEBUG_COMMUNICATION + else if (multicount) { + if (who->replyBytesRemaining) { + who->replyBytesRemaining -= (count + padBytes); + } else { + CARD32 replylen; + replylen = ((xGenericReply *)buf)->length; + who->replyBytesRemaining = + (replylen * 4) + SIZEOF(xReply) - count - padBytes; + } + } +#endif + if (oco->count + count + padBytes > oco->size) + { + FD_CLR(oc->fd, &OutputPending); + if(!XFD_ANYSET(&OutputPending)) { + CriticalOutputPending = FALSE; + NewOutputPending = FALSE; + } + return FlushClient(who, oc, buf, count); + } + + NewOutputPending = TRUE; + FD_SET(oc->fd, &OutputPending); + memmove((char *)oco->buf + oco->count, buf, count); + oco->count += count + padBytes; + return(count); +} + + /******************** + * FlushClient() + * If the client isn't keeping up with us, then we try to continue + * buffering the data and set the apropriate bit in ClientsWritable + * (which is used by WaitFor in the select). If the connection yields + * a permanent error, or we can't allocate any more space, we then + * close the connection. + * + **********************/ + +int +FlushClient(ClientPtr who, OsCommPtr oc, const void *__extraBuf, int extraCount) +{ + ConnectionOutputPtr oco = oc->output; + int connection = oc->fd; + XtransConnInfo trans_conn = oc->trans_conn; + struct iovec iov[3]; + static char padBuffer[3]; + const char *extraBuf = __extraBuf; + long written; + long padsize; + long notWritten; + long todo; + + if (!oco) + return 0; + written = 0; + padsize = padlength[extraCount & 3]; + notWritten = oco->count + extraCount + padsize; + todo = notWritten; + while (notWritten) { + long before = written; /* amount of whole thing written */ + long remain = todo; /* amount to try this time, <= notWritten */ + int i = 0; + long len; + + /* You could be very general here and have "in" and "out" iovecs + * and write a loop without using a macro, but what the heck. This + * translates to: + * + * how much of this piece is new? + * if more new then we are trying this time, clamp + * if nothing new + * then bump down amount already written, for next piece + * else put new stuff in iovec, will need all of next piece + * + * Note that todo had better be at least 1 or else we'll end up + * writing 0 iovecs. + */ +#define InsertIOV(pointer, length) \ + len = (length) - before; \ + if (len > remain) \ + len = remain; \ + if (len <= 0) { \ + before = (-len); \ + } else { \ + iov[i].iov_len = len; \ + iov[i].iov_base = (pointer) + before; \ + i++; \ + remain -= len; \ + before = 0; \ + } + + InsertIOV ((char *)oco->buf, oco->count) + InsertIOV ((char *)extraBuf, extraCount) + InsertIOV (padBuffer, padsize) + + errno = 0; + if (trans_conn && (len = _XSERVTransWritev(trans_conn, iov, i)) >= 0) + { + written += len; + notWritten -= len; + todo = notWritten; + } + else if (ETEST(errno) +#ifdef SUNSYSV /* check for another brain-damaged OS bug */ + || (errno == 0) +#endif +#ifdef EMSGSIZE /* check for another brain-damaged OS bug */ + || ((errno == EMSGSIZE) && (todo == 1)) +#endif + ) + { + /* If we've arrived here, then the client is stuffed to the gills + and not ready to accept more. Make a note of it and buffer + the rest. */ + errno=0; + FD_SET(connection, &ClientsWriteBlocked); + AnyClientsWriteBlocked = TRUE; + + if (written < oco->count) + { + if (written > 0) + { + oco->count -= written; + memmove((char *)oco->buf, + (char *)oco->buf + written, + oco->count); + written = 0; + } + } + else + { + written -= oco->count; + oco->count = 0; + } + + if (notWritten > oco->size) + { + unsigned char *obuf; + + obuf = (unsigned char *)realloc(oco->buf, + notWritten + BUFSIZE); + if (!obuf) + { + _XSERVTransDisconnect(oc->trans_conn); + _XSERVTransClose(oc->trans_conn); + oc->trans_conn = NULL; + MarkClientException(who); + oco->count = 0; + return(-1); + } + oco->size = notWritten + BUFSIZE; + oco->buf = obuf; + } + + /* If the amount written extended into the padBuffer, then the + difference "extraCount - written" may be less than 0 */ + if ((len = extraCount - written) > 0) + memmove ((char *)oco->buf + oco->count, + extraBuf + written, + len); + + oco->count = notWritten; /* this will include the pad */ + /* return only the amount explicitly requested */ + return extraCount; + } +#ifdef EMSGSIZE /* check for another brain-damaged OS bug */ + else if (errno == EMSGSIZE) + { + todo >>= 1; + } +#endif + else + { + if (oc->trans_conn) + { + _XSERVTransDisconnect(oc->trans_conn); + _XSERVTransClose(oc->trans_conn); + oc->trans_conn = NULL; + } + MarkClientException(who); + oco->count = 0; + return(-1); + } + } + + /* everything was flushed out */ + oco->count = 0; + /* check to see if this client was write blocked */ + if (AnyClientsWriteBlocked) + { + FD_CLR(oc->fd, &ClientsWriteBlocked); + if (! XFD_ANYSET(&ClientsWriteBlocked)) + AnyClientsWriteBlocked = FALSE; + } + if (oco->size > BUFWATERMARK) + { + free(oco->buf); + free(oco); + } + else + { + oco->next = FreeOutputs; + FreeOutputs = oco; + } + oc->output = (ConnectionOutputPtr)NULL; + return extraCount; /* return only the amount explicitly requested */ +} + +static ConnectionInputPtr +AllocateInputBuffer(void) +{ + ConnectionInputPtr oci; + + oci = malloc(sizeof(ConnectionInput)); + if (!oci) + return NULL; + oci->buffer = malloc(BUFSIZE); + if (!oci->buffer) + { + free(oci); + return NULL; + } + oci->size = BUFSIZE; + oci->bufptr = oci->buffer; + oci->bufcnt = 0; + oci->lenLastReq = 0; + return oci; +} + +static ConnectionOutputPtr +AllocateOutputBuffer(void) +{ + ConnectionOutputPtr oco; + + oco = malloc(sizeof(ConnectionOutput)); + if (!oco) + return NULL; + oco->buf = calloc(1, BUFSIZE); + if (!oco->buf) + { + free(oco); + return NULL; + } + oco->size = BUFSIZE; + oco->count = 0; + return oco; +} + +void +FreeOsBuffers(OsCommPtr oc) +{ + ConnectionInputPtr oci; + ConnectionOutputPtr oco; + + if (AvailableInput == oc) + AvailableInput = (OsCommPtr)NULL; + if ((oci = oc->input)) + { + if (FreeInputs) + { + free(oci->buffer); + free(oci); + } + else + { + FreeInputs = oci; + oci->next = (ConnectionInputPtr)NULL; + oci->bufptr = oci->buffer; + oci->bufcnt = 0; + oci->lenLastReq = 0; + } + } + if ((oco = oc->output)) + { + if (FreeOutputs) + { + free(oco->buf); + free(oco); + } + else + { + FreeOutputs = oco; + oco->next = (ConnectionOutputPtr)NULL; + oco->count = 0; + } + } +} + +void +ResetOsBuffers(void) +{ + ConnectionInputPtr oci; + ConnectionOutputPtr oco; + + while ((oci = FreeInputs)) + { + FreeInputs = oci->next; + free(oci->buffer); + free(oci); + } + while ((oco = FreeOutputs)) + { + FreeOutputs = oco->next; + free(oco->buf); + free(oco); + } +} diff --git a/xorg-server/os/log.c b/xorg-server/os/log.c index 33dd51f2c..a377be7e8 100644 --- a/xorg-server/os/log.c +++ b/xorg-server/os/log.c @@ -1,618 +1,617 @@ -/* - -Copyright 1987, 1998 The Open Group - -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. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall -not be used in advertising or otherwise to promote the sale, use or -other dealings in this Software without prior written authorization -from The Open Group. - - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, -Copyright 1994 Quarterdeck Office Systems. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the names of Digital and -Quarterdeck not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -DIGITAL AND QUARTERDECK DISCLAIM ALL WARRANTIES WITH REGARD TO THIS -SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT -OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS -OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE -OR PERFORMANCE OF THIS SOFTWARE. - -*/ - -/* - * Copyright (c) 1997-2003 by The XFree86 Project, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the copyright holder(s) - * and author(s) shall not be used in advertising or otherwise to promote - * the sale, use or other dealings in this Software without prior written - * authorization from the copyright holder(s) and author(s). - */ - - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include /* for malloc() */ -#include - -#include "input.h" -#include "site.h" -#include "opaque.h" - -#ifdef WIN32 -#include -#ifndef _MSC_VER -#define getpid(x) _getpid(x) -#endif -#endif - -#ifdef _MSC_VER -#define S_ISREG(m) (((m)&_S_IFMT) == _S_IFREG) -#endif - -#ifdef XF86BIGFONT -#include "xf86bigfontsrv.h" -#endif - -#ifdef DDXOSVERRORF -void (*OsVendorVErrorFProc)(const char *, va_list args) = NULL; -#endif - -static FILE *logFile = NULL; -static Bool logFlush = FALSE; -static Bool logSync = FALSE; -static int logVerbosity = DEFAULT_LOG_VERBOSITY; -static int logFileVerbosity = DEFAULT_LOG_FILE_VERBOSITY; - -/* Buffer to information logged before the log file is opened. */ -static char *saveBuffer = NULL; -static int bufferSize = 0, bufferUnused = 0, bufferPos = 0; -static Bool needBuffer = TRUE; - -#ifdef __APPLE__ -static char __crashreporter_info_buff__[4096] = {0}; -static const char *__crashreporter_info__ = &__crashreporter_info_buff__[0]; -asm (".desc ___crashreporter_info__, 0x10"); -#endif - -/* Prefix strings for log messages. */ -#ifndef X_UNKNOWN_STRING -#define X_UNKNOWN_STRING "(\?\?)" -#endif -#ifndef X_PROBE_STRING -#define X_PROBE_STRING "(--)" -#endif -#ifndef X_CONFIG_STRING -#define X_CONFIG_STRING "(**)" -#endif -#ifndef X_DEFAULT_STRING -#define X_DEFAULT_STRING "(==)" -#endif -#ifndef X_CMDLINE_STRING -#define X_CMDLINE_STRING "(++)" -#endif -#ifndef X_NOTICE_STRING -#define X_NOTICE_STRING "(!!)" -#endif -#ifndef X_ERROR_STRING -#define X_ERROR_STRING "(EE)" -#endif -#ifndef X_WARNING_STRING -#define X_WARNING_STRING "(WW)" -#endif -#ifndef X_INFO_STRING -#define X_INFO_STRING "(II)" -#endif -#ifndef X_NOT_IMPLEMENTED_STRING -#define X_NOT_IMPLEMENTED_STRING "(NI)" -#endif - -/* - * LogInit is called to start logging to a file. It is also called (with - * NULL arguments) when logging to a file is not wanted. It must always be - * called, otherwise log messages will continue to accumulate in a buffer. - * - * %s, if present in the fname or backup strings, is expanded to the display - * string. - */ - -const char * -LogInit(const char *fname, const char *backup) -{ - char *logFileName = NULL; - - if (fname && *fname) { - /* xalloc() can't be used yet. */ - logFileName = malloc(strlen(fname) + strlen(display) + 1); - if (!logFileName) - FatalError("Cannot allocate space for the log file name\n"); - sprintf(logFileName, fname, display); - - if (backup && *backup) { - struct stat buf; - - if (!stat(logFileName, &buf) && S_ISREG(buf.st_mode)) { - char *suffix; - char *oldLog; - - oldLog = malloc(strlen(logFileName) + strlen(backup) + - strlen(display) + 1); - suffix = malloc(strlen(backup) + strlen(display) + 1); - if (!oldLog || !suffix) - FatalError("Cannot allocate space for the log file name\n"); - sprintf(suffix, backup, display); - sprintf(oldLog, "%s%s", logFileName, suffix); - free(suffix); - if (rename(logFileName, oldLog) == -1) { - FatalError("Cannot move old log file \"%s\" to \"%s\"\n", - logFileName, oldLog); - } - free(oldLog); - } - } - if ((logFile = fopen(logFileName, "w")) == NULL) - FatalError("Cannot open log file \"%s\"\n", logFileName); - setvbuf(logFile, NULL, _IONBF, 0); - - /* Flush saved log information. */ - if (saveBuffer && bufferSize > 0) { - fwrite(saveBuffer, bufferPos, 1, logFile); - fflush(logFile); -#ifndef WIN32 - fsync(fileno(logFile)); -#endif - } - } - - /* - * Unconditionally free the buffer, and flag that the buffer is no longer - * needed. - */ - if (saveBuffer && bufferSize > 0) { - free(saveBuffer); /* Must be free(), not xfree() */ - saveBuffer = NULL; - bufferSize = 0; - } - needBuffer = FALSE; - - return logFileName; -} - -void -LogClose(void) -{ - if (logFile) { - fclose(logFile); - logFile = NULL; - } -} - -Bool -LogSetParameter(LogParameter param, int value) -{ - switch (param) { - case XLOG_FLUSH: - logFlush = value ? TRUE : FALSE; - return TRUE; - case XLOG_SYNC: - logSync = value ? TRUE : FALSE; - return TRUE; - case XLOG_VERBOSITY: - logVerbosity = value; - return TRUE; - case XLOG_FILE_VERBOSITY: - logFileVerbosity = value; - return TRUE; - default: - return FALSE; - } -} - -/* This function does the actual log message writes. */ - -void -LogVWrite(int verb, const char *f, va_list args) -{ - char tmpBuffer[1024]; - int len = 0; - static Bool newline = TRUE; - - if (newline) { - sprintf(tmpBuffer, "[%10.3f] ", GetTimeInMillis() / 1000.0); - len = strlen(tmpBuffer); - if (logFile) - fwrite(tmpBuffer, len, 1, logFile); - } - - /* - * Since a va_list can only be processed once, write the string to a - * buffer, and then write the buffer out to the appropriate output - * stream(s). - */ - if (verb < 0 || logFileVerbosity >= verb || logVerbosity >= verb) { - vsnprintf(tmpBuffer, sizeof(tmpBuffer)-1, f, args); - tmpBuffer[sizeof(tmpBuffer)-1]=0; - len = strlen(tmpBuffer); - } - newline = (tmpBuffer[len-1] == '\n'); - if ((verb < 0 || logVerbosity >= verb) && len > 0) - fwrite(tmpBuffer, len, 1, stderr); - if ((verb < 0 || logFileVerbosity >= verb) && len > 0) { - if (logFile) { - fwrite(tmpBuffer, len, 1, logFile); - if (logFlush) { - fflush(logFile); -#ifndef WIN32 - if (logSync) - fsync(fileno(logFile)); -#endif - } - } else if (needBuffer) { - /* - * Note, this code is used before OsInit() has been called, so - * xalloc() and friends can't be used. - */ - if (len > bufferUnused) { - bufferSize += 1024; - bufferUnused += 1024; - if (saveBuffer) - saveBuffer = realloc(saveBuffer, bufferSize); - else - saveBuffer = malloc(bufferSize); - if (!saveBuffer) - FatalError("realloc() failed while saving log messages\n"); - } - bufferUnused -= len; - memcpy(saveBuffer + bufferPos, tmpBuffer, len); - bufferPos += len; - } - } -} - -void -LogWrite(int verb, const char *f, ...) -{ - va_list args; - - va_start(args, f); - LogVWrite(verb, f, args); - va_end(args); -} - -void -LogVMessageVerb(MessageType type, int verb, const char *format, va_list args) -{ - const char *s = X_UNKNOWN_STRING; - char tmpBuf[1024]; - - /* Ignore verbosity for X_ERROR */ - if (logVerbosity >= verb || logFileVerbosity >= verb || type == X_ERROR) { - switch (type) { - case X_PROBED: - s = X_PROBE_STRING; - break; - case X_CONFIG: - s = X_CONFIG_STRING; - break; - case X_DEFAULT: - s = X_DEFAULT_STRING; - break; - case X_CMDLINE: - s = X_CMDLINE_STRING; - break; - case X_NOTICE: - s = X_NOTICE_STRING; - break; - case X_ERROR: - s = X_ERROR_STRING; - if (verb > 0) - verb = 0; - break; - case X_WARNING: - s = X_WARNING_STRING; - break; - case X_INFO: - s = X_INFO_STRING; - break; - case X_NOT_IMPLEMENTED: - s = X_NOT_IMPLEMENTED_STRING; - break; - case X_UNKNOWN: - s = X_UNKNOWN_STRING; - break; - case X_NONE: - s = NULL; - break; - } - - /* if s is not NULL we need a space before format */ - snprintf(tmpBuf, sizeof(tmpBuf), "%s%s%s", s ? s : "", - s ? " " : "", - format); - LogVWrite(verb, tmpBuf, args); - } -} - -/* Log message with verbosity level specified. */ -void -LogMessageVerb(MessageType type, int verb, const char *format, ...) -{ - va_list ap; - - va_start(ap, format); - LogVMessageVerb(type, verb, format, ap); - va_end(ap); -} - -/* Log a message with the standard verbosity level of 1. */ -void -LogMessage(MessageType type, const char *format, ...) -{ - va_list ap; - - va_start(ap, format); - LogVMessageVerb(type, 1, format, ap); - va_end(ap); -} - -#ifdef __GNUC__ -void AbortServer(void) __attribute__((noreturn)); -#endif - -void -AbortServer(void) -{ -#ifdef XF86BIGFONT - XF86BigfontCleanup(); -#endif - CloseWellKnownConnections(); - OsCleanup(TRUE); - CloseDownDevices(); - AbortDDX(); - fflush(stderr); - if (CoreDump) - OsAbort(); - exit (1); -} - -#define AUDIT_PREFIX "AUDIT: %s: %ld: " -#ifndef AUDIT_TIMEOUT -#define AUDIT_TIMEOUT ((CARD32)(120 * 1000)) /* 2 mn */ -#endif - -static int nrepeat = 0; -static int oldlen = -1; -static OsTimerPtr auditTimer = NULL; - -void -FreeAuditTimer(void) -{ - if (auditTimer != NULL) { - /* Force output of pending messages */ - TimerForce(auditTimer); - TimerFree(auditTimer); - auditTimer = NULL; - } -} - -static char * -AuditPrefix(void) -{ - time_t tm; - char *autime, *s; - char *tmpBuf; - int len; - - time(&tm); - autime = ctime(&tm); - if ((s = strchr(autime, '\n'))) - *s = '\0'; - len = strlen(AUDIT_PREFIX) + strlen(autime) + 10 + 1; - tmpBuf = malloc(len); - if (!tmpBuf) - return NULL; - snprintf(tmpBuf, len, AUDIT_PREFIX, autime, (unsigned long)getpid()); - return tmpBuf; -} - -void -AuditF(const char * f, ...) -{ - va_list args; - - va_start(args, f); - - VAuditF(f, args); - va_end(args); -} - -static CARD32 -AuditFlush(OsTimerPtr timer, CARD32 now, pointer arg) -{ - char *prefix; - - if (nrepeat > 0) { - prefix = AuditPrefix(); - ErrorF("%slast message repeated %d times\n", - prefix != NULL ? prefix : "", nrepeat); - nrepeat = 0; - if (prefix != NULL) - free(prefix); - return AUDIT_TIMEOUT; - } else { - /* if the timer expires without anything to print, flush the message */ - oldlen = -1; - return 0; - } -} - -void -VAuditF(const char *f, va_list args) -{ - char *prefix; - char buf[1024]; - int len; - static char oldbuf[1024]; - - prefix = AuditPrefix(); - len = vsnprintf(buf, sizeof(buf), f, args); - - if (len == oldlen && strcmp(buf, oldbuf) == 0) { - /* Message already seen */ - nrepeat++; - } else { - /* new message */ - if (auditTimer != NULL) - TimerForce(auditTimer); - ErrorF("%s%s", prefix != NULL ? prefix : "", buf); - strlcpy(oldbuf, buf, sizeof(oldbuf)); - oldlen = len; - nrepeat = 0; - auditTimer = TimerSet(auditTimer, 0, AUDIT_TIMEOUT, AuditFlush, NULL); - } - if (prefix != NULL) - free(prefix); -} - -void -FatalError(const char *f, ...) -{ - va_list args; - static Bool beenhere = FALSE; - - if (beenhere) - ErrorF("\nFatalError re-entered, aborting\n"); - else - ErrorF("\nFatal server error:\n"); - - va_start(args, f); -#ifdef __APPLE__ - (void)vsnprintf(__crashreporter_info_buff__, sizeof(__crashreporter_info_buff__), f, args); -#endif - VErrorF(f, args); - va_end(args); - ErrorF("\n"); - if (!beenhere) - OsVendorFatalError(); - if (!beenhere) { - beenhere = TRUE; - AbortServer(); - } else - OsAbort(); - /*NOTREACHED*/ -} - -void -VErrorF(const char *f, va_list args) -{ -#ifdef DDXOSVERRORF - if (OsVendorVErrorFProc) - OsVendorVErrorFProc(f, args); - else - LogVWrite(-1, f, args); -#else - LogVWrite(-1, f, args); -#endif -} - -void -ErrorF(const char * f, ...) -{ - va_list args; - - va_start(args, f); - VErrorF(f, args); - va_end(args); -} - -/* A perror() workalike. */ - -void -Error(char *str) -{ - char *err = NULL; - int saveErrno = errno; - - if (str) { - err = malloc(strlen(strerror(saveErrno)) + strlen(str) + 2 + 1); - if (!err) - return; - sprintf(err, "%s: ", str); - strcat(err, strerror(saveErrno)); - LogWrite(-1, "%s", err); - free(err); - } else - LogWrite(-1, "%s", strerror(saveErrno)); -} - -void -LogPrintMarkers(void) -{ - /* Show what the message marker symbols mean. */ - LogWrite(0, "Markers: "); - LogMessageVerb(X_PROBED, 0, "probed, "); - LogMessageVerb(X_CONFIG, 0, "from config file, "); - LogMessageVerb(X_DEFAULT, 0, "default setting,\n\t"); - LogMessageVerb(X_CMDLINE, 0, "from command line, "); - LogMessageVerb(X_NOTICE, 0, "notice, "); - LogMessageVerb(X_INFO, 0, "informational,\n\t"); - LogMessageVerb(X_WARNING, 0, "warning, "); - LogMessageVerb(X_ERROR, 0, "error, "); - LogMessageVerb(X_NOT_IMPLEMENTED, 0, "not implemented, "); - LogMessageVerb(X_UNKNOWN, 0, "unknown.\n"); -} - +/* + +Copyright 1987, 1998 The Open Group + +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. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, +Copyright 1994 Quarterdeck Office Systems. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the names of Digital and +Quarterdeck not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +DIGITAL AND QUARTERDECK DISCLAIM ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT +OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE +OR PERFORMANCE OF THIS SOFTWARE. + +*/ + +/* + * Copyright (c) 1997-2003 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include /* for malloc() */ +#include + +#include "input.h" +#include "site.h" +#include "opaque.h" + +#ifdef WIN32 +#include +#ifndef _MSC_VER +#define getpid(x) _getpid(x) +#endif +#endif + +#ifdef _MSC_VER +#define S_ISREG(m) (((m)&_S_IFMT) == _S_IFREG) +#endif + +#ifdef XF86BIGFONT +#include "xf86bigfontsrv.h" +#endif + +#ifdef DDXOSVERRORF +void (*OsVendorVErrorFProc)(const char *, va_list args) = NULL; +#endif + +static FILE *logFile = NULL; +static Bool logFlush = FALSE; +static Bool logSync = FALSE; +static int logVerbosity = DEFAULT_LOG_VERBOSITY; +static int logFileVerbosity = DEFAULT_LOG_FILE_VERBOSITY; + +/* Buffer to information logged before the log file is opened. */ +static char *saveBuffer = NULL; +static int bufferSize = 0, bufferUnused = 0, bufferPos = 0; +static Bool needBuffer = TRUE; + +#ifdef __APPLE__ +static char __crashreporter_info_buff__[4096] = {0}; +static const char *__crashreporter_info__ = &__crashreporter_info_buff__[0]; +asm (".desc ___crashreporter_info__, 0x10"); +#endif + +/* Prefix strings for log messages. */ +#ifndef X_UNKNOWN_STRING +#define X_UNKNOWN_STRING "(\?\?)" +#endif +#ifndef X_PROBE_STRING +#define X_PROBE_STRING "(--)" +#endif +#ifndef X_CONFIG_STRING +#define X_CONFIG_STRING "(**)" +#endif +#ifndef X_DEFAULT_STRING +#define X_DEFAULT_STRING "(==)" +#endif +#ifndef X_CMDLINE_STRING +#define X_CMDLINE_STRING "(++)" +#endif +#ifndef X_NOTICE_STRING +#define X_NOTICE_STRING "(!!)" +#endif +#ifndef X_ERROR_STRING +#define X_ERROR_STRING "(EE)" +#endif +#ifndef X_WARNING_STRING +#define X_WARNING_STRING "(WW)" +#endif +#ifndef X_INFO_STRING +#define X_INFO_STRING "(II)" +#endif +#ifndef X_NOT_IMPLEMENTED_STRING +#define X_NOT_IMPLEMENTED_STRING "(NI)" +#endif + +/* + * LogInit is called to start logging to a file. It is also called (with + * NULL arguments) when logging to a file is not wanted. It must always be + * called, otherwise log messages will continue to accumulate in a buffer. + * + * %s, if present in the fname or backup strings, is expanded to the display + * string. + */ + +const char * +LogInit(const char *fname, const char *backup) +{ + char *logFileName = NULL; + + if (fname && *fname) { + /* malloc() can't be used yet. */ + logFileName = malloc(strlen(fname) + strlen(display) + 1); + if (!logFileName) + FatalError("Cannot allocate space for the log file name\n"); + sprintf(logFileName, fname, display); + + if (backup && *backup) { + struct stat buf; + + if (!stat(logFileName, &buf) && S_ISREG(buf.st_mode)) { + char *suffix; + char *oldLog; + + oldLog = malloc(strlen(logFileName) + strlen(backup) + + strlen(display) + 1); + suffix = malloc(strlen(backup) + strlen(display) + 1); + if (!oldLog || !suffix) + FatalError("Cannot allocate space for the log file name\n"); + sprintf(suffix, backup, display); + sprintf(oldLog, "%s%s", logFileName, suffix); + free(suffix); + if (rename(logFileName, oldLog) == -1) { + FatalError("Cannot move old log file \"%s\" to \"%s\"\n", + logFileName, oldLog); + } + free(oldLog); + } + } + if ((logFile = fopen(logFileName, "w")) == NULL) + FatalError("Cannot open log file \"%s\"\n", logFileName); + setvbuf(logFile, NULL, _IONBF, 0); + + /* Flush saved log information. */ + if (saveBuffer && bufferSize > 0) { + fwrite(saveBuffer, bufferPos, 1, logFile); + fflush(logFile); +#ifndef WIN32 + fsync(fileno(logFile)); +#endif + } + } + + /* + * Unconditionally free the buffer, and flag that the buffer is no longer + * needed. + */ + if (saveBuffer && bufferSize > 0) { + free(saveBuffer); /* Must be free(), not free() */ + saveBuffer = NULL; + bufferSize = 0; + } + needBuffer = FALSE; + + return logFileName; +} + +void +LogClose(void) +{ + if (logFile) { + fclose(logFile); + logFile = NULL; + } +} + +Bool +LogSetParameter(LogParameter param, int value) +{ + switch (param) { + case XLOG_FLUSH: + logFlush = value ? TRUE : FALSE; + return TRUE; + case XLOG_SYNC: + logSync = value ? TRUE : FALSE; + return TRUE; + case XLOG_VERBOSITY: + logVerbosity = value; + return TRUE; + case XLOG_FILE_VERBOSITY: + logFileVerbosity = value; + return TRUE; + default: + return FALSE; + } +} + +/* This function does the actual log message writes. */ + +void +LogVWrite(int verb, const char *f, va_list args) +{ + char tmpBuffer[1024]; + int len = 0; + static Bool newline = TRUE; + + if (newline) { + sprintf(tmpBuffer, "[%10.3f] ", GetTimeInMillis() / 1000.0); + len = strlen(tmpBuffer); + if (logFile) + fwrite(tmpBuffer, len, 1, logFile); + } + + /* + * Since a va_list can only be processed once, write the string to a + * buffer, and then write the buffer out to the appropriate output + * stream(s). + */ + if (verb < 0 || logFileVerbosity >= verb || logVerbosity >= verb) { + vsnprintf(tmpBuffer, sizeof(tmpBuffer)-1, f, args); + tmpBuffer[sizeof(tmpBuffer)-1]=0; + len = strlen(tmpBuffer); + } + newline = (tmpBuffer[len-1] == '\n'); + if ((verb < 0 || logVerbosity >= verb) && len > 0) + fwrite(tmpBuffer, len, 1, stderr); + if ((verb < 0 || logFileVerbosity >= verb) && len > 0) { + if (logFile) { + fwrite(tmpBuffer, len, 1, logFile); + if (logFlush) { + fflush(logFile); +#ifndef WIN32 + if (logSync) + fsync(fileno(logFile)); +#endif + } + } else if (needBuffer) { + /* + * Note, this code is used before OsInit() has been called, so + * malloc() and friends can't be used. + */ + if (len > bufferUnused) { + bufferSize += 1024; + bufferUnused += 1024; + if (saveBuffer) + saveBuffer = realloc(saveBuffer, bufferSize); + else + saveBuffer = malloc(bufferSize); + if (!saveBuffer) + FatalError("realloc() failed while saving log messages\n"); + } + bufferUnused -= len; + memcpy(saveBuffer + bufferPos, tmpBuffer, len); + bufferPos += len; + } + } +} + +void +LogWrite(int verb, const char *f, ...) +{ + va_list args; + + va_start(args, f); + LogVWrite(verb, f, args); + va_end(args); +} + +void +LogVMessageVerb(MessageType type, int verb, const char *format, va_list args) +{ + const char *s = X_UNKNOWN_STRING; + char tmpBuf[1024]; + + /* Ignore verbosity for X_ERROR */ + if (logVerbosity >= verb || logFileVerbosity >= verb || type == X_ERROR) { + switch (type) { + case X_PROBED: + s = X_PROBE_STRING; + break; + case X_CONFIG: + s = X_CONFIG_STRING; + break; + case X_DEFAULT: + s = X_DEFAULT_STRING; + break; + case X_CMDLINE: + s = X_CMDLINE_STRING; + break; + case X_NOTICE: + s = X_NOTICE_STRING; + break; + case X_ERROR: + s = X_ERROR_STRING; + if (verb > 0) + verb = 0; + break; + case X_WARNING: + s = X_WARNING_STRING; + break; + case X_INFO: + s = X_INFO_STRING; + break; + case X_NOT_IMPLEMENTED: + s = X_NOT_IMPLEMENTED_STRING; + break; + case X_UNKNOWN: + s = X_UNKNOWN_STRING; + break; + case X_NONE: + s = NULL; + break; + } + + /* if s is not NULL we need a space before format */ + snprintf(tmpBuf, sizeof(tmpBuf), "%s%s%s", s ? s : "", + s ? " " : "", + format); + LogVWrite(verb, tmpBuf, args); + } +} + +/* Log message with verbosity level specified. */ +void +LogMessageVerb(MessageType type, int verb, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + LogVMessageVerb(type, verb, format, ap); + va_end(ap); +} + +/* Log a message with the standard verbosity level of 1. */ +void +LogMessage(MessageType type, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + LogVMessageVerb(type, 1, format, ap); + va_end(ap); +} + +void +AbortServer(void) _X_NORETURN; + +void +AbortServer(void) +{ +#ifdef XF86BIGFONT + XF86BigfontCleanup(); +#endif + CloseWellKnownConnections(); + OsCleanup(TRUE); + CloseDownDevices(); + AbortDDX(); + fflush(stderr); + if (CoreDump) + OsAbort(); + exit (1); +} + +#define AUDIT_PREFIX "AUDIT: %s: %ld: " +#ifndef AUDIT_TIMEOUT +#define AUDIT_TIMEOUT ((CARD32)(120 * 1000)) /* 2 mn */ +#endif + +static int nrepeat = 0; +static int oldlen = -1; +static OsTimerPtr auditTimer = NULL; + +void +FreeAuditTimer(void) +{ + if (auditTimer != NULL) { + /* Force output of pending messages */ + TimerForce(auditTimer); + TimerFree(auditTimer); + auditTimer = NULL; + } +} + +static char * +AuditPrefix(void) +{ + time_t tm; + char *autime, *s; + char *tmpBuf; + int len; + + time(&tm); + autime = ctime(&tm); + if ((s = strchr(autime, '\n'))) + *s = '\0'; + len = strlen(AUDIT_PREFIX) + strlen(autime) + 10 + 1; + tmpBuf = malloc(len); + if (!tmpBuf) + return NULL; + snprintf(tmpBuf, len, AUDIT_PREFIX, autime, (unsigned long)getpid()); + return tmpBuf; +} + +void +AuditF(const char * f, ...) +{ + va_list args; + + va_start(args, f); + + VAuditF(f, args); + va_end(args); +} + +static CARD32 +AuditFlush(OsTimerPtr timer, CARD32 now, pointer arg) +{ + char *prefix; + + if (nrepeat > 0) { + prefix = AuditPrefix(); + ErrorF("%slast message repeated %d times\n", + prefix != NULL ? prefix : "", nrepeat); + nrepeat = 0; + if (prefix != NULL) + free(prefix); + return AUDIT_TIMEOUT; + } else { + /* if the timer expires without anything to print, flush the message */ + oldlen = -1; + return 0; + } +} + +void +VAuditF(const char *f, va_list args) +{ + char *prefix; + char buf[1024]; + int len; + static char oldbuf[1024]; + + prefix = AuditPrefix(); + len = vsnprintf(buf, sizeof(buf), f, args); + + if (len == oldlen && strcmp(buf, oldbuf) == 0) { + /* Message already seen */ + nrepeat++; + } else { + /* new message */ + if (auditTimer != NULL) + TimerForce(auditTimer); + ErrorF("%s%s", prefix != NULL ? prefix : "", buf); + strlcpy(oldbuf, buf, sizeof(oldbuf)); + oldlen = len; + nrepeat = 0; + auditTimer = TimerSet(auditTimer, 0, AUDIT_TIMEOUT, AuditFlush, NULL); + } + if (prefix != NULL) + free(prefix); +} + +void +FatalError(const char *f, ...) +{ + va_list args; + static Bool beenhere = FALSE; + + if (beenhere) + ErrorF("\nFatalError re-entered, aborting\n"); + else + ErrorF("\nFatal server error:\n"); + + va_start(args, f); +#ifdef __APPLE__ + (void)vsnprintf(__crashreporter_info_buff__, sizeof(__crashreporter_info_buff__), f, args); +#endif + VErrorF(f, args); + va_end(args); + ErrorF("\n"); + if (!beenhere) + OsVendorFatalError(); + if (!beenhere) { + beenhere = TRUE; + AbortServer(); + } else + OsAbort(); + /*NOTREACHED*/ +} + +void +VErrorF(const char *f, va_list args) +{ +#ifdef DDXOSVERRORF + if (OsVendorVErrorFProc) + OsVendorVErrorFProc(f, args); + else + LogVWrite(-1, f, args); +#else + LogVWrite(-1, f, args); +#endif +} + +void +ErrorF(const char * f, ...) +{ + va_list args; + + va_start(args, f); + VErrorF(f, args); + va_end(args); +} + +/* A perror() workalike. */ + +void +Error(char *str) +{ + char *err = NULL; + int saveErrno = errno; + + if (str) { + err = malloc(strlen(strerror(saveErrno)) + strlen(str) + 2 + 1); + if (!err) + return; + sprintf(err, "%s: ", str); + strcat(err, strerror(saveErrno)); + LogWrite(-1, "%s", err); + free(err); + } else + LogWrite(-1, "%s", strerror(saveErrno)); +} + +void +LogPrintMarkers(void) +{ + /* Show what the message marker symbols mean. */ + LogWrite(0, "Markers: "); + LogMessageVerb(X_PROBED, 0, "probed, "); + LogMessageVerb(X_CONFIG, 0, "from config file, "); + LogMessageVerb(X_DEFAULT, 0, "default setting,\n\t"); + LogMessageVerb(X_CMDLINE, 0, "from command line, "); + LogMessageVerb(X_NOTICE, 0, "notice, "); + LogMessageVerb(X_INFO, 0, "informational,\n\t"); + LogMessageVerb(X_WARNING, 0, "warning, "); + LogMessageVerb(X_ERROR, 0, "error, "); + LogMessageVerb(X_NOT_IMPLEMENTED, 0, "not implemented, "); + LogMessageVerb(X_UNKNOWN, 0, "unknown.\n"); +} + diff --git a/xorg-server/os/mitauth.c b/xorg-server/os/mitauth.c index 5baf552bc..8dfb42be6 100644 --- a/xorg-server/os/mitauth.c +++ b/xorg-server/os/mitauth.c @@ -55,12 +55,12 @@ MitAddCookie ( { struct auth *new; - new = xalloc (sizeof (struct auth)); + new = malloc(sizeof (struct auth)); if (!new) return 0; - new->data = xalloc ((unsigned) data_length); + new->data = malloc((unsigned) data_length); if (!new->data) { - xfree(new); + free(new); return 0; } new->next = mit_auth; @@ -96,8 +96,8 @@ MitResetCookie (void) for (auth = mit_auth; auth; auth=next) { next = auth->next; - xfree (auth->data); - xfree (auth); + free(auth->data); + free(auth); } mit_auth = 0; return 0; @@ -152,8 +152,8 @@ MitRemoveCookie ( prev->next = auth->next; else mit_auth = auth->next; - xfree (auth->data); - xfree (auth); + free(auth->data); + free(auth); return 1; } } diff --git a/xorg-server/os/osinit.c b/xorg-server/os/osinit.c index 23a45e5b7..d04ac6636 100644 --- a/xorg-server/os/osinit.c +++ b/xorg-server/os/osinit.c @@ -1,330 +1,329 @@ -/*********************************************************** - -Copyright 1987, 1998 The Open Group - -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. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. - - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -******************************************************************/ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include -#include -#include "os.h" -#include "osdep.h" -#include -#include -#include -#ifdef HAVE_DLFCN_H -# include -#endif -#ifdef HAVE_BACKTRACE -#include -#endif - - -#include "dixstruct.h" - -#ifndef PATH_MAX -#ifdef MAXPATHLEN -#define PATH_MAX MAXPATHLEN -#else -#define PATH_MAX 1024 -#endif -#endif - -#if defined(__SCO__) -#include -#endif - -#if !defined(SYSV) && !defined(WIN32) -#include -#endif - -#ifndef ADMPATH -#define ADMPATH "/usr/adm/X%smsgs" -#endif - -extern char *display; -#ifdef RLIMIT_DATA -int limitDataSpace = -1; -#endif -#ifdef RLIMIT_STACK -int limitStackSpace = -1; -#endif -#ifdef RLIMIT_NOFILE -int limitNoFile = -1; -#endif - -static OsSigWrapperPtr OsSigWrapper = NULL; - -OsSigWrapperPtr -OsRegisterSigWrapper(OsSigWrapperPtr newSigWrapper) -{ - OsSigWrapperPtr oldSigWrapper = OsSigWrapper; - - OsSigWrapper = newSigWrapper; - - return oldSigWrapper; -} - -/* - * OsSigHandler -- - * Catch unexpected signals and exit or continue cleanly. - */ -static void -#ifdef SA_SIGINFO -OsSigHandler(int signo, siginfo_t *sip, void *unused) -#else -OsSigHandler(int signo) -#endif -{ -#ifdef RTLD_DI_SETSIGNAL - const char *dlerr = dlerror(); - - if (dlerr) { - LogMessage(X_ERROR, "Dynamic loader error: %s\n", dlerr); - } -#endif /* RTLD_DI_SETSIGNAL */ - - if (OsSigWrapper != NULL) { - if (OsSigWrapper(signo) == 0) { - /* ddx handled signal and wants us to continue */ - return; - } - } - - /* log, cleanup, and abort */ - xorg_backtrace(); - -#ifdef SA_SIGINFO - if (sip->si_code == SI_USER) { - ErrorF("Recieved signal %d sent by process %ld, uid %ld\n", - signo, (long) sip->si_pid, (long) sip->si_uid); - } else { - switch (signo) { - case SIGSEGV: - case SIGBUS: - case SIGILL: - case SIGFPE: - ErrorF("%s at address %p\n", strsignal(signo), sip->si_addr); - } - } -#endif - - FatalError("Caught signal %d (%s). Server aborting\n", - signo, strsignal(signo)); -} - -void -OsInit(void) -{ - static Bool been_here = FALSE; - static char* admpath = ADMPATH; - static char* devnull = "/dev/null"; - char fname[PATH_MAX]; - - if (!been_here) { -#ifndef _MSC_VER - struct sigaction act, oact; - int i; - int siglist[] = { SIGSEGV, SIGQUIT, SIGILL, SIGFPE, SIGBUS, -#ifdef SIGSYS - SIGSYS, -#endif -#ifdef SIGXCPU - SIGXCPU, -#endif -#ifdef SIGXFSZ - SIGXFSZ, -#endif -#ifdef SIGEMT - SIGEMT, -#endif - 0 /* must be last */ }; - sigemptyset(&act.sa_mask); -#ifdef SA_SIGINFO - act.sa_sigaction = OsSigHandler; - act.sa_flags = SA_SIGINFO; -#else - act.sa_handler = OsSigHandler; - act.sa_flags = 0; -#endif - for (i = 0; siglist[i] != 0; i++) { - if (sigaction(siglist[i], &act, &oact)) { - ErrorF("failed to install signal handler for signal %d: %s\n", - siglist[i], strerror(errno)); - } - } -#ifdef HAVE_BACKTRACE - /* - * initialize the backtracer, since the ctor calls dlopen(), which - * calls malloc(), which isn't signal-safe. - */ - do { - void *array; - backtrace(&array, 1); - } while (0); -#endif - -#ifdef RTLD_DI_SETSIGNAL - /* Tell runtime linker to send a signal we can catch instead of SIGKILL - * for failures to load libraries/modules at runtime so we can clean up - * after ourselves. - */ - int failure_signal = SIGQUIT; - dlinfo(RTLD_SELF, RTLD_DI_SETSIGNAL, &failure_signal); -#endif -#endif -#if !defined(__SCO__) && !defined(__CYGWIN__) && !defined(__UNIXWARE__) - fclose(stdin); - fclose(stdout); -#endif - /* - * If a write of zero bytes to stderr returns non-zero, i.e. -1, - * then writing to stderr failed, and we'll write somewhere else - * instead. (Apparently this never happens in the Real World.) - */ - if (write (2, fname, 0) == -1) - { - FILE *err; - - if (strlen (display) + strlen (admpath) + 1 < sizeof fname) - sprintf (fname, admpath, display); - else - strcpy (fname, devnull); - /* - * uses stdio to avoid os dependencies here, - * a real os would use - * open (fname, O_WRONLY|O_APPEND|O_CREAT, 0666) - */ - if (!(err = fopen (fname, "a+"))) - err = fopen (devnull, "w"); - if (err && (fileno(err) != 2)) { - dup2 (fileno (err), 2); - fclose (err); - } -#if defined(SYSV) || defined(SVR4) || defined(WIN32) || defined(__CYGWIN__) - { - static char buf[BUFSIZ]; - setvbuf (stderr, buf, _IOLBF, BUFSIZ); - } -#else - setlinebuf(stderr); -#endif - } - -#ifndef _MSC_VER - if (getpgrp () == 0) - setpgid (0, 0); -#endif - -#ifdef RLIMIT_DATA - if (limitDataSpace >= 0) - { - struct rlimit rlim; - - if (!getrlimit(RLIMIT_DATA, &rlim)) - { - if ((limitDataSpace > 0) && (limitDataSpace < rlim.rlim_max)) - rlim.rlim_cur = limitDataSpace; - else - rlim.rlim_cur = rlim.rlim_max; - (void)setrlimit(RLIMIT_DATA, &rlim); - } - } -#endif -#ifdef RLIMIT_STACK - if (limitStackSpace >= 0) - { - struct rlimit rlim; - - if (!getrlimit(RLIMIT_STACK, &rlim)) - { - if ((limitStackSpace > 0) && (limitStackSpace < rlim.rlim_max)) - rlim.rlim_cur = limitStackSpace; - else - rlim.rlim_cur = rlim.rlim_max; - (void)setrlimit(RLIMIT_STACK, &rlim); - } - } -#endif -#ifdef RLIMIT_NOFILE - if (limitNoFile >= 0) - { - struct rlimit rlim; - - if (!getrlimit(RLIMIT_NOFILE, &rlim)) - { - if ((limitNoFile > 0) && (limitNoFile < rlim.rlim_max)) - rlim.rlim_cur = limitNoFile; - else - rlim.rlim_cur = rlim.rlim_max; - (void)setrlimit(RLIMIT_NOFILE, &rlim); - } - } -#endif - LockServer(); - been_here = TRUE; - } - TimerInit(); - OsVendorInit(); - /* - * No log file by default. OsVendorInit() should call LogInit() with the - * log file name if logging to a file is desired. - */ - LogInit(NULL, NULL); - if (!SmartScheduleDisable) - if (!SmartScheduleInit ()) - SmartScheduleDisable = TRUE; -} - -void -OsCleanup(Bool terminating) -{ - if (terminating) - { - UnlockServer(); - } -} +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +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. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include "os.h" +#include "osdep.h" +#include +#include +#include +#ifdef HAVE_DLFCN_H +# include +#endif +#ifdef HAVE_BACKTRACE +#include +#endif + + +#include "dixstruct.h" + +#ifndef PATH_MAX +#ifdef MAXPATHLEN +#define PATH_MAX MAXPATHLEN +#else +#define PATH_MAX 1024 +#endif +#endif + +#if defined(__SCO__) +#include +#endif + +#if !defined(SYSV) && !defined(WIN32) +#include +#endif + +#ifndef ADMPATH +#define ADMPATH "/usr/adm/X%smsgs" +#endif + +extern char *display; +#ifdef RLIMIT_DATA +int limitDataSpace = -1; +#endif +#ifdef RLIMIT_STACK +int limitStackSpace = -1; +#endif +#ifdef RLIMIT_NOFILE +int limitNoFile = -1; +#endif + +static OsSigWrapperPtr OsSigWrapper = NULL; + +OsSigWrapperPtr +OsRegisterSigWrapper(OsSigWrapperPtr newSigWrapper) +{ + OsSigWrapperPtr oldSigWrapper = OsSigWrapper; + + OsSigWrapper = newSigWrapper; + + return oldSigWrapper; +} + +/* + * OsSigHandler -- + * Catch unexpected signals and exit or continue cleanly. + */ +static void +#ifdef SA_SIGINFO +OsSigHandler(int signo, siginfo_t *sip, void *unused) +#else +OsSigHandler(int signo) +#endif +{ +#ifdef RTLD_DI_SETSIGNAL + const char *dlerr = dlerror(); + + if (dlerr) { + LogMessage(X_ERROR, "Dynamic loader error: %s\n", dlerr); + } +#endif /* RTLD_DI_SETSIGNAL */ + + if (OsSigWrapper != NULL) { + if (OsSigWrapper(signo) == 0) { + /* ddx handled signal and wants us to continue */ + return; + } + } + + /* log, cleanup, and abort */ + xorg_backtrace(); + +#ifdef SA_SIGINFO + if (sip->si_code == SI_USER) { + ErrorF("Recieved signal %d sent by process %ld, uid %ld\n", + signo, (long) sip->si_pid, (long) sip->si_uid); + } else { + switch (signo) { + case SIGSEGV: + case SIGBUS: + case SIGILL: + case SIGFPE: + ErrorF("%s at address %p\n", strsignal(signo), sip->si_addr); + } + } +#endif + + FatalError("Caught signal %d (%s). Server aborting\n", + signo, strsignal(signo)); +} + +void +OsInit(void) +{ + static Bool been_here = FALSE; + static char* devnull = "/dev/null"; + char fname[PATH_MAX]; + + if (!been_here) { +#ifndef _MSC_VER + struct sigaction act, oact; + int i; + int siglist[] = { SIGSEGV, SIGQUIT, SIGILL, SIGFPE, SIGBUS, +#ifdef SIGSYS + SIGSYS, +#endif +#ifdef SIGXCPU + SIGXCPU, +#endif +#ifdef SIGXFSZ + SIGXFSZ, +#endif +#ifdef SIGEMT + SIGEMT, +#endif + 0 /* must be last */ }; + sigemptyset(&act.sa_mask); +#ifdef SA_SIGINFO + act.sa_sigaction = OsSigHandler; + act.sa_flags = SA_SIGINFO; +#else + act.sa_handler = OsSigHandler; + act.sa_flags = 0; +#endif + for (i = 0; siglist[i] != 0; i++) { + if (sigaction(siglist[i], &act, &oact)) { + ErrorF("failed to install signal handler for signal %d: %s\n", + siglist[i], strerror(errno)); + } + } +#ifdef HAVE_BACKTRACE + /* + * initialize the backtracer, since the ctor calls dlopen(), which + * calls malloc(), which isn't signal-safe. + */ + do { + void *array; + backtrace(&array, 1); + } while (0); +#endif + +#ifdef RTLD_DI_SETSIGNAL + /* Tell runtime linker to send a signal we can catch instead of SIGKILL + * for failures to load libraries/modules at runtime so we can clean up + * after ourselves. + */ + int failure_signal = SIGQUIT; + dlinfo(RTLD_SELF, RTLD_DI_SETSIGNAL, &failure_signal); +#endif +#endif +#if !defined(__SCO__) && !defined(__CYGWIN__) && !defined(__UNIXWARE__) + fclose(stdin); + fclose(stdout); +#endif + /* + * If a write of zero bytes to stderr returns non-zero, i.e. -1, + * then writing to stderr failed, and we'll write somewhere else + * instead. (Apparently this never happens in the Real World.) + */ + if (write (2, fname, 0) == -1) + { + FILE *err; + + if (strlen (display) + strlen (ADMPATH) + 1 < sizeof fname) + sprintf (fname, ADMPATH, display); + else + strcpy (fname, devnull); + /* + * uses stdio to avoid os dependencies here, + * a real os would use + * open (fname, O_WRONLY|O_APPEND|O_CREAT, 0666) + */ + if (!(err = fopen (fname, "a+"))) + err = fopen (devnull, "w"); + if (err && (fileno(err) != 2)) { + dup2 (fileno (err), 2); + fclose (err); + } +#if defined(SYSV) || defined(SVR4) || defined(WIN32) || defined(__CYGWIN__) + { + static char buf[BUFSIZ]; + setvbuf (stderr, buf, _IOLBF, BUFSIZ); + } +#else + setlinebuf(stderr); +#endif + } + +#ifndef _MSC_VER + if (getpgrp () == 0) + setpgid (0, 0); +#endif + +#ifdef RLIMIT_DATA + if (limitDataSpace >= 0) + { + struct rlimit rlim; + + if (!getrlimit(RLIMIT_DATA, &rlim)) + { + if ((limitDataSpace > 0) && (limitDataSpace < rlim.rlim_max)) + rlim.rlim_cur = limitDataSpace; + else + rlim.rlim_cur = rlim.rlim_max; + (void)setrlimit(RLIMIT_DATA, &rlim); + } + } +#endif +#ifdef RLIMIT_STACK + if (limitStackSpace >= 0) + { + struct rlimit rlim; + + if (!getrlimit(RLIMIT_STACK, &rlim)) + { + if ((limitStackSpace > 0) && (limitStackSpace < rlim.rlim_max)) + rlim.rlim_cur = limitStackSpace; + else + rlim.rlim_cur = rlim.rlim_max; + (void)setrlimit(RLIMIT_STACK, &rlim); + } + } +#endif +#ifdef RLIMIT_NOFILE + if (limitNoFile >= 0) + { + struct rlimit rlim; + + if (!getrlimit(RLIMIT_NOFILE, &rlim)) + { + if ((limitNoFile > 0) && (limitNoFile < rlim.rlim_max)) + rlim.rlim_cur = limitNoFile; + else + rlim.rlim_cur = rlim.rlim_max; + (void)setrlimit(RLIMIT_NOFILE, &rlim); + } + } +#endif + LockServer(); + been_here = TRUE; + } + TimerInit(); + OsVendorInit(); + /* + * No log file by default. OsVendorInit() should call LogInit() with the + * log file name if logging to a file is desired. + */ + LogInit(NULL, NULL); + if (!SmartScheduleDisable) + if (!SmartScheduleInit ()) + SmartScheduleDisable = TRUE; +} + +void +OsCleanup(Bool terminating) +{ + if (terminating) + { + UnlockServer(); + } +} diff --git a/xorg-server/os/rpcauth.c b/xorg-server/os/rpcauth.c index a63304375..b40f9359a 100644 --- a/xorg-server/os/rpcauth.c +++ b/xorg-server/os/rpcauth.c @@ -66,7 +66,7 @@ authdes_ezdecode(const char *inmsg, int len) XDR xdr; SVCXPRT xprt; - temp_inmsg = xalloc(len); + temp_inmsg = malloc(len); memmove(temp_inmsg, inmsg, len); memset((char *)&msg, 0, sizeof(msg)); @@ -79,7 +79,7 @@ authdes_ezdecode(const char *inmsg, int len) why = AUTH_FAILED; xdrmem_create(&xdr, temp_inmsg, len, XDR_DECODE); - if ((r.rq_clntcred = xalloc(MAX_AUTH_BYTES)) == NULL) + if ((r.rq_clntcred = malloc(MAX_AUTH_BYTES)) == NULL) goto bad1; r.rq_xprt = &xprt; @@ -106,7 +106,7 @@ authdes_ezdecode(const char *inmsg, int len) return (((struct authdes_cred *) r.rq_clntcred)->adc_fullname.name); bad2: - xfree(r.rq_clntcred); + free(r.rq_clntcred); bad1: return ((char *)0); /* ((struct authdes_cred *) NULL); */ } diff --git a/xorg-server/os/utils.c b/xorg-server/os/utils.c index 9a10be7c4..cc5332300 100644 --- a/xorg-server/os/utils.c +++ b/xorg-server/os/utils.c @@ -1,1972 +1,1925 @@ -/* - -Copyright 1987, 1998 The Open Group - -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. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall -not be used in advertising or otherwise to promote the sale, use or -other dealings in this Software without prior written authorization -from The Open Group. - - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, -Copyright 1994 Quarterdeck Office Systems. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the names of Digital and -Quarterdeck not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -DIGITAL AND QUARTERDECK DISCLAIM ALL WARRANTIES WITH REGARD TO THIS -SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT -OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS -OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE -OR PERFORMANCE OF THIS SOFTWARE. - -*/ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#ifdef __CYGWIN__ -#include -#include -/* - Sigh... We really need a prototype for this to know it is stdcall, - but #include-ing here is not a good idea... -*/ -__stdcall unsigned long GetTickCount(void); -#endif - -#if defined(WIN32) && !defined(__CYGWIN__) -#include -#endif -#include -#include -#include -#if !defined(WIN32) || !defined(__MINGW32__) -#include -#include -#endif -#include "misc.h" -#include -#define XSERV_t -#define TRANS_SERVER -#define TRANS_REOPEN -#include -#include "input.h" -#include "dixfont.h" -#include "osdep.h" -#include "extension.h" -#ifdef X_POSIX_C_SOURCE -#define _POSIX_C_SOURCE X_POSIX_C_SOURCE -#include -#undef _POSIX_C_SOURCE -#else -#if defined(_POSIX_SOURCE) -#include -#else -#define _POSIX_SOURCE -#include -#undef _POSIX_SOURCE -#endif -#endif -#ifndef WIN32 -#include -#endif -#if !defined(SYSV) && !defined(WIN32) -#include -#endif -#include -#include /* for isspace */ -#include - -#include /* for malloc() */ - -#if defined(TCPCONN) || defined(STREAMSCONN) -# ifndef WIN32 -# include -# endif -#endif - -#include "opaque.h" - -#include "dixstruct.h" - -#include "xkbsrv.h" - -#include "picture.h" - -Bool noTestExtensions; -#ifdef COMPOSITE -Bool noCompositeExtension = FALSE; -#endif - -#ifdef DAMAGE -Bool noDamageExtension = FALSE; -#endif -#ifdef DBE -Bool noDbeExtension = FALSE; -#endif -#ifdef DPMSExtension -Bool noDPMSExtension = FALSE; -#endif -#ifdef GLXEXT -Bool noGlxExtension = FALSE; -Bool noGlxVisualInit = FALSE; -#endif -#ifdef SCREENSAVER -Bool noScreenSaverExtension = FALSE; -#endif -#ifdef MITSHM -Bool noMITShmExtension = FALSE; -#endif -#ifdef RANDR -Bool noRRExtension = FALSE; -#endif -Bool noRenderExtension = FALSE; -#ifdef XCSECURITY -Bool noSecurityExtension = FALSE; -#endif -#ifdef RES -Bool noResExtension = FALSE; -#endif -#ifdef XF86BIGFONT -Bool noXFree86BigfontExtension = FALSE; -#endif -#ifdef XFreeXDGA -Bool noXFree86DGAExtension = FALSE; -#endif -#ifdef XF86DRI -Bool noXFree86DRIExtension = FALSE; -#endif -#ifdef XF86VIDMODE -Bool noXFree86VidModeExtension = FALSE; -#endif -#ifdef XFIXES -Bool noXFixesExtension = FALSE; -#endif -#ifdef PANORAMIX -/* Xinerama is disabled by default unless enabled via +xinerama */ -Bool noPanoramiXExtension = TRUE; -#endif -#ifdef XSELINUX -Bool noSELinuxExtension = FALSE; -int selinuxEnforcingState = SELINUX_MODE_DEFAULT; -#endif -#ifdef XV -Bool noXvExtension = FALSE; -#endif -#ifdef DRI2 -Bool noDRI2Extension = FALSE; -#endif - -Bool noGEExtension = FALSE; - -#define X_INCLUDE_NETDB_H -#include - -#include - -Bool CoreDump; - -#ifdef PANORAMIX -Bool PanoramiXExtensionDisabledHack = FALSE; -#endif - -int auditTrailLevel = 1; - -#if defined(SVR4) || defined(__linux__) || defined(CSRG_BASED) -#define HAS_SAVED_IDS_AND_SETEUID -#endif - -static char *dev_tty_from_init = NULL; /* since we need to parse it anyway */ - -OsSigHandlerPtr -OsSignal(int sig, OsSigHandlerPtr handler) -{ -#ifdef X_NOT_POSIX - return signal(sig, handler); -#else - struct sigaction act, oact; - - sigemptyset(&act.sa_mask); - if (handler != SIG_IGN) - sigaddset(&act.sa_mask, sig); - act.sa_flags = 0; - act.sa_handler = handler; - if (sigaction(sig, &act, &oact)) - perror("sigaction"); - return oact.sa_handler; -#endif -} - -/* - * Explicit support for a server lock file like the ones used for UUCP. - * For architectures with virtual terminals that can run more than one - * server at a time. This keeps the servers from stomping on each other - * if the user forgets to give them different display numbers. - */ -#define LOCK_DIR "/tmp" -#define LOCK_TMP_PREFIX "/.tX" -#define LOCK_PREFIX "/.X" -#define LOCK_SUFFIX "-lock" - -#ifndef PATH_MAX -#include -#ifndef PATH_MAX -#ifdef MAXPATHLEN -#define PATH_MAX MAXPATHLEN -#else -#define PATH_MAX 1024 -#endif -#endif -#endif - -static Bool StillLocking = FALSE; -static char szLockFile[PATH_MAX]; -static Bool nolock = FALSE; - -/* - * LockServer -- - * Check if the server lock file exists. If so, check if the PID - * contained inside is valid. If so, then die. Otherwise, create - * the lock file containing the PID. - */ -void -LockServer(void) -{ -#if defined(WIN32) && !defined(__CYGWIN__) - char MutexName[100]; - sprintf(MutexName, "Global\\VcXsrv_Mutex_%d\n", getpid()); - if (!CreateMutex(NULL,TRUE,MutexName) || GetLastError()== ERROR_ALREADY_EXISTS) - { - FatalError("Server is already active for display %d\n", atoi(display)); - } -#else - char port[20]; - char tmp[PATH_MAX], pid_str[12]; - int lfd, i, haslock, l_pid, t; - char *tmppath = NULL; - int len; - - if (nolock) return; - /* - * Path names - */ - tmppath = LOCK_DIR; - sprintf(port, "%d", atoi(display)); - - len = strlen(LOCK_PREFIX) > strlen(LOCK_TMP_PREFIX) ? strlen(LOCK_PREFIX) : - strlen(LOCK_TMP_PREFIX); - len += strlen(tmppath) + strlen(port) + strlen(LOCK_SUFFIX) + 1; - if (len > sizeof(szLockFile)) - FatalError("Display name `%s' is too long\n", port); - (void)sprintf(tmp, "%s" LOCK_TMP_PREFIX "%s" LOCK_SUFFIX, tmppath, port); - (void)sprintf(szLockFile, "%s" LOCK_PREFIX "%s" LOCK_SUFFIX, tmppath, port); - - /* - * Create a temporary file containing our PID. Attempt three times - * to create the file. - */ - StillLocking = TRUE; - i = 0; - do { - i++; - lfd = open(tmp, O_CREAT | O_EXCL | O_WRONLY, 0644); - if (lfd < 0) - sleep(2); - else - break; - } while (i < 3); - if (lfd < 0) { - unlink(tmp); - i = 0; - do { - i++; - lfd = open(tmp, O_CREAT | O_EXCL | O_WRONLY, 0644); - if (lfd < 0) - sleep(2); - else - break; - } while (i < 3); - } - if (lfd < 0) - FatalError("Could not create lock file in %s\n", tmp); - (void) sprintf(pid_str, "%10ld\n", (long)getpid()); - (void) write(lfd, pid_str, 11); - (void) chmod(tmp, 0444); - (void) close(lfd); - - /* - * OK. Now the tmp file exists. Try three times to move it in place - * for the lock. - */ - i = 0; - haslock = 0; - while ((!haslock) && (i++ < 3)) { - haslock = (link(tmp,szLockFile) == 0); - if (haslock) { - /* - * We're done. - */ - break; - } - else { - /* - * Read the pid from the existing file - */ - lfd = open(szLockFile, O_RDONLY); - if (lfd < 0) { - unlink(tmp); - FatalError("Can't read lock file %s\n", szLockFile); - } - pid_str[0] = '\0'; - if (read(lfd, pid_str, 11) != 11) { - /* - * Bogus lock file. - */ - unlink(szLockFile); - close(lfd); - continue; - } - pid_str[11] = '\0'; - sscanf(pid_str, "%d", &l_pid); - close(lfd); - - /* - * Now try to kill the PID to see if it exists. - */ - errno = 0; - t = kill(l_pid, 0); - if ((t< 0) && (errno == ESRCH)) { - /* - * Stale lock file. - */ - unlink(szLockFile); - continue; - } - else if (((t < 0) && (errno == EPERM)) || (t == 0)) { - /* - * Process is still active. - */ - unlink(tmp); - FatalError("Server is already active for display %s\n%s %s\n%s\n", - port, "\tIf this server is no longer running, remove", - szLockFile, "\tand start again."); - } - } - } - unlink(tmp); - if (!haslock) - FatalError("Could not create server lock file: %s\n", szLockFile); - StillLocking = FALSE; -#endif -} - -/* - * UnlockServer -- - * Remove the server lock file. - */ -void -UnlockServer(void) -{ - if (nolock) return; - - if (!StillLocking){ - - (void) unlink(szLockFile); - } -} - -/* Force connections to close on SIGHUP from init */ - -void -AutoResetServer (int sig) -{ - int olderrno = errno; - - dispatchException |= DE_RESET; - isItTimeToYield = TRUE; - errno = olderrno; -} - -/* Force connections to close and then exit on SIGTERM, SIGINT */ - -void -GiveUp(int sig) -{ - int olderrno = errno; - - dispatchException |= DE_TERMINATE; - isItTimeToYield = TRUE; - errno = olderrno; -} - -#if (defined WIN32 && defined __MINGW32__) || defined(__CYGWIN__) -CARD32 -GetTimeInMillis (void) -{ - return GetTickCount (); -} -#else -CARD32 -GetTimeInMillis(void) -{ - struct timeval tv; - -#ifdef MONOTONIC_CLOCK - struct timespec tp; - if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) - return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000L); -#endif - - X_GETTIMEOFDAY(&tv); - return(tv.tv_sec * 1000) + (tv.tv_usec / 1000); -} -#endif - -void -AdjustWaitForDelay (pointer waitTime, unsigned long newdelay) -{ - static struct timeval delay_val; - struct timeval **wt = (struct timeval **) waitTime; - unsigned long olddelay; - - if (*wt == NULL) - { - delay_val.tv_sec = newdelay / 1000; - delay_val.tv_usec = 1000 * (newdelay % 1000); - *wt = &delay_val; - } - else - { - olddelay = (*wt)->tv_sec * 1000 + (*wt)->tv_usec / 1000; - if (newdelay < olddelay) - { - (*wt)->tv_sec = newdelay / 1000; - (*wt)->tv_usec = 1000 * (newdelay % 1000); - } - } -} - -void UseMsg(void) -{ - ErrorF("use: X [:] [option]\n"); - ErrorF("-a # default pointer acceleration (factor)\n"); - ErrorF("-ac disable access control restrictions\n"); - ErrorF("-audit int set audit trail level\n"); - ErrorF("-auth file select authorization file\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"); - ErrorF("c # key-click volume (0-100)\n"); - ErrorF("-cc int default color visual class\n"); - ErrorF("-nocursor disable the cursor\n"); - ErrorF("-core generate core dump on fatal error\n"); - ErrorF("-dpi int screen resolution in dots per inch\n"); -#ifdef DPMSExtension - ErrorF("-dpms disables VESA DPMS monitor control\n"); -#endif - ErrorF("-deferglyphs [none|all|16] defer loading of [no|all|16-bit] glyphs\n"); - ErrorF("-f # bell base (0-100)\n"); - ErrorF("-fc string cursor font\n"); - ErrorF("-fn string default font name\n"); - ErrorF("-fp string default font path\n"); - ErrorF("-help prints message with these options\n"); - ErrorF("-I ignore all remaining arguments\n"); -#ifdef RLIMIT_DATA - ErrorF("-ld int limit data space to N Kb\n"); -#endif -#ifdef RLIMIT_NOFILE - ErrorF("-lf int limit number of open files to N\n"); -#endif -#ifdef RLIMIT_STACK - ErrorF("-ls int limit stack space to N Kb\n"); -#endif - ErrorF("-nolock disable the locking mechanism\n"); -#ifndef NOLOGOHACK - ErrorF("-logo enable logo in screen saver\n"); - ErrorF("nologo disable logo in screen saver\n"); -#endif - ErrorF("-nolisten string don't listen on protocol\n"); - ErrorF("-noreset don't reset after last client exists\n"); - ErrorF("-reset reset after last client exists\n"); - ErrorF("-p # screen-saver pattern duration (minutes)\n"); - ErrorF("-pn accept failure to listen on all ports\n"); - ErrorF("-nopn reject failure to listen on all ports\n"); - ErrorF("-r turns off auto-repeat\n"); - ErrorF("r turns on auto-repeat \n"); - ErrorF("-render [default|mono|gray|color] set render color alloc policy\n"); - ErrorF("-retro start with classic stipple and cursor\n"); - ErrorF("-s # screen-saver timeout (minutes)\n"); - ErrorF("-t # default pointer threshold (pixels/t)\n"); - ErrorF("-terminate terminate at server reset\n"); - ErrorF("-to # connection time out\n"); - ErrorF("-tst disable testing extensions\n"); - ErrorF("ttyxx server started from init on /dev/ttyxx\n"); - ErrorF("v video blanking for screen-saver\n"); - ErrorF("-v screen-saver without video blanking\n"); - ErrorF("-wm WhenMapped default backing-store\n"); - ErrorF("-wr create root window with white background\n"); - ErrorF("-maxbigreqsize set maximal bigrequest size \n"); -#ifdef PANORAMIX - ErrorF("+xinerama Enable XINERAMA extension\n"); - ErrorF("-xinerama Disable XINERAMA extension\n"); -#endif - ErrorF("-dumbSched Disable smart scheduling, enable old behavior\n"); - ErrorF("-schedInterval int Set scheduler interval in msec\n"); - ErrorF("+extension name Enable extension\n"); - ErrorF("-extension name Disable extension\n"); -#ifdef XDMCP - XdmcpUseMsg(); -#endif - XkbUseMsg(); - ddxUseMsg(); -} - -/* This function performs a rudimentary sanity check - * on the display name passed in on the command-line, - * since this string is used to generate filenames. - * It is especially important that the display name - * not contain a "/" and not start with a "-". - * --kvajk - */ -static int -VerifyDisplayName(const char *d) -{ - if ( d == (char *)0 ) return( 0 ); /* null */ - if ( *d == '\0' ) return( 0 ); /* empty */ - if ( *d == '-' ) return( 0 ); /* could be confused for an option */ - if ( *d == '.' ) return( 0 ); /* must not equal "." or ".." */ - if ( strchr(d, '/') != (char *)0 ) return( 0 ); /* very important!!! */ - return( 1 ); -} - -/* - * This function parses the command line. Handles device-independent fields - * and allows ddx to handle additional fields. It is not allowed to modify - * argc or any of the strings pointed to by argv. - */ -void -ProcessCommandLine(int argc, char *argv[]) -{ - int i, skip; - - defaultKeyboardControl.autoRepeat = TRUE; - -#ifdef NO_PART_NET - PartialNetwork = FALSE; -#else - PartialNetwork = TRUE; -#endif - - for ( i = 1; i < argc; i++ ) - { - /* call ddx first, so it can peek/override if it wants */ - if((skip = ddxProcessArgument(argc, argv, i))) - { - i += (skip - 1); - } - else if(argv[i][0] == ':') - { - /* initialize display */ - display = argv[i]; - display++; - if( ! VerifyDisplayName( display ) ) { - ErrorF("Bad display name: %s\n", display); - UseMsg(); - FatalError("Bad display name, exiting: %s\n", display); - } - } - else if ( strcmp( argv[i], "-a") == 0) - { - if(++i < argc) - defaultPointerControl.num = atoi(argv[i]); - else - UseMsg(); - } - else if ( strcmp( argv[i], "-ac") == 0) - { - defeatAccessControl = TRUE; - } - else if ( strcmp( argv[i], "-audit") == 0) - { - if(++i < argc) - auditTrailLevel = atoi(argv[i]); - else - UseMsg(); - } - else if ( strcmp( argv[i], "-auth") == 0) - { - if(++i < argc) - InitAuthorization (argv[i]); - else - UseMsg(); - } - else if ( strcmp( argv[i], "-br") == 0) ; /* default */ - else if ( strcmp( argv[i], "+bs") == 0) - enableBackingStore = TRUE; - else if ( strcmp( argv[i], "-bs") == 0) - disableBackingStore = TRUE; - else if ( strcmp( argv[i], "c") == 0) - { - if(++i < argc) - defaultKeyboardControl.click = atoi(argv[i]); - else - UseMsg(); - } - else if ( strcmp( argv[i], "-c") == 0) - { - defaultKeyboardControl.click = 0; - } - else if ( strcmp( argv[i], "-cc") == 0) - { - if(++i < argc) - defaultColorVisualClass = atoi(argv[i]); - else - UseMsg(); - } - else if ( strcmp( argv[i], "-core") == 0) - { -#if !defined(WIN32) || !defined(__MINGW32__) - struct rlimit core_limit; - getrlimit (RLIMIT_CORE, &core_limit); - core_limit.rlim_cur = core_limit.rlim_max; - setrlimit (RLIMIT_CORE, &core_limit); -#endif - CoreDump = TRUE; - } - else if ( strcmp( argv[i], "-nocursor") == 0) - { - EnableCursor = FALSE; - } - else if ( strcmp( argv[i], "-dpi") == 0) - { - if(++i < argc) - monitorResolution = atoi(argv[i]); - else - UseMsg(); - } -#ifdef DPMSExtension - else if ( strcmp( argv[i], "dpms") == 0) - /* ignored for compatibility */ ; - else if ( strcmp( argv[i], "-dpms") == 0) - DPMSDisabledSwitch = TRUE; -#endif - else if ( strcmp( argv[i], "-deferglyphs") == 0) - { - if(++i >= argc || !ParseGlyphCachingMode(argv[i])) - UseMsg(); - } - else if ( strcmp( argv[i], "-f") == 0) - { - if(++i < argc) - defaultKeyboardControl.bell = atoi(argv[i]); - else - UseMsg(); - } - else if ( strcmp( argv[i], "-fc") == 0) - { - if(++i < argc) - defaultCursorFont = argv[i]; - else - UseMsg(); - } - else if ( strcmp( argv[i], "-fn") == 0) - { - if(++i < argc) - defaultTextFont = argv[i]; - else - UseMsg(); - } - else if ( strcmp( argv[i], "-fp") == 0) - { - if(++i < argc) - { - defaultFontPath = argv[i]; - } - else - UseMsg(); - } - else if ( strcmp( argv[i], "-help") == 0) - { - UseMsg(); - exit(0); - } - else if ( (skip=XkbProcessArguments(argc,argv,i))!=0 ) { - if (skip>0) - i+= skip-1; - else UseMsg(); - } -#ifdef RLIMIT_DATA - else if ( strcmp( argv[i], "-ld") == 0) - { - if(++i < argc) - { - limitDataSpace = atoi(argv[i]); - if (limitDataSpace > 0) - limitDataSpace *= 1024; - } - else - UseMsg(); - } -#endif -#ifdef RLIMIT_NOFILE - else if ( strcmp( argv[i], "-lf") == 0) - { - if(++i < argc) - limitNoFile = atoi(argv[i]); - else - UseMsg(); - } -#endif -#ifdef RLIMIT_STACK - else if ( strcmp( argv[i], "-ls") == 0) - { - if(++i < argc) - { - limitStackSpace = atoi(argv[i]); - if (limitStackSpace > 0) - limitStackSpace *= 1024; - } - else - UseMsg(); - } -#endif - else if ( strcmp ( argv[i], "-nolock") == 0) - { -#if !defined(WIN32) && !defined(__CYGWIN__) - if (getuid() != 0) - ErrorF("Warning: the -nolock option can only be used by root\n"); - else -#endif - nolock = TRUE; - } -#ifndef NOLOGOHACK - else if ( strcmp( argv[i], "-logo") == 0) - { - logoScreenSaver = 1; - } - else if ( strcmp( argv[i], "nologo") == 0) - { - logoScreenSaver = 0; - } -#endif - else if ( strcmp( argv[i], "-nolisten") == 0) - { - if(++i < argc) { - if (_XSERVTransNoListen(argv[i])) - FatalError ("Failed to disable listen for %s transport", - argv[i]); - } else - UseMsg(); - } - else if ( strcmp( argv[i], "-noreset") == 0) - { - dispatchExceptionAtReset = 0; - } - else if ( strcmp( argv[i], "-reset") == 0) - { - dispatchExceptionAtReset = DE_RESET; - } - else if ( strcmp( argv[i], "-p") == 0) - { - if(++i < argc) - defaultScreenSaverInterval = ((CARD32)atoi(argv[i])) * - MILLI_PER_MIN; - else - UseMsg(); - } - else if (strcmp(argv[i], "-pogo") == 0) - { - dispatchException = DE_TERMINATE; - } - else if ( strcmp( argv[i], "-pn") == 0) - PartialNetwork = TRUE; - else if ( strcmp( argv[i], "-nopn") == 0) - PartialNetwork = FALSE; - else if ( strcmp( argv[i], "r") == 0) - defaultKeyboardControl.autoRepeat = TRUE; - else if ( strcmp( argv[i], "-r") == 0) - defaultKeyboardControl.autoRepeat = FALSE; - else if ( strcmp( argv[i], "-retro") == 0) - party_like_its_1989 = TRUE; - else if ( strcmp( argv[i], "-s") == 0) - { - if(++i < argc) - defaultScreenSaverTime = ((CARD32)atoi(argv[i])) * - MILLI_PER_MIN; - else - UseMsg(); - } - else if ( strcmp( argv[i], "-t") == 0) - { - if(++i < argc) - defaultPointerControl.threshold = atoi(argv[i]); - else - UseMsg(); - } - else if ( strcmp( argv[i], "-terminate") == 0) - { - dispatchExceptionAtReset = DE_TERMINATE; - } - else if ( strcmp( argv[i], "-to") == 0) - { - if(++i < argc) - TimeOutValue = ((CARD32)atoi(argv[i])) * MILLI_PER_SECOND; - else - UseMsg(); - } - else if ( strcmp( argv[i], "-tst") == 0) - { - noTestExtensions = TRUE; - } - else if ( strcmp( argv[i], "v") == 0) - defaultScreenSaverBlanking = PreferBlanking; - else if ( strcmp( argv[i], "-v") == 0) - defaultScreenSaverBlanking = DontPreferBlanking; - else if ( strcmp( argv[i], "-wm") == 0) - defaultBackingStore = WhenMapped; - else if ( strcmp( argv[i], "-wr") == 0) - whiteRoot = TRUE; - else if ( strcmp( argv[i], "-maxbigreqsize") == 0) { - if(++i < argc) { - long reqSizeArg = atol(argv[i]); - - /* Request size > 128MB does not make much sense... */ - if( reqSizeArg > 0L && reqSizeArg < 128L ) { - maxBigRequestSize = (reqSizeArg * 1048576L) - 1L; - } - else - { - UseMsg(); - } - } - else - { - UseMsg(); - } - } -#ifdef PANORAMIX - else if ( strcmp( argv[i], "+xinerama") == 0){ - noPanoramiXExtension = FALSE; - } - else if ( strcmp( argv[i], "-xinerama") == 0){ - noPanoramiXExtension = TRUE; - } - else if ( strcmp( argv[i], "-disablexineramaextension") == 0){ - PanoramiXExtensionDisabledHack = TRUE; - } -#endif - else if ( strcmp( argv[i], "-I") == 0) - { - /* ignore all remaining arguments */ - break; - } - else if (strncmp (argv[i], "tty", 3) == 0) - { - /* just in case any body is interested */ - dev_tty_from_init = argv[i]; - } -#ifdef XDMCP - else if ((skip = XdmcpOptions(argc, argv, i)) != i) - { - i = skip - 1; - } -#endif - 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(); - } - else if ( strcmp( argv[i], "-render" ) == 0) - { - if (++i < argc) - { - int policy = PictureParseCmapPolicy (argv[i]); - - if (policy != PictureCmapPolicyInvalid) - PictureCmapPolicy = policy; - else - UseMsg (); - } - else - UseMsg (); - } - else if ( strcmp( argv[i], "+extension") == 0) - { - if (++i < argc) - { - if (!EnableDisableExtension(argv[i], TRUE)) - EnableDisableExtensionError(argv[i], TRUE); - } - else - UseMsg(); - } - else if ( strcmp( argv[i], "-extension") == 0) - { - if (++i < argc) - { - if (!EnableDisableExtension(argv[i], FALSE)) - EnableDisableExtensionError(argv[i], FALSE); - } - else - UseMsg(); - } - else - { - ErrorF("Unrecognized option: %s\n", argv[i]); - UseMsg(); - FatalError("Unrecognized option: %s\n", argv[i]); - } - } -} - -/* Implement a simple-minded font authorization scheme. The authorization - name is "hp-hostname-1", the contents are simply the host name. */ -int -set_font_authorizations(char **authorizations, int *authlen, pointer client) -{ -#define AUTHORIZATION_NAME "hp-hostname-1" -#if defined(TCPCONN) || defined(STREAMSCONN) - static char *result = NULL; - static char *p = NULL; - - if (p == NULL) - { - char hname[1024], *hnameptr; - unsigned int len; -#if defined(IPv6) && defined(AF_INET6) - struct addrinfo hints, *ai = NULL; -#else - struct hostent *host; -#ifdef XTHREADS_NEEDS_BYNAMEPARAMS - _Xgethostbynameparams hparams; -#endif -#endif - - gethostname(hname, 1024); -#if defined(IPv6) && defined(AF_INET6) - bzero(&hints, sizeof(hints)); - hints.ai_flags = AI_CANONNAME; - if (getaddrinfo(hname, NULL, &hints, &ai) == 0) { - hnameptr = ai->ai_canonname; - } else { - hnameptr = hname; - } -#else - host = _XGethostbyname(hname, hparams); - if (host == NULL) - hnameptr = hname; - else - hnameptr = host->h_name; -#endif - - len = strlen(hnameptr) + 1; - result = xalloc(len + sizeof(AUTHORIZATION_NAME) + 4); - - p = result; - *p++ = sizeof(AUTHORIZATION_NAME) >> 8; - *p++ = sizeof(AUTHORIZATION_NAME) & 0xff; - *p++ = (len) >> 8; - *p++ = (len & 0xff); - - memmove(p, AUTHORIZATION_NAME, sizeof(AUTHORIZATION_NAME)); - p += sizeof(AUTHORIZATION_NAME); - memmove(p, hnameptr, len); - p += len; -#if defined(IPv6) && defined(AF_INET6) - if (ai) { - freeaddrinfo(ai); - } -#endif - } - *authlen = p - result; - *authorizations = result; - return 1; -#else /* TCPCONN */ - return 0; -#endif /* TCPCONN */ -} - -void * -Xalloc(unsigned long amount) -{ - void *ptr; - - if ((long)amount <= 0) { - return NULL; - } - /* aligned extra on long word boundary */ - amount = (amount + (sizeof(long) - 1)) & ~(sizeof(long) - 1); - ptr = malloc(amount); - return ptr; -} - -/***************** - * XNFalloc - * "no failure" realloc - *****************/ - -void * -XNFalloc(unsigned long amount) -{ - void *ptr; - - if ((long)amount <= 0) - return NULL; - /* aligned extra on long word boundary */ - amount = (amount + (sizeof(long) - 1)) & ~(sizeof(long) - 1); - ptr = malloc(amount); - if (!ptr) - FatalError("Out of memory"); - return ptr; -} - -/***************** - * Xcalloc - *****************/ - -void * -Xcalloc(unsigned long amount) -{ - void *ret; - - ret = Xalloc (amount); - if (ret) - bzero (ret, (int) amount); - return ret; -} - -/***************** - * XNFcalloc - *****************/ - -void * -XNFcalloc(unsigned long amount) -{ - void *ret; - - ret = Xalloc (amount); - if (ret) - bzero (ret, (int) amount); - else if ((long)amount > 0) - FatalError("Out of memory"); - return ret; -} - -/***************** - * Xrealloc - *****************/ - -void * -Xrealloc(pointer ptr, unsigned long amount) -{ - if ((long)amount <= 0) - { - if (ptr && !amount) - free(ptr); - return NULL; - } - amount = (amount + (sizeof(long) - 1)) & ~(sizeof(long) - 1); - if (ptr) - ptr = realloc(ptr, amount); - else - ptr = malloc(amount); - - return ptr; -} - -/***************** - * XNFrealloc - * "no failure" realloc - *****************/ - -void * -XNFrealloc(pointer ptr, unsigned long amount) -{ - if ((ptr = Xrealloc(ptr, amount)) == NULL) - { - if ((long)amount > 0) - FatalError( "Out of memory" ); - } - return ptr; -} - -/***************** - * Xfree - * calls free - *****************/ - -void -Xfree(pointer ptr) -{ - if (ptr) - free(ptr); -} - - -char * -Xstrdup(const char *s) -{ - char *sd; - - if (s == NULL) - return NULL; - - sd = Xalloc(strlen(s) + 1); - if (sd != NULL) - strcpy(sd, s); - return sd; -} - - -char * -XNFstrdup(const char *s) -{ - char *sd; - - if (s == NULL) - return NULL; - - sd = XNFalloc(strlen(s) + 1); - strcpy(sd, s); - return sd; -} - - -#if defined(SIGVTALRM) && !defined(__CYGWIN__) -#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; - - if (SmartScheduleDisable) - return; - 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); -#endif -} - -void -SmartScheduleStartTimer (void) -{ -#ifdef SMART_SCHEDULE_POSSIBLE - struct itimerval timer; - - if (SmartScheduleDisable) - return; - 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; - setitimer (ITIMER_REAL, &timer, 0); -#endif -} - -#ifdef SMART_SCHEDULE_POSSIBLE -static void -SmartScheduleTimer (int sig) -{ - SmartScheduleTime += SmartScheduleInterval; -} -#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; - } - return TRUE; -#else - return FALSE; -#endif -} - -#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 -#ifdef SIGCHLD - sigaddset (&set, SIGCHLD); -#endif - sigprocmask (SIG_BLOCK, &set, &PreviousSignalMask); - } -#endif -} - -void -OsReleaseSignals (void) -{ -#ifdef SIG_BLOCK - if (--BlockedSignalCount == 0) - { - sigprocmask (SIG_SETMASK, &PreviousSignalMask, 0); - } -#endif -} - -/* - * Pending signals may interfere with core dumping. Provide a - * mechanism to block signals when aborting. - */ - -void -OsAbort (void) -{ -#ifndef __APPLE__ - OsBlockSignals(); -#endif - abort(); -} - -#if !defined(WIN32) -/* - * "safer" versions of system(3), popen(3) and pclose(3) which give up - * 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 -System(char *command) -{ - int pid, p; -#ifdef SIGCHLD - void (*csig)(int); -#endif - int status; - - if (!command) - return(1); - -#ifdef SIGCHLD - csig = signal(SIGCHLD, SIG_DFL); - if (csig == SIG_ERR) { - perror("signal"); - return -1; - } -#endif - -#ifdef DEBUG - ErrorF("System: `%s'\n", command); -#endif - - switch (pid = fork()) { - case -1: /* error */ - p = -1; - case 0: /* child */ - if (setgid(getgid()) == -1) - _exit(127); - if (setuid(getuid()) == -1) - _exit(127); - execl("/bin/sh", "sh", "-c", command, (char *)NULL); - _exit(127); - default: /* parent */ - do { - p = waitpid(pid, &status, 0); - } while (p == -1 && errno == EINTR); - - } - -#ifdef SIGCHLD - if (signal(SIGCHLD, csig) == SIG_ERR) { - perror("signal"); - return -1; - } -#endif - - return p == -1 ? -1 : status; -} - -static struct pid { - struct pid *next; - FILE *fp; - int pid; -} *pidlist; - -OsSigHandlerPtr old_alarm = NULL; /* XXX horrible awful hack */ - -pointer -Popen(char *command, char *type) -{ - struct pid *cur; - FILE *iop; - int pdes[2], pid; - - if (command == NULL || type == NULL) - return NULL; - - if ((*type != 'r' && *type != 'w') || type[1]) - return NULL; - - if ((cur = xalloc(sizeof(struct pid))) == NULL) - return NULL; - - if (pipe(pdes) < 0) { - xfree(cur); - return NULL; - } - - /* Ignore the smart scheduler while this is going on */ - old_alarm = OsSignal(SIGALRM, SIG_IGN); - if (old_alarm == SIG_ERR) { - perror("signal"); - return NULL; - } - - switch (pid = fork()) { - case -1: /* error */ - close(pdes[0]); - close(pdes[1]); - xfree(cur); - if (OsSignal(SIGALRM, old_alarm) == SIG_ERR) - perror("signal"); - return NULL; - case 0: /* child */ - if (setgid(getgid()) == -1) - _exit(127); - if (setuid(getuid()) == -1) - _exit(127); - if (*type == 'r') { - if (pdes[1] != 1) { - /* stdout */ - dup2(pdes[1], 1); - close(pdes[1]); - } - close(pdes[0]); - } else { - if (pdes[0] != 0) { - /* stdin */ - dup2(pdes[0], 0); - close(pdes[0]); - } - close(pdes[1]); - } - execl("/bin/sh", "sh", "-c", command, (char *)NULL); - _exit(127); - } - - /* Avoid EINTR during stdio calls */ - OsBlockSignals (); - - /* parent */ - if (*type == 'r') { - iop = fdopen(pdes[0], type); - close(pdes[1]); - } else { - iop = fdopen(pdes[1], type); - close(pdes[0]); - } - - cur->fp = iop; - cur->pid = pid; - cur->next = pidlist; - pidlist = cur; - -#ifdef DEBUG - ErrorF("Popen: `%s', fp = %p\n", command, iop); -#endif - - return iop; -} - -/* fopen that drops privileges */ -pointer -Fopen(char *file, char *type) -{ - FILE *iop; -#ifndef HAS_SAVED_IDS_AND_SETEUID - struct pid *cur; - int pdes[2], pid; - - if (file == NULL || type == NULL) - return NULL; - - if ((*type != 'r' && *type != 'w') || type[1]) - return NULL; - - if ((cur = xalloc(sizeof(struct pid))) == NULL) - return NULL; - - if (pipe(pdes) < 0) { - xfree(cur); - return NULL; - } - - switch (pid = fork()) { - case -1: /* error */ - close(pdes[0]); - close(pdes[1]); - xfree(cur); - return NULL; - case 0: /* child */ - if (setgid(getgid()) == -1) - _exit(127); - if (setuid(getuid()) == -1) - _exit(127); - if (*type == 'r') { - if (pdes[1] != 1) { - /* stdout */ - dup2(pdes[1], 1); - close(pdes[1]); - } - close(pdes[0]); - } else { - if (pdes[0] != 0) { - /* stdin */ - dup2(pdes[0], 0); - close(pdes[0]); - } - close(pdes[1]); - } - execl("/bin/cat", "cat", file, (char *)NULL); - _exit(127); - } - - /* Avoid EINTR during stdio calls */ - OsBlockSignals (); - - /* parent */ - if (*type == 'r') { - iop = fdopen(pdes[0], type); - close(pdes[1]); - } else { - iop = fdopen(pdes[1], type); - close(pdes[0]); - } - - cur->fp = iop; - cur->pid = pid; - cur->next = pidlist; - pidlist = cur; - -#ifdef DEBUG - ErrorF("Fopen(%s), fp = %p\n", file, iop); -#endif - - return iop; -#else - int ruid, euid; - - ruid = getuid(); - euid = geteuid(); - - if (seteuid(ruid) == -1) { - return NULL; - } - iop = fopen(file, type); - - if (seteuid(euid) == -1) { - fclose(iop); - return NULL; - } - return iop; -#endif /* HAS_SAVED_IDS_AND_SETEUID */ -} - -int -Pclose(pointer iop) -{ - struct pid *cur, *last; - int pstat; - int pid; - -#ifdef DEBUG - ErrorF("Pclose: fp = %p\n", iop); -#endif - - fclose(iop); - - for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next) - if (cur->fp == iop) - break; - if (cur == NULL) - return -1; - - do { - pid = waitpid(cur->pid, &pstat, 0); - } while (pid == -1 && errno == EINTR); - - if (last == NULL) - pidlist = cur->next; - else - last->next = cur->next; - xfree(cur); - - /* allow EINTR again */ - OsReleaseSignals (); - - if (old_alarm && OsSignal(SIGALRM, old_alarm) == SIG_ERR) { - perror("signal"); - return -1; - } - - return pid == -1 ? -1 : pstat; -} - -int -Fclose(pointer iop) -{ -#ifdef HAS_SAVED_IDS_AND_SETEUID - return fclose(iop); -#else - return Pclose(iop); -#endif -} - -#endif /* !WIN32 */ - - -/* - * 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 _MSC_VER -#ifndef REMOVE_ENV_LD -#define REMOVE_ENV_LD 1 -#endif - -/* Remove long environment variables? */ -#ifndef REMOVE_LONG_ENV -#define REMOVE_LONG_ENV 1 -#endif -#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 -#ifndef WIN32 -#define CHECK_EUID 1 -#else -#define CHECK_EUID 0 -#endif -#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 2048 -#define MAX_ENV_PATH_LENGTH 2048 /* Limit for *PATH and TERMCAP */ - -#if USE_ISPRINT -#include -#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 -}; - -#if defined(VENDORSUPPORT) -#define BUGADDRESS VENDORSUPPORT -#elif defined(BUILDERADDR) -#define BUGADDRESS BUILDERADDR -#else -#define BUGADDRESS "xorg@freedesktop.org" -#endif - -void -CheckUserParameters(int argc, char **argv, char **envp) -{ - enum BadCode bad = NotBad; - int i = 0, j; - char *a, *e = NULL; - -#if CHECK_EUID - if (geteuid() == 0 && getuid() != geteuid()) -#endif - { - /* Check each argv[] */ - for (i = 1; i < argc; i++) { - if (strcmp(argv[i], "-fp") == 0) - { - i++; /* continue with next argument. skip the length check */ - if (i >= argc) - break; - } else - { - 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)) { - 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 - 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); - break; - case ArgTooLong: - ErrorF("Command line argument number %d is too long\n", i); - break; - case UnprintableArg: - ErrorF("Command line argument number %d contains unprintable" - " characters\n", i); - break; - case EnvTooLong: - ErrorF("Environment variable `%s' is too long\n", e); - 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"); - 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 -#include -#include -#endif /* USE_PAM */ - -void -CheckUserAuthorization(void) -{ -#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 -} - -/* - * Tokenize a string into a NULL terminated array of strings. Always returns - * an allocated array unless an error occurs. - */ -char** -xstrtokenize(const char *str, const char *separators) -{ - char **list, **nlist; - char *tok, *tmp; - unsigned num = 0, n; - - if (!str) - return NULL; - list = calloc(1, sizeof(*list)); - if (!list) - return NULL; - tmp = strdup(str); - if (!tmp) - goto error; - for (tok = strtok(tmp, separators); tok; tok = strtok(NULL, separators)) { - nlist = realloc(list, (num + 2) * sizeof(*list)); - if (!nlist) - goto error; - list = nlist; - list[num] = strdup(tok); - if (!list[num]) - goto error; - list[++num] = NULL; - } - free(tmp); - return list; - -error: - free(tmp); - for (n = 0; n < num; n++) - free(list[n]); - free(list); - return NULL; -} - -#ifdef __SCO__ -#include - -static void -lockit (int fd, short what) -{ - struct flock lck; - - lck.l_whence = 0; - lck.l_start = 0; - lck.l_len = 1; - lck.l_type = what; - - (void)fcntl (fd, F_SETLKW, &lck); -} - -/* SCO OpenServer 5 lacks pread/pwrite. Emulate them. */ -ssize_t -pread (int fd, void *buf, size_t nbytes, off_t offset) -{ - off_t saved; - ssize_t ret; - - lockit (fd, F_RDLCK); - saved = lseek (fd, 0, SEEK_CUR); - lseek (fd, offset, SEEK_SET); - ret = read (fd, buf, nbytes); - lseek (fd, saved, SEEK_SET); - lockit (fd, F_UNLCK); - - return ret; -} - -ssize_t -pwrite (int fd, const void *buf, size_t nbytes, off_t offset) -{ - off_t saved; - ssize_t ret; - - lockit (fd, F_WRLCK); - saved = lseek (fd, 0, SEEK_CUR); - lseek (fd, offset, SEEK_SET); - ret = write (fd, buf, nbytes); - lseek (fd, saved, SEEK_SET); - lockit (fd, F_UNLCK); - - return ret; -} -#endif /* __SCO__ */ +/* + +Copyright 1987, 1998 The Open Group + +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. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, +Copyright 1994 Quarterdeck Office Systems. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the names of Digital and +Quarterdeck not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +DIGITAL AND QUARTERDECK DISCLAIM ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT +OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE +OR PERFORMANCE OF THIS SOFTWARE. + +*/ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#ifdef __CYGWIN__ +#include +#include +/* + Sigh... We really need a prototype for this to know it is stdcall, + but #include-ing here is not a good idea... +*/ +__stdcall unsigned long GetTickCount(void); +#endif + +#if defined(WIN32) && !defined(__CYGWIN__) +#include +#endif +#include +#include +#include +#if !defined(WIN32) || !defined(__MINGW32__) +#include +#include +#endif +#include "misc.h" +#include +#define XSERV_t +#define TRANS_SERVER +#define TRANS_REOPEN +#include +#include "input.h" +#include "dixfont.h" +#include "osdep.h" +#include "extension.h" +#ifdef X_POSIX_C_SOURCE +#define _POSIX_C_SOURCE X_POSIX_C_SOURCE +#include +#undef _POSIX_C_SOURCE +#else +#if defined(_POSIX_SOURCE) +#include +#else +#define _POSIX_SOURCE +#include +#undef _POSIX_SOURCE +#endif +#endif +#ifndef WIN32 +#include +#endif +#if !defined(SYSV) && !defined(WIN32) +#include +#endif +#include +#include /* for isspace */ +#include + +#include /* for malloc() */ + +#if defined(TCPCONN) || defined(STREAMSCONN) +# ifndef WIN32 +# include +# endif +#endif + +#include "opaque.h" + +#include "dixstruct.h" + +#include "xkbsrv.h" + +#include "picture.h" + +Bool noTestExtensions; +#ifdef COMPOSITE +Bool noCompositeExtension = FALSE; +#endif + +#ifdef DAMAGE +Bool noDamageExtension = FALSE; +#endif +#ifdef DBE +Bool noDbeExtension = FALSE; +#endif +#ifdef DPMSExtension +Bool noDPMSExtension = FALSE; +#endif +#ifdef GLXEXT +Bool noGlxExtension = FALSE; +Bool noGlxVisualInit = FALSE; +#endif +#ifdef SCREENSAVER +Bool noScreenSaverExtension = FALSE; +#endif +#ifdef MITSHM +Bool noMITShmExtension = FALSE; +#endif +#ifdef RANDR +Bool noRRExtension = FALSE; +#endif +Bool noRenderExtension = FALSE; +#ifdef XCSECURITY +Bool noSecurityExtension = FALSE; +#endif +#ifdef RES +Bool noResExtension = FALSE; +#endif +#ifdef XF86BIGFONT +Bool noXFree86BigfontExtension = FALSE; +#endif +#ifdef XFreeXDGA +Bool noXFree86DGAExtension = FALSE; +#endif +#ifdef XF86DRI +Bool noXFree86DRIExtension = FALSE; +#endif +#ifdef XF86VIDMODE +Bool noXFree86VidModeExtension = FALSE; +#endif +#ifdef XFIXES +Bool noXFixesExtension = FALSE; +#endif +#ifdef PANORAMIX +/* Xinerama is disabled by default unless enabled via +xinerama */ +Bool noPanoramiXExtension = TRUE; +#endif +#ifdef XSELINUX +Bool noSELinuxExtension = FALSE; +int selinuxEnforcingState = SELINUX_MODE_DEFAULT; +#endif +#ifdef XV +Bool noXvExtension = FALSE; +#endif +#ifdef DRI2 +Bool noDRI2Extension = FALSE; +#endif + +Bool noGEExtension = FALSE; + +#define X_INCLUDE_NETDB_H +#include + +#include + +Bool CoreDump; + +#ifdef PANORAMIX +Bool PanoramiXExtensionDisabledHack = FALSE; +#endif + +int auditTrailLevel = 1; + +#if defined(SVR4) || defined(__linux__) || defined(CSRG_BASED) +#define HAS_SAVED_IDS_AND_SETEUID +#endif + +static char *dev_tty_from_init = NULL; /* since we need to parse it anyway */ + +OsSigHandlerPtr +OsSignal(int sig, OsSigHandlerPtr handler) +{ +#ifdef X_NOT_POSIX + return signal(sig, handler); +#else + struct sigaction act, oact; + + sigemptyset(&act.sa_mask); + if (handler != SIG_IGN) + sigaddset(&act.sa_mask, sig); + act.sa_flags = 0; + act.sa_handler = handler; + if (sigaction(sig, &act, &oact)) + perror("sigaction"); + return oact.sa_handler; +#endif +} + +/* + * Explicit support for a server lock file like the ones used for UUCP. + * For architectures with virtual terminals that can run more than one + * server at a time. This keeps the servers from stomping on each other + * if the user forgets to give them different display numbers. + */ +#define LOCK_DIR "/tmp" +#define LOCK_TMP_PREFIX "/.tX" +#define LOCK_PREFIX "/.X" +#define LOCK_SUFFIX "-lock" + +#ifndef PATH_MAX +#include +#ifndef PATH_MAX +#ifdef MAXPATHLEN +#define PATH_MAX MAXPATHLEN +#else +#define PATH_MAX 1024 +#endif +#endif +#endif + +static Bool StillLocking = FALSE; +static char szLockFile[PATH_MAX]; +static Bool nolock = FALSE; + +/* + * LockServer -- + * Check if the server lock file exists. If so, check if the PID + * contained inside is valid. If so, then die. Otherwise, create + * the lock file containing the PID. + */ +void +LockServer(void) +{ +#if defined(WIN32) && !defined(__CYGWIN__) + char MutexName[100]; + sprintf(MutexName, "Global\\VcXsrv_Mutex_%d\n", getpid()); + if (!CreateMutex(NULL,TRUE,MutexName) || GetLastError()== ERROR_ALREADY_EXISTS) + { + FatalError("Server is already active for display %d\n", atoi(display)); + } +#else + char port[20]; + char tmp[PATH_MAX], pid_str[12]; + int lfd, i, haslock, l_pid, t; + char *tmppath = NULL; + int len; + + if (nolock) return; + /* + * Path names + */ + tmppath = LOCK_DIR; + sprintf(port, "%d", atoi(display)); + + len = strlen(LOCK_PREFIX) > strlen(LOCK_TMP_PREFIX) ? strlen(LOCK_PREFIX) : + strlen(LOCK_TMP_PREFIX); + len += strlen(tmppath) + strlen(port) + strlen(LOCK_SUFFIX) + 1; + if (len > sizeof(szLockFile)) + FatalError("Display name `%s' is too long\n", port); + (void)sprintf(tmp, "%s" LOCK_TMP_PREFIX "%s" LOCK_SUFFIX, tmppath, port); + (void)sprintf(szLockFile, "%s" LOCK_PREFIX "%s" LOCK_SUFFIX, tmppath, port); + + /* + * Create a temporary file containing our PID. Attempt three times + * to create the file. + */ + StillLocking = TRUE; + i = 0; + do { + i++; + lfd = open(tmp, O_CREAT | O_EXCL | O_WRONLY, 0644); + if (lfd < 0) + sleep(2); + else + break; + } while (i < 3); + if (lfd < 0) { + unlink(tmp); + i = 0; + do { + i++; + lfd = open(tmp, O_CREAT | O_EXCL | O_WRONLY, 0644); + if (lfd < 0) + sleep(2); + else + break; + } while (i < 3); + } + if (lfd < 0) + FatalError("Could not create lock file in %s\n", tmp); + (void) sprintf(pid_str, "%10ld\n", (long)getpid()); + (void) write(lfd, pid_str, 11); + (void) chmod(tmp, 0444); + (void) close(lfd); + + /* + * OK. Now the tmp file exists. Try three times to move it in place + * for the lock. + */ + i = 0; + haslock = 0; + while ((!haslock) && (i++ < 3)) { + haslock = (link(tmp,szLockFile) == 0); + if (haslock) { + /* + * We're done. + */ + break; + } + else { + /* + * Read the pid from the existing file + */ + lfd = open(szLockFile, O_RDONLY); + if (lfd < 0) { + unlink(tmp); + FatalError("Can't read lock file %s\n", szLockFile); + } + pid_str[0] = '\0'; + if (read(lfd, pid_str, 11) != 11) { + /* + * Bogus lock file. + */ + unlink(szLockFile); + close(lfd); + continue; + } + pid_str[11] = '\0'; + sscanf(pid_str, "%d", &l_pid); + close(lfd); + + /* + * Now try to kill the PID to see if it exists. + */ + errno = 0; + t = kill(l_pid, 0); + if ((t< 0) && (errno == ESRCH)) { + /* + * Stale lock file. + */ + unlink(szLockFile); + continue; + } + else if (((t < 0) && (errno == EPERM)) || (t == 0)) { + /* + * Process is still active. + */ + unlink(tmp); + FatalError("Server is already active for display %s\n%s %s\n%s\n", + port, "\tIf this server is no longer running, remove", + szLockFile, "\tand start again."); + } + } + } + unlink(tmp); + if (!haslock) + FatalError("Could not create server lock file: %s\n", szLockFile); + StillLocking = FALSE; +#endif +} + +/* + * UnlockServer -- + * Remove the server lock file. + */ +void +UnlockServer(void) +{ + if (nolock) return; + + if (!StillLocking){ + + (void) unlink(szLockFile); + } +} + +/* Force connections to close on SIGHUP from init */ + +void +AutoResetServer (int sig) +{ + int olderrno = errno; + + dispatchException |= DE_RESET; + isItTimeToYield = TRUE; + errno = olderrno; +} + +/* Force connections to close and then exit on SIGTERM, SIGINT */ + +void +GiveUp(int sig) +{ + int olderrno = errno; + + dispatchException |= DE_TERMINATE; + isItTimeToYield = TRUE; + errno = olderrno; +} + +#if (defined WIN32 && defined __MINGW32__) || defined(__CYGWIN__) +CARD32 +GetTimeInMillis (void) +{ + return GetTickCount (); +} +#else +CARD32 +GetTimeInMillis(void) +{ + struct timeval tv; + +#ifdef MONOTONIC_CLOCK + struct timespec tp; + if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) + return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000L); +#endif + + X_GETTIMEOFDAY(&tv); + return(tv.tv_sec * 1000) + (tv.tv_usec / 1000); +} +#endif + +void +AdjustWaitForDelay (pointer waitTime, unsigned long newdelay) +{ + static struct timeval delay_val; + struct timeval **wt = (struct timeval **) waitTime; + unsigned long olddelay; + + if (*wt == NULL) + { + delay_val.tv_sec = newdelay / 1000; + delay_val.tv_usec = 1000 * (newdelay % 1000); + *wt = &delay_val; + } + else + { + olddelay = (*wt)->tv_sec * 1000 + (*wt)->tv_usec / 1000; + if (newdelay < olddelay) + { + (*wt)->tv_sec = newdelay / 1000; + (*wt)->tv_usec = 1000 * (newdelay % 1000); + } + } +} + +void UseMsg(void) +{ + ErrorF("use: X [:] [option]\n"); + ErrorF("-a # default pointer acceleration (factor)\n"); + ErrorF("-ac disable access control restrictions\n"); + ErrorF("-audit int set audit trail level\n"); + ErrorF("-auth file select authorization file\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"); + ErrorF("c # key-click volume (0-100)\n"); + ErrorF("-cc int default color visual class\n"); + ErrorF("-nocursor disable the cursor\n"); + ErrorF("-core generate core dump on fatal error\n"); + ErrorF("-dpi int screen resolution in dots per inch\n"); +#ifdef DPMSExtension + ErrorF("-dpms disables VESA DPMS monitor control\n"); +#endif + ErrorF("-deferglyphs [none|all|16] defer loading of [no|all|16-bit] glyphs\n"); + ErrorF("-f # bell base (0-100)\n"); + ErrorF("-fc string cursor font\n"); + ErrorF("-fn string default font name\n"); + ErrorF("-fp string default font path\n"); + ErrorF("-help prints message with these options\n"); + ErrorF("-I ignore all remaining arguments\n"); +#ifdef RLIMIT_DATA + ErrorF("-ld int limit data space to N Kb\n"); +#endif +#ifdef RLIMIT_NOFILE + ErrorF("-lf int limit number of open files to N\n"); +#endif +#ifdef RLIMIT_STACK + ErrorF("-ls int limit stack space to N Kb\n"); +#endif + ErrorF("-nolock disable the locking mechanism\n"); +#ifndef NOLOGOHACK + ErrorF("-logo enable logo in screen saver\n"); + ErrorF("nologo disable logo in screen saver\n"); +#endif + ErrorF("-nolisten string don't listen on protocol\n"); + ErrorF("-noreset don't reset after last client exists\n"); + ErrorF("-reset reset after last client exists\n"); + ErrorF("-p # screen-saver pattern duration (minutes)\n"); + ErrorF("-pn accept failure to listen on all ports\n"); + ErrorF("-nopn reject failure to listen on all ports\n"); + ErrorF("-r turns off auto-repeat\n"); + ErrorF("r turns on auto-repeat \n"); + ErrorF("-render [default|mono|gray|color] set render color alloc policy\n"); + ErrorF("-retro start with classic stipple and cursor\n"); + ErrorF("-s # screen-saver timeout (minutes)\n"); + ErrorF("-t # default pointer threshold (pixels/t)\n"); + ErrorF("-terminate terminate at server reset\n"); + ErrorF("-to # connection time out\n"); + ErrorF("-tst disable testing extensions\n"); + ErrorF("ttyxx server started from init on /dev/ttyxx\n"); + ErrorF("v video blanking for screen-saver\n"); + ErrorF("-v screen-saver without video blanking\n"); + ErrorF("-wm WhenMapped default backing-store\n"); + ErrorF("-wr create root window with white background\n"); + ErrorF("-maxbigreqsize set maximal bigrequest size \n"); +#ifdef PANORAMIX + ErrorF("+xinerama Enable XINERAMA extension\n"); + ErrorF("-xinerama Disable XINERAMA extension\n"); +#endif + ErrorF("-dumbSched Disable smart scheduling, enable old behavior\n"); + ErrorF("-schedInterval int Set scheduler interval in msec\n"); + ErrorF("+extension name Enable extension\n"); + ErrorF("-extension name Disable extension\n"); +#ifdef XDMCP + XdmcpUseMsg(); +#endif + XkbUseMsg(); + ddxUseMsg(); +} + +/* This function performs a rudimentary sanity check + * on the display name passed in on the command-line, + * since this string is used to generate filenames. + * It is especially important that the display name + * not contain a "/" and not start with a "-". + * --kvajk + */ +static int +VerifyDisplayName(const char *d) +{ + if ( d == (char *)0 ) return( 0 ); /* null */ + if ( *d == '\0' ) return( 0 ); /* empty */ + if ( *d == '-' ) return( 0 ); /* could be confused for an option */ + if ( *d == '.' ) return( 0 ); /* must not equal "." or ".." */ + if ( strchr(d, '/') != (char *)0 ) return( 0 ); /* very important!!! */ + return( 1 ); +} + +/* + * This function parses the command line. Handles device-independent fields + * and allows ddx to handle additional fields. It is not allowed to modify + * argc or any of the strings pointed to by argv. + */ +void +ProcessCommandLine(int argc, char *argv[]) +{ + int i, skip; + + defaultKeyboardControl.autoRepeat = TRUE; + +#ifdef NO_PART_NET + PartialNetwork = FALSE; +#else + PartialNetwork = TRUE; +#endif + + for ( i = 1; i < argc; i++ ) + { + /* call ddx first, so it can peek/override if it wants */ + if((skip = ddxProcessArgument(argc, argv, i))) + { + i += (skip - 1); + } + else if(argv[i][0] == ':') + { + /* initialize display */ + display = argv[i]; + display++; + if( ! VerifyDisplayName( display ) ) { + ErrorF("Bad display name: %s\n", display); + UseMsg(); + FatalError("Bad display name, exiting: %s\n", display); + } + } + else if ( strcmp( argv[i], "-a") == 0) + { + if(++i < argc) + defaultPointerControl.num = atoi(argv[i]); + else + UseMsg(); + } + else if ( strcmp( argv[i], "-ac") == 0) + { + defeatAccessControl = TRUE; + } + else if ( strcmp( argv[i], "-audit") == 0) + { + if(++i < argc) + auditTrailLevel = atoi(argv[i]); + else + UseMsg(); + } + else if ( strcmp( argv[i], "-auth") == 0) + { + if(++i < argc) + InitAuthorization (argv[i]); + else + UseMsg(); + } + else if ( strcmp( argv[i], "-br") == 0) ; /* default */ + else if ( strcmp( argv[i], "+bs") == 0) + enableBackingStore = TRUE; + else if ( strcmp( argv[i], "-bs") == 0) + disableBackingStore = TRUE; + else if ( strcmp( argv[i], "c") == 0) + { + if(++i < argc) + defaultKeyboardControl.click = atoi(argv[i]); + else + UseMsg(); + } + else if ( strcmp( argv[i], "-c") == 0) + { + defaultKeyboardControl.click = 0; + } + else if ( strcmp( argv[i], "-cc") == 0) + { + if(++i < argc) + defaultColorVisualClass = atoi(argv[i]); + else + UseMsg(); + } + else if ( strcmp( argv[i], "-core") == 0) + { +#if !defined(WIN32) || !defined(__MINGW32__) + struct rlimit core_limit; + getrlimit (RLIMIT_CORE, &core_limit); + core_limit.rlim_cur = core_limit.rlim_max; + setrlimit (RLIMIT_CORE, &core_limit); +#endif + CoreDump = TRUE; + } + else if ( strcmp( argv[i], "-nocursor") == 0) + { + EnableCursor = FALSE; + } + else if ( strcmp( argv[i], "-dpi") == 0) + { + if(++i < argc) + monitorResolution = atoi(argv[i]); + else + UseMsg(); + } +#ifdef DPMSExtension + else if ( strcmp( argv[i], "dpms") == 0) + /* ignored for compatibility */ ; + else if ( strcmp( argv[i], "-dpms") == 0) + DPMSDisabledSwitch = TRUE; +#endif + else if ( strcmp( argv[i], "-deferglyphs") == 0) + { + if(++i >= argc || !ParseGlyphCachingMode(argv[i])) + UseMsg(); + } + else if ( strcmp( argv[i], "-f") == 0) + { + if(++i < argc) + defaultKeyboardControl.bell = atoi(argv[i]); + else + UseMsg(); + } + else if ( strcmp( argv[i], "-fc") == 0) + { + if(++i < argc) + defaultCursorFont = argv[i]; + else + UseMsg(); + } + else if ( strcmp( argv[i], "-fn") == 0) + { + if(++i < argc) + defaultTextFont = argv[i]; + else + UseMsg(); + } + else if ( strcmp( argv[i], "-fp") == 0) + { + if(++i < argc) + { + defaultFontPath = argv[i]; + } + else + UseMsg(); + } + else if ( strcmp( argv[i], "-help") == 0) + { + UseMsg(); + exit(0); + } + else if ( (skip=XkbProcessArguments(argc,argv,i))!=0 ) { + if (skip>0) + i+= skip-1; + else UseMsg(); + } +#ifdef RLIMIT_DATA + else if ( strcmp( argv[i], "-ld") == 0) + { + if(++i < argc) + { + limitDataSpace = atoi(argv[i]); + if (limitDataSpace > 0) + limitDataSpace *= 1024; + } + else + UseMsg(); + } +#endif +#ifdef RLIMIT_NOFILE + else if ( strcmp( argv[i], "-lf") == 0) + { + if(++i < argc) + limitNoFile = atoi(argv[i]); + else + UseMsg(); + } +#endif +#ifdef RLIMIT_STACK + else if ( strcmp( argv[i], "-ls") == 0) + { + if(++i < argc) + { + limitStackSpace = atoi(argv[i]); + if (limitStackSpace > 0) + limitStackSpace *= 1024; + } + else + UseMsg(); + } +#endif + else if ( strcmp ( argv[i], "-nolock") == 0) + { +#if !defined(WIN32) && !defined(__CYGWIN__) + if (getuid() != 0) + ErrorF("Warning: the -nolock option can only be used by root\n"); + else +#endif + nolock = TRUE; + } +#ifndef NOLOGOHACK + else if ( strcmp( argv[i], "-logo") == 0) + { + logoScreenSaver = 1; + } + else if ( strcmp( argv[i], "nologo") == 0) + { + logoScreenSaver = 0; + } +#endif + else if ( strcmp( argv[i], "-nolisten") == 0) + { + if(++i < argc) { + if (_XSERVTransNoListen(argv[i])) + FatalError ("Failed to disable listen for %s transport", + argv[i]); + } else + UseMsg(); + } + else if ( strcmp( argv[i], "-noreset") == 0) + { + dispatchExceptionAtReset = 0; + } + else if ( strcmp( argv[i], "-reset") == 0) + { + dispatchExceptionAtReset = DE_RESET; + } + else if ( strcmp( argv[i], "-p") == 0) + { + if(++i < argc) + defaultScreenSaverInterval = ((CARD32)atoi(argv[i])) * + MILLI_PER_MIN; + else + UseMsg(); + } + else if (strcmp(argv[i], "-pogo") == 0) + { + dispatchException = DE_TERMINATE; + } + else if ( strcmp( argv[i], "-pn") == 0) + PartialNetwork = TRUE; + else if ( strcmp( argv[i], "-nopn") == 0) + PartialNetwork = FALSE; + else if ( strcmp( argv[i], "r") == 0) + defaultKeyboardControl.autoRepeat = TRUE; + else if ( strcmp( argv[i], "-r") == 0) + defaultKeyboardControl.autoRepeat = FALSE; + else if ( strcmp( argv[i], "-retro") == 0) + party_like_its_1989 = TRUE; + else if ( strcmp( argv[i], "-s") == 0) + { + if(++i < argc) + defaultScreenSaverTime = ((CARD32)atoi(argv[i])) * + MILLI_PER_MIN; + else + UseMsg(); + } + else if ( strcmp( argv[i], "-t") == 0) + { + if(++i < argc) + defaultPointerControl.threshold = atoi(argv[i]); + else + UseMsg(); + } + else if ( strcmp( argv[i], "-terminate") == 0) + { + dispatchExceptionAtReset = DE_TERMINATE; + } + else if ( strcmp( argv[i], "-to") == 0) + { + if(++i < argc) + TimeOutValue = ((CARD32)atoi(argv[i])) * MILLI_PER_SECOND; + else + UseMsg(); + } + else if ( strcmp( argv[i], "-tst") == 0) + { + noTestExtensions = TRUE; + } + else if ( strcmp( argv[i], "v") == 0) + defaultScreenSaverBlanking = PreferBlanking; + else if ( strcmp( argv[i], "-v") == 0) + defaultScreenSaverBlanking = DontPreferBlanking; + else if ( strcmp( argv[i], "-wm") == 0) + defaultBackingStore = WhenMapped; + else if ( strcmp( argv[i], "-wr") == 0) + whiteRoot = TRUE; + else if ( strcmp( argv[i], "-maxbigreqsize") == 0) { + if(++i < argc) { + long reqSizeArg = atol(argv[i]); + + /* Request size > 128MB does not make much sense... */ + if( reqSizeArg > 0L && reqSizeArg < 128L ) { + maxBigRequestSize = (reqSizeArg * 1048576L) - 1L; + } + else + { + UseMsg(); + } + } + else + { + UseMsg(); + } + } +#ifdef PANORAMIX + else if ( strcmp( argv[i], "+xinerama") == 0){ + noPanoramiXExtension = FALSE; + } + else if ( strcmp( argv[i], "-xinerama") == 0){ + noPanoramiXExtension = TRUE; + } + else if ( strcmp( argv[i], "-disablexineramaextension") == 0){ + PanoramiXExtensionDisabledHack = TRUE; + } +#endif + else if ( strcmp( argv[i], "-I") == 0) + { + /* ignore all remaining arguments */ + break; + } + else if (strncmp (argv[i], "tty", 3) == 0) + { + /* just in case any body is interested */ + dev_tty_from_init = argv[i]; + } +#ifdef XDMCP + else if ((skip = XdmcpOptions(argc, argv, i)) != i) + { + i = skip - 1; + } +#endif + 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(); + } + else if ( strcmp( argv[i], "-render" ) == 0) + { + if (++i < argc) + { + int policy = PictureParseCmapPolicy (argv[i]); + + if (policy != PictureCmapPolicyInvalid) + PictureCmapPolicy = policy; + else + UseMsg (); + } + else + UseMsg (); + } + else if ( strcmp( argv[i], "+extension") == 0) + { + if (++i < argc) + { + if (!EnableDisableExtension(argv[i], TRUE)) + EnableDisableExtensionError(argv[i], TRUE); + } + else + UseMsg(); + } + else if ( strcmp( argv[i], "-extension") == 0) + { + if (++i < argc) + { + if (!EnableDisableExtension(argv[i], FALSE)) + EnableDisableExtensionError(argv[i], FALSE); + } + else + UseMsg(); + } + else + { + ErrorF("Unrecognized option: %s\n", argv[i]); + UseMsg(); + FatalError("Unrecognized option: %s\n", argv[i]); + } + } +} + +/* Implement a simple-minded font authorization scheme. The authorization + name is "hp-hostname-1", the contents are simply the host name. */ +int +set_font_authorizations(char **authorizations, int *authlen, pointer client) +{ +#define AUTHORIZATION_NAME "hp-hostname-1" +#if defined(TCPCONN) || defined(STREAMSCONN) + static char *result = NULL; + static char *p = NULL; + + if (p == NULL) + { + char hname[1024], *hnameptr; + unsigned int len; +#if defined(IPv6) && defined(AF_INET6) + struct addrinfo hints, *ai = NULL; +#else + struct hostent *host; +#ifdef XTHREADS_NEEDS_BYNAMEPARAMS + _Xgethostbynameparams hparams; +#endif +#endif + + gethostname(hname, 1024); +#if defined(IPv6) && defined(AF_INET6) + bzero(&hints, sizeof(hints)); + hints.ai_flags = AI_CANONNAME; + if (getaddrinfo(hname, NULL, &hints, &ai) == 0) { + hnameptr = ai->ai_canonname; + } else { + hnameptr = hname; + } +#else + host = _XGethostbyname(hname, hparams); + if (host == NULL) + hnameptr = hname; + else + hnameptr = host->h_name; +#endif + + len = strlen(hnameptr) + 1; + result = malloc(len + sizeof(AUTHORIZATION_NAME) + 4); + + p = result; + *p++ = sizeof(AUTHORIZATION_NAME) >> 8; + *p++ = sizeof(AUTHORIZATION_NAME) & 0xff; + *p++ = (len) >> 8; + *p++ = (len & 0xff); + + memmove(p, AUTHORIZATION_NAME, sizeof(AUTHORIZATION_NAME)); + p += sizeof(AUTHORIZATION_NAME); + memmove(p, hnameptr, len); + p += len; +#if defined(IPv6) && defined(AF_INET6) + if (ai) { + freeaddrinfo(ai); + } +#endif + } + *authlen = p - result; + *authorizations = result; + return 1; +#else /* TCPCONN */ + return 0; +#endif /* TCPCONN */ +} + +void * +Xalloc(unsigned long amount) +{ + /* + * Xalloc used to return NULL when large amount of memory is requested. In + * order to catch the buggy callers this warning has been added, slated to + * removal by anyone who touches this code (or just looks at it) in 2011. + * + * -- Mikhail Gusarov + */ + if ((long)amount <= 0) + ErrorF("Warning: Xalloc: " + "requesting unpleasantly large amount of memory: %lu bytes.\n", + amount); + + return malloc(amount); +} + +void * +XNFalloc(unsigned long amount) +{ + void *ptr = malloc(amount); + if (!ptr) + FatalError("Out of memory"); + return ptr; +} + +void * +Xcalloc(unsigned long amount) +{ + return calloc(1, amount); +} + +void * +XNFcalloc(unsigned long amount) +{ + void *ret = calloc(1, amount); + if (!ret) + FatalError("XNFcalloc: Out of memory"); + return ret; +} + +void * +Xrealloc(void *ptr, unsigned long amount) +{ + /* + * Xrealloc used to return NULL when large amount of memory is requested. In + * order to catch the buggy callers this warning has been added, slated to + * removal by anyone who touches this code (or just looks at it) in 2011. + * + * -- Mikhail Gusarov + */ + if ((long)amount <= 0) + ErrorF("Warning: Xrealloc: " + "requesting unpleasantly large amount of memory: %lu bytes.\n", + amount); + + return realloc(ptr, amount); +} + +void * +XNFrealloc(void *ptr, unsigned long amount) +{ + void *ret = realloc(ptr, amount); + if (!ret) + FatalError("XNFrealloc: Out of memory"); + return ret; +} + +void +Xfree(void *ptr) +{ + free(ptr); +} + + +char * +Xstrdup(const char *s) +{ + if (s == NULL) + return NULL; + return strdup(s); +} + +char * +XNFstrdup(const char *s) +{ + char *ret; + + if (s == NULL) + return NULL; + + ret = strdup(s); + if (!ret) + FatalError("XNFstrdup: Out of memory"); + return ret; +} + + +#if defined(SIGVTALRM) && !defined(__CYGWIN__) +#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; + + if (SmartScheduleDisable) + return; + 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); +#endif +} + +void +SmartScheduleStartTimer (void) +{ +#ifdef SMART_SCHEDULE_POSSIBLE + struct itimerval timer; + + if (SmartScheduleDisable) + return; + 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; + setitimer (ITIMER_REAL, &timer, 0); +#endif +} + +#ifdef SMART_SCHEDULE_POSSIBLE +static void +SmartScheduleTimer (int sig) +{ + SmartScheduleTime += SmartScheduleInterval; +} +#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; + } + return TRUE; +#else + return FALSE; +#endif +} + +#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 +#ifdef SIGCHLD + sigaddset (&set, SIGCHLD); +#endif + sigprocmask (SIG_BLOCK, &set, &PreviousSignalMask); + } +#endif +} + +void +OsReleaseSignals (void) +{ +#ifdef SIG_BLOCK + if (--BlockedSignalCount == 0) + { + sigprocmask (SIG_SETMASK, &PreviousSignalMask, 0); + } +#endif +} + +/* + * Pending signals may interfere with core dumping. Provide a + * mechanism to block signals when aborting. + */ + +void +OsAbort (void) +{ +#ifndef __APPLE__ + OsBlockSignals(); +#endif + abort(); +} + +#if !defined(WIN32) +/* + * "safer" versions of system(3), popen(3) and pclose(3) which give up + * 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 +System(char *command) +{ + int pid, p; +#ifdef SIGCHLD + void (*csig)(int); +#endif + int status; + + if (!command) + return(1); + +#ifdef SIGCHLD + csig = signal(SIGCHLD, SIG_DFL); + if (csig == SIG_ERR) { + perror("signal"); + return -1; + } +#endif + +#ifdef DEBUG + ErrorF("System: `%s'\n", command); +#endif + + switch (pid = fork()) { + case -1: /* error */ + p = -1; + case 0: /* child */ + if (setgid(getgid()) == -1) + _exit(127); + if (setuid(getuid()) == -1) + _exit(127); + execl("/bin/sh", "sh", "-c", command, (char *)NULL); + _exit(127); + default: /* parent */ + do { + p = waitpid(pid, &status, 0); + } while (p == -1 && errno == EINTR); + + } + +#ifdef SIGCHLD + if (signal(SIGCHLD, csig) == SIG_ERR) { + perror("signal"); + return -1; + } +#endif + + return p == -1 ? -1 : status; +} + +static struct pid { + struct pid *next; + FILE *fp; + int pid; +} *pidlist; + +OsSigHandlerPtr old_alarm = NULL; /* XXX horrible awful hack */ + +pointer +Popen(char *command, char *type) +{ + struct pid *cur; + FILE *iop; + int pdes[2], pid; + + if (command == NULL || type == NULL) + return NULL; + + if ((*type != 'r' && *type != 'w') || type[1]) + return NULL; + + if ((cur = malloc(sizeof(struct pid))) == NULL) + return NULL; + + if (pipe(pdes) < 0) { + free(cur); + return NULL; + } + + /* Ignore the smart scheduler while this is going on */ + old_alarm = OsSignal(SIGALRM, SIG_IGN); + if (old_alarm == SIG_ERR) { + perror("signal"); + return NULL; + } + + switch (pid = fork()) { + case -1: /* error */ + close(pdes[0]); + close(pdes[1]); + free(cur); + if (OsSignal(SIGALRM, old_alarm) == SIG_ERR) + perror("signal"); + return NULL; + case 0: /* child */ + if (setgid(getgid()) == -1) + _exit(127); + if (setuid(getuid()) == -1) + _exit(127); + if (*type == 'r') { + if (pdes[1] != 1) { + /* stdout */ + dup2(pdes[1], 1); + close(pdes[1]); + } + close(pdes[0]); + } else { + if (pdes[0] != 0) { + /* stdin */ + dup2(pdes[0], 0); + close(pdes[0]); + } + close(pdes[1]); + } + execl("/bin/sh", "sh", "-c", command, (char *)NULL); + _exit(127); + } + + /* Avoid EINTR during stdio calls */ + OsBlockSignals (); + + /* parent */ + if (*type == 'r') { + iop = fdopen(pdes[0], type); + close(pdes[1]); + } else { + iop = fdopen(pdes[1], type); + close(pdes[0]); + } + + cur->fp = iop; + cur->pid = pid; + cur->next = pidlist; + pidlist = cur; + +#ifdef DEBUG + ErrorF("Popen: `%s', fp = %p\n", command, iop); +#endif + + return iop; +} + +/* fopen that drops privileges */ +pointer +Fopen(char *file, char *type) +{ + FILE *iop; +#ifndef HAS_SAVED_IDS_AND_SETEUID + struct pid *cur; + int pdes[2], pid; + + if (file == NULL || type == NULL) + return NULL; + + if ((*type != 'r' && *type != 'w') || type[1]) + return NULL; + + if ((cur = malloc(sizeof(struct pid))) == NULL) + return NULL; + + if (pipe(pdes) < 0) { + free(cur); + return NULL; + } + + switch (pid = fork()) { + case -1: /* error */ + close(pdes[0]); + close(pdes[1]); + free(cur); + return NULL; + case 0: /* child */ + if (setgid(getgid()) == -1) + _exit(127); + if (setuid(getuid()) == -1) + _exit(127); + if (*type == 'r') { + if (pdes[1] != 1) { + /* stdout */ + dup2(pdes[1], 1); + close(pdes[1]); + } + close(pdes[0]); + } else { + if (pdes[0] != 0) { + /* stdin */ + dup2(pdes[0], 0); + close(pdes[0]); + } + close(pdes[1]); + } + execl("/bin/cat", "cat", file, (char *)NULL); + _exit(127); + } + + /* Avoid EINTR during stdio calls */ + OsBlockSignals (); + + /* parent */ + if (*type == 'r') { + iop = fdopen(pdes[0], type); + close(pdes[1]); + } else { + iop = fdopen(pdes[1], type); + close(pdes[0]); + } + + cur->fp = iop; + cur->pid = pid; + cur->next = pidlist; + pidlist = cur; + +#ifdef DEBUG + ErrorF("Fopen(%s), fp = %p\n", file, iop); +#endif + + return iop; +#else + int ruid, euid; + + ruid = getuid(); + euid = geteuid(); + + if (seteuid(ruid) == -1) { + return NULL; + } + iop = fopen(file, type); + + if (seteuid(euid) == -1) { + fclose(iop); + return NULL; + } + return iop; +#endif /* HAS_SAVED_IDS_AND_SETEUID */ +} + +int +Pclose(pointer iop) +{ + struct pid *cur, *last; + int pstat; + int pid; + +#ifdef DEBUG + ErrorF("Pclose: fp = %p\n", iop); +#endif + + fclose(iop); + + for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next) + if (cur->fp == iop) + break; + if (cur == NULL) + return -1; + + do { + pid = waitpid(cur->pid, &pstat, 0); + } while (pid == -1 && errno == EINTR); + + if (last == NULL) + pidlist = cur->next; + else + last->next = cur->next; + free(cur); + + /* allow EINTR again */ + OsReleaseSignals (); + + if (old_alarm && OsSignal(SIGALRM, old_alarm) == SIG_ERR) { + perror("signal"); + return -1; + } + + return pid == -1 ? -1 : pstat; +} + +int +Fclose(pointer iop) +{ +#ifdef HAS_SAVED_IDS_AND_SETEUID + return fclose(iop); +#else + return Pclose(iop); +#endif +} + +#endif /* !WIN32 */ + + +/* + * 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 _MSC_VER +#ifndef REMOVE_ENV_LD +#define REMOVE_ENV_LD 1 +#endif + +/* Remove long environment variables? */ +#ifndef REMOVE_LONG_ENV +#define REMOVE_LONG_ENV 1 +#endif +#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 +#ifndef WIN32 +#define CHECK_EUID 1 +#else +#define CHECK_EUID 0 +#endif +#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 2048 +#define MAX_ENV_PATH_LENGTH 2048 /* Limit for *PATH and TERMCAP */ + +#if USE_ISPRINT +#include +#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 +}; + +#if defined(VENDORSUPPORT) +#define BUGADDRESS VENDORSUPPORT +#elif defined(BUILDERADDR) +#define BUGADDRESS BUILDERADDR +#else +#define BUGADDRESS "xorg@freedesktop.org" +#endif + +void +CheckUserParameters(int argc, char **argv, char **envp) +{ + enum BadCode bad = NotBad; + int i = 0, j; + char *a, *e = NULL; + +#if CHECK_EUID + if (geteuid() == 0 && getuid() != geteuid()) +#endif + { + /* Check each argv[] */ + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-fp") == 0) + { + i++; /* continue with next argument. skip the length check */ + if (i >= argc) + break; + } else + { + 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)) { + 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 + 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); + break; + case ArgTooLong: + ErrorF("Command line argument number %d is too long\n", i); + break; + case UnprintableArg: + ErrorF("Command line argument number %d contains unprintable" + " characters\n", i); + break; + case EnvTooLong: + ErrorF("Environment variable `%s' is too long\n", e); + 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"); + 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 +#include +#include +#endif /* USE_PAM */ + +void +CheckUserAuthorization(void) +{ +#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 +} + +/* + * Tokenize a string into a NULL terminated array of strings. Always returns + * an allocated array unless an error occurs. + */ +char** +xstrtokenize(const char *str, const char *separators) +{ + char **list, **nlist; + char *tok, *tmp; + unsigned num = 0, n; + + if (!str) + return NULL; + list = calloc(1, sizeof(*list)); + if (!list) + return NULL; + tmp = strdup(str); + if (!tmp) + goto error; + for (tok = strtok(tmp, separators); tok; tok = strtok(NULL, separators)) { + nlist = realloc(list, (num + 2) * sizeof(*list)); + if (!nlist) + goto error; + list = nlist; + list[num] = strdup(tok); + if (!list[num]) + goto error; + list[++num] = NULL; + } + free(tmp); + return list; + +error: + free(tmp); + for (n = 0; n < num; n++) + free(list[n]); + free(list); + return NULL; +} + +#ifdef __SCO__ +#include + +static void +lockit (int fd, short what) +{ + struct flock lck; + + lck.l_whence = 0; + lck.l_start = 0; + lck.l_len = 1; + lck.l_type = what; + + (void)fcntl (fd, F_SETLKW, &lck); +} + +/* SCO OpenServer 5 lacks pread/pwrite. Emulate them. */ +ssize_t +pread (int fd, void *buf, size_t nbytes, off_t offset) +{ + off_t saved; + ssize_t ret; + + lockit (fd, F_RDLCK); + saved = lseek (fd, 0, SEEK_CUR); + lseek (fd, offset, SEEK_SET); + ret = read (fd, buf, nbytes); + lseek (fd, saved, SEEK_SET); + lockit (fd, F_UNLCK); + + return ret; +} + +ssize_t +pwrite (int fd, const void *buf, size_t nbytes, off_t offset) +{ + off_t saved; + ssize_t ret; + + lockit (fd, F_WRLCK); + saved = lseek (fd, 0, SEEK_CUR); + lseek (fd, offset, SEEK_SET); + ret = write (fd, buf, nbytes); + lseek (fd, saved, SEEK_SET); + lockit (fd, F_UNLCK); + + return ret; +} +#endif /* __SCO__ */ diff --git a/xorg-server/os/xdmauth.c b/xorg-server/os/xdmauth.c index 7834b56f8..b58d1d7cc 100644 --- a/xorg-server/os/xdmauth.c +++ b/xorg-server/os/xdmauth.c @@ -239,7 +239,7 @@ XdmClientAuthTimeout (long now) prev->next = next; else xdmClients = next; - xfree (client); + free(client); } else prev = client; @@ -259,20 +259,20 @@ XdmAuthorizationValidate (unsigned char *plain, int length, *reason = "Bad XDM authorization key length"; return NULL; } - client = xalloc (sizeof (XdmClientAuthRec)); + client = malloc(sizeof (XdmClientAuthRec)); if (!client) return NULL; XdmClientAuthDecode (plain, client); if (!XdmcpCompareKeys (&client->rho, rho)) { - xfree (client); + free(client); if (reason) *reason = "Invalid XDM-AUTHORIZATION-1 key (failed key comparison)"; return NULL; } for (i = 18; i < 24; i++) if (plain[i] != 0) { - xfree (client); + free(client); if (reason) *reason = "Invalid XDM-AUTHORIZATION-1 key (failed NULL check)"; return NULL; @@ -287,15 +287,15 @@ XdmAuthorizationValidate (unsigned char *plain, int length, #if defined(TCPCONN) || defined(STREAMSCONN) if (family == FamilyInternet && memcmp((char *)addr, client->client, 4) != 0) { - xfree (client); - xfree (addr); + free(client); + free(addr); if (reason) *reason = "Invalid XDM-AUTHORIZATION-1 key (failed address comparison)"; return NULL; } #endif - xfree (addr); + free(addr); } } now = time(0); @@ -308,7 +308,7 @@ XdmAuthorizationValidate (unsigned char *plain, int length, XdmClientAuthTimeout (now); if (abs (client->time - now) > TwentyMinutes) { - xfree (client); + free(client); if (reason) *reason = "Excessive XDM-AUTHORIZATION-1 time offset"; return NULL; @@ -317,7 +317,7 @@ XdmAuthorizationValidate (unsigned char *plain, int length, { if (XdmClientAuthCompare (existing, client)) { - xfree (client); + free(client); if (reason) *reason = "XDM authorization key matches an existing client!"; return NULL; @@ -363,7 +363,7 @@ XdmAddCookie (unsigned short data_length, const char *data, XID id) /* the first octet of the key must be zero */ if (key_bits[0] != '\0') return 0; - new = xalloc (sizeof (XdmAuthorizationRec)); + new = malloc(sizeof (XdmAuthorizationRec)); if (!new) return 0; new->next = xdmAuth; @@ -385,7 +385,7 @@ XdmCheckCookie (unsigned short cookie_length, const char *cookie, /* Auth packets must be a multiple of 8 bytes long */ if (cookie_length & 7) return (XID) -1; - plain = xalloc (cookie_length); + plain = malloc(cookie_length); if (!plain) return (XID) -1; for (auth = xdmAuth; auth; auth=auth->next) { @@ -394,11 +394,11 @@ XdmCheckCookie (unsigned short cookie_length, const char *cookie, { client->next = xdmClients; xdmClients = client; - xfree (plain); + free(plain); return auth->id; } } - xfree (plain); + free(plain); return (XID) -1; } @@ -411,13 +411,13 @@ XdmResetCookie (void) for (auth = xdmAuth; auth; auth=next_auth) { next_auth = auth->next; - xfree (auth); + free(auth); } xdmAuth = 0; for (client = xdmClients; client; client=next_client) { next_client = client->next; - xfree (client); + free(client); } xdmClients = (XdmClientAuthPtr) 0; return 1; @@ -430,21 +430,21 @@ XdmToID (unsigned short cookie_length, char *cookie) XdmClientAuthPtr client; unsigned char *plain; - plain = xalloc (cookie_length); + plain = malloc(cookie_length); if (!plain) return (XID) -1; for (auth = xdmAuth; auth; auth=auth->next) { XdmcpUnwrap ((unsigned char *)cookie, (unsigned char *)&auth->key, plain, cookie_length); if ((client = XdmAuthorizationValidate (plain, cookie_length, &auth->rho, NULL, NULL)) != NULL) { - xfree (client); - xfree (cookie); - xfree (plain); + free(client); + free(cookie); + free(plain); return auth->id; } } - xfree (cookie); - xfree (plain); + free(cookie); + free(plain); return (XID) -1; } @@ -489,7 +489,7 @@ XdmRemoveCookie (unsigned short data_length, const char *data) XdmcpCompareKeys (key_bits, &auth->key)) { xdmAuth = auth->next; - xfree (auth); + free(auth); return 1; } } diff --git a/xorg-server/os/xdmcp.c b/xorg-server/os/xdmcp.c index ca890871e..6b0dd73c1 100644 --- a/xorg-server/os/xdmcp.c +++ b/xorg-server/os/xdmcp.c @@ -396,7 +396,7 @@ XdmcpRegisterAuthentication ( AuthenticationNames.length + 1) && XdmcpReallocARRAYofARRAY8 (&AuthenticationDatas, AuthenticationDatas.length + 1) && - (newFuncs = xalloc ((AuthenticationNames.length + 1) * sizeof (AuthenticationFuncsRec))))) + (newFuncs = malloc((AuthenticationNames.length + 1) * sizeof (AuthenticationFuncsRec))))) { XdmcpDisposeARRAY8 (&AuthenticationName); XdmcpDisposeARRAY8 (&AuthenticationData); @@ -407,7 +407,7 @@ XdmcpRegisterAuthentication ( newFuncs[AuthenticationNames.length-1].Validator = Validator; newFuncs[AuthenticationNames.length-1].Generator = Generator; newFuncs[AuthenticationNames.length-1].AddAuth = AddAuth; - xfree (AuthenticationFuncsList); + free(AuthenticationFuncsList); AuthenticationFuncsList = newFuncs; AuthenticationNames.data[AuthenticationNames.length-1] = AuthenticationName; AuthenticationDatas.data[AuthenticationDatas.length-1] = AuthenticationData; @@ -497,18 +497,18 @@ XdmcpRegisterConnection ( } if (ConnectionAddresses.length + 1 == 256) return; - newAddress = xalloc (addrlen * sizeof (CARD8)); + newAddress = malloc(addrlen * sizeof (CARD8)); if (!newAddress) return; if (!XdmcpReallocARRAY16 (&ConnectionTypes, ConnectionTypes.length + 1)) { - xfree (newAddress); + free(newAddress); return; } if (!XdmcpReallocARRAYofARRAY8 (&ConnectionAddresses, ConnectionAddresses.length + 1)) { - xfree (newAddress); + free(newAddress); return; } ConnectionTypes.data[ConnectionTypes.length - 1] = (CARD16) type; @@ -538,12 +538,12 @@ XdmcpRegisterAuthorization (const char *name, int namelen) ARRAY8 authName; int i; - authName.data = xalloc (namelen * sizeof (CARD8)); + authName.data = malloc(namelen * sizeof (CARD8)); if (!authName.data) return; if (!XdmcpReallocARRAYofARRAY8 (&AuthorizationNames, AuthorizationNames.length +1)) { - xfree (authName.data); + free(authName.data); return; } for (i = 0; i < namelen; i++) diff --git a/xorg-server/os/xprintf.c b/xorg-server/os/xprintf.c index bf70661ac..cdd276a3d 100644 --- a/xorg-server/os/xprintf.c +++ b/xorg-server/os/xprintf.c @@ -1,116 +1,116 @@ -/* - * printf routines which xalloc their buffer - */ -/* - * Copyright (c) 2004 Alexander Gottwald - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name(s) of the above copyright - * holders shall not be used in advertising or otherwise to promote the sale, - * use or other dealings in this Software without prior written authorization. - */ -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include -#include "os.h" -#include -#include - -#ifndef va_copy -# ifdef __va_copy -# define va_copy __va_copy -# else -# ifndef _MSC_VER -# error "no working va_copy was found" -# endif -# endif -#endif - -char * -Xvprintf(const char *format, va_list va) -{ - char *ret; - int size; - -#ifdef _MSC_VER - size = vsnprintf(NULL, 0, format, va); -#else - va_list va2; - - va_copy(va2, va); - size = vsnprintf(NULL, 0, format, va2); - va_end(va2); -#endif - - ret = (char *)Xalloc(size + 1); - if (ret == NULL) - return NULL; - - vsnprintf(ret, size + 1, format, va); - ret[size] = 0; - return ret; -} - -char *Xprintf(const char *format, ...) -{ - char *ret; - va_list va; - va_start(va, format); - ret = Xvprintf(format, va); - va_end(va); - return ret; -} - -char * -XNFvprintf(const char *format, va_list va) -{ - char *ret; - int size; - -#ifdef _MSC_VER - size = vsnprintf(NULL, 0, format, va); -#else - va_list va2; - - va_copy(va2, va); - size = vsnprintf(NULL, 0, format, va2); - va_end(va2); -#endif - - ret = (char *)XNFalloc(size + 1); - if (ret == NULL) - return NULL; - - vsnprintf(ret, size + 1, format, va); - ret[size] = 0; - return ret; -} - -char *XNFprintf(const char *format, ...) -{ - char *ret; - va_list va; - va_start(va, format); - ret = XNFvprintf(format, va); - va_end(va); - return ret; -} +/* + * printf routines which xalloc their buffer + */ +/* + * Copyright (c) 2004 Alexander Gottwald + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include "os.h" +#include +#include + +#ifndef va_copy +# ifdef __va_copy +# define va_copy __va_copy +# else +# ifndef _MSC_VER +# error "no working va_copy was found" +# endif +# endif +#endif + +char * +Xvprintf(const char *format, va_list va) +{ + char *ret; + int size; + +#ifdef _MSC_VER + size = vsnprintf(NULL, 0, format, va); +#else + va_list va2; + + va_copy(va2, va); + size = vsnprintf(NULL, 0, format, va2); + va_end(va2); +#endif + + ret = (char *)malloc(size + 1); + if (ret == NULL) + return NULL; + + vsnprintf(ret, size + 1, format, va); + ret[size] = 0; + return ret; +} + +char *Xprintf(const char *format, ...) +{ + char *ret; + va_list va; + va_start(va, format); + ret = Xvprintf(format, va); + va_end(va); + return ret; +} + +char * +XNFvprintf(const char *format, va_list va) +{ + char *ret; + int size; + +#ifdef _MSC_VER + size = vsnprintf(NULL, 0, format, va); +#else + va_list va2; + + va_copy(va2, va); + size = vsnprintf(NULL, 0, format, va2); + va_end(va2); +#endif + + ret = (char *)xnfalloc(size + 1); + if (ret == NULL) + return NULL; + + vsnprintf(ret, size + 1, format, va); + ret[size] = 0; + return ret; +} + +char *XNFprintf(const char *format, ...) +{ + char *ret; + va_list va; + va_start(va, format); + ret = XNFvprintf(format, va); + va_end(va); + return ret; +} diff --git a/xorg-server/os/xsha1.c b/xorg-server/os/xsha1.c index 355862fb1..518745b4c 100644 --- a/xorg-server/os/xsha1.c +++ b/xorg-server/os/xsha1.c @@ -1,168 +1,168 @@ -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include "os.h" -#include "xsha1.h" - -#if defined(HAVE_SHA1_IN_LIBMD) /* Use libmd for SHA1 */ \ - || defined(HAVE_SHA1_IN_LIBC) /* Use libc for SHA1 */ - -# include - -void *x_sha1_init(void) -{ - SHA1_CTX *ctx = xalloc(sizeof(*ctx)); - if (!ctx) - return NULL; - SHA1Init(ctx); - return ctx; -} - -int x_sha1_update(void *ctx, void *data, int size) -{ - SHA1_CTX *sha1_ctx = ctx; - SHA1Update(sha1_ctx, data, size); - return 1; -} - -int x_sha1_final(void *ctx, unsigned char result[20]) -{ - SHA1_CTX *sha1_ctx = ctx; - SHA1Final(result, sha1_ctx); - xfree(sha1_ctx); - return 1; -} - -#elif defined(HAVE_SHA1_IN_COMMONCRYPTO) /* Use CommonCrypto for SHA1 */ - -#include - -void *x_sha1_init(void) -{ - CC_SHA1_CTX *ctx = xalloc(sizeof(*ctx)); - if (!ctx) - return NULL; - CC_SHA1_Init(ctx); - return ctx; -} - -int x_sha1_update(void *ctx, void *data, int size) -{ - CC_SHA1_CTX *sha1_ctx = ctx; - CC_SHA1_Update(sha1_ctx, data, size); - return 1; -} - -int x_sha1_final(void *ctx, unsigned char result[20]) -{ - CC_SHA1_CTX *sha1_ctx = ctx; - CC_SHA1_Final(result, sha1_ctx); - xfree(sha1_ctx); - return 1; -} - -#elif defined(HAVE_SHA1_IN_LIBGCRYPT) /* Use libgcrypt for SHA1 */ - -# include - -void *x_sha1_init(void) -{ - static int init; - gcry_md_hd_t h; - gcry_error_t err; - - if (!init) { - if (!gcry_check_version(NULL)) - return NULL; - gcry_control(GCRYCTL_DISABLE_SECMEM, 0); - gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); - init = 1; - } - - err = gcry_md_open(&h, GCRY_MD_SHA1, 0); - if (err) - return NULL; - return h; -} - -int x_sha1_update(void *ctx, void *data, int size) -{ - gcry_md_hd_t h = ctx; - gcry_md_write(h, data, size); - return 1; -} - -int x_sha1_final(void *ctx, unsigned char result[20]) -{ - gcry_md_hd_t h = ctx; - memcpy(result, gcry_md_read(h, GCRY_MD_SHA1), 20); - gcry_md_close(h); - return 1; -} - -#elif defined(HAVE_SHA1_IN_LIBSHA1) /* Use libsha1 */ - -# include - -void *x_sha1_init(void) -{ - sha1_ctx *ctx = xalloc(sizeof(*ctx)); - if(!ctx) - return NULL; - sha1_begin(ctx); - return ctx; -} - -int x_sha1_update(void *ctx, void *data, int size) -{ - sha1_hash(data, size, ctx); - return 1; -} - -int x_sha1_final(void *ctx, unsigned char result[20]) -{ - sha1_end(result, ctx); - xfree(ctx); - return 1; -} - -#else /* Use OpenSSL's libcrypto */ - -# include /* buggy openssl/sha.h wants size_t */ -# include - -void *x_sha1_init(void) -{ - int ret; - SHA_CTX *ctx = xalloc(sizeof(*ctx)); - if (!ctx) - return NULL; - ret = SHA1_Init(ctx); - if (!ret) { - xfree(ctx); - return NULL; - } - return ctx; -} - -int x_sha1_update(void *ctx, void *data, int size) -{ - int ret; - SHA_CTX *sha_ctx = ctx; - ret = SHA1_Update(sha_ctx, data, size); - if (!ret) - xfree(sha_ctx); - return ret; -} - -int x_sha1_final(void *ctx, unsigned char result[20]) -{ - int ret; - SHA_CTX *sha_ctx = ctx; - ret = SHA1_Final(result, sha_ctx); - xfree(sha_ctx); - return ret; -} - -#endif +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "os.h" +#include "xsha1.h" + +#if defined(HAVE_SHA1_IN_LIBMD) /* Use libmd for SHA1 */ \ + || defined(HAVE_SHA1_IN_LIBC) /* Use libc for SHA1 */ + +# include + +void *x_sha1_init(void) +{ + SHA1_CTX *ctx = malloc(sizeof(*ctx)); + if (!ctx) + return NULL; + SHA1Init(ctx); + return ctx; +} + +int x_sha1_update(void *ctx, void *data, int size) +{ + SHA1_CTX *sha1_ctx = ctx; + SHA1Update(sha1_ctx, data, size); + return 1; +} + +int x_sha1_final(void *ctx, unsigned char result[20]) +{ + SHA1_CTX *sha1_ctx = ctx; + SHA1Final(result, sha1_ctx); + free(sha1_ctx); + return 1; +} + +#elif defined(HAVE_SHA1_IN_COMMONCRYPTO) /* Use CommonCrypto for SHA1 */ + +#include + +void *x_sha1_init(void) +{ + CC_SHA1_CTX *ctx = malloc(sizeof(*ctx)); + if (!ctx) + return NULL; + CC_SHA1_Init(ctx); + return ctx; +} + +int x_sha1_update(void *ctx, void *data, int size) +{ + CC_SHA1_CTX *sha1_ctx = ctx; + CC_SHA1_Update(sha1_ctx, data, size); + return 1; +} + +int x_sha1_final(void *ctx, unsigned char result[20]) +{ + CC_SHA1_CTX *sha1_ctx = ctx; + CC_SHA1_Final(result, sha1_ctx); + free(sha1_ctx); + return 1; +} + +#elif defined(HAVE_SHA1_IN_LIBGCRYPT) /* Use libgcrypt for SHA1 */ + +# include + +void *x_sha1_init(void) +{ + static int init; + gcry_md_hd_t h; + gcry_error_t err; + + if (!init) { + if (!gcry_check_version(NULL)) + return NULL; + gcry_control(GCRYCTL_DISABLE_SECMEM, 0); + gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); + init = 1; + } + + err = gcry_md_open(&h, GCRY_MD_SHA1, 0); + if (err) + return NULL; + return h; +} + +int x_sha1_update(void *ctx, void *data, int size) +{ + gcry_md_hd_t h = ctx; + gcry_md_write(h, data, size); + return 1; +} + +int x_sha1_final(void *ctx, unsigned char result[20]) +{ + gcry_md_hd_t h = ctx; + memcpy(result, gcry_md_read(h, GCRY_MD_SHA1), 20); + gcry_md_close(h); + return 1; +} + +#elif defined(HAVE_SHA1_IN_LIBSHA1) /* Use libsha1 */ + +# include + +void *x_sha1_init(void) +{ + sha1_ctx *ctx = malloc(sizeof(*ctx)); + if(!ctx) + return NULL; + sha1_begin(ctx); + return ctx; +} + +int x_sha1_update(void *ctx, void *data, int size) +{ + sha1_hash(data, size, ctx); + return 1; +} + +int x_sha1_final(void *ctx, unsigned char result[20]) +{ + sha1_end(result, ctx); + free(ctx); + return 1; +} + +#else /* Use OpenSSL's libcrypto */ + +# include /* buggy openssl/sha.h wants size_t */ +# include + +void *x_sha1_init(void) +{ + int ret; + SHA_CTX *ctx = malloc(sizeof(*ctx)); + if (!ctx) + return NULL; + ret = SHA1_Init(ctx); + if (!ret) { + free(ctx); + return NULL; + } + return ctx; +} + +int x_sha1_update(void *ctx, void *data, int size) +{ + int ret; + SHA_CTX *sha_ctx = ctx; + ret = SHA1_Update(sha_ctx, data, size); + if (!ret) + free(sha_ctx); + return ret; +} + +int x_sha1_final(void *ctx, unsigned char result[20]) +{ + int ret; + SHA_CTX *sha_ctx = ctx; + ret = SHA1_Final(result, sha_ctx); + free(sha_ctx); + return ret; +} + +#endif -- cgit v1.2.3