summaryrefslogtreecommitdiff
path: root/os/utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'os/utils.c')
-rw-r--r--os/utils.c271
1 files changed, 202 insertions, 69 deletions
diff --git a/os/utils.c b/os/utils.c
index 30c9f4f..4dc46a1 100644
--- a/os/utils.c
+++ b/os/utils.c
@@ -46,15 +46,25 @@ in this Software without prior written authorization from The Open Group.
* 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
@@ -76,32 +86,46 @@ in this Software without prior written authorization from The Open Group.
#endif
#endif /* PATH_MAX */
-#ifdef SIGNALRETURNSINT
-#define SIGVAL int
-#else
-#define SIGVAL void
-#endif
-
#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;
-extern int ListenPort;
+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(n)
- int n;
+AutoResetServer(int n)
{
+ int olderrno = errno;
#ifdef DEBUG
- fprintf(stderr, "got a reset signal\n");
+ WRITES("got a reset signal\n");
#endif
dispatchException |= DE_RESET;
@@ -110,28 +134,31 @@ AutoResetServer(n)
#ifdef SIGNALS_RESET_WHEN_CAUGHT
signal(SIGHUP, AutoResetServer);
#endif
+ errno = olderrno;
}
+/* ARGSUSED */
SIGVAL
-GiveUp()
+GiveUp(int n)
{
-
+ int olderrno = errno;
#ifdef DEBUG
- fprintf(stderr, "got a TERM signal\n");
+ WRITES("got a TERM signal\n");
#endif
dispatchException |= DE_TERMINATE;
isItTimeToYield = TRUE;
+ errno = olderrno;
}
/* ARGSUSED */
SIGVAL
-ServerReconfig(n)
- int n;
+ServerReconfig(int n)
{
+ int olderrno = errno;
#ifdef DEBUG
- fprintf(stderr, "got a re-config signal\n");
+ WRITES("got a re-config signal\n");
#endif
dispatchException |= DE_RECONFIG;
@@ -140,16 +167,17 @@ ServerReconfig(n)
#ifdef SIGNALS_RESET_WHEN_CAUGHT
signal(SIGUSR1, ServerReconfig);
#endif
+ errno = olderrno;
}
/* ARGSUSED */
SIGVAL
-ServerCacheFlush(n)
- int n;
+ServerCacheFlush(int n)
{
+ int olderrno = errno;
#ifdef DEBUG
- fprintf(stderr, "got a flush signal\n");
+ WRITES("got a flush signal\n");
#endif
dispatchException |= DE_FLUSH;
@@ -158,16 +186,17 @@ ServerCacheFlush(n)
#ifdef SIGNALS_RESET_WHEN_CAUGHT
signal(SIGUSR2, ServerCacheFlush);
#endif
+ errno = olderrno;
}
/* ARGSUSED */
SIGVAL
-CleanupChild(n)
- int n;
+CleanupChild(int n)
{
+ int olderrno = errno;
#ifdef DEBUG
- fprintf(stderr, "got a child signal\n");
+ WRITES("got a child signal\n");
#endif
wait(NULL);
@@ -175,10 +204,11 @@ CleanupChild(n)
#ifdef SIGNALS_RESET_WHEN_CAUGHT
signal(SIGCHLD, CleanupChild);
#endif
+ errno = olderrno;
}
long
-GetTimeInMillis()
+GetTimeInMillis(void)
{
struct timeval tp;
@@ -187,14 +217,15 @@ GetTimeInMillis()
}
static void
-usage()
+usage(void)
{
- fprintf(stderr, "usage: %s [-config config_file] [-port tcp_port]\n",
+ fprintf(stderr, "usage: %s [-config config_file] [-port tcp_port] [-droppriv] [-daemon] [-nodaemon] [-user user_name] [-ls listen_socket]\n",
progname);
exit(1);
}
-OsInitAllocator ()
+void
+OsInitAllocator (void)
{
#ifdef MEMBUG
CheckMemory ();
@@ -211,19 +242,14 @@ OsInitAllocator ()
*
* [] denotes optional and ... denotes repitition.
*
- * The string must be _exactly_ in the above format. Since this is
- * an internal option used by the font server, it's ok to be strict
- * about the format of the string.
+ * The string must be _exactly_ in the above format.
*/
void
-ProcessLSoption (str)
-
-char *str;
-
+ProcessLSoption (char *str)
{
char *ptr = str;
- char *slash, *next;
+ char *slash;
char number[20];
int count = 0;
int len, i;
@@ -238,12 +264,18 @@ char *str;
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';
@@ -252,6 +284,9 @@ char *str;
ptr = slash + 1;
slash = (char *) strchr (ptr, '/');
+ if (slash == NULL) {
+ usage();
+ }
len = slash - ptr;
strncpy (number, ptr, len);
number[len] = '\0';
@@ -264,7 +299,9 @@ char *str;
else
{
char *comma = (char *) strchr (ptr, ',');
-
+ if (comma == NULL) {
+ usage();
+ }
len = comma - ptr;
strncpy (number, ptr, len);
number[len] = '\0';
@@ -279,24 +316,34 @@ char *str;
/* ARGSUSED */
void
-ProcessCmdLine(argc, argv)
- int argc;
- char **argv;
+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])
+ if (argv[i + 1]) {
ListenPort = atoi(argv[++i]);
- else
+ 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];
@@ -341,14 +388,13 @@ unsigned long MemoryFail;
* expectations of malloc, but this makes lint happier.
*/
-unsigned long *
-FSalloc (amount)
- unsigned long amount;
+pointer
+FSalloc (unsigned long amount)
{
register pointer ptr;
if ((long)amount < 0)
- return (unsigned long *)NULL;
+ return 0;
if (amount == 0)
amount++;
/* aligned extra on long word boundary */
@@ -356,27 +402,26 @@ FSalloc (amount)
#ifdef MEMBUG
if (!Must_have_memory && MemoryFail &&
((random() % MEM_FAIL_SCALE) < MemoryFail))
- return (unsigned long *)NULL;
+ return 0;
if (ptr = (pointer)fmalloc(amount))
- return (unsigned long *) ptr;
+ return ptr;
#else
- if (ptr = (pointer)malloc(amount))
- return (unsigned long *)ptr;
+ if ((ptr = (pointer)malloc(amount)) != 0)
+ return ptr;
#endif
if (Must_have_memory)
- FatalError("Out of memory\n");
- return (unsigned long *)NULL;
+ FatalError("out of memory\n");
+ return 0;
}
/*****************
* FScalloc
*****************/
-unsigned long *
-FScalloc (amount)
- unsigned long amount;
+pointer
+FScalloc (unsigned long amount)
{
- unsigned long *ret;
+ pointer ret;
ret = FSalloc (amount);
if (ret)
@@ -388,26 +433,22 @@ FScalloc (amount)
* FSrealloc
*****************/
-unsigned long *
-FSrealloc (ptr, amount)
- register pointer ptr;
- unsigned long amount;
+pointer
+FSrealloc (pointer ptr, unsigned long amount)
{
- char *realloc();
-
#ifdef MEMBUG
if (!Must_have_memory && MemoryFail &&
((random() % MEM_FAIL_SCALE) < MemoryFail))
- return (unsigned long *)NULL;
+ return 0;
ptr = (pointer)frealloc((char *) ptr, amount);
if (ptr)
- return (unsigned long *) ptr;
+ return ptr;
#else
if ((long)amount <= 0)
{
if (ptr && !amount)
free(ptr);
- return (unsigned long *)NULL;
+ return 0;
}
amount = (amount + 3) & ~3;
if (ptr)
@@ -415,11 +456,11 @@ FSrealloc (ptr, amount)
else
ptr = (pointer)malloc(amount);
if (ptr)
- return (unsigned long *)ptr;
+ return ptr;
#endif
if (Must_have_memory)
- FatalError("Out of memory\n");
- return (unsigned long *)NULL;
+ FatalError("out of memory\n");
+ return 0;
}
/*****************
@@ -428,8 +469,7 @@ FSrealloc (ptr, amount)
*****************/
void
-FSfree(ptr)
- register pointer ptr;
+FSfree(pointer ptr)
{
#ifdef MEMBUG
if (ptr)
@@ -441,3 +481,96 @@ FSfree(ptr)
}
#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) {
+ BecomeOrphan();
+ 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;
+}