summaryrefslogtreecommitdiff
path: root/app/xfs/os/utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/xfs/os/utils.c')
-rw-r--r--app/xfs/os/utils.c575
1 files changed, 575 insertions, 0 deletions
diff --git a/app/xfs/os/utils.c b/app/xfs/os/utils.c
new file mode 100644
index 000000000..fcc1c2a06
--- /dev/null
+++ b/app/xfs/os/utils.c
@@ -0,0 +1,575 @@
+/* $Xorg: utils.c,v 1.4 2001/02/09 02:05:45 xorgcvs Exp $ */
+/*
+ * misc os utilities
+ */
+/*
+
+Copyright 1990, 1991, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+ * Copyright 1990, 1991 Network Computing Devices;
+ * Portions Copyright 1987 by Digital Equipment Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the names of Network Computing Devices, or Digital
+ * not be used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ *
+ * NETWORK COMPUTING DEVICES, AND DIGITAL DISCLAIM ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES,
+ * OR DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+ * THIS SOFTWARE.
+ */
+/* $XFree86: xc/programs/xfs/os/utils.c,v 3.20 2002/10/15 01:45:03 dawes Exp $ */
+
+#include <stdio.h>
+#include <X11/Xos.h>
+#include <stdlib.h>
+#include "misc.h"
+#include "globals.h"
+#include <signal.h>
+#ifdef MEMBUG
+#include <util/memleak/memleak.h>
+#endif
+#include <sys/wait.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <string.h>
+
+#ifndef X_NOT_POSIX
+#ifdef _POSIX_SOURCE
+#include <limits.h>
+#else
+#define _POSIX_SOURCE
+#include <limits.h>
+#undef _POSIX_SOURCE
+#endif
+#endif /* X_NOT_POSIX */
+#ifndef PATH_MAX
+#include <sys/param.h>
+#ifndef PATH_MAX
+#ifdef MAXPATHLEN
+#define PATH_MAX MAXPATHLEN
+#else
+#define PATH_MAX 1024
+#endif
+#endif
+#endif /* PATH_MAX */
+
+#if defined(X_NOT_POSIX) && (defined(SYSV) || defined(SVR4))
+#define SIGNALS_RESET_WHEN_CAUGHT
+#endif
+
+#include <stdlib.h>
+
+extern char *configfilename;
+static Bool dropPriv = FALSE; /* whether or not to drop root privileges */
+#ifdef DEFAULT_DAEMON
+static Bool becomeDaemon = TRUE; /* whether to become a daemon or not */
+#else
+static Bool becomeDaemon = FALSE; /* whether to become a daemon or not */
+#endif
+static const char *userId = NULL;
+char *progname;
+Bool CloneSelf;
+Bool portFromCmdline = FALSE;
+
+OldListenRec *OldListen = NULL;
+int OldListenCount = 0;
+
+#ifdef STDERR_FILENO
+# define WRITES write(STDERR_FILENO, s, strlen(s))
+#else
+# define WRITES write(fileno(stderr), s, strlen(s))
+#endif
+
+static char *pidFile = XFSPIDDIR "/xfs.pid";
+static int pidFd;
+static FILE *pidFilePtr;
+static int StorePid (void);
+
+/* ARGSUSED */
+SIGVAL
+AutoResetServer(int n)
+{
+ int olderrno = errno;
+
+#ifdef DEBUG
+ WRITES("got a reset signal\n");
+#endif
+
+ dispatchException |= DE_RESET;
+ isItTimeToYield = TRUE;
+
+#ifdef SIGNALS_RESET_WHEN_CAUGHT
+ signal(SIGHUP, AutoResetServer);
+#endif
+ errno = olderrno;
+}
+
+/* ARGSUSED */
+SIGVAL
+GiveUp(int n)
+{
+ int olderrno = errno;
+#ifdef DEBUG
+ WRITES("got a TERM signal\n");
+#endif
+
+ dispatchException |= DE_TERMINATE;
+ isItTimeToYield = TRUE;
+ errno = olderrno;
+}
+
+/* ARGSUSED */
+SIGVAL
+ServerReconfig(int n)
+{
+ int olderrno = errno;
+
+#ifdef DEBUG
+ WRITES("got a re-config signal\n");
+#endif
+
+ dispatchException |= DE_RECONFIG;
+ isItTimeToYield = TRUE;
+
+#ifdef SIGNALS_RESET_WHEN_CAUGHT
+ signal(SIGUSR1, ServerReconfig);
+#endif
+ errno = olderrno;
+}
+
+/* ARGSUSED */
+SIGVAL
+ServerCacheFlush(int n)
+{
+ int olderrno = errno;
+
+#ifdef DEBUG
+ WRITES("got a flush signal\n");
+#endif
+
+ dispatchException |= DE_FLUSH;
+ isItTimeToYield = TRUE;
+
+#ifdef SIGNALS_RESET_WHEN_CAUGHT
+ signal(SIGUSR2, ServerCacheFlush);
+#endif
+ errno = olderrno;
+}
+
+/* ARGSUSED */
+SIGVAL
+CleanupChild(int n)
+{
+ int olderrno = errno;
+
+#ifdef DEBUG
+ WRITES("got a child signal\n");
+#endif
+
+ wait(NULL);
+
+#ifdef SIGNALS_RESET_WHEN_CAUGHT
+ signal(SIGCHLD, CleanupChild);
+#endif
+ errno = olderrno;
+}
+
+long
+GetTimeInMillis(void)
+{
+ struct timeval tp;
+
+ X_GETTIMEOFDAY(&tp);
+ return ((tp.tv_sec * 1000) + (tp.tv_usec / 1000));
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: %s [-config config_file] [-port tcp_port] [-droppriv] [-daemon] [-nodaemon] [-user user_name] [-ls listen_socket]\n",
+ progname);
+ exit(1);
+}
+
+void
+OsInitAllocator (void)
+{
+#ifdef MEMBUG
+ CheckMemory ();
+#endif
+}
+
+
+/*
+ * The '-ls' option is used for cloning the font server.
+ *
+ * We expect a single string of the form...
+ *
+ * transport_id/fd/portnum[,transport_id/fd/portnum]...
+ *
+ * [] denotes optional and ... denotes repitition.
+ *
+ * The string must be _exactly_ in the above format.
+ */
+
+void
+ProcessLSoption (char *str)
+{
+ char *ptr = str;
+ char *slash;
+ char number[20];
+ int count = 0;
+ int len, i;
+
+ while (*ptr != '\0')
+ {
+ if (*ptr == ',')
+ count++;
+ ptr++;
+ }
+
+ OldListenCount = count + 1;
+ OldListen = (OldListenRec *) malloc (
+ OldListenCount * sizeof (OldListenRec));
+ if (OldListen == NULL) {
+ fprintf(stderr, "ProcessLSoption: malloc error\n");
+ exit(1);
+ }
+ ptr = str;
+
+ for (i = 0; i < OldListenCount; i++)
+ {
+ slash = (char *) strchr (ptr, '/');
+ if (slash == NULL) {
+ usage();
+ }
+ len = slash - ptr;
+ strncpy (number, ptr, len);
+ number[len] = '\0';
+ OldListen[i].trans_id = atoi (number);
+
+ ptr = slash + 1;
+
+ slash = (char *) strchr (ptr, '/');
+ if (slash == NULL) {
+ usage();
+ }
+ len = slash - ptr;
+ strncpy (number, ptr, len);
+ number[len] = '\0';
+ OldListen[i].fd = atoi (number);
+
+ ptr = slash + 1;
+
+ if (i == OldListenCount - 1)
+ OldListen[i].portnum = atoi (ptr);
+ else
+ {
+ char *comma = (char *) strchr (ptr, ',');
+ if (comma == NULL) {
+ usage();
+ }
+ len = comma - ptr;
+ strncpy (number, ptr, len);
+ number[len] = '\0';
+ OldListen[i].portnum = atoi (number);
+
+ ptr = comma + 1;
+ }
+ }
+}
+
+
+
+/* ARGSUSED */
+void
+ProcessCmdLine(int argc, char **argv)
+{
+ int i;
+
+ progname = argv[0];
+ for (i = 1; i < argc; i++) {
+ if (!strcmp(argv[i], "-port")) {
+ if (argv[i + 1]) {
+ ListenPort = atoi(argv[++i]);
+ portFromCmdline = TRUE;
+ } else
+ usage();
+ } else if (!strcmp(argv[i], "-ls")) {
+ if (argv[i + 1])
+ ProcessLSoption (argv[++i]);
+ else
+ usage();
+ } else if (!strcmp(argv[i], "-droppriv")) {
+ dropPriv = TRUE;
+ } else if (!strcmp(argv[i], "-daemon")) {
+ becomeDaemon = TRUE;
+ } else if (!strcmp(argv[i], "-nodaemon")) {
+ becomeDaemon = FALSE;
+ } else if (!strcmp(argv[i], "-user")) {
+ if (argv[i + 1])
+ userId = argv[++i];
+ else
+ usage();
+ } else if (!strcmp(argv[i], "-cf") || !strcmp(argv[i], "-config")) {
+ if (argv[i + 1])
+ configfilename = argv[++i];
+ else
+ usage();
+ }
+#ifdef MEMBUG
+ else if ( strcmp( argv[i], "-alloc") == 0)
+ {
+ extern unsigned long MemoryFail;
+ if(++i < argc)
+ MemoryFail = atoi(argv[i]);
+ else
+ usage ();
+ }
+#endif
+ else
+ usage();
+ }
+}
+
+
+#ifndef SPECIAL_MALLOC
+
+unsigned long Must_have_memory;
+
+#ifdef MEMBUG
+#define MEM_FAIL_SCALE 100000
+unsigned long MemoryFail;
+
+#endif
+
+/* FSalloc -- FS's internal memory allocator. Why does it return unsigned
+ * int * instead of the more common char *? Well, if you read K&R you'll
+ * see they say that alloc must return a pointer "suitable for conversion"
+ * to whatever type you really want. In a full-blown generic allocator
+ * there's no way to solve the alignment problems without potentially
+ * wasting lots of space. But we have a more limited problem. We know
+ * we're only ever returning pointers to structures which will have to
+ * be long word aligned. So we are making a stronger guarantee. It might
+ * have made sense to make FSalloc return char * to conform with people's
+ * expectations of malloc, but this makes lint happier.
+ */
+
+pointer
+FSalloc (unsigned long amount)
+{
+ register pointer ptr;
+
+ if ((long)amount < 0)
+ return 0;
+ if (amount == 0)
+ amount++;
+ /* aligned extra on long word boundary */
+ amount = (amount + 3) & ~3;
+#ifdef MEMBUG
+ if (!Must_have_memory && MemoryFail &&
+ ((random() % MEM_FAIL_SCALE) < MemoryFail))
+ return 0;
+ if (ptr = (pointer)fmalloc(amount))
+ return ptr;
+#else
+ if ((ptr = (pointer)malloc(amount)) != 0)
+ return ptr;
+#endif
+ if (Must_have_memory)
+ FatalError("out of memory\n");
+ return 0;
+}
+
+/*****************
+ * FScalloc
+ *****************/
+
+pointer
+FScalloc (unsigned long amount)
+{
+ pointer ret;
+
+ ret = FSalloc (amount);
+ if (ret)
+ bzero ((char *) ret, (int) amount);
+ return ret;
+}
+
+/*****************
+ * FSrealloc
+ *****************/
+
+pointer
+FSrealloc (pointer ptr, unsigned long amount)
+{
+#ifdef MEMBUG
+ if (!Must_have_memory && MemoryFail &&
+ ((random() % MEM_FAIL_SCALE) < MemoryFail))
+ return 0;
+ ptr = (pointer)frealloc((char *) ptr, amount);
+ if (ptr)
+ return ptr;
+#else
+ if ((long)amount <= 0)
+ {
+ if (ptr && !amount)
+ free(ptr);
+ return 0;
+ }
+ amount = (amount + 3) & ~3;
+ if (ptr)
+ ptr = (pointer)realloc((char *)ptr, amount);
+ else
+ ptr = (pointer)malloc(amount);
+ if (ptr)
+ return ptr;
+#endif
+ if (Must_have_memory)
+ FatalError("out of memory\n");
+ return 0;
+}
+
+/*****************
+ * FSfree
+ * calls free
+ *****************/
+
+void
+FSfree(pointer ptr)
+{
+#ifdef MEMBUG
+ if (ptr)
+ ffree((char *)ptr);
+#else
+ if (ptr)
+ free((char *)ptr);
+#endif
+}
+
+#endif /* SPECIAL_MALLOC */
+
+
+void
+SetUserId(void)
+{
+ /* become xfs user (or other specified on command line) if possible */
+ if ((geteuid() == 0) && (dropPriv || userId)) {
+ const char *user;
+ struct passwd *pwent;
+
+ if (!userId)
+ user = "xfs";
+ else
+ user = userId;
+ pwent = getpwnam(user);
+ if (pwent) {
+ if (setgid(pwent->pw_gid)) {
+ FatalError("fatal: couldn't set groupid to xfs user's group\n");
+ }
+#ifndef QNX4
+#ifndef __CYGWIN__
+ if (setgroups(0, NULL)) {
+ FatalError("fatal: couldn't drop supplementary groups\n");
+ }
+#endif
+ if (initgroups(user, pwent->pw_gid)) {
+ FatalError("fatal: couldn't init supplementary groups\n");
+ }
+#endif /* QNX4 */
+ if (setuid(pwent->pw_uid)) {
+ FatalError("fatal: couldn't set userid to %s user\n", user);
+ }
+ }
+ } else if (dropPriv || userId) {
+ FatalError("fatal: -droppriv or -user flag specified, but xfs not run as root\n");
+ }
+}
+
+
+void
+SetDaemonState(void)
+{
+ int oldpid;
+
+ if (becomeDaemon) {
+ BecomeDaemon();
+ if ((oldpid = StorePid ())) {
+ if (oldpid == -1)
+ ErrorF ("error opening process-id file %s\n", pidFile);
+ else
+ ErrorF ("process-id file %s indicates another xfs is "
+ "running (pid %d); exiting\n", pidFile, oldpid);
+ exit(1);
+ }
+ }
+}
+
+
+static int
+StorePid (void)
+{
+ int oldpid;
+
+ if (pidFile[0] != '\0') {
+ pidFd = open (pidFile, O_RDWR);
+ if (pidFd == -1 && errno == ENOENT)
+ pidFd = open (pidFile, O_RDWR|O_CREAT, 0666);
+ if (pidFd == -1 || !(pidFilePtr = fdopen (pidFd, "r+")))
+ {
+ ErrorF ("cannot open process-id file %s: %s\n", pidFile,
+ strerror (errno));
+ return -1;
+ }
+ if (fscanf (pidFilePtr, "%d\n", &oldpid) != 1)
+ oldpid = -1;
+ if (fseek (pidFilePtr, 0L, SEEK_SET) == -1)
+ {
+ ErrorF ("cannot seek process-id file %s: %s\n", pidFile,
+ strerror (errno));
+ return -1;
+ }
+ if (fprintf (pidFilePtr, "%5ld\n", (long) getpid ()) != 6)
+ {
+ ErrorF ("cannot write to process-id file %s: %s\n", pidFile,
+ strerror (errno));
+ return -1;
+ }
+ (void) fflush (pidFilePtr);
+ (void) fclose (pidFilePtr);
+ }
+ return 0;
+}