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