diff options
author | George Lebl <jirka@5z.com> | 2001-08-22 23:11:55 +0000 |
---|---|---|
committer | George Lebl <jirka@src.gnome.org> | 2001-08-22 23:11:55 +0000 |
commit | 6addcb9098b45bf43074de34157812c77822bd4d (patch) | |
tree | 215d0a2ea5a97551314fafdb66a16e013bf977f0 /utils/gdmopen.c | |
parent | 2ea344ca665dbe6faa9d6058ed989ff59eb8d8e7 (diff) | |
download | gdm-6addcb9098b45bf43074de34157812c77822bd4d.tar.gz |
Add two new small sbin utils. gdmopen is like open (based on it) but
Wed Aug 22 23:01:59 2001 George Lebl <jirka@5z.com>
* configure.in, Makefile.am, utils/gdmopen.c, utils/gdmaskpass.c:
Add two new small sbin utils. gdmopen is like open (based on it)
but better suited for gdm. Exitcode is returned so no temp files
are needed. Process is cleaned up on a signal, the new vt is
deallocated after use. And unlike openvt this thing actually waits
for the child. Gdmaskpass just asks for the root password, for
use in the XKeepsCrashing script. Both of these things will only
run as root as I'm too paranoid and it doesn't make sense for
them to run otherwise for gdm anyway.
* configure.in: Fix sbin expansion.
* daemon/gdm.c, daemon/misc.[ch], daemon/slave.c, daemon/server.c:
Use gdmopen to run dialog and add helper functions for doing this.
* daemon/gdm.h, daemon/slave.c, daemon/server.[ch]: When a server is
busy, ask the user if we want to run it on a new display number
or retry.
* daemon/gdm.c, daemon/misc.c, daemon/slave.c: Make sure to whack
any extra helper processes we launch when we are killed so that
we don't leave things like 'dialog' processes around
* daemon/gdm.c, config/XKeepsCrashing: Use gdmaskpass, ask if
the user wants to view X logs if X is crashing. And use gdmopen
in the script and correctly abort with exit 32. Also make it
not use the ugly tempfile stuff (Though a tempfile is still given
to the script for now)
* gdm.spec.in: raise epoch to 1, people abuse this field, and if they
do abuse it again and raise it beyond 1, I'll just max it out since
it makes package upgrading not work.
* daemon/slave.c, daemon/verify-(pam|crypt|shadow).c: add
/sbin/nologin as a thing to test for for disabled logins in
addition to /bin/false and /bin/true (it worked, but this adds a
nicer message)
* daemon/xdmcp.c: fix a warning.
* gui/gdmflexiserver.desktop.in: kill TryExec here
Diffstat (limited to 'utils/gdmopen.c')
-rw-r--r-- | utils/gdmopen.c | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/utils/gdmopen.c b/utils/gdmopen.c new file mode 100644 index 00000000..d5c8574d --- /dev/null +++ b/utils/gdmopen.c @@ -0,0 +1,201 @@ +/* + * gdmopen.c by the Queen of England, based upon original open. + * Simplified for the purposes of gdm. All useless (to me) + * functionality stripped. Also returns what the command returns. + * Return of 66 means error with open. + * + * Original header: + * + * open.c open a vt to run a new command (or shell). + * + * Copyright (c) 1994 by Jon Tombs <jon@gtex02.us.es> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include "config.h" +#include <stdio.h> +#include <signal.h> +#include <unistd.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <dirent.h> +#include <pwd.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <sys/vt.h> +#include <sys/types.h> +#include <sys/wait.h> + +#ifndef FALSE +#define FALSE 0 +#define TRUE !FALSE +#endif + + +/* + * Where your VTs are hidden + */ +#ifdef __linux__ +#define VTNAME "/dev/tty%d" +#endif + +#ifdef ESIX_5_3_2_D +#define VTBASE "/dev/vt%02d" +#endif + +const char *GDMOPENversion = "gdmopen " VERSION " simplified (was: open: 1.4 (c) Jon Tombs 1994)"; + +#ifndef VTNAME +#error vt device name must be defined in open.c +#endif + +static pid_t child_pid = -1; +struct vt_stat vt; +static int vtno; +static int fd = 0; +static int do_dealloc = FALSE; + +static void +sighandler (int sig) +{ + if (child_pid > 1) { + if (kill (child_pid, sig) == 0) + waitpid (child_pid, NULL, 0); + } + + if (do_dealloc) { + /* Switch back... */ + (void) ioctl(fd, VT_ACTIVATE, vt.v_active); + /* wait to be really sure we have switched */ + (void) ioctl(fd, VT_WAITACTIVE, vt.v_active); + + /* Now deallocate our new one */ + (void) ioctl(fd, VT_DISALLOCATE, vtno); + } + + /* Kill myself with this signal */ + signal (sig, SIG_DFL); + kill (getpid (), sig); +} + +int +main (int argc, char *argv[]) +{ + char vtname[256]; + int status; + + if (getuid () != geteuid () || + getuid () != 0) { + fprintf (stderr, "gdmopen: Only root wants to run me\n"); + return 66; + } + + signal (SIGTERM, sighandler); + signal (SIGINT, sighandler); + signal (SIGHUP, sighandler); + + if (argc <= 1) { + fprintf (stderr, "gdmopen: must supply a command!\n"); + return 66; + } + + fd = open ("/dev/console", O_WRONLY, 0); + if (fd < 0) { + perror ("gdmopen: Failed to open /dev/console"); + return 66; + } + + errno = 0; + if ((ioctl(fd, VT_OPENQRY, &vtno) < 0) || (vtno == -1)) { + perror ("gdmopen: Cannot find a free VT"); + close (fd); + return 66; + } + + if (ioctl(fd, VT_GETSTATE, &vt) < 0) { + perror ("gdmopen: can't get VTstate"); + close(fd); + return 66; + } + + snprintf (vtname, sizeof (vtname), VTNAME, vtno); + + chown (vtname, 0, -1); + + child_pid = fork(); + if (child_pid == 0) { + + signal (SIGTERM, SIG_DFL); + signal (SIGINT, SIG_DFL); + signal (SIGHUP, SIG_DFL); + + /* leave current vt */ + if ( +#ifdef ESIX_5_3_2_D + setpgrp() < 0 +#else + setsid() < 0 +#endif + ) { + fprintf(stderr, "open: Unable to set new session (%s)\n", + strerror(errno)); + } + close(0); + close(1); + close(2); + close(fd); + + /* and grab new one */ + fd = open (vtname, O_RDWR); + if (fd < 0) { /* Shouldn't happen */ + _exit (66); /* silently die */ + } + dup(fd); + dup(fd); + + /* + * Can't tell anyone if any of these fail, so throw away + * the return values + */ + (void) ioctl(fd, VT_ACTIVATE, vtno); + /* wait to be really sure we have switched */ + (void) ioctl(fd, VT_WAITACTIVE, vtno); + + execvp (argv[1], &argv[1]); + + _exit (66); /* failed */ + } + + if (child_pid < 0) { + perror ("gdmopen: fork() error"); + return 66; + } + + do_dealloc = TRUE; + + waitpid (child_pid, &status, 0); + child_pid = -1; + + do_dealloc = FALSE; + + /* Switch back... */ + (void) ioctl(fd, VT_ACTIVATE, vt.v_active); + /* wait to be really sure we have switched */ + (void) ioctl(fd, VT_WAITACTIVE, vt.v_active); + + /* Now deallocate our new one */ + (void) ioctl(fd, VT_DISALLOCATE, vtno); + + close (fd); + + if (WIFEXITED (status)) + return WEXITSTATUS (status); + else + return 66; +} |