1/***********************************************************
2
3Copyright 1987, 1998  The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from The Open Group.
24
25
26Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
27
28                        All Rights Reserved
29
30Permission to use, copy, modify, and distribute this software and its
31documentation for any purpose and without fee is hereby granted,
32provided that the above copyright notice appear in all copies and that
33both that copyright notice and this permission notice appear in
34supporting documentation, and that the name of Digital not be
35used in advertising or publicity pertaining to distribution of the
36software without specific, written prior permission.
37
38DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
39ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
40DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
41ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
42WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
43ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
44SOFTWARE.
45
46******************************************************************/
47
48#ifdef HAVE_DIX_CONFIG_H
49#include <dix-config.h>
50#endif
51
52#include <stdio.h>
53#include <X11/X.h>
54#include "os.h"
55#include "osdep.h"
56#include <X11/Xos.h>
57#include <signal.h>
58#include <errno.h>
59#ifdef HAVE_DLFCN_H
60# include <dlfcn.h>
61#endif
62#ifdef HAVE_BACKTRACE
63#include <execinfo.h>
64#endif
65
66
67#include "dixstruct.h"
68
69#ifndef PATH_MAX
70#ifdef MAXPATHLEN
71#define PATH_MAX MAXPATHLEN
72#else
73#define PATH_MAX 1024
74#endif
75#endif
76
77
78#if !defined(SYSV) && !defined(WIN32)
79#include <sys/resource.h>
80#endif
81
82#ifndef ADMPATH
83#define ADMPATH "/usr/adm/X%smsgs"
84#endif
85
86extern char *display;
87#ifdef RLIMIT_DATA
88int limitDataSpace = -1;
89#endif
90#ifdef RLIMIT_STACK
91int limitStackSpace = -1;
92#endif
93#ifdef RLIMIT_NOFILE
94int limitNoFile = -1;
95#endif
96
97static OsSigWrapperPtr OsSigWrapper = NULL;
98
99OsSigWrapperPtr
100OsRegisterSigWrapper(OsSigWrapperPtr newSigWrapper)
101{
102    OsSigWrapperPtr oldSigWrapper = OsSigWrapper;
103
104    OsSigWrapper = newSigWrapper;
105
106    return oldSigWrapper;
107}
108
109/*
110 * OsSigHandler --
111 *    Catch unexpected signals and exit or continue cleanly.
112 */
113static void
114#ifdef SA_SIGINFO
115OsSigHandler(int signo, siginfo_t *sip, void *unused)
116#else
117OsSigHandler(int signo)
118#endif
119{
120#ifdef RTLD_DI_SETSIGNAL
121  const char *dlerr = dlerror();
122
123  if (dlerr) {
124      LogMessage(X_ERROR, "Dynamic loader error: %s\n", dlerr);
125  }
126#endif /* RTLD_DI_SETSIGNAL */
127
128  if (OsSigWrapper != NULL) {
129      if (OsSigWrapper(signo) == 0) {
130	  /* ddx handled signal and wants us to continue */
131	  return;
132      }
133  }
134
135  /* log, cleanup, and abort */
136  xorg_backtrace();
137
138#ifdef SA_SIGINFO
139  if (sip->si_code == SI_USER) {
140      ErrorF("Recieved signal %d sent by process %ld, uid %ld\n",
141	     signo, (long) sip->si_pid, (long) sip->si_uid);
142  } else {
143      switch (signo) {
144          case SIGSEGV:
145          case SIGBUS:
146          case SIGILL:
147          case SIGFPE:
148	      ErrorF("%s at address %p\n", strsignal(signo), sip->si_addr);
149      }
150  }
151#endif
152
153  FatalError("Caught signal %d (%s). Server aborting\n",
154	     signo, strsignal(signo));
155}
156
157void
158OsInit(void)
159{
160    static Bool been_here = FALSE;
161    static char* devnull = "/dev/null";
162    char fname[PATH_MAX];
163
164    if (!been_here) {
165	struct sigaction act, oact;
166	int i;
167	int siglist[] = { SIGSEGV, SIGQUIT, SIGILL, SIGFPE, SIGBUS,
168			  SIGSYS,
169			  SIGXCPU,
170			  SIGXFSZ,
171#ifdef SIGEMT
172			  SIGEMT,
173#endif
174			  0 /* must be last */ };
175	sigemptyset(&act.sa_mask);
176#ifdef SA_SIGINFO
177	act.sa_sigaction = OsSigHandler;
178	act.sa_flags = SA_SIGINFO;
179#else
180        act.sa_handler = OsSigHandler;
181        act.sa_flags = 0;
182#endif
183	for (i = 0; siglist[i] != 0; i++) {
184	    if (sigaction(siglist[i], &act, &oact)) {
185		ErrorF("failed to install signal handler for signal %d: %s\n",
186		       siglist[i], strerror(errno));
187	    }
188	}
189#ifdef HAVE_BACKTRACE
190	/*
191	 * initialize the backtracer, since the ctor calls dlopen(), which
192	 * calls malloc(), which isn't signal-safe.
193	 */
194	do {
195	    void *array;
196	    backtrace(&array, 1);
197	} while (0);
198#endif
199
200#ifdef RTLD_DI_SETSIGNAL
201	/* Tell runtime linker to send a signal we can catch instead of SIGKILL
202	 * for failures to load libraries/modules at runtime so we can clean up
203	 * after ourselves.
204	 */
205	int failure_signal = SIGQUIT;
206	dlinfo(RTLD_SELF, RTLD_DI_SETSIGNAL, &failure_signal);
207#endif
208
209#if !defined(__CYGWIN__)
210	fclose(stdin);
211	fclose(stdout);
212#endif
213	/*
214	 * If a write of zero bytes to stderr returns non-zero, i.e. -1,
215	 * then writing to stderr failed, and we'll write somewhere else
216	 * instead. (Apparently this never happens in the Real World.)
217	 */
218	if (write (2, fname, 0) == -1)
219	{
220	    FILE *err;
221
222	    if (strlen (display) + strlen (ADMPATH) + 1 < sizeof fname)
223		sprintf (fname, ADMPATH, display);
224	    else
225		strcpy (fname, devnull);
226	    /*
227	     * uses stdio to avoid os dependencies here,
228	     * a real os would use
229 	     *  open (fname, O_WRONLY|O_APPEND|O_CREAT, 0666)
230	     */
231	    if (!(err = fopen (fname, "a+")))
232		err = fopen (devnull, "w");
233	    if (err && (fileno(err) != 2)) {
234		dup2 (fileno (err), 2);
235		fclose (err);
236	    }
237#if defined(SYSV) || defined(SVR4) || defined(WIN32) || defined(__CYGWIN__)
238	    {
239	    static char buf[BUFSIZ];
240	    setvbuf (stderr, buf, _IOLBF, BUFSIZ);
241	    }
242#else
243	    setlinebuf(stderr);
244#endif
245	}
246
247	if (getpgrp () == 0)
248	    setpgid (0, 0);
249
250#ifdef RLIMIT_DATA
251	if (limitDataSpace >= 0)
252	{
253	    struct rlimit	rlim;
254
255	    if (!getrlimit(RLIMIT_DATA, &rlim))
256	    {
257		if ((limitDataSpace > 0) && (limitDataSpace < rlim.rlim_max))
258		    rlim.rlim_cur = limitDataSpace;
259		else
260		    rlim.rlim_cur = rlim.rlim_max;
261		(void)setrlimit(RLIMIT_DATA, &rlim);
262	    }
263	}
264#endif
265#ifdef RLIMIT_STACK
266	if (limitStackSpace >= 0)
267	{
268	    struct rlimit	rlim;
269
270	    if (!getrlimit(RLIMIT_STACK, &rlim))
271	    {
272		if ((limitStackSpace > 0) && (limitStackSpace < rlim.rlim_max))
273		    rlim.rlim_cur = limitStackSpace;
274		else
275		    rlim.rlim_cur = rlim.rlim_max;
276		(void)setrlimit(RLIMIT_STACK, &rlim);
277	    }
278	}
279#endif
280#ifdef RLIMIT_NOFILE
281	if (limitNoFile >= 0)
282	{
283	    struct rlimit	rlim;
284
285	    if (!getrlimit(RLIMIT_NOFILE, &rlim))
286	    {
287		if ((limitNoFile > 0) && (limitNoFile < rlim.rlim_max))
288		    rlim.rlim_cur = limitNoFile;
289		else
290		    rlim.rlim_cur = rlim.rlim_max;
291		(void)setrlimit(RLIMIT_NOFILE, &rlim);
292	    }
293	}
294#endif
295	LockServer();
296	been_here = TRUE;
297    }
298    TimerInit();
299    OsVendorInit();
300    /*
301     * No log file by default.  OsVendorInit() should call LogInit() with the
302     * log file name if logging to a file is desired.
303     */
304    LogInit(NULL, NULL);
305    SmartScheduleInit ();
306}
307
308void
309OsCleanup(Bool terminating)
310{
311    if (terminating)
312    {
313	UnlockServer();
314    }
315}
316