xref: /OK3568_Linux_fs/external/xserver/os/utils.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun 
3*4882a593Smuzhiyun Copyright 1987, 1998  The Open Group
4*4882a593Smuzhiyun 
5*4882a593Smuzhiyun Permission to use, copy, modify, distribute, and sell this software and its
6*4882a593Smuzhiyun documentation for any purpose is hereby granted without fee, provided that
7*4882a593Smuzhiyun the above copyright notice appear in all copies and that both that
8*4882a593Smuzhiyun copyright notice and this permission notice appear in supporting
9*4882a593Smuzhiyun documentation.
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun The above copyright notice and this permission notice shall be included
12*4882a593Smuzhiyun in all copies or substantial portions of the Software.
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15*4882a593Smuzhiyun OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16*4882a593Smuzhiyun MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17*4882a593Smuzhiyun IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18*4882a593Smuzhiyun OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19*4882a593Smuzhiyun ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20*4882a593Smuzhiyun OTHER DEALINGS IN THE SOFTWARE.
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun Except as contained in this notice, the name of The Open Group shall
23*4882a593Smuzhiyun not be used in advertising or otherwise to promote the sale, use or
24*4882a593Smuzhiyun other dealings in this Software without prior written authorization
25*4882a593Smuzhiyun from The Open Group.
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
28*4882a593Smuzhiyun Copyright 1994 Quarterdeck Office Systems.
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun                         All Rights Reserved
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun Permission to use, copy, modify, and distribute this software and its
33*4882a593Smuzhiyun documentation for any purpose and without fee is hereby granted,
34*4882a593Smuzhiyun provided that the above copyright notice appear in all copies and that
35*4882a593Smuzhiyun both that copyright notice and this permission notice appear in
36*4882a593Smuzhiyun supporting documentation, and that the names of Digital and
37*4882a593Smuzhiyun Quarterdeck not be used in advertising or publicity pertaining to
38*4882a593Smuzhiyun distribution of the software without specific, written prior
39*4882a593Smuzhiyun permission.
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun DIGITAL AND QUARTERDECK DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
42*4882a593Smuzhiyun SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
43*4882a593Smuzhiyun FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT
44*4882a593Smuzhiyun OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
45*4882a593Smuzhiyun OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
46*4882a593Smuzhiyun OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
47*4882a593Smuzhiyun OR PERFORMANCE OF THIS SOFTWARE.
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun */
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
52*4882a593Smuzhiyun #include <dix-config.h>
53*4882a593Smuzhiyun #endif
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun #ifdef __CYGWIN__
56*4882a593Smuzhiyun #include <stdlib.h>
57*4882a593Smuzhiyun #include <signal.h>
58*4882a593Smuzhiyun /*
59*4882a593Smuzhiyun    Sigh... We really need a prototype for this to know it is stdcall,
60*4882a593Smuzhiyun    but #include-ing <windows.h> here is not a good idea...
61*4882a593Smuzhiyun */
62*4882a593Smuzhiyun __stdcall unsigned long GetTickCount(void);
63*4882a593Smuzhiyun #endif
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun #if defined(WIN32) && !defined(__CYGWIN__)
66*4882a593Smuzhiyun #include <X11/Xwinsock.h>
67*4882a593Smuzhiyun #endif
68*4882a593Smuzhiyun #include <X11/Xos.h>
69*4882a593Smuzhiyun #include <stdio.h>
70*4882a593Smuzhiyun #include <time.h>
71*4882a593Smuzhiyun #if !defined(WIN32) || !defined(__MINGW32__)
72*4882a593Smuzhiyun #include <sys/time.h>
73*4882a593Smuzhiyun #include <sys/resource.h>
74*4882a593Smuzhiyun #endif
75*4882a593Smuzhiyun #include "misc.h"
76*4882a593Smuzhiyun #include <X11/X.h>
77*4882a593Smuzhiyun #define XSERV_t
78*4882a593Smuzhiyun #define TRANS_SERVER
79*4882a593Smuzhiyun #define TRANS_REOPEN
80*4882a593Smuzhiyun #include <X11/Xtrans/Xtrans.h>
81*4882a593Smuzhiyun #include "input.h"
82*4882a593Smuzhiyun #include "dixfont.h"
83*4882a593Smuzhiyun #include <X11/fonts/libxfont2.h>
84*4882a593Smuzhiyun #include "osdep.h"
85*4882a593Smuzhiyun #include "extension.h"
86*4882a593Smuzhiyun #include <signal.h>
87*4882a593Smuzhiyun #ifndef WIN32
88*4882a593Smuzhiyun #include <sys/wait.h>
89*4882a593Smuzhiyun #endif
90*4882a593Smuzhiyun #if !defined(SYSV) && !defined(WIN32)
91*4882a593Smuzhiyun #include <sys/resource.h>
92*4882a593Smuzhiyun #endif
93*4882a593Smuzhiyun #include <sys/stat.h>
94*4882a593Smuzhiyun #include <ctype.h>              /* for isspace */
95*4882a593Smuzhiyun #include <stdarg.h>
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun #include <stdlib.h>             /* for malloc() */
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun #if defined(TCPCONN)
100*4882a593Smuzhiyun #ifndef WIN32
101*4882a593Smuzhiyun #include <netdb.h>
102*4882a593Smuzhiyun #endif
103*4882a593Smuzhiyun #endif
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun #include "opaque.h"
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun #include "dixstruct.h"
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun #include "xkbsrv.h"
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun #include "picture.h"
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun Bool noTestExtensions;
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun #ifdef COMPOSITE
116*4882a593Smuzhiyun Bool noCompositeExtension = FALSE;
117*4882a593Smuzhiyun #endif
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun #ifdef DAMAGE
120*4882a593Smuzhiyun Bool noDamageExtension = FALSE;
121*4882a593Smuzhiyun #endif
122*4882a593Smuzhiyun #ifdef DBE
123*4882a593Smuzhiyun Bool noDbeExtension = FALSE;
124*4882a593Smuzhiyun #endif
125*4882a593Smuzhiyun #ifdef DPMSExtension
126*4882a593Smuzhiyun #include "dpmsproc.h"
127*4882a593Smuzhiyun Bool noDPMSExtension = FALSE;
128*4882a593Smuzhiyun #endif
129*4882a593Smuzhiyun #ifdef GLXEXT
130*4882a593Smuzhiyun Bool noGlxExtension = FALSE;
131*4882a593Smuzhiyun #endif
132*4882a593Smuzhiyun #ifdef SCREENSAVER
133*4882a593Smuzhiyun Bool noScreenSaverExtension = FALSE;
134*4882a593Smuzhiyun #endif
135*4882a593Smuzhiyun #ifdef MITSHM
136*4882a593Smuzhiyun Bool noMITShmExtension = FALSE;
137*4882a593Smuzhiyun #endif
138*4882a593Smuzhiyun #ifdef RANDR
139*4882a593Smuzhiyun Bool noRRExtension = FALSE;
140*4882a593Smuzhiyun #endif
141*4882a593Smuzhiyun Bool noRenderExtension = FALSE;
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun #ifdef XCSECURITY
144*4882a593Smuzhiyun Bool noSecurityExtension = FALSE;
145*4882a593Smuzhiyun #endif
146*4882a593Smuzhiyun #ifdef RES
147*4882a593Smuzhiyun Bool noResExtension = FALSE;
148*4882a593Smuzhiyun #endif
149*4882a593Smuzhiyun #ifdef XF86BIGFONT
150*4882a593Smuzhiyun Bool noXFree86BigfontExtension = FALSE;
151*4882a593Smuzhiyun #endif
152*4882a593Smuzhiyun #ifdef XFreeXDGA
153*4882a593Smuzhiyun Bool noXFree86DGAExtension = FALSE;
154*4882a593Smuzhiyun #endif
155*4882a593Smuzhiyun #ifdef XF86DRI
156*4882a593Smuzhiyun Bool noXFree86DRIExtension = FALSE;
157*4882a593Smuzhiyun #endif
158*4882a593Smuzhiyun #ifdef XF86VIDMODE
159*4882a593Smuzhiyun Bool noXFree86VidModeExtension = FALSE;
160*4882a593Smuzhiyun #endif
161*4882a593Smuzhiyun Bool noXFixesExtension = FALSE;
162*4882a593Smuzhiyun #ifdef PANORAMIX
163*4882a593Smuzhiyun /* Xinerama is disabled by default unless enabled via +xinerama */
164*4882a593Smuzhiyun Bool noPanoramiXExtension = TRUE;
165*4882a593Smuzhiyun #endif
166*4882a593Smuzhiyun #ifdef XSELINUX
167*4882a593Smuzhiyun Bool noSELinuxExtension = FALSE;
168*4882a593Smuzhiyun int selinuxEnforcingState = SELINUX_MODE_DEFAULT;
169*4882a593Smuzhiyun #endif
170*4882a593Smuzhiyun #ifdef XV
171*4882a593Smuzhiyun Bool noXvExtension = FALSE;
172*4882a593Smuzhiyun #endif
173*4882a593Smuzhiyun #ifdef DRI2
174*4882a593Smuzhiyun Bool noDRI2Extension = FALSE;
175*4882a593Smuzhiyun #endif
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun Bool noGEExtension = FALSE;
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun #define X_INCLUDE_NETDB_H
180*4882a593Smuzhiyun #include <X11/Xos_r.h>
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun #include <errno.h>
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun Bool CoreDump;
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun Bool enableIndirectGLX = FALSE;
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun #ifdef PANORAMIX
189*4882a593Smuzhiyun Bool PanoramiXExtensionDisabledHack = FALSE;
190*4882a593Smuzhiyun #endif
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun int auditTrailLevel = 1;
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun char *SeatId = NULL;
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun sig_atomic_t inSignalContext = FALSE;
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun #if defined(SVR4) || defined(__linux__) || defined(CSRG_BASED)
199*4882a593Smuzhiyun #define HAS_SAVED_IDS_AND_SETEUID
200*4882a593Smuzhiyun #endif
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun #ifdef MONOTONIC_CLOCK
203*4882a593Smuzhiyun static clockid_t clockid;
204*4882a593Smuzhiyun #endif
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun OsSigHandlerPtr
OsSignal(int sig,OsSigHandlerPtr handler)207*4882a593Smuzhiyun OsSignal(int sig, OsSigHandlerPtr handler)
208*4882a593Smuzhiyun {
209*4882a593Smuzhiyun #if defined(WIN32) && !defined(__CYGWIN__)
210*4882a593Smuzhiyun     return signal(sig, handler);
211*4882a593Smuzhiyun #else
212*4882a593Smuzhiyun     struct sigaction act, oact;
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun     sigemptyset(&act.sa_mask);
215*4882a593Smuzhiyun     if (handler != SIG_IGN)
216*4882a593Smuzhiyun         sigaddset(&act.sa_mask, sig);
217*4882a593Smuzhiyun     act.sa_flags = 0;
218*4882a593Smuzhiyun     act.sa_handler = handler;
219*4882a593Smuzhiyun     if (sigaction(sig, &act, &oact))
220*4882a593Smuzhiyun         perror("sigaction");
221*4882a593Smuzhiyun     return oact.sa_handler;
222*4882a593Smuzhiyun #endif
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun /*
226*4882a593Smuzhiyun  * Explicit support for a server lock file like the ones used for UUCP.
227*4882a593Smuzhiyun  * For architectures with virtual terminals that can run more than one
228*4882a593Smuzhiyun  * server at a time.  This keeps the servers from stomping on each other
229*4882a593Smuzhiyun  * if the user forgets to give them different display numbers.
230*4882a593Smuzhiyun  */
231*4882a593Smuzhiyun #define LOCK_DIR "/tmp"
232*4882a593Smuzhiyun #define LOCK_TMP_PREFIX "/.tX"
233*4882a593Smuzhiyun #define LOCK_PREFIX "/.X"
234*4882a593Smuzhiyun #define LOCK_SUFFIX "-lock"
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun #if !defined(WIN32) || defined(__CYGWIN__)
237*4882a593Smuzhiyun #define LOCK_SERVER
238*4882a593Smuzhiyun #endif
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun #ifndef LOCK_SERVER
241*4882a593Smuzhiyun void
LockServer(void)242*4882a593Smuzhiyun LockServer(void)
243*4882a593Smuzhiyun {}
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun void
UnlockServer(void)246*4882a593Smuzhiyun UnlockServer(void)
247*4882a593Smuzhiyun {}
248*4882a593Smuzhiyun #else /* LOCK_SERVER */
249*4882a593Smuzhiyun static Bool StillLocking = FALSE;
250*4882a593Smuzhiyun static char LockFile[PATH_MAX];
251*4882a593Smuzhiyun static Bool nolock = FALSE;
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun /*
254*4882a593Smuzhiyun  * LockServer --
255*4882a593Smuzhiyun  *      Check if the server lock file exists.  If so, check if the PID
256*4882a593Smuzhiyun  *      contained inside is valid.  If so, then die.  Otherwise, create
257*4882a593Smuzhiyun  *      the lock file containing the PID.
258*4882a593Smuzhiyun  */
259*4882a593Smuzhiyun void
LockServer(void)260*4882a593Smuzhiyun LockServer(void)
261*4882a593Smuzhiyun {
262*4882a593Smuzhiyun     char tmp[PATH_MAX], pid_str[12];
263*4882a593Smuzhiyun     int lfd, i, haslock, l_pid, t;
264*4882a593Smuzhiyun     const char *tmppath = LOCK_DIR;
265*4882a593Smuzhiyun     int len;
266*4882a593Smuzhiyun     char port[20];
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun     if (nolock || NoListenAll)
269*4882a593Smuzhiyun         return;
270*4882a593Smuzhiyun     /*
271*4882a593Smuzhiyun      * Path names
272*4882a593Smuzhiyun      */
273*4882a593Smuzhiyun     snprintf(port, sizeof(port), "%d", atoi(display));
274*4882a593Smuzhiyun     len = strlen(LOCK_PREFIX) > strlen(LOCK_TMP_PREFIX) ? strlen(LOCK_PREFIX) :
275*4882a593Smuzhiyun         strlen(LOCK_TMP_PREFIX);
276*4882a593Smuzhiyun     len += strlen(tmppath) + strlen(port) + strlen(LOCK_SUFFIX) + 1;
277*4882a593Smuzhiyun     if (len > sizeof(LockFile))
278*4882a593Smuzhiyun         FatalError("Display name `%s' is too long\n", port);
279*4882a593Smuzhiyun     (void) sprintf(tmp, "%s" LOCK_TMP_PREFIX "%s" LOCK_SUFFIX, tmppath, port);
280*4882a593Smuzhiyun     (void) sprintf(LockFile, "%s" LOCK_PREFIX "%s" LOCK_SUFFIX, tmppath, port);
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun     /*
283*4882a593Smuzhiyun      * Create a temporary file containing our PID.  Attempt three times
284*4882a593Smuzhiyun      * to create the file.
285*4882a593Smuzhiyun      */
286*4882a593Smuzhiyun     StillLocking = TRUE;
287*4882a593Smuzhiyun     i = 0;
288*4882a593Smuzhiyun     do {
289*4882a593Smuzhiyun         i++;
290*4882a593Smuzhiyun         lfd = open(tmp, O_CREAT | O_EXCL | O_WRONLY, 0644);
291*4882a593Smuzhiyun         if (lfd < 0)
292*4882a593Smuzhiyun             sleep(2);
293*4882a593Smuzhiyun         else
294*4882a593Smuzhiyun             break;
295*4882a593Smuzhiyun     } while (i < 3);
296*4882a593Smuzhiyun     if (lfd < 0) {
297*4882a593Smuzhiyun         unlink(tmp);
298*4882a593Smuzhiyun         i = 0;
299*4882a593Smuzhiyun         do {
300*4882a593Smuzhiyun             i++;
301*4882a593Smuzhiyun             lfd = open(tmp, O_CREAT | O_EXCL | O_WRONLY, 0644);
302*4882a593Smuzhiyun             if (lfd < 0)
303*4882a593Smuzhiyun                 sleep(2);
304*4882a593Smuzhiyun             else
305*4882a593Smuzhiyun                 break;
306*4882a593Smuzhiyun         } while (i < 3);
307*4882a593Smuzhiyun     }
308*4882a593Smuzhiyun     if (lfd < 0)
309*4882a593Smuzhiyun         FatalError("Could not create lock file in %s\n", tmp);
310*4882a593Smuzhiyun     snprintf(pid_str, sizeof(pid_str), "%10lu\n", (unsigned long) getpid());
311*4882a593Smuzhiyun     if (write(lfd, pid_str, 11) != 11)
312*4882a593Smuzhiyun         FatalError("Could not write pid to lock file in %s\n", tmp);
313*4882a593Smuzhiyun     (void) fchmod(lfd, 0444);
314*4882a593Smuzhiyun     (void) close(lfd);
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun     /*
317*4882a593Smuzhiyun      * OK.  Now the tmp file exists.  Try three times to move it in place
318*4882a593Smuzhiyun      * for the lock.
319*4882a593Smuzhiyun      */
320*4882a593Smuzhiyun     i = 0;
321*4882a593Smuzhiyun     haslock = 0;
322*4882a593Smuzhiyun     while ((!haslock) && (i++ < 3)) {
323*4882a593Smuzhiyun         haslock = (link(tmp, LockFile) == 0);
324*4882a593Smuzhiyun         if (haslock) {
325*4882a593Smuzhiyun             /*
326*4882a593Smuzhiyun              * We're done.
327*4882a593Smuzhiyun              */
328*4882a593Smuzhiyun             break;
329*4882a593Smuzhiyun         }
330*4882a593Smuzhiyun         else {
331*4882a593Smuzhiyun             /*
332*4882a593Smuzhiyun              * Read the pid from the existing file
333*4882a593Smuzhiyun              */
334*4882a593Smuzhiyun             lfd = open(LockFile, O_RDONLY | O_NOFOLLOW);
335*4882a593Smuzhiyun             if (lfd < 0) {
336*4882a593Smuzhiyun                 unlink(tmp);
337*4882a593Smuzhiyun                 FatalError("Can't read lock file %s\n", LockFile);
338*4882a593Smuzhiyun             }
339*4882a593Smuzhiyun             pid_str[0] = '\0';
340*4882a593Smuzhiyun             if (read(lfd, pid_str, 11) != 11) {
341*4882a593Smuzhiyun                 /*
342*4882a593Smuzhiyun                  * Bogus lock file.
343*4882a593Smuzhiyun                  */
344*4882a593Smuzhiyun                 unlink(LockFile);
345*4882a593Smuzhiyun                 close(lfd);
346*4882a593Smuzhiyun                 continue;
347*4882a593Smuzhiyun             }
348*4882a593Smuzhiyun             pid_str[11] = '\0';
349*4882a593Smuzhiyun             sscanf(pid_str, "%d", &l_pid);
350*4882a593Smuzhiyun             close(lfd);
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun             /*
353*4882a593Smuzhiyun              * Now try to kill the PID to see if it exists.
354*4882a593Smuzhiyun              */
355*4882a593Smuzhiyun             errno = 0;
356*4882a593Smuzhiyun             t = kill(l_pid, 0);
357*4882a593Smuzhiyun             if ((t < 0) && (errno == ESRCH)) {
358*4882a593Smuzhiyun                 /*
359*4882a593Smuzhiyun                  * Stale lock file.
360*4882a593Smuzhiyun                  */
361*4882a593Smuzhiyun                 unlink(LockFile);
362*4882a593Smuzhiyun                 continue;
363*4882a593Smuzhiyun             }
364*4882a593Smuzhiyun             else if (((t < 0) && (errno == EPERM)) || (t == 0)) {
365*4882a593Smuzhiyun                 /*
366*4882a593Smuzhiyun                  * Process is still active.
367*4882a593Smuzhiyun                  */
368*4882a593Smuzhiyun                 unlink(tmp);
369*4882a593Smuzhiyun                 FatalError
370*4882a593Smuzhiyun                     ("Server is already active for display %s\n%s %s\n%s\n",
371*4882a593Smuzhiyun                      port, "\tIf this server is no longer running, remove",
372*4882a593Smuzhiyun                      LockFile, "\tand start again.");
373*4882a593Smuzhiyun             }
374*4882a593Smuzhiyun         }
375*4882a593Smuzhiyun     }
376*4882a593Smuzhiyun     unlink(tmp);
377*4882a593Smuzhiyun     if (!haslock)
378*4882a593Smuzhiyun         FatalError("Could not create server lock file: %s\n", LockFile);
379*4882a593Smuzhiyun     StillLocking = FALSE;
380*4882a593Smuzhiyun }
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun /*
383*4882a593Smuzhiyun  * UnlockServer --
384*4882a593Smuzhiyun  *      Remove the server lock file.
385*4882a593Smuzhiyun  */
386*4882a593Smuzhiyun void
UnlockServer(void)387*4882a593Smuzhiyun UnlockServer(void)
388*4882a593Smuzhiyun {
389*4882a593Smuzhiyun     if (nolock || NoListenAll)
390*4882a593Smuzhiyun         return;
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun     if (!StillLocking) {
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun         (void) unlink(LockFile);
395*4882a593Smuzhiyun     }
396*4882a593Smuzhiyun }
397*4882a593Smuzhiyun #endif /* LOCK_SERVER */
398*4882a593Smuzhiyun 
399*4882a593Smuzhiyun /* Force connections to close on SIGHUP from init */
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun void
AutoResetServer(int sig)402*4882a593Smuzhiyun AutoResetServer(int sig)
403*4882a593Smuzhiyun {
404*4882a593Smuzhiyun     int olderrno = errno;
405*4882a593Smuzhiyun 
406*4882a593Smuzhiyun     dispatchException |= DE_RESET;
407*4882a593Smuzhiyun     isItTimeToYield = TRUE;
408*4882a593Smuzhiyun     errno = olderrno;
409*4882a593Smuzhiyun }
410*4882a593Smuzhiyun 
411*4882a593Smuzhiyun /* Force connections to close and then exit on SIGTERM, SIGINT */
412*4882a593Smuzhiyun 
413*4882a593Smuzhiyun void
GiveUp(int sig)414*4882a593Smuzhiyun GiveUp(int sig)
415*4882a593Smuzhiyun {
416*4882a593Smuzhiyun     int olderrno = errno;
417*4882a593Smuzhiyun 
418*4882a593Smuzhiyun     dispatchException |= DE_TERMINATE;
419*4882a593Smuzhiyun     isItTimeToYield = TRUE;
420*4882a593Smuzhiyun     errno = olderrno;
421*4882a593Smuzhiyun }
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun #ifdef MONOTONIC_CLOCK
424*4882a593Smuzhiyun void
ForceClockId(clockid_t forced_clockid)425*4882a593Smuzhiyun ForceClockId(clockid_t forced_clockid)
426*4882a593Smuzhiyun {
427*4882a593Smuzhiyun     struct timespec tp;
428*4882a593Smuzhiyun 
429*4882a593Smuzhiyun     BUG_RETURN (clockid);
430*4882a593Smuzhiyun 
431*4882a593Smuzhiyun     clockid = forced_clockid;
432*4882a593Smuzhiyun 
433*4882a593Smuzhiyun     if (clock_gettime(clockid, &tp) != 0) {
434*4882a593Smuzhiyun         FatalError("Forced clock id failed to retrieve current time: %s\n",
435*4882a593Smuzhiyun                    strerror(errno));
436*4882a593Smuzhiyun         return;
437*4882a593Smuzhiyun     }
438*4882a593Smuzhiyun }
439*4882a593Smuzhiyun #endif
440*4882a593Smuzhiyun 
441*4882a593Smuzhiyun #if (defined WIN32 && defined __MINGW32__) || defined(__CYGWIN__)
442*4882a593Smuzhiyun CARD32
GetTimeInMillis(void)443*4882a593Smuzhiyun GetTimeInMillis(void)
444*4882a593Smuzhiyun {
445*4882a593Smuzhiyun     return GetTickCount();
446*4882a593Smuzhiyun }
447*4882a593Smuzhiyun CARD64
GetTimeInMicros(void)448*4882a593Smuzhiyun GetTimeInMicros(void)
449*4882a593Smuzhiyun {
450*4882a593Smuzhiyun     return (CARD64) GetTickCount() * 1000;
451*4882a593Smuzhiyun }
452*4882a593Smuzhiyun #else
453*4882a593Smuzhiyun CARD32
GetTimeInMillis(void)454*4882a593Smuzhiyun GetTimeInMillis(void)
455*4882a593Smuzhiyun {
456*4882a593Smuzhiyun     struct timeval tv;
457*4882a593Smuzhiyun 
458*4882a593Smuzhiyun #ifdef MONOTONIC_CLOCK
459*4882a593Smuzhiyun     struct timespec tp;
460*4882a593Smuzhiyun 
461*4882a593Smuzhiyun     if (!clockid) {
462*4882a593Smuzhiyun #ifdef CLOCK_MONOTONIC_COARSE
463*4882a593Smuzhiyun         if (clock_getres(CLOCK_MONOTONIC_COARSE, &tp) == 0 &&
464*4882a593Smuzhiyun             (tp.tv_nsec / 1000) <= 1000 &&
465*4882a593Smuzhiyun             clock_gettime(CLOCK_MONOTONIC_COARSE, &tp) == 0)
466*4882a593Smuzhiyun             clockid = CLOCK_MONOTONIC_COARSE;
467*4882a593Smuzhiyun         else
468*4882a593Smuzhiyun #endif
469*4882a593Smuzhiyun         if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
470*4882a593Smuzhiyun             clockid = CLOCK_MONOTONIC;
471*4882a593Smuzhiyun         else
472*4882a593Smuzhiyun             clockid = ~0L;
473*4882a593Smuzhiyun     }
474*4882a593Smuzhiyun     if (clockid != ~0L && clock_gettime(clockid, &tp) == 0)
475*4882a593Smuzhiyun         return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000L);
476*4882a593Smuzhiyun #endif
477*4882a593Smuzhiyun 
478*4882a593Smuzhiyun     X_GETTIMEOFDAY(&tv);
479*4882a593Smuzhiyun     return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
480*4882a593Smuzhiyun }
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun CARD64
GetTimeInMicros(void)483*4882a593Smuzhiyun GetTimeInMicros(void)
484*4882a593Smuzhiyun {
485*4882a593Smuzhiyun     struct timeval tv;
486*4882a593Smuzhiyun #ifdef MONOTONIC_CLOCK
487*4882a593Smuzhiyun     struct timespec tp;
488*4882a593Smuzhiyun     static clockid_t uclockid;
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun     if (!uclockid) {
491*4882a593Smuzhiyun         if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
492*4882a593Smuzhiyun             uclockid = CLOCK_MONOTONIC;
493*4882a593Smuzhiyun         else
494*4882a593Smuzhiyun             uclockid = ~0L;
495*4882a593Smuzhiyun     }
496*4882a593Smuzhiyun     if (uclockid != ~0L && clock_gettime(uclockid, &tp) == 0)
497*4882a593Smuzhiyun         return (CARD64) tp.tv_sec * (CARD64)1000000 + tp.tv_nsec / 1000;
498*4882a593Smuzhiyun #endif
499*4882a593Smuzhiyun 
500*4882a593Smuzhiyun     X_GETTIMEOFDAY(&tv);
501*4882a593Smuzhiyun     return (CARD64) tv.tv_sec * (CARD64)1000000 + (CARD64) tv.tv_usec;
502*4882a593Smuzhiyun }
503*4882a593Smuzhiyun #endif
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun void
UseMsg(void)506*4882a593Smuzhiyun UseMsg(void)
507*4882a593Smuzhiyun {
508*4882a593Smuzhiyun     ErrorF("use: X [:<display>] [option]\n");
509*4882a593Smuzhiyun     ErrorF("-a #                   default pointer acceleration (factor)\n");
510*4882a593Smuzhiyun     ErrorF("-ac                    disable access control restrictions\n");
511*4882a593Smuzhiyun     ErrorF("-audit int             set audit trail level\n");
512*4882a593Smuzhiyun     ErrorF("-auth file             select authorization file\n");
513*4882a593Smuzhiyun     ErrorF("-br                    create root window with black background\n");
514*4882a593Smuzhiyun     ErrorF("+bs                    enable any backing store support\n");
515*4882a593Smuzhiyun     ErrorF("-bs                    disable any backing store support\n");
516*4882a593Smuzhiyun     ErrorF("-c                     turns off key-click\n");
517*4882a593Smuzhiyun     ErrorF("c #                    key-click volume (0-100)\n");
518*4882a593Smuzhiyun     ErrorF("-cc int                default color visual class\n");
519*4882a593Smuzhiyun     ErrorF("-nocursor              disable the cursor\n");
520*4882a593Smuzhiyun     ErrorF("-core                  generate core dump on fatal error\n");
521*4882a593Smuzhiyun     ErrorF("-displayfd fd          file descriptor to write display number to when ready to connect\n");
522*4882a593Smuzhiyun     ErrorF("-dpi int               screen resolution in dots per inch\n");
523*4882a593Smuzhiyun #ifdef DPMSExtension
524*4882a593Smuzhiyun     ErrorF("-dpms                  disables VESA DPMS monitor control\n");
525*4882a593Smuzhiyun #endif
526*4882a593Smuzhiyun     ErrorF
527*4882a593Smuzhiyun         ("-deferglyphs [none|all|16] defer loading of [no|all|16-bit] glyphs\n");
528*4882a593Smuzhiyun     ErrorF("-f #                   bell base (0-100)\n");
529*4882a593Smuzhiyun     ErrorF("-fc string             cursor font\n");
530*4882a593Smuzhiyun     ErrorF("-fn string             default font name\n");
531*4882a593Smuzhiyun     ErrorF("-fp string             default font path\n");
532*4882a593Smuzhiyun     ErrorF("-help                  prints message with these options\n");
533*4882a593Smuzhiyun     ErrorF("+iglx                  Allow creating indirect GLX contexts\n");
534*4882a593Smuzhiyun     ErrorF("-iglx                  Prohibit creating indirect GLX contexts (default)\n");
535*4882a593Smuzhiyun     ErrorF("-I                     ignore all remaining arguments\n");
536*4882a593Smuzhiyun #ifdef RLIMIT_DATA
537*4882a593Smuzhiyun     ErrorF("-ld int                limit data space to N Kb\n");
538*4882a593Smuzhiyun #endif
539*4882a593Smuzhiyun #ifdef RLIMIT_NOFILE
540*4882a593Smuzhiyun     ErrorF("-lf int                limit number of open files to N\n");
541*4882a593Smuzhiyun #endif
542*4882a593Smuzhiyun #ifdef RLIMIT_STACK
543*4882a593Smuzhiyun     ErrorF("-ls int                limit stack space to N Kb\n");
544*4882a593Smuzhiyun #endif
545*4882a593Smuzhiyun #ifdef LOCK_SERVER
546*4882a593Smuzhiyun     ErrorF("-nolock                disable the locking mechanism\n");
547*4882a593Smuzhiyun #endif
548*4882a593Smuzhiyun     ErrorF("-maxclients n          set maximum number of clients (power of two)\n");
549*4882a593Smuzhiyun     ErrorF("-nolisten string       don't listen on protocol\n");
550*4882a593Smuzhiyun     ErrorF("-listen string         listen on protocol\n");
551*4882a593Smuzhiyun     ErrorF("-noreset               don't reset after last client exists\n");
552*4882a593Smuzhiyun     ErrorF("-background [none]     create root window with no background\n");
553*4882a593Smuzhiyun     ErrorF("-reset                 reset after last client exists\n");
554*4882a593Smuzhiyun     ErrorF("-p #                   screen-saver pattern duration (minutes)\n");
555*4882a593Smuzhiyun     ErrorF("-pn                    accept failure to listen on all ports\n");
556*4882a593Smuzhiyun     ErrorF("-nopn                  reject failure to listen on all ports\n");
557*4882a593Smuzhiyun     ErrorF("-r                     turns off auto-repeat\n");
558*4882a593Smuzhiyun     ErrorF("r                      turns on auto-repeat \n");
559*4882a593Smuzhiyun     ErrorF("-render [default|mono|gray|color] set render color alloc policy\n");
560*4882a593Smuzhiyun     ErrorF("-retro                 start with classic stipple and cursor\n");
561*4882a593Smuzhiyun     ErrorF("-s #                   screen-saver timeout (minutes)\n");
562*4882a593Smuzhiyun     ErrorF("-seat string           seat to run on\n");
563*4882a593Smuzhiyun     ErrorF("-t #                   default pointer threshold (pixels/t)\n");
564*4882a593Smuzhiyun     ErrorF("-terminate             terminate at server reset\n");
565*4882a593Smuzhiyun     ErrorF("-to #                  connection time out\n");
566*4882a593Smuzhiyun     ErrorF("-tst                   disable testing extensions\n");
567*4882a593Smuzhiyun     ErrorF("ttyxx                  server started from init on /dev/ttyxx\n");
568*4882a593Smuzhiyun     ErrorF("v                      video blanking for screen-saver\n");
569*4882a593Smuzhiyun     ErrorF("-v                     screen-saver without video blanking\n");
570*4882a593Smuzhiyun     ErrorF("-wm                    WhenMapped default backing-store\n");
571*4882a593Smuzhiyun     ErrorF("-wr                    create root window with white background\n");
572*4882a593Smuzhiyun     ErrorF("-maxbigreqsize         set maximal bigrequest size \n");
573*4882a593Smuzhiyun #ifdef PANORAMIX
574*4882a593Smuzhiyun     ErrorF("+xinerama              Enable XINERAMA extension\n");
575*4882a593Smuzhiyun     ErrorF("-xinerama              Disable XINERAMA extension\n");
576*4882a593Smuzhiyun #endif
577*4882a593Smuzhiyun     ErrorF
578*4882a593Smuzhiyun         ("-dumbSched             Disable smart scheduling and threaded input, enable old behavior\n");
579*4882a593Smuzhiyun     ErrorF("-schedInterval int     Set scheduler interval in msec\n");
580*4882a593Smuzhiyun     ErrorF("-sigstop               Enable SIGSTOP based startup\n");
581*4882a593Smuzhiyun     ErrorF("+extension name        Enable extension\n");
582*4882a593Smuzhiyun     ErrorF("-extension name        Disable extension\n");
583*4882a593Smuzhiyun #ifdef XDMCP
584*4882a593Smuzhiyun     XdmcpUseMsg();
585*4882a593Smuzhiyun #endif
586*4882a593Smuzhiyun     XkbUseMsg();
587*4882a593Smuzhiyun     ddxUseMsg();
588*4882a593Smuzhiyun }
589*4882a593Smuzhiyun 
590*4882a593Smuzhiyun /*  This function performs a rudimentary sanity check
591*4882a593Smuzhiyun  *  on the display name passed in on the command-line,
592*4882a593Smuzhiyun  *  since this string is used to generate filenames.
593*4882a593Smuzhiyun  *  It is especially important that the display name
594*4882a593Smuzhiyun  *  not contain a "/" and not start with a "-".
595*4882a593Smuzhiyun  *                                            --kvajk
596*4882a593Smuzhiyun  */
597*4882a593Smuzhiyun static int
VerifyDisplayName(const char * d)598*4882a593Smuzhiyun VerifyDisplayName(const char *d)
599*4882a593Smuzhiyun {
600*4882a593Smuzhiyun     int i;
601*4882a593Smuzhiyun     int period_found = FALSE;
602*4882a593Smuzhiyun     int after_period = 0;
603*4882a593Smuzhiyun 
604*4882a593Smuzhiyun     if (d == (char *) 0)
605*4882a593Smuzhiyun         return 0;               /*  null  */
606*4882a593Smuzhiyun     if (*d == '\0')
607*4882a593Smuzhiyun         return 0;               /*  empty  */
608*4882a593Smuzhiyun     if (*d == '-')
609*4882a593Smuzhiyun         return 0;               /*  could be confused for an option  */
610*4882a593Smuzhiyun     if (*d == '.')
611*4882a593Smuzhiyun         return 0;               /*  must not equal "." or ".."  */
612*4882a593Smuzhiyun     if (strchr(d, '/') != (char *) 0)
613*4882a593Smuzhiyun         return 0;               /*  very important!!!  */
614*4882a593Smuzhiyun 
615*4882a593Smuzhiyun     /* Since we run atoi() on the display later, only allow
616*4882a593Smuzhiyun        for digits, or exception of :0.0 and similar (two decimal points max)
617*4882a593Smuzhiyun        */
618*4882a593Smuzhiyun     for (i = 0; i < strlen(d); i++) {
619*4882a593Smuzhiyun         if (!isdigit(d[i])) {
620*4882a593Smuzhiyun             if (d[i] != '.' || period_found)
621*4882a593Smuzhiyun                 return 0;
622*4882a593Smuzhiyun             period_found = TRUE;
623*4882a593Smuzhiyun         } else if (period_found)
624*4882a593Smuzhiyun             after_period++;
625*4882a593Smuzhiyun 
626*4882a593Smuzhiyun         if (after_period > 2)
627*4882a593Smuzhiyun             return 0;
628*4882a593Smuzhiyun     }
629*4882a593Smuzhiyun 
630*4882a593Smuzhiyun     /* don't allow for :0. */
631*4882a593Smuzhiyun     if (period_found && after_period == 0)
632*4882a593Smuzhiyun         return 0;
633*4882a593Smuzhiyun 
634*4882a593Smuzhiyun     if (atol(d) > INT_MAX)
635*4882a593Smuzhiyun         return 0;
636*4882a593Smuzhiyun 
637*4882a593Smuzhiyun     return 1;
638*4882a593Smuzhiyun }
639*4882a593Smuzhiyun 
640*4882a593Smuzhiyun static const char *defaultNoListenList[] = {
641*4882a593Smuzhiyun #ifndef LISTEN_TCP
642*4882a593Smuzhiyun     "tcp",
643*4882a593Smuzhiyun #endif
644*4882a593Smuzhiyun #ifndef LISTEN_UNIX
645*4882a593Smuzhiyun     "unix",
646*4882a593Smuzhiyun #endif
647*4882a593Smuzhiyun #ifndef LISTEN_LOCAL
648*4882a593Smuzhiyun     "local",
649*4882a593Smuzhiyun #endif
650*4882a593Smuzhiyun     NULL
651*4882a593Smuzhiyun };
652*4882a593Smuzhiyun 
653*4882a593Smuzhiyun /*
654*4882a593Smuzhiyun  * This function parses the command line. Handles device-independent fields
655*4882a593Smuzhiyun  * and allows ddx to handle additional fields.  It is not allowed to modify
656*4882a593Smuzhiyun  * argc or any of the strings pointed to by argv.
657*4882a593Smuzhiyun  */
658*4882a593Smuzhiyun void
ProcessCommandLine(int argc,char * argv[])659*4882a593Smuzhiyun ProcessCommandLine(int argc, char *argv[])
660*4882a593Smuzhiyun {
661*4882a593Smuzhiyun     int i, skip;
662*4882a593Smuzhiyun 
663*4882a593Smuzhiyun     defaultKeyboardControl.autoRepeat = TRUE;
664*4882a593Smuzhiyun 
665*4882a593Smuzhiyun #ifdef NO_PART_NET
666*4882a593Smuzhiyun     PartialNetwork = FALSE;
667*4882a593Smuzhiyun #else
668*4882a593Smuzhiyun     PartialNetwork = TRUE;
669*4882a593Smuzhiyun #endif
670*4882a593Smuzhiyun 
671*4882a593Smuzhiyun     for (i = 0; defaultNoListenList[i] != NULL; i++) {
672*4882a593Smuzhiyun         if (_XSERVTransNoListen(defaultNoListenList[i]))
673*4882a593Smuzhiyun                     ErrorF("Failed to disable listen for %s transport",
674*4882a593Smuzhiyun                            defaultNoListenList[i]);
675*4882a593Smuzhiyun     }
676*4882a593Smuzhiyun 
677*4882a593Smuzhiyun     for (i = 1; i < argc; i++) {
678*4882a593Smuzhiyun         /* call ddx first, so it can peek/override if it wants */
679*4882a593Smuzhiyun         if ((skip = ddxProcessArgument(argc, argv, i))) {
680*4882a593Smuzhiyun             i += (skip - 1);
681*4882a593Smuzhiyun         }
682*4882a593Smuzhiyun         else if (argv[i][0] == ':') {
683*4882a593Smuzhiyun             /* initialize display */
684*4882a593Smuzhiyun             display = argv[i];
685*4882a593Smuzhiyun             explicit_display = TRUE;
686*4882a593Smuzhiyun             display++;
687*4882a593Smuzhiyun             if (!VerifyDisplayName(display)) {
688*4882a593Smuzhiyun                 ErrorF("Bad display name: %s\n", display);
689*4882a593Smuzhiyun                 UseMsg();
690*4882a593Smuzhiyun                 FatalError("Bad display name, exiting: %s\n", display);
691*4882a593Smuzhiyun             }
692*4882a593Smuzhiyun         }
693*4882a593Smuzhiyun         else if (strcmp(argv[i], "-a") == 0) {
694*4882a593Smuzhiyun             if (++i < argc)
695*4882a593Smuzhiyun                 defaultPointerControl.num = atoi(argv[i]);
696*4882a593Smuzhiyun             else
697*4882a593Smuzhiyun                 UseMsg();
698*4882a593Smuzhiyun         }
699*4882a593Smuzhiyun         else if (strcmp(argv[i], "-ac") == 0) {
700*4882a593Smuzhiyun             defeatAccessControl = TRUE;
701*4882a593Smuzhiyun         }
702*4882a593Smuzhiyun         else if (strcmp(argv[i], "-audit") == 0) {
703*4882a593Smuzhiyun             if (++i < argc)
704*4882a593Smuzhiyun                 auditTrailLevel = atoi(argv[i]);
705*4882a593Smuzhiyun             else
706*4882a593Smuzhiyun                 UseMsg();
707*4882a593Smuzhiyun         }
708*4882a593Smuzhiyun         else if (strcmp(argv[i], "-auth") == 0) {
709*4882a593Smuzhiyun             if (++i < argc)
710*4882a593Smuzhiyun                 InitAuthorization(argv[i]);
711*4882a593Smuzhiyun             else
712*4882a593Smuzhiyun                 UseMsg();
713*4882a593Smuzhiyun         }
714*4882a593Smuzhiyun         else if (strcmp(argv[i], "-br") == 0);  /* default */
715*4882a593Smuzhiyun         else if (strcmp(argv[i], "+bs") == 0)
716*4882a593Smuzhiyun             enableBackingStore = TRUE;
717*4882a593Smuzhiyun         else if (strcmp(argv[i], "-bs") == 0)
718*4882a593Smuzhiyun             disableBackingStore = TRUE;
719*4882a593Smuzhiyun         else if (strcmp(argv[i], "c") == 0) {
720*4882a593Smuzhiyun             if (++i < argc)
721*4882a593Smuzhiyun                 defaultKeyboardControl.click = atoi(argv[i]);
722*4882a593Smuzhiyun             else
723*4882a593Smuzhiyun                 UseMsg();
724*4882a593Smuzhiyun         }
725*4882a593Smuzhiyun         else if (strcmp(argv[i], "-c") == 0) {
726*4882a593Smuzhiyun             defaultKeyboardControl.click = 0;
727*4882a593Smuzhiyun         }
728*4882a593Smuzhiyun         else if (strcmp(argv[i], "-cc") == 0) {
729*4882a593Smuzhiyun             if (++i < argc)
730*4882a593Smuzhiyun                 defaultColorVisualClass = atoi(argv[i]);
731*4882a593Smuzhiyun             else
732*4882a593Smuzhiyun                 UseMsg();
733*4882a593Smuzhiyun         }
734*4882a593Smuzhiyun         else if (strcmp(argv[i], "-core") == 0) {
735*4882a593Smuzhiyun #if !defined(WIN32) || !defined(__MINGW32__)
736*4882a593Smuzhiyun             struct rlimit core_limit;
737*4882a593Smuzhiyun 
738*4882a593Smuzhiyun             getrlimit(RLIMIT_CORE, &core_limit);
739*4882a593Smuzhiyun             core_limit.rlim_cur = core_limit.rlim_max;
740*4882a593Smuzhiyun             setrlimit(RLIMIT_CORE, &core_limit);
741*4882a593Smuzhiyun #endif
742*4882a593Smuzhiyun             CoreDump = TRUE;
743*4882a593Smuzhiyun         }
744*4882a593Smuzhiyun         else if (strcmp(argv[i], "-nocursor") == 0) {
745*4882a593Smuzhiyun             EnableCursor = FALSE;
746*4882a593Smuzhiyun         }
747*4882a593Smuzhiyun         else if (strcmp(argv[i], "-dpi") == 0) {
748*4882a593Smuzhiyun             if (++i < argc)
749*4882a593Smuzhiyun                 monitorResolution = atoi(argv[i]);
750*4882a593Smuzhiyun             else
751*4882a593Smuzhiyun                 UseMsg();
752*4882a593Smuzhiyun         }
753*4882a593Smuzhiyun         else if (strcmp(argv[i], "-displayfd") == 0) {
754*4882a593Smuzhiyun             if (++i < argc) {
755*4882a593Smuzhiyun                 displayfd = atoi(argv[i]);
756*4882a593Smuzhiyun #ifdef LOCK_SERVER
757*4882a593Smuzhiyun                 nolock = TRUE;
758*4882a593Smuzhiyun #endif
759*4882a593Smuzhiyun             }
760*4882a593Smuzhiyun             else
761*4882a593Smuzhiyun                 UseMsg();
762*4882a593Smuzhiyun         }
763*4882a593Smuzhiyun #ifdef DPMSExtension
764*4882a593Smuzhiyun         else if (strcmp(argv[i], "dpms") == 0)
765*4882a593Smuzhiyun             /* ignored for compatibility */ ;
766*4882a593Smuzhiyun         else if (strcmp(argv[i], "-dpms") == 0)
767*4882a593Smuzhiyun             DPMSDisabledSwitch = TRUE;
768*4882a593Smuzhiyun #endif
769*4882a593Smuzhiyun         else if (strcmp(argv[i], "-deferglyphs") == 0) {
770*4882a593Smuzhiyun             if (++i >= argc || !xfont2_parse_glyph_caching_mode(argv[i]))
771*4882a593Smuzhiyun                 UseMsg();
772*4882a593Smuzhiyun         }
773*4882a593Smuzhiyun         else if (strcmp(argv[i], "-f") == 0) {
774*4882a593Smuzhiyun             if (++i < argc)
775*4882a593Smuzhiyun                 defaultKeyboardControl.bell = atoi(argv[i]);
776*4882a593Smuzhiyun             else
777*4882a593Smuzhiyun                 UseMsg();
778*4882a593Smuzhiyun         }
779*4882a593Smuzhiyun         else if (strcmp(argv[i], "-fc") == 0) {
780*4882a593Smuzhiyun             if (++i < argc)
781*4882a593Smuzhiyun                 defaultCursorFont = argv[i];
782*4882a593Smuzhiyun             else
783*4882a593Smuzhiyun                 UseMsg();
784*4882a593Smuzhiyun         }
785*4882a593Smuzhiyun         else if (strcmp(argv[i], "-fn") == 0) {
786*4882a593Smuzhiyun             if (++i < argc)
787*4882a593Smuzhiyun                 defaultTextFont = argv[i];
788*4882a593Smuzhiyun             else
789*4882a593Smuzhiyun                 UseMsg();
790*4882a593Smuzhiyun         }
791*4882a593Smuzhiyun         else if (strcmp(argv[i], "-fp") == 0) {
792*4882a593Smuzhiyun             if (++i < argc) {
793*4882a593Smuzhiyun                 defaultFontPath = argv[i];
794*4882a593Smuzhiyun             }
795*4882a593Smuzhiyun             else
796*4882a593Smuzhiyun                 UseMsg();
797*4882a593Smuzhiyun         }
798*4882a593Smuzhiyun         else if (strcmp(argv[i], "-help") == 0) {
799*4882a593Smuzhiyun             UseMsg();
800*4882a593Smuzhiyun             exit(0);
801*4882a593Smuzhiyun         }
802*4882a593Smuzhiyun         else if (strcmp(argv[i], "+iglx") == 0)
803*4882a593Smuzhiyun             enableIndirectGLX = TRUE;
804*4882a593Smuzhiyun         else if (strcmp(argv[i], "-iglx") == 0)
805*4882a593Smuzhiyun             enableIndirectGLX = FALSE;
806*4882a593Smuzhiyun         else if ((skip = XkbProcessArguments(argc, argv, i)) != 0) {
807*4882a593Smuzhiyun             if (skip > 0)
808*4882a593Smuzhiyun                 i += skip - 1;
809*4882a593Smuzhiyun             else
810*4882a593Smuzhiyun                 UseMsg();
811*4882a593Smuzhiyun         }
812*4882a593Smuzhiyun #ifdef RLIMIT_DATA
813*4882a593Smuzhiyun         else if (strcmp(argv[i], "-ld") == 0) {
814*4882a593Smuzhiyun             if (++i < argc) {
815*4882a593Smuzhiyun                 limitDataSpace = atoi(argv[i]);
816*4882a593Smuzhiyun                 if (limitDataSpace > 0)
817*4882a593Smuzhiyun                     limitDataSpace *= 1024;
818*4882a593Smuzhiyun             }
819*4882a593Smuzhiyun             else
820*4882a593Smuzhiyun                 UseMsg();
821*4882a593Smuzhiyun         }
822*4882a593Smuzhiyun #endif
823*4882a593Smuzhiyun #ifdef RLIMIT_NOFILE
824*4882a593Smuzhiyun         else if (strcmp(argv[i], "-lf") == 0) {
825*4882a593Smuzhiyun             if (++i < argc)
826*4882a593Smuzhiyun                 limitNoFile = atoi(argv[i]);
827*4882a593Smuzhiyun             else
828*4882a593Smuzhiyun                 UseMsg();
829*4882a593Smuzhiyun         }
830*4882a593Smuzhiyun #endif
831*4882a593Smuzhiyun #ifdef RLIMIT_STACK
832*4882a593Smuzhiyun         else if (strcmp(argv[i], "-ls") == 0) {
833*4882a593Smuzhiyun             if (++i < argc) {
834*4882a593Smuzhiyun                 limitStackSpace = atoi(argv[i]);
835*4882a593Smuzhiyun                 if (limitStackSpace > 0)
836*4882a593Smuzhiyun                     limitStackSpace *= 1024;
837*4882a593Smuzhiyun             }
838*4882a593Smuzhiyun             else
839*4882a593Smuzhiyun                 UseMsg();
840*4882a593Smuzhiyun         }
841*4882a593Smuzhiyun #endif
842*4882a593Smuzhiyun #ifdef LOCK_SERVER
843*4882a593Smuzhiyun         else if (strcmp(argv[i], "-nolock") == 0) {
844*4882a593Smuzhiyun #if !defined(WIN32) && !defined(__CYGWIN__)
845*4882a593Smuzhiyun             if (getuid() != 0)
846*4882a593Smuzhiyun                 ErrorF
847*4882a593Smuzhiyun                     ("Warning: the -nolock option can only be used by root\n");
848*4882a593Smuzhiyun             else
849*4882a593Smuzhiyun #endif
850*4882a593Smuzhiyun                 nolock = TRUE;
851*4882a593Smuzhiyun         }
852*4882a593Smuzhiyun #endif
853*4882a593Smuzhiyun 	else if ( strcmp( argv[i], "-maxclients") == 0)
854*4882a593Smuzhiyun 	{
855*4882a593Smuzhiyun 	    if (++i < argc) {
856*4882a593Smuzhiyun 		LimitClients = atoi(argv[i]);
857*4882a593Smuzhiyun 		if (LimitClients != 64 &&
858*4882a593Smuzhiyun 		    LimitClients != 128 &&
859*4882a593Smuzhiyun 		    LimitClients != 256 &&
860*4882a593Smuzhiyun 		    LimitClients != 512 &&
861*4882a593Smuzhiyun                     LimitClients != 1024 &&
862*4882a593Smuzhiyun                     LimitClients != 2048) {
863*4882a593Smuzhiyun 		    FatalError("maxclients must be one of 64, 128, 256, 512, 1024 or 2048\n");
864*4882a593Smuzhiyun 		}
865*4882a593Smuzhiyun 	    } else
866*4882a593Smuzhiyun 		UseMsg();
867*4882a593Smuzhiyun 	}
868*4882a593Smuzhiyun         else if (strcmp(argv[i], "-nolisten") == 0) {
869*4882a593Smuzhiyun             if (++i < argc) {
870*4882a593Smuzhiyun                 if (_XSERVTransNoListen(argv[i]))
871*4882a593Smuzhiyun                     ErrorF("Failed to disable listen for %s transport",
872*4882a593Smuzhiyun                            argv[i]);
873*4882a593Smuzhiyun             }
874*4882a593Smuzhiyun             else
875*4882a593Smuzhiyun                 UseMsg();
876*4882a593Smuzhiyun         }
877*4882a593Smuzhiyun         else if (strcmp(argv[i], "-listen") == 0) {
878*4882a593Smuzhiyun             if (++i < argc) {
879*4882a593Smuzhiyun                 if (_XSERVTransListen(argv[i]))
880*4882a593Smuzhiyun                     ErrorF("Failed to enable listen for %s transport",
881*4882a593Smuzhiyun                            argv[i]);
882*4882a593Smuzhiyun             }
883*4882a593Smuzhiyun             else
884*4882a593Smuzhiyun                 UseMsg();
885*4882a593Smuzhiyun         }
886*4882a593Smuzhiyun         else if (strcmp(argv[i], "-noreset") == 0) {
887*4882a593Smuzhiyun             dispatchExceptionAtReset = 0;
888*4882a593Smuzhiyun         }
889*4882a593Smuzhiyun         else if (strcmp(argv[i], "-reset") == 0) {
890*4882a593Smuzhiyun             dispatchExceptionAtReset = DE_RESET;
891*4882a593Smuzhiyun         }
892*4882a593Smuzhiyun         else if (strcmp(argv[i], "-p") == 0) {
893*4882a593Smuzhiyun             if (++i < argc)
894*4882a593Smuzhiyun                 defaultScreenSaverInterval = ((CARD32) atoi(argv[i])) *
895*4882a593Smuzhiyun                     MILLI_PER_MIN;
896*4882a593Smuzhiyun             else
897*4882a593Smuzhiyun                 UseMsg();
898*4882a593Smuzhiyun         }
899*4882a593Smuzhiyun         else if (strcmp(argv[i], "-pogo") == 0) {
900*4882a593Smuzhiyun             dispatchException = DE_TERMINATE;
901*4882a593Smuzhiyun         }
902*4882a593Smuzhiyun         else if (strcmp(argv[i], "-pn") == 0)
903*4882a593Smuzhiyun             PartialNetwork = TRUE;
904*4882a593Smuzhiyun         else if (strcmp(argv[i], "-nopn") == 0)
905*4882a593Smuzhiyun             PartialNetwork = FALSE;
906*4882a593Smuzhiyun         else if (strcmp(argv[i], "r") == 0)
907*4882a593Smuzhiyun             defaultKeyboardControl.autoRepeat = TRUE;
908*4882a593Smuzhiyun         else if (strcmp(argv[i], "-r") == 0)
909*4882a593Smuzhiyun             defaultKeyboardControl.autoRepeat = FALSE;
910*4882a593Smuzhiyun         else if (strcmp(argv[i], "-retro") == 0)
911*4882a593Smuzhiyun             party_like_its_1989 = TRUE;
912*4882a593Smuzhiyun         else if (strcmp(argv[i], "-s") == 0) {
913*4882a593Smuzhiyun             if (++i < argc)
914*4882a593Smuzhiyun                 defaultScreenSaverTime = ((CARD32) atoi(argv[i])) *
915*4882a593Smuzhiyun                     MILLI_PER_MIN;
916*4882a593Smuzhiyun             else
917*4882a593Smuzhiyun                 UseMsg();
918*4882a593Smuzhiyun         }
919*4882a593Smuzhiyun         else if (strcmp(argv[i], "-seat") == 0) {
920*4882a593Smuzhiyun             if (++i < argc)
921*4882a593Smuzhiyun                 SeatId = argv[i];
922*4882a593Smuzhiyun             else
923*4882a593Smuzhiyun                 UseMsg();
924*4882a593Smuzhiyun         }
925*4882a593Smuzhiyun         else if (strcmp(argv[i], "-t") == 0) {
926*4882a593Smuzhiyun             if (++i < argc)
927*4882a593Smuzhiyun                 defaultPointerControl.threshold = atoi(argv[i]);
928*4882a593Smuzhiyun             else
929*4882a593Smuzhiyun                 UseMsg();
930*4882a593Smuzhiyun         }
931*4882a593Smuzhiyun         else if (strcmp(argv[i], "-terminate") == 0) {
932*4882a593Smuzhiyun             dispatchExceptionAtReset = DE_TERMINATE;
933*4882a593Smuzhiyun         }
934*4882a593Smuzhiyun         else if (strcmp(argv[i], "-to") == 0) {
935*4882a593Smuzhiyun             if (++i < argc)
936*4882a593Smuzhiyun                 TimeOutValue = ((CARD32) atoi(argv[i])) * MILLI_PER_SECOND;
937*4882a593Smuzhiyun             else
938*4882a593Smuzhiyun                 UseMsg();
939*4882a593Smuzhiyun         }
940*4882a593Smuzhiyun         else if (strcmp(argv[i], "-tst") == 0) {
941*4882a593Smuzhiyun             noTestExtensions = TRUE;
942*4882a593Smuzhiyun         }
943*4882a593Smuzhiyun         else if (strcmp(argv[i], "v") == 0)
944*4882a593Smuzhiyun             defaultScreenSaverBlanking = PreferBlanking;
945*4882a593Smuzhiyun         else if (strcmp(argv[i], "-v") == 0)
946*4882a593Smuzhiyun             defaultScreenSaverBlanking = DontPreferBlanking;
947*4882a593Smuzhiyun         else if (strcmp(argv[i], "-wm") == 0)
948*4882a593Smuzhiyun             defaultBackingStore = WhenMapped;
949*4882a593Smuzhiyun         else if (strcmp(argv[i], "-wr") == 0)
950*4882a593Smuzhiyun             whiteRoot = TRUE;
951*4882a593Smuzhiyun         else if (strcmp(argv[i], "-background") == 0) {
952*4882a593Smuzhiyun             if (++i < argc) {
953*4882a593Smuzhiyun                 if (!strcmp(argv[i], "none"))
954*4882a593Smuzhiyun                     bgNoneRoot = TRUE;
955*4882a593Smuzhiyun                 else
956*4882a593Smuzhiyun                     UseMsg();
957*4882a593Smuzhiyun             }
958*4882a593Smuzhiyun         }
959*4882a593Smuzhiyun         else if (strcmp(argv[i], "-maxbigreqsize") == 0) {
960*4882a593Smuzhiyun             if (++i < argc) {
961*4882a593Smuzhiyun                 long reqSizeArg = atol(argv[i]);
962*4882a593Smuzhiyun 
963*4882a593Smuzhiyun                 /* Request size > 128MB does not make much sense... */
964*4882a593Smuzhiyun                 if (reqSizeArg > 0L && reqSizeArg < 128L) {
965*4882a593Smuzhiyun                     maxBigRequestSize = (reqSizeArg * 1048576L) - 1L;
966*4882a593Smuzhiyun                 }
967*4882a593Smuzhiyun                 else {
968*4882a593Smuzhiyun                     UseMsg();
969*4882a593Smuzhiyun                 }
970*4882a593Smuzhiyun             }
971*4882a593Smuzhiyun             else {
972*4882a593Smuzhiyun                 UseMsg();
973*4882a593Smuzhiyun             }
974*4882a593Smuzhiyun         }
975*4882a593Smuzhiyun #ifdef PANORAMIX
976*4882a593Smuzhiyun         else if (strcmp(argv[i], "+xinerama") == 0) {
977*4882a593Smuzhiyun             noPanoramiXExtension = FALSE;
978*4882a593Smuzhiyun         }
979*4882a593Smuzhiyun         else if (strcmp(argv[i], "-xinerama") == 0) {
980*4882a593Smuzhiyun             noPanoramiXExtension = TRUE;
981*4882a593Smuzhiyun         }
982*4882a593Smuzhiyun         else if (strcmp(argv[i], "-disablexineramaextension") == 0) {
983*4882a593Smuzhiyun             PanoramiXExtensionDisabledHack = TRUE;
984*4882a593Smuzhiyun         }
985*4882a593Smuzhiyun #endif
986*4882a593Smuzhiyun         else if (strcmp(argv[i], "-I") == 0) {
987*4882a593Smuzhiyun             /* ignore all remaining arguments */
988*4882a593Smuzhiyun             break;
989*4882a593Smuzhiyun         }
990*4882a593Smuzhiyun         else if (strncmp(argv[i], "tty", 3) == 0) {
991*4882a593Smuzhiyun             /* init supplies us with this useless information */
992*4882a593Smuzhiyun         }
993*4882a593Smuzhiyun #ifdef XDMCP
994*4882a593Smuzhiyun         else if ((skip = XdmcpOptions(argc, argv, i)) != i) {
995*4882a593Smuzhiyun             i = skip - 1;
996*4882a593Smuzhiyun         }
997*4882a593Smuzhiyun #endif
998*4882a593Smuzhiyun         else if (strcmp(argv[i], "-dumbSched") == 0) {
999*4882a593Smuzhiyun             InputThreadEnable = FALSE;
1000*4882a593Smuzhiyun #ifdef HAVE_SETITIMER
1001*4882a593Smuzhiyun             SmartScheduleSignalEnable = FALSE;
1002*4882a593Smuzhiyun #endif
1003*4882a593Smuzhiyun         }
1004*4882a593Smuzhiyun         else if (strcmp(argv[i], "-schedInterval") == 0) {
1005*4882a593Smuzhiyun             if (++i < argc) {
1006*4882a593Smuzhiyun                 SmartScheduleInterval = atoi(argv[i]);
1007*4882a593Smuzhiyun                 SmartScheduleSlice = SmartScheduleInterval;
1008*4882a593Smuzhiyun             }
1009*4882a593Smuzhiyun             else
1010*4882a593Smuzhiyun                 UseMsg();
1011*4882a593Smuzhiyun         }
1012*4882a593Smuzhiyun         else if (strcmp(argv[i], "-schedMax") == 0) {
1013*4882a593Smuzhiyun             if (++i < argc) {
1014*4882a593Smuzhiyun                 SmartScheduleMaxSlice = atoi(argv[i]);
1015*4882a593Smuzhiyun             }
1016*4882a593Smuzhiyun             else
1017*4882a593Smuzhiyun                 UseMsg();
1018*4882a593Smuzhiyun         }
1019*4882a593Smuzhiyun         else if (strcmp(argv[i], "-render") == 0) {
1020*4882a593Smuzhiyun             if (++i < argc) {
1021*4882a593Smuzhiyun                 int policy = PictureParseCmapPolicy(argv[i]);
1022*4882a593Smuzhiyun 
1023*4882a593Smuzhiyun                 if (policy != PictureCmapPolicyInvalid)
1024*4882a593Smuzhiyun                     PictureCmapPolicy = policy;
1025*4882a593Smuzhiyun                 else
1026*4882a593Smuzhiyun                     UseMsg();
1027*4882a593Smuzhiyun             }
1028*4882a593Smuzhiyun             else
1029*4882a593Smuzhiyun                 UseMsg();
1030*4882a593Smuzhiyun         }
1031*4882a593Smuzhiyun         else if (strcmp(argv[i], "-sigstop") == 0) {
1032*4882a593Smuzhiyun             RunFromSigStopParent = TRUE;
1033*4882a593Smuzhiyun         }
1034*4882a593Smuzhiyun         else if (strcmp(argv[i], "+extension") == 0) {
1035*4882a593Smuzhiyun             if (++i < argc) {
1036*4882a593Smuzhiyun                 if (!EnableDisableExtension(argv[i], TRUE))
1037*4882a593Smuzhiyun                     EnableDisableExtensionError(argv[i], TRUE);
1038*4882a593Smuzhiyun             }
1039*4882a593Smuzhiyun             else
1040*4882a593Smuzhiyun                 UseMsg();
1041*4882a593Smuzhiyun         }
1042*4882a593Smuzhiyun         else if (strcmp(argv[i], "-extension") == 0) {
1043*4882a593Smuzhiyun             if (++i < argc) {
1044*4882a593Smuzhiyun                 if (!EnableDisableExtension(argv[i], FALSE))
1045*4882a593Smuzhiyun                     EnableDisableExtensionError(argv[i], FALSE);
1046*4882a593Smuzhiyun             }
1047*4882a593Smuzhiyun             else
1048*4882a593Smuzhiyun                 UseMsg();
1049*4882a593Smuzhiyun         }
1050*4882a593Smuzhiyun         else {
1051*4882a593Smuzhiyun             ErrorF("Unrecognized option: %s\n", argv[i]);
1052*4882a593Smuzhiyun             UseMsg();
1053*4882a593Smuzhiyun             FatalError("Unrecognized option: %s\n", argv[i]);
1054*4882a593Smuzhiyun         }
1055*4882a593Smuzhiyun     }
1056*4882a593Smuzhiyun }
1057*4882a593Smuzhiyun 
1058*4882a593Smuzhiyun /* Implement a simple-minded font authorization scheme.  The authorization
1059*4882a593Smuzhiyun    name is "hp-hostname-1", the contents are simply the host name. */
1060*4882a593Smuzhiyun int
set_font_authorizations(char ** authorizations,int * authlen,void * client)1061*4882a593Smuzhiyun set_font_authorizations(char **authorizations, int *authlen, void *client)
1062*4882a593Smuzhiyun {
1063*4882a593Smuzhiyun #define AUTHORIZATION_NAME "hp-hostname-1"
1064*4882a593Smuzhiyun #if defined(TCPCONN)
1065*4882a593Smuzhiyun     static char *result = NULL;
1066*4882a593Smuzhiyun     static char *p = NULL;
1067*4882a593Smuzhiyun 
1068*4882a593Smuzhiyun     if (p == NULL) {
1069*4882a593Smuzhiyun         char hname[1024], *hnameptr;
1070*4882a593Smuzhiyun         unsigned int len;
1071*4882a593Smuzhiyun 
1072*4882a593Smuzhiyun #if defined(IPv6) && defined(AF_INET6)
1073*4882a593Smuzhiyun         struct addrinfo hints, *ai = NULL;
1074*4882a593Smuzhiyun #else
1075*4882a593Smuzhiyun         struct hostent *host;
1076*4882a593Smuzhiyun 
1077*4882a593Smuzhiyun #ifdef XTHREADS_NEEDS_BYNAMEPARAMS
1078*4882a593Smuzhiyun         _Xgethostbynameparams hparams;
1079*4882a593Smuzhiyun #endif
1080*4882a593Smuzhiyun #endif
1081*4882a593Smuzhiyun 
1082*4882a593Smuzhiyun         gethostname(hname, 1024);
1083*4882a593Smuzhiyun #if defined(IPv6) && defined(AF_INET6)
1084*4882a593Smuzhiyun         memset(&hints, 0, sizeof(hints));
1085*4882a593Smuzhiyun         hints.ai_flags = AI_CANONNAME;
1086*4882a593Smuzhiyun         if (getaddrinfo(hname, NULL, &hints, &ai) == 0) {
1087*4882a593Smuzhiyun             hnameptr = ai->ai_canonname;
1088*4882a593Smuzhiyun         }
1089*4882a593Smuzhiyun         else {
1090*4882a593Smuzhiyun             hnameptr = hname;
1091*4882a593Smuzhiyun         }
1092*4882a593Smuzhiyun #else
1093*4882a593Smuzhiyun         host = _XGethostbyname(hname, hparams);
1094*4882a593Smuzhiyun         if (host == NULL)
1095*4882a593Smuzhiyun             hnameptr = hname;
1096*4882a593Smuzhiyun         else
1097*4882a593Smuzhiyun             hnameptr = host->h_name;
1098*4882a593Smuzhiyun #endif
1099*4882a593Smuzhiyun 
1100*4882a593Smuzhiyun         len = strlen(hnameptr) + 1;
1101*4882a593Smuzhiyun         result = malloc(len + sizeof(AUTHORIZATION_NAME) + 4);
1102*4882a593Smuzhiyun 
1103*4882a593Smuzhiyun         p = result;
1104*4882a593Smuzhiyun         *p++ = sizeof(AUTHORIZATION_NAME) >> 8;
1105*4882a593Smuzhiyun         *p++ = sizeof(AUTHORIZATION_NAME) & 0xff;
1106*4882a593Smuzhiyun         *p++ = (len) >> 8;
1107*4882a593Smuzhiyun         *p++ = (len & 0xff);
1108*4882a593Smuzhiyun 
1109*4882a593Smuzhiyun         memmove(p, AUTHORIZATION_NAME, sizeof(AUTHORIZATION_NAME));
1110*4882a593Smuzhiyun         p += sizeof(AUTHORIZATION_NAME);
1111*4882a593Smuzhiyun         memmove(p, hnameptr, len);
1112*4882a593Smuzhiyun         p += len;
1113*4882a593Smuzhiyun #if defined(IPv6) && defined(AF_INET6)
1114*4882a593Smuzhiyun         if (ai) {
1115*4882a593Smuzhiyun             freeaddrinfo(ai);
1116*4882a593Smuzhiyun         }
1117*4882a593Smuzhiyun #endif
1118*4882a593Smuzhiyun     }
1119*4882a593Smuzhiyun     *authlen = p - result;
1120*4882a593Smuzhiyun     *authorizations = result;
1121*4882a593Smuzhiyun     return 1;
1122*4882a593Smuzhiyun #else                           /* TCPCONN */
1123*4882a593Smuzhiyun     return 0;
1124*4882a593Smuzhiyun #endif                          /* TCPCONN */
1125*4882a593Smuzhiyun }
1126*4882a593Smuzhiyun 
1127*4882a593Smuzhiyun void *
XNFalloc(unsigned long amount)1128*4882a593Smuzhiyun XNFalloc(unsigned long amount)
1129*4882a593Smuzhiyun {
1130*4882a593Smuzhiyun     void *ptr = malloc(amount);
1131*4882a593Smuzhiyun 
1132*4882a593Smuzhiyun     if (!ptr)
1133*4882a593Smuzhiyun         FatalError("Out of memory");
1134*4882a593Smuzhiyun     return ptr;
1135*4882a593Smuzhiyun }
1136*4882a593Smuzhiyun 
1137*4882a593Smuzhiyun /* The original XNFcalloc was used with the xnfcalloc macro which multiplied
1138*4882a593Smuzhiyun  * the arguments at the call site without allowing calloc to check for overflow.
1139*4882a593Smuzhiyun  * XNFcallocarray was added to fix that without breaking ABI.
1140*4882a593Smuzhiyun  */
1141*4882a593Smuzhiyun void *
XNFcalloc(unsigned long amount)1142*4882a593Smuzhiyun XNFcalloc(unsigned long amount)
1143*4882a593Smuzhiyun {
1144*4882a593Smuzhiyun     return XNFcallocarray(1, amount);
1145*4882a593Smuzhiyun }
1146*4882a593Smuzhiyun 
1147*4882a593Smuzhiyun void *
XNFcallocarray(size_t nmemb,size_t size)1148*4882a593Smuzhiyun XNFcallocarray(size_t nmemb, size_t size)
1149*4882a593Smuzhiyun {
1150*4882a593Smuzhiyun     void *ret = calloc(nmemb, size);
1151*4882a593Smuzhiyun 
1152*4882a593Smuzhiyun     if (!ret)
1153*4882a593Smuzhiyun         FatalError("XNFcalloc: Out of memory");
1154*4882a593Smuzhiyun     return ret;
1155*4882a593Smuzhiyun }
1156*4882a593Smuzhiyun 
1157*4882a593Smuzhiyun void *
XNFrealloc(void * ptr,unsigned long amount)1158*4882a593Smuzhiyun XNFrealloc(void *ptr, unsigned long amount)
1159*4882a593Smuzhiyun {
1160*4882a593Smuzhiyun     void *ret = realloc(ptr, amount);
1161*4882a593Smuzhiyun 
1162*4882a593Smuzhiyun     if (!ret)
1163*4882a593Smuzhiyun         FatalError("XNFrealloc: Out of memory");
1164*4882a593Smuzhiyun     return ret;
1165*4882a593Smuzhiyun }
1166*4882a593Smuzhiyun 
1167*4882a593Smuzhiyun void *
XNFreallocarray(void * ptr,size_t nmemb,size_t size)1168*4882a593Smuzhiyun XNFreallocarray(void *ptr, size_t nmemb, size_t size)
1169*4882a593Smuzhiyun {
1170*4882a593Smuzhiyun     void *ret = reallocarray(ptr, nmemb, size);
1171*4882a593Smuzhiyun 
1172*4882a593Smuzhiyun     if (!ret)
1173*4882a593Smuzhiyun         FatalError("XNFreallocarray: Out of memory");
1174*4882a593Smuzhiyun     return ret;
1175*4882a593Smuzhiyun }
1176*4882a593Smuzhiyun 
1177*4882a593Smuzhiyun char *
Xstrdup(const char * s)1178*4882a593Smuzhiyun Xstrdup(const char *s)
1179*4882a593Smuzhiyun {
1180*4882a593Smuzhiyun     if (s == NULL)
1181*4882a593Smuzhiyun         return NULL;
1182*4882a593Smuzhiyun     return strdup(s);
1183*4882a593Smuzhiyun }
1184*4882a593Smuzhiyun 
1185*4882a593Smuzhiyun char *
XNFstrdup(const char * s)1186*4882a593Smuzhiyun XNFstrdup(const char *s)
1187*4882a593Smuzhiyun {
1188*4882a593Smuzhiyun     char *ret;
1189*4882a593Smuzhiyun 
1190*4882a593Smuzhiyun     if (s == NULL)
1191*4882a593Smuzhiyun         return NULL;
1192*4882a593Smuzhiyun 
1193*4882a593Smuzhiyun     ret = strdup(s);
1194*4882a593Smuzhiyun     if (!ret)
1195*4882a593Smuzhiyun         FatalError("XNFstrdup: Out of memory");
1196*4882a593Smuzhiyun     return ret;
1197*4882a593Smuzhiyun }
1198*4882a593Smuzhiyun 
1199*4882a593Smuzhiyun void
SmartScheduleStopTimer(void)1200*4882a593Smuzhiyun SmartScheduleStopTimer(void)
1201*4882a593Smuzhiyun {
1202*4882a593Smuzhiyun #ifdef HAVE_SETITIMER
1203*4882a593Smuzhiyun     struct itimerval timer;
1204*4882a593Smuzhiyun 
1205*4882a593Smuzhiyun     if (!SmartScheduleSignalEnable)
1206*4882a593Smuzhiyun         return;
1207*4882a593Smuzhiyun     timer.it_interval.tv_sec = 0;
1208*4882a593Smuzhiyun     timer.it_interval.tv_usec = 0;
1209*4882a593Smuzhiyun     timer.it_value.tv_sec = 0;
1210*4882a593Smuzhiyun     timer.it_value.tv_usec = 0;
1211*4882a593Smuzhiyun     (void) setitimer(ITIMER_REAL, &timer, 0);
1212*4882a593Smuzhiyun #endif
1213*4882a593Smuzhiyun }
1214*4882a593Smuzhiyun 
1215*4882a593Smuzhiyun void
SmartScheduleStartTimer(void)1216*4882a593Smuzhiyun SmartScheduleStartTimer(void)
1217*4882a593Smuzhiyun {
1218*4882a593Smuzhiyun #ifdef HAVE_SETITIMER
1219*4882a593Smuzhiyun     struct itimerval timer;
1220*4882a593Smuzhiyun 
1221*4882a593Smuzhiyun     if (!SmartScheduleSignalEnable)
1222*4882a593Smuzhiyun         return;
1223*4882a593Smuzhiyun     timer.it_interval.tv_sec = 0;
1224*4882a593Smuzhiyun     timer.it_interval.tv_usec = SmartScheduleInterval * 1000;
1225*4882a593Smuzhiyun     timer.it_value.tv_sec = 0;
1226*4882a593Smuzhiyun     timer.it_value.tv_usec = SmartScheduleInterval * 1000;
1227*4882a593Smuzhiyun     setitimer(ITIMER_REAL, &timer, 0);
1228*4882a593Smuzhiyun #endif
1229*4882a593Smuzhiyun }
1230*4882a593Smuzhiyun 
1231*4882a593Smuzhiyun #ifdef HAVE_SETITIMER
1232*4882a593Smuzhiyun static void
SmartScheduleTimer(int sig)1233*4882a593Smuzhiyun SmartScheduleTimer(int sig)
1234*4882a593Smuzhiyun {
1235*4882a593Smuzhiyun     SmartScheduleTime += SmartScheduleInterval;
1236*4882a593Smuzhiyun }
1237*4882a593Smuzhiyun 
1238*4882a593Smuzhiyun static int
SmartScheduleEnable(void)1239*4882a593Smuzhiyun SmartScheduleEnable(void)
1240*4882a593Smuzhiyun {
1241*4882a593Smuzhiyun     int ret = 0;
1242*4882a593Smuzhiyun     struct sigaction act;
1243*4882a593Smuzhiyun 
1244*4882a593Smuzhiyun     if (!SmartScheduleSignalEnable)
1245*4882a593Smuzhiyun         return 0;
1246*4882a593Smuzhiyun 
1247*4882a593Smuzhiyun     memset((char *) &act, 0, sizeof(struct sigaction));
1248*4882a593Smuzhiyun 
1249*4882a593Smuzhiyun     /* Set up the timer signal function */
1250*4882a593Smuzhiyun     act.sa_flags = SA_RESTART;
1251*4882a593Smuzhiyun     act.sa_handler = SmartScheduleTimer;
1252*4882a593Smuzhiyun     sigemptyset(&act.sa_mask);
1253*4882a593Smuzhiyun     sigaddset(&act.sa_mask, SIGALRM);
1254*4882a593Smuzhiyun     ret = sigaction(SIGALRM, &act, 0);
1255*4882a593Smuzhiyun     return ret;
1256*4882a593Smuzhiyun }
1257*4882a593Smuzhiyun 
1258*4882a593Smuzhiyun static int
SmartSchedulePause(void)1259*4882a593Smuzhiyun SmartSchedulePause(void)
1260*4882a593Smuzhiyun {
1261*4882a593Smuzhiyun     int ret = 0;
1262*4882a593Smuzhiyun     struct sigaction act;
1263*4882a593Smuzhiyun 
1264*4882a593Smuzhiyun     if (!SmartScheduleSignalEnable)
1265*4882a593Smuzhiyun         return 0;
1266*4882a593Smuzhiyun 
1267*4882a593Smuzhiyun     memset((char *) &act, 0, sizeof(struct sigaction));
1268*4882a593Smuzhiyun 
1269*4882a593Smuzhiyun     act.sa_handler = SIG_IGN;
1270*4882a593Smuzhiyun     sigemptyset(&act.sa_mask);
1271*4882a593Smuzhiyun     ret = sigaction(SIGALRM, &act, 0);
1272*4882a593Smuzhiyun     return ret;
1273*4882a593Smuzhiyun }
1274*4882a593Smuzhiyun #endif
1275*4882a593Smuzhiyun 
1276*4882a593Smuzhiyun void
SmartScheduleInit(void)1277*4882a593Smuzhiyun SmartScheduleInit(void)
1278*4882a593Smuzhiyun {
1279*4882a593Smuzhiyun #ifdef HAVE_SETITIMER
1280*4882a593Smuzhiyun     if (SmartScheduleEnable() < 0) {
1281*4882a593Smuzhiyun         perror("sigaction for smart scheduler");
1282*4882a593Smuzhiyun         SmartScheduleSignalEnable = FALSE;
1283*4882a593Smuzhiyun     }
1284*4882a593Smuzhiyun #endif
1285*4882a593Smuzhiyun }
1286*4882a593Smuzhiyun 
1287*4882a593Smuzhiyun #ifdef SIG_BLOCK
1288*4882a593Smuzhiyun static sigset_t PreviousSignalMask;
1289*4882a593Smuzhiyun static int BlockedSignalCount;
1290*4882a593Smuzhiyun #endif
1291*4882a593Smuzhiyun 
1292*4882a593Smuzhiyun void
OsBlockSignals(void)1293*4882a593Smuzhiyun OsBlockSignals(void)
1294*4882a593Smuzhiyun {
1295*4882a593Smuzhiyun #ifdef SIG_BLOCK
1296*4882a593Smuzhiyun     if (BlockedSignalCount++ == 0) {
1297*4882a593Smuzhiyun         sigset_t set;
1298*4882a593Smuzhiyun 
1299*4882a593Smuzhiyun         sigemptyset(&set);
1300*4882a593Smuzhiyun         sigaddset(&set, SIGALRM);
1301*4882a593Smuzhiyun         sigaddset(&set, SIGVTALRM);
1302*4882a593Smuzhiyun #ifdef SIGWINCH
1303*4882a593Smuzhiyun         sigaddset(&set, SIGWINCH);
1304*4882a593Smuzhiyun #endif
1305*4882a593Smuzhiyun         sigaddset(&set, SIGTSTP);
1306*4882a593Smuzhiyun         sigaddset(&set, SIGTTIN);
1307*4882a593Smuzhiyun         sigaddset(&set, SIGTTOU);
1308*4882a593Smuzhiyun         sigaddset(&set, SIGCHLD);
1309*4882a593Smuzhiyun         xthread_sigmask(SIG_BLOCK, &set, &PreviousSignalMask);
1310*4882a593Smuzhiyun     }
1311*4882a593Smuzhiyun #endif
1312*4882a593Smuzhiyun }
1313*4882a593Smuzhiyun 
1314*4882a593Smuzhiyun void
OsReleaseSignals(void)1315*4882a593Smuzhiyun OsReleaseSignals(void)
1316*4882a593Smuzhiyun {
1317*4882a593Smuzhiyun #ifdef SIG_BLOCK
1318*4882a593Smuzhiyun     if (--BlockedSignalCount == 0) {
1319*4882a593Smuzhiyun         xthread_sigmask(SIG_SETMASK, &PreviousSignalMask, 0);
1320*4882a593Smuzhiyun     }
1321*4882a593Smuzhiyun #endif
1322*4882a593Smuzhiyun }
1323*4882a593Smuzhiyun 
1324*4882a593Smuzhiyun void
OsResetSignals(void)1325*4882a593Smuzhiyun OsResetSignals(void)
1326*4882a593Smuzhiyun {
1327*4882a593Smuzhiyun #ifdef SIG_BLOCK
1328*4882a593Smuzhiyun     while (BlockedSignalCount > 0)
1329*4882a593Smuzhiyun         OsReleaseSignals();
1330*4882a593Smuzhiyun     input_force_unlock();
1331*4882a593Smuzhiyun #endif
1332*4882a593Smuzhiyun }
1333*4882a593Smuzhiyun 
1334*4882a593Smuzhiyun /*
1335*4882a593Smuzhiyun  * Pending signals may interfere with core dumping. Provide a
1336*4882a593Smuzhiyun  * mechanism to block signals when aborting.
1337*4882a593Smuzhiyun  */
1338*4882a593Smuzhiyun 
1339*4882a593Smuzhiyun void
OsAbort(void)1340*4882a593Smuzhiyun OsAbort(void)
1341*4882a593Smuzhiyun {
1342*4882a593Smuzhiyun #ifndef __APPLE__
1343*4882a593Smuzhiyun     OsBlockSignals();
1344*4882a593Smuzhiyun #endif
1345*4882a593Smuzhiyun #if !defined(WIN32) || defined(__CYGWIN__)
1346*4882a593Smuzhiyun     /* abort() raises SIGABRT, so we have to stop handling that to prevent
1347*4882a593Smuzhiyun      * recursion
1348*4882a593Smuzhiyun      */
1349*4882a593Smuzhiyun     OsSignal(SIGABRT, SIG_DFL);
1350*4882a593Smuzhiyun #endif
1351*4882a593Smuzhiyun     abort();
1352*4882a593Smuzhiyun }
1353*4882a593Smuzhiyun 
1354*4882a593Smuzhiyun #if !defined(WIN32)
1355*4882a593Smuzhiyun /*
1356*4882a593Smuzhiyun  * "safer" versions of system(3), popen(3) and pclose(3) which give up
1357*4882a593Smuzhiyun  * all privs before running a command.
1358*4882a593Smuzhiyun  *
1359*4882a593Smuzhiyun  * This is based on the code in FreeBSD 2.2 libc.
1360*4882a593Smuzhiyun  *
1361*4882a593Smuzhiyun  * XXX It'd be good to redirect stderr so that it ends up in the log file
1362*4882a593Smuzhiyun  * as well.  As it is now, xkbcomp messages don't end up in the log file.
1363*4882a593Smuzhiyun  */
1364*4882a593Smuzhiyun 
1365*4882a593Smuzhiyun int
System(const char * command)1366*4882a593Smuzhiyun System(const char *command)
1367*4882a593Smuzhiyun {
1368*4882a593Smuzhiyun     int pid, p;
1369*4882a593Smuzhiyun     void (*csig) (int);
1370*4882a593Smuzhiyun     int status;
1371*4882a593Smuzhiyun 
1372*4882a593Smuzhiyun     if (!command)
1373*4882a593Smuzhiyun         return 1;
1374*4882a593Smuzhiyun 
1375*4882a593Smuzhiyun     csig = OsSignal(SIGCHLD, SIG_DFL);
1376*4882a593Smuzhiyun     if (csig == SIG_ERR) {
1377*4882a593Smuzhiyun         perror("signal");
1378*4882a593Smuzhiyun         return -1;
1379*4882a593Smuzhiyun     }
1380*4882a593Smuzhiyun     DebugF("System: `%s'\n", command);
1381*4882a593Smuzhiyun 
1382*4882a593Smuzhiyun     switch (pid = fork()) {
1383*4882a593Smuzhiyun     case -1:                   /* error */
1384*4882a593Smuzhiyun         p = -1;
1385*4882a593Smuzhiyun         break;
1386*4882a593Smuzhiyun     case 0:                    /* child */
1387*4882a593Smuzhiyun         if (setgid(getgid()) == -1)
1388*4882a593Smuzhiyun             _exit(127);
1389*4882a593Smuzhiyun         if (setuid(getuid()) == -1)
1390*4882a593Smuzhiyun             _exit(127);
1391*4882a593Smuzhiyun         execl("/bin/sh", "sh", "-c", command, (char *) NULL);
1392*4882a593Smuzhiyun         _exit(127);
1393*4882a593Smuzhiyun     default:                   /* parent */
1394*4882a593Smuzhiyun         do {
1395*4882a593Smuzhiyun             p = waitpid(pid, &status, 0);
1396*4882a593Smuzhiyun         } while (p == -1 && errno == EINTR);
1397*4882a593Smuzhiyun 
1398*4882a593Smuzhiyun     }
1399*4882a593Smuzhiyun 
1400*4882a593Smuzhiyun     if (OsSignal(SIGCHLD, csig) == SIG_ERR) {
1401*4882a593Smuzhiyun         perror("signal");
1402*4882a593Smuzhiyun         return -1;
1403*4882a593Smuzhiyun     }
1404*4882a593Smuzhiyun 
1405*4882a593Smuzhiyun     return p == -1 ? -1 : status;
1406*4882a593Smuzhiyun }
1407*4882a593Smuzhiyun 
1408*4882a593Smuzhiyun static struct pid {
1409*4882a593Smuzhiyun     struct pid *next;
1410*4882a593Smuzhiyun     FILE *fp;
1411*4882a593Smuzhiyun     int pid;
1412*4882a593Smuzhiyun } *pidlist;
1413*4882a593Smuzhiyun 
1414*4882a593Smuzhiyun void *
Popen(const char * command,const char * type)1415*4882a593Smuzhiyun Popen(const char *command, const char *type)
1416*4882a593Smuzhiyun {
1417*4882a593Smuzhiyun     struct pid *cur;
1418*4882a593Smuzhiyun     FILE *iop;
1419*4882a593Smuzhiyun     int pdes[2], pid;
1420*4882a593Smuzhiyun 
1421*4882a593Smuzhiyun     if (command == NULL || type == NULL)
1422*4882a593Smuzhiyun         return NULL;
1423*4882a593Smuzhiyun 
1424*4882a593Smuzhiyun     if ((*type != 'r' && *type != 'w') || type[1])
1425*4882a593Smuzhiyun         return NULL;
1426*4882a593Smuzhiyun 
1427*4882a593Smuzhiyun     if ((cur = malloc(sizeof(struct pid))) == NULL)
1428*4882a593Smuzhiyun         return NULL;
1429*4882a593Smuzhiyun 
1430*4882a593Smuzhiyun     if (pipe(pdes) < 0) {
1431*4882a593Smuzhiyun         free(cur);
1432*4882a593Smuzhiyun         return NULL;
1433*4882a593Smuzhiyun     }
1434*4882a593Smuzhiyun 
1435*4882a593Smuzhiyun     /* Ignore the smart scheduler while this is going on */
1436*4882a593Smuzhiyun #ifdef HAVE_SETITIMER
1437*4882a593Smuzhiyun     if (SmartSchedulePause() < 0) {
1438*4882a593Smuzhiyun         close(pdes[0]);
1439*4882a593Smuzhiyun         close(pdes[1]);
1440*4882a593Smuzhiyun         free(cur);
1441*4882a593Smuzhiyun         perror("signal");
1442*4882a593Smuzhiyun         return NULL;
1443*4882a593Smuzhiyun     }
1444*4882a593Smuzhiyun #endif
1445*4882a593Smuzhiyun 
1446*4882a593Smuzhiyun     switch (pid = fork()) {
1447*4882a593Smuzhiyun     case -1:                   /* error */
1448*4882a593Smuzhiyun         close(pdes[0]);
1449*4882a593Smuzhiyun         close(pdes[1]);
1450*4882a593Smuzhiyun         free(cur);
1451*4882a593Smuzhiyun #ifdef HAVE_SETITIMER
1452*4882a593Smuzhiyun         if (SmartScheduleEnable() < 0)
1453*4882a593Smuzhiyun             perror("signal");
1454*4882a593Smuzhiyun #endif
1455*4882a593Smuzhiyun         return NULL;
1456*4882a593Smuzhiyun     case 0:                    /* child */
1457*4882a593Smuzhiyun         if (setgid(getgid()) == -1)
1458*4882a593Smuzhiyun             _exit(127);
1459*4882a593Smuzhiyun         if (setuid(getuid()) == -1)
1460*4882a593Smuzhiyun             _exit(127);
1461*4882a593Smuzhiyun         if (*type == 'r') {
1462*4882a593Smuzhiyun             if (pdes[1] != 1) {
1463*4882a593Smuzhiyun                 /* stdout */
1464*4882a593Smuzhiyun                 dup2(pdes[1], 1);
1465*4882a593Smuzhiyun                 close(pdes[1]);
1466*4882a593Smuzhiyun             }
1467*4882a593Smuzhiyun             close(pdes[0]);
1468*4882a593Smuzhiyun         }
1469*4882a593Smuzhiyun         else {
1470*4882a593Smuzhiyun             if (pdes[0] != 0) {
1471*4882a593Smuzhiyun                 /* stdin */
1472*4882a593Smuzhiyun                 dup2(pdes[0], 0);
1473*4882a593Smuzhiyun                 close(pdes[0]);
1474*4882a593Smuzhiyun             }
1475*4882a593Smuzhiyun             close(pdes[1]);
1476*4882a593Smuzhiyun         }
1477*4882a593Smuzhiyun         execl("/bin/sh", "sh", "-c", command, (char *) NULL);
1478*4882a593Smuzhiyun         _exit(127);
1479*4882a593Smuzhiyun     }
1480*4882a593Smuzhiyun 
1481*4882a593Smuzhiyun     /* Avoid EINTR during stdio calls */
1482*4882a593Smuzhiyun     OsBlockSignals();
1483*4882a593Smuzhiyun 
1484*4882a593Smuzhiyun     /* parent */
1485*4882a593Smuzhiyun     if (*type == 'r') {
1486*4882a593Smuzhiyun         iop = fdopen(pdes[0], type);
1487*4882a593Smuzhiyun         close(pdes[1]);
1488*4882a593Smuzhiyun     }
1489*4882a593Smuzhiyun     else {
1490*4882a593Smuzhiyun         iop = fdopen(pdes[1], type);
1491*4882a593Smuzhiyun         close(pdes[0]);
1492*4882a593Smuzhiyun     }
1493*4882a593Smuzhiyun 
1494*4882a593Smuzhiyun     cur->fp = iop;
1495*4882a593Smuzhiyun     cur->pid = pid;
1496*4882a593Smuzhiyun     cur->next = pidlist;
1497*4882a593Smuzhiyun     pidlist = cur;
1498*4882a593Smuzhiyun 
1499*4882a593Smuzhiyun     DebugF("Popen: `%s', fp = %p\n", command, iop);
1500*4882a593Smuzhiyun 
1501*4882a593Smuzhiyun     return iop;
1502*4882a593Smuzhiyun }
1503*4882a593Smuzhiyun 
1504*4882a593Smuzhiyun /* fopen that drops privileges */
1505*4882a593Smuzhiyun void *
Fopen(const char * file,const char * type)1506*4882a593Smuzhiyun Fopen(const char *file, const char *type)
1507*4882a593Smuzhiyun {
1508*4882a593Smuzhiyun     FILE *iop;
1509*4882a593Smuzhiyun 
1510*4882a593Smuzhiyun #ifndef HAS_SAVED_IDS_AND_SETEUID
1511*4882a593Smuzhiyun     struct pid *cur;
1512*4882a593Smuzhiyun     int pdes[2], pid;
1513*4882a593Smuzhiyun 
1514*4882a593Smuzhiyun     if (file == NULL || type == NULL)
1515*4882a593Smuzhiyun         return NULL;
1516*4882a593Smuzhiyun 
1517*4882a593Smuzhiyun     if ((*type != 'r' && *type != 'w') || type[1])
1518*4882a593Smuzhiyun         return NULL;
1519*4882a593Smuzhiyun 
1520*4882a593Smuzhiyun     if ((cur = malloc(sizeof(struct pid))) == NULL)
1521*4882a593Smuzhiyun         return NULL;
1522*4882a593Smuzhiyun 
1523*4882a593Smuzhiyun     if (pipe(pdes) < 0) {
1524*4882a593Smuzhiyun         free(cur);
1525*4882a593Smuzhiyun         return NULL;
1526*4882a593Smuzhiyun     }
1527*4882a593Smuzhiyun 
1528*4882a593Smuzhiyun     switch (pid = fork()) {
1529*4882a593Smuzhiyun     case -1:                   /* error */
1530*4882a593Smuzhiyun         close(pdes[0]);
1531*4882a593Smuzhiyun         close(pdes[1]);
1532*4882a593Smuzhiyun         free(cur);
1533*4882a593Smuzhiyun         return NULL;
1534*4882a593Smuzhiyun     case 0:                    /* child */
1535*4882a593Smuzhiyun         if (setgid(getgid()) == -1)
1536*4882a593Smuzhiyun             _exit(127);
1537*4882a593Smuzhiyun         if (setuid(getuid()) == -1)
1538*4882a593Smuzhiyun             _exit(127);
1539*4882a593Smuzhiyun         if (*type == 'r') {
1540*4882a593Smuzhiyun             if (pdes[1] != 1) {
1541*4882a593Smuzhiyun                 /* stdout */
1542*4882a593Smuzhiyun                 dup2(pdes[1], 1);
1543*4882a593Smuzhiyun                 close(pdes[1]);
1544*4882a593Smuzhiyun             }
1545*4882a593Smuzhiyun             close(pdes[0]);
1546*4882a593Smuzhiyun         }
1547*4882a593Smuzhiyun         else {
1548*4882a593Smuzhiyun             if (pdes[0] != 0) {
1549*4882a593Smuzhiyun                 /* stdin */
1550*4882a593Smuzhiyun                 dup2(pdes[0], 0);
1551*4882a593Smuzhiyun                 close(pdes[0]);
1552*4882a593Smuzhiyun             }
1553*4882a593Smuzhiyun             close(pdes[1]);
1554*4882a593Smuzhiyun         }
1555*4882a593Smuzhiyun         execl("/bin/cat", "cat", file, (char *) NULL);
1556*4882a593Smuzhiyun         _exit(127);
1557*4882a593Smuzhiyun     }
1558*4882a593Smuzhiyun 
1559*4882a593Smuzhiyun     /* Avoid EINTR during stdio calls */
1560*4882a593Smuzhiyun     OsBlockSignals();
1561*4882a593Smuzhiyun 
1562*4882a593Smuzhiyun     /* parent */
1563*4882a593Smuzhiyun     if (*type == 'r') {
1564*4882a593Smuzhiyun         iop = fdopen(pdes[0], type);
1565*4882a593Smuzhiyun         close(pdes[1]);
1566*4882a593Smuzhiyun     }
1567*4882a593Smuzhiyun     else {
1568*4882a593Smuzhiyun         iop = fdopen(pdes[1], type);
1569*4882a593Smuzhiyun         close(pdes[0]);
1570*4882a593Smuzhiyun     }
1571*4882a593Smuzhiyun 
1572*4882a593Smuzhiyun     cur->fp = iop;
1573*4882a593Smuzhiyun     cur->pid = pid;
1574*4882a593Smuzhiyun     cur->next = pidlist;
1575*4882a593Smuzhiyun     pidlist = cur;
1576*4882a593Smuzhiyun 
1577*4882a593Smuzhiyun     DebugF("Fopen(%s), fp = %p\n", file, iop);
1578*4882a593Smuzhiyun 
1579*4882a593Smuzhiyun     return iop;
1580*4882a593Smuzhiyun #else
1581*4882a593Smuzhiyun     int ruid, euid;
1582*4882a593Smuzhiyun 
1583*4882a593Smuzhiyun     ruid = getuid();
1584*4882a593Smuzhiyun     euid = geteuid();
1585*4882a593Smuzhiyun 
1586*4882a593Smuzhiyun     if (seteuid(ruid) == -1) {
1587*4882a593Smuzhiyun         return NULL;
1588*4882a593Smuzhiyun     }
1589*4882a593Smuzhiyun     iop = fopen(file, type);
1590*4882a593Smuzhiyun 
1591*4882a593Smuzhiyun     if (seteuid(euid) == -1) {
1592*4882a593Smuzhiyun         fclose(iop);
1593*4882a593Smuzhiyun         return NULL;
1594*4882a593Smuzhiyun     }
1595*4882a593Smuzhiyun     return iop;
1596*4882a593Smuzhiyun #endif                          /* HAS_SAVED_IDS_AND_SETEUID */
1597*4882a593Smuzhiyun }
1598*4882a593Smuzhiyun 
1599*4882a593Smuzhiyun int
Pclose(void * iop)1600*4882a593Smuzhiyun Pclose(void *iop)
1601*4882a593Smuzhiyun {
1602*4882a593Smuzhiyun     struct pid *cur, *last;
1603*4882a593Smuzhiyun     int pstat;
1604*4882a593Smuzhiyun     int pid;
1605*4882a593Smuzhiyun 
1606*4882a593Smuzhiyun     DebugF("Pclose: fp = %p\n", iop);
1607*4882a593Smuzhiyun     fclose(iop);
1608*4882a593Smuzhiyun 
1609*4882a593Smuzhiyun     for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next)
1610*4882a593Smuzhiyun         if (cur->fp == iop)
1611*4882a593Smuzhiyun             break;
1612*4882a593Smuzhiyun     if (cur == NULL)
1613*4882a593Smuzhiyun         return -1;
1614*4882a593Smuzhiyun 
1615*4882a593Smuzhiyun     do {
1616*4882a593Smuzhiyun         pid = waitpid(cur->pid, &pstat, 0);
1617*4882a593Smuzhiyun     } while (pid == -1 && errno == EINTR);
1618*4882a593Smuzhiyun 
1619*4882a593Smuzhiyun     if (last == NULL)
1620*4882a593Smuzhiyun         pidlist = cur->next;
1621*4882a593Smuzhiyun     else
1622*4882a593Smuzhiyun         last->next = cur->next;
1623*4882a593Smuzhiyun     free(cur);
1624*4882a593Smuzhiyun 
1625*4882a593Smuzhiyun     /* allow EINTR again */
1626*4882a593Smuzhiyun     OsReleaseSignals();
1627*4882a593Smuzhiyun 
1628*4882a593Smuzhiyun #ifdef HAVE_SETITIMER
1629*4882a593Smuzhiyun     if (SmartScheduleEnable() < 0) {
1630*4882a593Smuzhiyun         perror("signal");
1631*4882a593Smuzhiyun         return -1;
1632*4882a593Smuzhiyun     }
1633*4882a593Smuzhiyun #endif
1634*4882a593Smuzhiyun 
1635*4882a593Smuzhiyun     return pid == -1 ? -1 : pstat;
1636*4882a593Smuzhiyun }
1637*4882a593Smuzhiyun 
1638*4882a593Smuzhiyun int
Fclose(void * iop)1639*4882a593Smuzhiyun Fclose(void *iop)
1640*4882a593Smuzhiyun {
1641*4882a593Smuzhiyun #ifdef HAS_SAVED_IDS_AND_SETEUID
1642*4882a593Smuzhiyun     return fclose(iop);
1643*4882a593Smuzhiyun #else
1644*4882a593Smuzhiyun     return Pclose(iop);
1645*4882a593Smuzhiyun #endif
1646*4882a593Smuzhiyun }
1647*4882a593Smuzhiyun 
1648*4882a593Smuzhiyun #endif                          /* !WIN32 */
1649*4882a593Smuzhiyun 
1650*4882a593Smuzhiyun #ifdef WIN32
1651*4882a593Smuzhiyun 
1652*4882a593Smuzhiyun #include <X11/Xwindows.h>
1653*4882a593Smuzhiyun 
1654*4882a593Smuzhiyun const char *
Win32TempDir(void)1655*4882a593Smuzhiyun Win32TempDir(void)
1656*4882a593Smuzhiyun {
1657*4882a593Smuzhiyun     static char buffer[PATH_MAX];
1658*4882a593Smuzhiyun 
1659*4882a593Smuzhiyun     if (GetTempPath(sizeof(buffer), buffer)) {
1660*4882a593Smuzhiyun         int len;
1661*4882a593Smuzhiyun 
1662*4882a593Smuzhiyun         buffer[sizeof(buffer) - 1] = 0;
1663*4882a593Smuzhiyun         len = strlen(buffer);
1664*4882a593Smuzhiyun         if (len > 0)
1665*4882a593Smuzhiyun             if (buffer[len - 1] == '\\')
1666*4882a593Smuzhiyun                 buffer[len - 1] = 0;
1667*4882a593Smuzhiyun         return buffer;
1668*4882a593Smuzhiyun     }
1669*4882a593Smuzhiyun     if (getenv("TEMP") != NULL)
1670*4882a593Smuzhiyun         return getenv("TEMP");
1671*4882a593Smuzhiyun     else if (getenv("TMP") != NULL)
1672*4882a593Smuzhiyun         return getenv("TMP");
1673*4882a593Smuzhiyun     else
1674*4882a593Smuzhiyun         return "/tmp";
1675*4882a593Smuzhiyun }
1676*4882a593Smuzhiyun 
1677*4882a593Smuzhiyun int
System(const char * cmdline)1678*4882a593Smuzhiyun System(const char *cmdline)
1679*4882a593Smuzhiyun {
1680*4882a593Smuzhiyun     STARTUPINFO si;
1681*4882a593Smuzhiyun     PROCESS_INFORMATION pi;
1682*4882a593Smuzhiyun     DWORD dwExitCode;
1683*4882a593Smuzhiyun     char *cmd = strdup(cmdline);
1684*4882a593Smuzhiyun 
1685*4882a593Smuzhiyun     ZeroMemory(&si, sizeof(si));
1686*4882a593Smuzhiyun     si.cb = sizeof(si);
1687*4882a593Smuzhiyun     ZeroMemory(&pi, sizeof(pi));
1688*4882a593Smuzhiyun 
1689*4882a593Smuzhiyun     if (!CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
1690*4882a593Smuzhiyun         LPVOID buffer;
1691*4882a593Smuzhiyun 
1692*4882a593Smuzhiyun         if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
1693*4882a593Smuzhiyun                            FORMAT_MESSAGE_FROM_SYSTEM |
1694*4882a593Smuzhiyun                            FORMAT_MESSAGE_IGNORE_INSERTS,
1695*4882a593Smuzhiyun                            NULL,
1696*4882a593Smuzhiyun                            GetLastError(),
1697*4882a593Smuzhiyun                            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
1698*4882a593Smuzhiyun                            (LPTSTR) &buffer, 0, NULL)) {
1699*4882a593Smuzhiyun             ErrorF("[xkb] Starting '%s' failed!\n", cmdline);
1700*4882a593Smuzhiyun         }
1701*4882a593Smuzhiyun         else {
1702*4882a593Smuzhiyun             ErrorF("[xkb] Starting '%s' failed: %s", cmdline, (char *) buffer);
1703*4882a593Smuzhiyun             LocalFree(buffer);
1704*4882a593Smuzhiyun         }
1705*4882a593Smuzhiyun 
1706*4882a593Smuzhiyun         free(cmd);
1707*4882a593Smuzhiyun         return -1;
1708*4882a593Smuzhiyun     }
1709*4882a593Smuzhiyun     /* Wait until child process exits. */
1710*4882a593Smuzhiyun     WaitForSingleObject(pi.hProcess, INFINITE);
1711*4882a593Smuzhiyun 
1712*4882a593Smuzhiyun     GetExitCodeProcess(pi.hProcess, &dwExitCode);
1713*4882a593Smuzhiyun 
1714*4882a593Smuzhiyun     /* Close process and thread handles. */
1715*4882a593Smuzhiyun     CloseHandle(pi.hProcess);
1716*4882a593Smuzhiyun     CloseHandle(pi.hThread);
1717*4882a593Smuzhiyun     free(cmd);
1718*4882a593Smuzhiyun 
1719*4882a593Smuzhiyun     return dwExitCode;
1720*4882a593Smuzhiyun }
1721*4882a593Smuzhiyun #endif
1722*4882a593Smuzhiyun 
1723*4882a593Smuzhiyun Bool
PrivsElevated(void)1724*4882a593Smuzhiyun PrivsElevated(void)
1725*4882a593Smuzhiyun {
1726*4882a593Smuzhiyun     static Bool privsTested = FALSE;
1727*4882a593Smuzhiyun     static Bool privsElevated = TRUE;
1728*4882a593Smuzhiyun 
1729*4882a593Smuzhiyun     if (!privsTested) {
1730*4882a593Smuzhiyun #if defined(WIN32)
1731*4882a593Smuzhiyun         privsElevated = FALSE;
1732*4882a593Smuzhiyun #else
1733*4882a593Smuzhiyun         if ((getuid() != geteuid()) || (getgid() != getegid())) {
1734*4882a593Smuzhiyun             privsElevated = TRUE;
1735*4882a593Smuzhiyun         }
1736*4882a593Smuzhiyun         else {
1737*4882a593Smuzhiyun #if defined(HAVE_ISSETUGID)
1738*4882a593Smuzhiyun             privsElevated = issetugid();
1739*4882a593Smuzhiyun #elif defined(HAVE_GETRESUID)
1740*4882a593Smuzhiyun             uid_t ruid, euid, suid;
1741*4882a593Smuzhiyun             gid_t rgid, egid, sgid;
1742*4882a593Smuzhiyun 
1743*4882a593Smuzhiyun             if ((getresuid(&ruid, &euid, &suid) == 0) &&
1744*4882a593Smuzhiyun                 (getresgid(&rgid, &egid, &sgid) == 0)) {
1745*4882a593Smuzhiyun                 privsElevated = (euid != suid) || (egid != sgid);
1746*4882a593Smuzhiyun             }
1747*4882a593Smuzhiyun             else {
1748*4882a593Smuzhiyun                 printf("Failed getresuid or getresgid");
1749*4882a593Smuzhiyun                 /* Something went wrong, make defensive assumption */
1750*4882a593Smuzhiyun                 privsElevated = TRUE;
1751*4882a593Smuzhiyun             }
1752*4882a593Smuzhiyun #else
1753*4882a593Smuzhiyun             if (getuid() == 0) {
1754*4882a593Smuzhiyun                 /* running as root: uid==euid==0 */
1755*4882a593Smuzhiyun                 privsElevated = FALSE;
1756*4882a593Smuzhiyun             }
1757*4882a593Smuzhiyun             else {
1758*4882a593Smuzhiyun                 /*
1759*4882a593Smuzhiyun                  * If there are saved ID's the process might still be privileged
1760*4882a593Smuzhiyun                  * even though the above test succeeded. If issetugid() and
1761*4882a593Smuzhiyun                  * getresgid() aren't available, test this by trying to set
1762*4882a593Smuzhiyun                  * euid to 0.
1763*4882a593Smuzhiyun                  */
1764*4882a593Smuzhiyun                 unsigned int oldeuid;
1765*4882a593Smuzhiyun 
1766*4882a593Smuzhiyun                 oldeuid = geteuid();
1767*4882a593Smuzhiyun 
1768*4882a593Smuzhiyun                 if (seteuid(0) != 0) {
1769*4882a593Smuzhiyun                     privsElevated = FALSE;
1770*4882a593Smuzhiyun                 }
1771*4882a593Smuzhiyun                 else {
1772*4882a593Smuzhiyun                     if (seteuid(oldeuid) != 0) {
1773*4882a593Smuzhiyun                         FatalError("Failed to drop privileges.  Exiting\n");
1774*4882a593Smuzhiyun                     }
1775*4882a593Smuzhiyun                     privsElevated = TRUE;
1776*4882a593Smuzhiyun                 }
1777*4882a593Smuzhiyun             }
1778*4882a593Smuzhiyun #endif
1779*4882a593Smuzhiyun         }
1780*4882a593Smuzhiyun #endif
1781*4882a593Smuzhiyun         privsTested = TRUE;
1782*4882a593Smuzhiyun     }
1783*4882a593Smuzhiyun     return privsElevated;
1784*4882a593Smuzhiyun }
1785*4882a593Smuzhiyun 
1786*4882a593Smuzhiyun /*
1787*4882a593Smuzhiyun  * CheckUserParameters: check for long command line arguments and long
1788*4882a593Smuzhiyun  * environment variables.  By default, these checks are only done when
1789*4882a593Smuzhiyun  * the server's euid != ruid.  In 3.3.x, these checks were done in an
1790*4882a593Smuzhiyun  * external wrapper utility.
1791*4882a593Smuzhiyun  */
1792*4882a593Smuzhiyun 
1793*4882a593Smuzhiyun /* Consider LD* variables insecure? */
1794*4882a593Smuzhiyun #ifndef REMOVE_ENV_LD
1795*4882a593Smuzhiyun #define REMOVE_ENV_LD 1
1796*4882a593Smuzhiyun #endif
1797*4882a593Smuzhiyun 
1798*4882a593Smuzhiyun /* Remove long environment variables? */
1799*4882a593Smuzhiyun #ifndef REMOVE_LONG_ENV
1800*4882a593Smuzhiyun #define REMOVE_LONG_ENV 1
1801*4882a593Smuzhiyun #endif
1802*4882a593Smuzhiyun 
1803*4882a593Smuzhiyun /*
1804*4882a593Smuzhiyun  * Disallow stdout or stderr as pipes?  It's possible to block the X server
1805*4882a593Smuzhiyun  * when piping stdout+stderr to a pipe.
1806*4882a593Smuzhiyun  *
1807*4882a593Smuzhiyun  * Don't enable this because it looks like it's going to cause problems.
1808*4882a593Smuzhiyun  */
1809*4882a593Smuzhiyun #ifndef NO_OUTPUT_PIPES
1810*4882a593Smuzhiyun #define NO_OUTPUT_PIPES 0
1811*4882a593Smuzhiyun #endif
1812*4882a593Smuzhiyun 
1813*4882a593Smuzhiyun /* Check args and env only if running setuid (euid == 0 && euid != uid) ? */
1814*4882a593Smuzhiyun #ifndef CHECK_EUID
1815*4882a593Smuzhiyun #ifndef WIN32
1816*4882a593Smuzhiyun #define CHECK_EUID 1
1817*4882a593Smuzhiyun #else
1818*4882a593Smuzhiyun #define CHECK_EUID 0
1819*4882a593Smuzhiyun #endif
1820*4882a593Smuzhiyun #endif
1821*4882a593Smuzhiyun 
1822*4882a593Smuzhiyun /*
1823*4882a593Smuzhiyun  * Maybe the locale can be faked to make isprint(3) report that everything
1824*4882a593Smuzhiyun  * is printable?  Avoid it by default.
1825*4882a593Smuzhiyun  */
1826*4882a593Smuzhiyun #ifndef USE_ISPRINT
1827*4882a593Smuzhiyun #define USE_ISPRINT 0
1828*4882a593Smuzhiyun #endif
1829*4882a593Smuzhiyun 
1830*4882a593Smuzhiyun #define MAX_ARG_LENGTH          128
1831*4882a593Smuzhiyun #define MAX_ENV_LENGTH          256
1832*4882a593Smuzhiyun #define MAX_ENV_PATH_LENGTH     2048    /* Limit for *PATH and TERMCAP */
1833*4882a593Smuzhiyun 
1834*4882a593Smuzhiyun #if USE_ISPRINT
1835*4882a593Smuzhiyun #include <ctype.h>
1836*4882a593Smuzhiyun #define checkPrintable(c) isprint(c)
1837*4882a593Smuzhiyun #else
1838*4882a593Smuzhiyun #define checkPrintable(c) (((c) & 0x7f) >= 0x20 && ((c) & 0x7f) != 0x7f)
1839*4882a593Smuzhiyun #endif
1840*4882a593Smuzhiyun 
1841*4882a593Smuzhiyun enum BadCode {
1842*4882a593Smuzhiyun     NotBad = 0,
1843*4882a593Smuzhiyun     UnsafeArg,
1844*4882a593Smuzhiyun     ArgTooLong,
1845*4882a593Smuzhiyun     UnprintableArg,
1846*4882a593Smuzhiyun     EnvTooLong,
1847*4882a593Smuzhiyun     OutputIsPipe,
1848*4882a593Smuzhiyun     InternalError
1849*4882a593Smuzhiyun };
1850*4882a593Smuzhiyun 
1851*4882a593Smuzhiyun #if defined(VENDORSUPPORT)
1852*4882a593Smuzhiyun #define BUGADDRESS VENDORSUPPORT
1853*4882a593Smuzhiyun #elif defined(BUILDERADDR)
1854*4882a593Smuzhiyun #define BUGADDRESS BUILDERADDR
1855*4882a593Smuzhiyun #else
1856*4882a593Smuzhiyun #define BUGADDRESS "xorg@freedesktop.org"
1857*4882a593Smuzhiyun #endif
1858*4882a593Smuzhiyun 
1859*4882a593Smuzhiyun void
CheckUserParameters(int argc,char ** argv,char ** envp)1860*4882a593Smuzhiyun CheckUserParameters(int argc, char **argv, char **envp)
1861*4882a593Smuzhiyun {
1862*4882a593Smuzhiyun     enum BadCode bad = NotBad;
1863*4882a593Smuzhiyun     int i = 0, j;
1864*4882a593Smuzhiyun     char *a, *e = NULL;
1865*4882a593Smuzhiyun 
1866*4882a593Smuzhiyun #if CHECK_EUID
1867*4882a593Smuzhiyun     if (PrivsElevated())
1868*4882a593Smuzhiyun #endif
1869*4882a593Smuzhiyun     {
1870*4882a593Smuzhiyun         /* Check each argv[] */
1871*4882a593Smuzhiyun         for (i = 1; i < argc; i++) {
1872*4882a593Smuzhiyun             if (strcmp(argv[i], "-fp") == 0) {
1873*4882a593Smuzhiyun                 i++;            /* continue with next argument. skip the length check */
1874*4882a593Smuzhiyun                 if (i >= argc)
1875*4882a593Smuzhiyun                     break;
1876*4882a593Smuzhiyun             }
1877*4882a593Smuzhiyun             else {
1878*4882a593Smuzhiyun                 if (strlen(argv[i]) > MAX_ARG_LENGTH) {
1879*4882a593Smuzhiyun                     bad = ArgTooLong;
1880*4882a593Smuzhiyun                     break;
1881*4882a593Smuzhiyun                 }
1882*4882a593Smuzhiyun             }
1883*4882a593Smuzhiyun             a = argv[i];
1884*4882a593Smuzhiyun             while (*a) {
1885*4882a593Smuzhiyun                 if (checkPrintable(*a) == 0) {
1886*4882a593Smuzhiyun                     bad = UnprintableArg;
1887*4882a593Smuzhiyun                     break;
1888*4882a593Smuzhiyun                 }
1889*4882a593Smuzhiyun                 a++;
1890*4882a593Smuzhiyun             }
1891*4882a593Smuzhiyun             if (bad)
1892*4882a593Smuzhiyun                 break;
1893*4882a593Smuzhiyun         }
1894*4882a593Smuzhiyun         if (!bad) {
1895*4882a593Smuzhiyun             /* Check each envp[] */
1896*4882a593Smuzhiyun             for (i = 0; envp[i]; i++) {
1897*4882a593Smuzhiyun 
1898*4882a593Smuzhiyun                 /* Check for bad environment variables and values */
1899*4882a593Smuzhiyun #if REMOVE_ENV_LD
1900*4882a593Smuzhiyun                 while (envp[i] && (strncmp(envp[i], "LD", 2) == 0)) {
1901*4882a593Smuzhiyun                     for (j = i; envp[j]; j++) {
1902*4882a593Smuzhiyun                         envp[j] = envp[j + 1];
1903*4882a593Smuzhiyun                     }
1904*4882a593Smuzhiyun                 }
1905*4882a593Smuzhiyun #endif
1906*4882a593Smuzhiyun                 if (envp[i] && (strlen(envp[i]) > MAX_ENV_LENGTH)) {
1907*4882a593Smuzhiyun #if REMOVE_LONG_ENV
1908*4882a593Smuzhiyun                     for (j = i; envp[j]; j++) {
1909*4882a593Smuzhiyun                         envp[j] = envp[j + 1];
1910*4882a593Smuzhiyun                     }
1911*4882a593Smuzhiyun                     i--;
1912*4882a593Smuzhiyun #else
1913*4882a593Smuzhiyun                     char *eq;
1914*4882a593Smuzhiyun                     int len;
1915*4882a593Smuzhiyun 
1916*4882a593Smuzhiyun                     eq = strchr(envp[i], '=');
1917*4882a593Smuzhiyun                     if (!eq)
1918*4882a593Smuzhiyun                         continue;
1919*4882a593Smuzhiyun                     len = eq - envp[i];
1920*4882a593Smuzhiyun                     e = strndup(envp[i], len);
1921*4882a593Smuzhiyun                     if (!e) {
1922*4882a593Smuzhiyun                         bad = InternalError;
1923*4882a593Smuzhiyun                         break;
1924*4882a593Smuzhiyun                     }
1925*4882a593Smuzhiyun                     if (len >= 4 &&
1926*4882a593Smuzhiyun                         (strcmp(e + len - 4, "PATH") == 0 ||
1927*4882a593Smuzhiyun                          strcmp(e, "TERMCAP") == 0)) {
1928*4882a593Smuzhiyun                         if (strlen(envp[i]) > MAX_ENV_PATH_LENGTH) {
1929*4882a593Smuzhiyun                             bad = EnvTooLong;
1930*4882a593Smuzhiyun                             break;
1931*4882a593Smuzhiyun                         }
1932*4882a593Smuzhiyun                         else {
1933*4882a593Smuzhiyun                             free(e);
1934*4882a593Smuzhiyun                         }
1935*4882a593Smuzhiyun                     }
1936*4882a593Smuzhiyun                     else {
1937*4882a593Smuzhiyun                         bad = EnvTooLong;
1938*4882a593Smuzhiyun                         break;
1939*4882a593Smuzhiyun                     }
1940*4882a593Smuzhiyun #endif
1941*4882a593Smuzhiyun                 }
1942*4882a593Smuzhiyun             }
1943*4882a593Smuzhiyun         }
1944*4882a593Smuzhiyun #if NO_OUTPUT_PIPES
1945*4882a593Smuzhiyun         if (!bad) {
1946*4882a593Smuzhiyun             struct stat buf;
1947*4882a593Smuzhiyun 
1948*4882a593Smuzhiyun             if (fstat(fileno(stdout), &buf) == 0 && S_ISFIFO(buf.st_mode))
1949*4882a593Smuzhiyun                 bad = OutputIsPipe;
1950*4882a593Smuzhiyun             if (fstat(fileno(stderr), &buf) == 0 && S_ISFIFO(buf.st_mode))
1951*4882a593Smuzhiyun                 bad = OutputIsPipe;
1952*4882a593Smuzhiyun         }
1953*4882a593Smuzhiyun #endif
1954*4882a593Smuzhiyun     }
1955*4882a593Smuzhiyun     switch (bad) {
1956*4882a593Smuzhiyun     case NotBad:
1957*4882a593Smuzhiyun         return;
1958*4882a593Smuzhiyun     case UnsafeArg:
1959*4882a593Smuzhiyun         ErrorF("Command line argument number %d is unsafe\n", i);
1960*4882a593Smuzhiyun         break;
1961*4882a593Smuzhiyun     case ArgTooLong:
1962*4882a593Smuzhiyun         ErrorF("Command line argument number %d is too long\n", i);
1963*4882a593Smuzhiyun         break;
1964*4882a593Smuzhiyun     case UnprintableArg:
1965*4882a593Smuzhiyun         ErrorF("Command line argument number %d contains unprintable"
1966*4882a593Smuzhiyun                " characters\n", i);
1967*4882a593Smuzhiyun         break;
1968*4882a593Smuzhiyun     case EnvTooLong:
1969*4882a593Smuzhiyun         ErrorF("Environment variable `%s' is too long\n", e);
1970*4882a593Smuzhiyun         break;
1971*4882a593Smuzhiyun     case OutputIsPipe:
1972*4882a593Smuzhiyun         ErrorF("Stdout and/or stderr is a pipe\n");
1973*4882a593Smuzhiyun         break;
1974*4882a593Smuzhiyun     case InternalError:
1975*4882a593Smuzhiyun         ErrorF("Internal Error\n");
1976*4882a593Smuzhiyun         break;
1977*4882a593Smuzhiyun     default:
1978*4882a593Smuzhiyun         ErrorF("Unknown error\n");
1979*4882a593Smuzhiyun         break;
1980*4882a593Smuzhiyun     }
1981*4882a593Smuzhiyun     FatalError("X server aborted because of unsafe environment\n");
1982*4882a593Smuzhiyun }
1983*4882a593Smuzhiyun 
1984*4882a593Smuzhiyun /*
1985*4882a593Smuzhiyun  * CheckUserAuthorization: check if the user is allowed to start the
1986*4882a593Smuzhiyun  * X server.  This usually means some sort of PAM checking, and it is
1987*4882a593Smuzhiyun  * usually only done for setuid servers (uid != euid).
1988*4882a593Smuzhiyun  */
1989*4882a593Smuzhiyun 
1990*4882a593Smuzhiyun #ifdef USE_PAM
1991*4882a593Smuzhiyun #include <security/pam_appl.h>
1992*4882a593Smuzhiyun #include <security/pam_misc.h>
1993*4882a593Smuzhiyun #include <pwd.h>
1994*4882a593Smuzhiyun #endif                          /* USE_PAM */
1995*4882a593Smuzhiyun 
1996*4882a593Smuzhiyun void
CheckUserAuthorization(void)1997*4882a593Smuzhiyun CheckUserAuthorization(void)
1998*4882a593Smuzhiyun {
1999*4882a593Smuzhiyun #ifdef USE_PAM
2000*4882a593Smuzhiyun     static struct pam_conv conv = {
2001*4882a593Smuzhiyun         misc_conv,
2002*4882a593Smuzhiyun         NULL
2003*4882a593Smuzhiyun     };
2004*4882a593Smuzhiyun 
2005*4882a593Smuzhiyun     pam_handle_t *pamh = NULL;
2006*4882a593Smuzhiyun     struct passwd *pw;
2007*4882a593Smuzhiyun     int retval;
2008*4882a593Smuzhiyun 
2009*4882a593Smuzhiyun     if (getuid() != geteuid()) {
2010*4882a593Smuzhiyun         pw = getpwuid(getuid());
2011*4882a593Smuzhiyun         if (pw == NULL)
2012*4882a593Smuzhiyun             FatalError("getpwuid() failed for uid %d\n", getuid());
2013*4882a593Smuzhiyun 
2014*4882a593Smuzhiyun         retval = pam_start("xserver", pw->pw_name, &conv, &pamh);
2015*4882a593Smuzhiyun         if (retval != PAM_SUCCESS)
2016*4882a593Smuzhiyun             FatalError("pam_start() failed.\n"
2017*4882a593Smuzhiyun                        "\tMissing or mangled PAM config file or module?\n");
2018*4882a593Smuzhiyun 
2019*4882a593Smuzhiyun         retval = pam_authenticate(pamh, 0);
2020*4882a593Smuzhiyun         if (retval != PAM_SUCCESS) {
2021*4882a593Smuzhiyun             pam_end(pamh, retval);
2022*4882a593Smuzhiyun             FatalError("PAM authentication failed, cannot start X server.\n"
2023*4882a593Smuzhiyun                        "\tPerhaps you do not have console ownership?\n");
2024*4882a593Smuzhiyun         }
2025*4882a593Smuzhiyun 
2026*4882a593Smuzhiyun         retval = pam_acct_mgmt(pamh, 0);
2027*4882a593Smuzhiyun         if (retval != PAM_SUCCESS) {
2028*4882a593Smuzhiyun             pam_end(pamh, retval);
2029*4882a593Smuzhiyun             FatalError("PAM authentication failed, cannot start X server.\n"
2030*4882a593Smuzhiyun                        "\tPerhaps you do not have console ownership?\n");
2031*4882a593Smuzhiyun         }
2032*4882a593Smuzhiyun 
2033*4882a593Smuzhiyun         /* this is not a session, so do not do session management */
2034*4882a593Smuzhiyun         pam_end(pamh, PAM_SUCCESS);
2035*4882a593Smuzhiyun     }
2036*4882a593Smuzhiyun #endif
2037*4882a593Smuzhiyun }
2038*4882a593Smuzhiyun 
2039*4882a593Smuzhiyun /*
2040*4882a593Smuzhiyun  * Tokenize a string into a NULL terminated array of strings. Always returns
2041*4882a593Smuzhiyun  * an allocated array unless an error occurs.
2042*4882a593Smuzhiyun  */
2043*4882a593Smuzhiyun char **
xstrtokenize(const char * str,const char * separators)2044*4882a593Smuzhiyun xstrtokenize(const char *str, const char *separators)
2045*4882a593Smuzhiyun {
2046*4882a593Smuzhiyun     char **list, **nlist;
2047*4882a593Smuzhiyun     char *tok, *tmp;
2048*4882a593Smuzhiyun     unsigned num = 0, n;
2049*4882a593Smuzhiyun 
2050*4882a593Smuzhiyun     if (!str)
2051*4882a593Smuzhiyun         return NULL;
2052*4882a593Smuzhiyun     list = calloc(1, sizeof(*list));
2053*4882a593Smuzhiyun     if (!list)
2054*4882a593Smuzhiyun         return NULL;
2055*4882a593Smuzhiyun     tmp = strdup(str);
2056*4882a593Smuzhiyun     if (!tmp)
2057*4882a593Smuzhiyun         goto error;
2058*4882a593Smuzhiyun     for (tok = strtok(tmp, separators); tok; tok = strtok(NULL, separators)) {
2059*4882a593Smuzhiyun         nlist = reallocarray(list, num + 2, sizeof(*list));
2060*4882a593Smuzhiyun         if (!nlist)
2061*4882a593Smuzhiyun             goto error;
2062*4882a593Smuzhiyun         list = nlist;
2063*4882a593Smuzhiyun         list[num] = strdup(tok);
2064*4882a593Smuzhiyun         if (!list[num])
2065*4882a593Smuzhiyun             goto error;
2066*4882a593Smuzhiyun         list[++num] = NULL;
2067*4882a593Smuzhiyun     }
2068*4882a593Smuzhiyun     free(tmp);
2069*4882a593Smuzhiyun     return list;
2070*4882a593Smuzhiyun 
2071*4882a593Smuzhiyun  error:
2072*4882a593Smuzhiyun     free(tmp);
2073*4882a593Smuzhiyun     for (n = 0; n < num; n++)
2074*4882a593Smuzhiyun         free(list[n]);
2075*4882a593Smuzhiyun     free(list);
2076*4882a593Smuzhiyun     return NULL;
2077*4882a593Smuzhiyun }
2078*4882a593Smuzhiyun 
2079*4882a593Smuzhiyun /* Format a signed number into a string in a signal safe manner. The string
2080*4882a593Smuzhiyun  * should be at least 21 characters in order to handle all int64_t values.
2081*4882a593Smuzhiyun  */
2082*4882a593Smuzhiyun void
FormatInt64(int64_t num,char * string)2083*4882a593Smuzhiyun FormatInt64(int64_t num, char *string)
2084*4882a593Smuzhiyun {
2085*4882a593Smuzhiyun     if (num < 0) {
2086*4882a593Smuzhiyun         string[0] = '-';
2087*4882a593Smuzhiyun         num *= -1;
2088*4882a593Smuzhiyun         string++;
2089*4882a593Smuzhiyun     }
2090*4882a593Smuzhiyun     FormatUInt64(num, string);
2091*4882a593Smuzhiyun }
2092*4882a593Smuzhiyun 
2093*4882a593Smuzhiyun /* Format a number into a string in a signal safe manner. The string should be
2094*4882a593Smuzhiyun  * at least 21 characters in order to handle all uint64_t values. */
2095*4882a593Smuzhiyun void
FormatUInt64(uint64_t num,char * string)2096*4882a593Smuzhiyun FormatUInt64(uint64_t num, char *string)
2097*4882a593Smuzhiyun {
2098*4882a593Smuzhiyun     uint64_t divisor;
2099*4882a593Smuzhiyun     int len;
2100*4882a593Smuzhiyun     int i;
2101*4882a593Smuzhiyun 
2102*4882a593Smuzhiyun     for (len = 1, divisor = 10;
2103*4882a593Smuzhiyun          len < 20 && num / divisor;
2104*4882a593Smuzhiyun          len++, divisor *= 10);
2105*4882a593Smuzhiyun 
2106*4882a593Smuzhiyun     for (i = len, divisor = 1; i > 0; i--, divisor *= 10)
2107*4882a593Smuzhiyun         string[i - 1] = '0' + ((num / divisor) % 10);
2108*4882a593Smuzhiyun 
2109*4882a593Smuzhiyun     string[len] = '\0';
2110*4882a593Smuzhiyun }
2111*4882a593Smuzhiyun 
2112*4882a593Smuzhiyun /**
2113*4882a593Smuzhiyun  * Format a double number as %.2f.
2114*4882a593Smuzhiyun  */
2115*4882a593Smuzhiyun void
FormatDouble(double dbl,char * string)2116*4882a593Smuzhiyun FormatDouble(double dbl, char *string)
2117*4882a593Smuzhiyun {
2118*4882a593Smuzhiyun     int slen = 0;
2119*4882a593Smuzhiyun     uint64_t frac;
2120*4882a593Smuzhiyun 
2121*4882a593Smuzhiyun     frac = (dbl > 0 ? dbl : -dbl) * 100.0 + 0.5;
2122*4882a593Smuzhiyun     frac %= 100;
2123*4882a593Smuzhiyun 
2124*4882a593Smuzhiyun     /* write decimal part to string */
2125*4882a593Smuzhiyun     if (dbl < 0 && dbl > -1)
2126*4882a593Smuzhiyun         string[slen++] = '-';
2127*4882a593Smuzhiyun     FormatInt64((int64_t)dbl, &string[slen]);
2128*4882a593Smuzhiyun 
2129*4882a593Smuzhiyun     while(string[slen] != '\0')
2130*4882a593Smuzhiyun         slen++;
2131*4882a593Smuzhiyun 
2132*4882a593Smuzhiyun     /* append fractional part, but only if we have enough characters. We
2133*4882a593Smuzhiyun      * expect string to be 21 chars (incl trailing \0) */
2134*4882a593Smuzhiyun     if (slen <= 17) {
2135*4882a593Smuzhiyun         string[slen++] = '.';
2136*4882a593Smuzhiyun         if (frac < 10)
2137*4882a593Smuzhiyun             string[slen++] = '0';
2138*4882a593Smuzhiyun 
2139*4882a593Smuzhiyun         FormatUInt64(frac, &string[slen]);
2140*4882a593Smuzhiyun     }
2141*4882a593Smuzhiyun }
2142*4882a593Smuzhiyun 
2143*4882a593Smuzhiyun 
2144*4882a593Smuzhiyun /* Format a number into a hexadecimal string in a signal safe manner. The string
2145*4882a593Smuzhiyun  * should be at least 17 characters in order to handle all uint64_t values. */
2146*4882a593Smuzhiyun void
FormatUInt64Hex(uint64_t num,char * string)2147*4882a593Smuzhiyun FormatUInt64Hex(uint64_t num, char *string)
2148*4882a593Smuzhiyun {
2149*4882a593Smuzhiyun     uint64_t divisor;
2150*4882a593Smuzhiyun     int len;
2151*4882a593Smuzhiyun     int i;
2152*4882a593Smuzhiyun 
2153*4882a593Smuzhiyun     for (len = 1, divisor = 0x10;
2154*4882a593Smuzhiyun          len < 16 && num / divisor;
2155*4882a593Smuzhiyun          len++, divisor *= 0x10);
2156*4882a593Smuzhiyun 
2157*4882a593Smuzhiyun     for (i = len, divisor = 1; i > 0; i--, divisor *= 0x10) {
2158*4882a593Smuzhiyun         int val = (num / divisor) % 0x10;
2159*4882a593Smuzhiyun 
2160*4882a593Smuzhiyun         if (val < 10)
2161*4882a593Smuzhiyun             string[i - 1] = '0' + val;
2162*4882a593Smuzhiyun         else
2163*4882a593Smuzhiyun             string[i - 1] = 'a' + val - 10;
2164*4882a593Smuzhiyun     }
2165*4882a593Smuzhiyun 
2166*4882a593Smuzhiyun     string[len] = '\0';
2167*4882a593Smuzhiyun }
2168*4882a593Smuzhiyun 
2169*4882a593Smuzhiyun #if !defined(WIN32) || defined(__CYGWIN__)
2170*4882a593Smuzhiyun /* Move a file descriptor out of the way of our select mask; this
2171*4882a593Smuzhiyun  * is useful for file descriptors which will never appear in the
2172*4882a593Smuzhiyun  * select mask to avoid reducing the number of clients that can
2173*4882a593Smuzhiyun  * connect to the server
2174*4882a593Smuzhiyun  */
2175*4882a593Smuzhiyun int
os_move_fd(int fd)2176*4882a593Smuzhiyun os_move_fd(int fd)
2177*4882a593Smuzhiyun {
2178*4882a593Smuzhiyun     int newfd;
2179*4882a593Smuzhiyun 
2180*4882a593Smuzhiyun #ifdef F_DUPFD_CLOEXEC
2181*4882a593Smuzhiyun     newfd = fcntl(fd, F_DUPFD_CLOEXEC, MAXCLIENTS);
2182*4882a593Smuzhiyun #else
2183*4882a593Smuzhiyun     newfd = fcntl(fd, F_DUPFD, MAXCLIENTS);
2184*4882a593Smuzhiyun #endif
2185*4882a593Smuzhiyun     if (newfd < 0)
2186*4882a593Smuzhiyun         return fd;
2187*4882a593Smuzhiyun #ifndef F_DUPFD_CLOEXEC
2188*4882a593Smuzhiyun     fcntl(newfd, F_SETFD, FD_CLOEXEC);
2189*4882a593Smuzhiyun #endif
2190*4882a593Smuzhiyun     close(fd);
2191*4882a593Smuzhiyun     return newfd;
2192*4882a593Smuzhiyun }
2193*4882a593Smuzhiyun #endif
2194