summaryrefslogtreecommitdiff
path: root/init/ttys.c
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>1999-06-13 21:02:58 +0000
committerRoland McGrath <roland@gnu.org>1999-06-13 21:02:58 +0000
commita01fd6ec57dfc18feacfc02e2a5d90531a194cf8 (patch)
tree3bc91edcca71a23af5a70d1a2d3b2cf4de482917 /init/ttys.c
parent839eaaea67dadbacfe916b7de3a6bd3deb6ddbbe (diff)
1999-06-13 Roland McGrath <roland@baalperazim.frob.com>
* ttys.c (struct terminal): Use `pid_t' for `pid' member. (ttys, nttys, ttyslen): Make variables static. (setup_terminal, add_terminal, find_line, startup_terminal, shutdown_terminal): Make all these functions static. Move all the /etc/ttys handling stuff into a separate source file. * init.c (_PATH_LOGIN, WINDOW_DELAY, struct terminal, nttys, ttyslen, setup_terminal, add_terminal, init_ttys, free_ttys, startup_terminal, startup_ttys, find_line, restart_terminal, shutdown_terminal, reread_ttys): Move to * ttys.c: ... here, new file. * ttys.h: New file, declare external functions in ttys.c. * Makefile (SRCS): Add ttys.c. (OBJS): Derive from $(SRCS). (LCLHDRS): New variable, add ttys.h.
Diffstat (limited to 'init/ttys.c')
-rw-r--r--init/ttys.c319
1 files changed, 319 insertions, 0 deletions
diff --git a/init/ttys.c b/init/ttys.c
new file mode 100644
index 00000000..204e81f0
--- /dev/null
+++ b/init/ttys.c
@@ -0,0 +1,319 @@
+/* /etc/ttys support for Hurd init
+ Copyright (C) 1993,94,95,96,97,98,99 Free Software Foundation, Inc.
+ This file is part of the GNU Hurd.
+
+ The GNU Hurd 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, or (at your option)
+ any later version.
+
+ The GNU Hurd is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the GNU Hurd; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <stdio.h>
+#include <signal.h>
+#include <unistd.h>
+#include <string.h>
+#include <argz.h>
+#include <hurd.h>
+#include <error.h>
+#include <assert.h>
+#include <ttyent.h>
+#include <utmp.h>
+
+
+extern pid_t run_for_real (char *filename, char *args, int arglen,
+ mach_port_t ctty, int setsid); /* init.c */
+
+
+/* How long to wait after starting window specs before starting getty */
+#define WINDOW_DELAY 3 /* seconds */
+
+#define _PATH_LOGIN "/bin/login"
+
+
+/* All the ttys in /etc/ttys. */
+struct terminal
+{
+ /* argz list for getty */
+ char *getty_argz;
+ size_t getty_argz_len;
+
+ /* argz list for window spec */
+ char *window_argz;
+ size_t window_argz_len;
+
+ int on;
+ pid_t pid;
+ int read;
+
+ char *name;
+};
+
+static struct terminal *ttys;
+/* Number of live elements in ttys */
+static int nttys;
+/* Total number of elements in ttys */
+static int ttyslen;
+
+
+/* Set up the getty and window fields of terminal spec T corresponding
+ to line TT. */
+static void
+setup_terminal (struct terminal *t, struct ttyent *tt)
+{
+ char *line;
+
+ if (t->getty_argz)
+ free (t->getty_argz);
+ if (t->window_argz)
+ free (t->window_argz);
+
+ if ((tt->ty_status & TTY_ON) && tt->ty_getty)
+ {
+ asprintf (&line, "%s %s", tt->ty_getty, tt->ty_name);
+ argz_create_sep (line, ' ', &t->getty_argz, &t->getty_argz_len);
+ free (line);
+ if (tt->ty_window)
+ argz_create_sep (tt->ty_window, ' ',
+ &t->window_argz, &t->window_argz_len);
+ else
+ t->window_argz = 0;
+ }
+ else
+ t->getty_argz = t->window_argz = 0;
+}
+
+
+/* Add a new terminal spec for TT and return it. */
+static struct terminal *
+add_terminal (struct ttyent *tt)
+{
+ struct terminal *t;
+
+ if (nttys >= ttyslen)
+ {
+ ttys = realloc (ttys, (ttyslen * 2) * sizeof (struct ttyent));
+ bzero (&ttys[nttys], ttyslen);
+ ttyslen *= 2;
+ }
+
+ t = &ttys[nttys];
+ nttys++;
+
+ t->name = malloc (strlen (tt->ty_name) + 1);
+ strcpy (t->name, tt->ty_name);
+
+ setup_terminal (t, tt);
+ if (t->getty_argz)
+ t->on = 1;
+
+ return t;
+}
+
+/* Read /etc/ttys and initialize ttys array. Return non-zero if we fail. */
+int
+init_ttys (void)
+{
+ struct ttyent *tt;
+
+ ttyslen = 10;
+ nttys = 0;
+
+ ttys = malloc (ttyslen * sizeof (struct ttyent));
+ bzero (ttys, ttyslen * sizeof (struct ttyent));
+
+ if (!setttyent ())
+ {
+ error (0, errno, "%s", _PATH_TTYS);
+ return 1;
+ }
+ while ((tt = getttyent ()))
+ {
+ if (!tt->ty_name)
+ continue;
+
+ add_terminal (tt);
+ }
+
+ endttyent ();
+ return 0;
+}
+
+/* Free everyting in the terminal array */
+void
+free_ttys (void)
+{
+ int i;
+
+ for (i = 0; i < nttys; i++)
+ {
+ if (ttys[i].getty_argz)
+ free (ttys[i].getty_argz);
+ if (ttys[i].window_argz)
+ free (ttys[i].window_argz);
+ free (ttys[i].name);
+ }
+ free (ttys);
+}
+
+/* Start line T. Return non-zero if we didn't actually start anything. */
+static int
+startup_terminal (struct terminal *t)
+{
+ pid_t pid;
+ assert (t->on);
+ assert (t->getty_argz);
+
+ if (t->window_argz)
+ {
+ pid = run_for_real (t->window_argz, t->window_argz,
+ t->window_argz_len, MACH_PORT_NULL, 1);
+ if (!pid)
+ goto error;
+
+ sleep (WINDOW_DELAY);
+ }
+
+ pid = run_for_real (t->getty_argz, t->getty_argz,
+ t->getty_argz_len, MACH_PORT_NULL, 0);
+ if (pid == 0)
+ {
+ error:
+ t->pid = 0;
+ t->on = 0;
+ return 1;
+ }
+ else
+ {
+ t->pid = pid;
+ return 0;
+ }
+}
+
+/* For each line in /etc/ttys, start up the specified program. Return
+ non-zero if we fail. */
+int
+startup_ttys (void)
+{
+ int i;
+ int didone, fail;
+
+ didone = 0;
+
+ for (i = 0; i < nttys; i++)
+ if (ttys[i].on)
+ {
+ fail = startup_terminal (&ttys[i]);
+ if (!fail)
+ didone = 1;
+ }
+ return !didone;
+}
+
+/* Find the terminal spec corresponding to line LINE. */
+static struct terminal *
+find_line (char *line)
+{
+ int i;
+
+ for (i = 0; i < nttys; i++)
+ if (!strcmp (ttys[i].name, line))
+ return &ttys[i];
+ return 0;
+}
+
+/* PID has just exited; restart the terminal it's on if necessary. */
+void
+restart_terminal (pid_t pid)
+{
+ int i;
+
+ for (i = 0; i < nttys; i++)
+ if (pid == ttys[i].pid)
+ {
+ if (logout (ttys[i].name))
+ logwtmp (ttys[i].name, "", "");
+ ttys[i].pid = 0;
+ if (ttys[i].on)
+ startup_terminal (&ttys[i]);
+ }
+}
+
+/* Shutdown the things running on terminal spec T. */
+static void
+shutdown_terminal (struct terminal *t)
+{
+ kill (t->pid, SIGHUP);
+ revoke (t->name);
+}
+
+/* Re-read /etc/ttys. If a line has turned off, kill what's there.
+ If a line has turned on, start it. */
+void
+reread_ttys (void)
+{
+ struct ttyent *tt;
+ struct terminal *t;
+ int on;
+ int i;
+
+ if (!setttyent ())
+ {
+ error (0, errno, "%s", _PATH_TTYS);
+ return;
+ }
+
+ /* Mark all the lines not yet read */
+ for (i = 0; i < nttys; i++)
+ ttys[i].read = 0;
+
+ while ((tt = getttyent ()))
+ {
+ if (!tt->ty_name)
+ continue;
+
+ t = find_line (tt->ty_name);
+ on = tt->ty_getty && (tt->ty_status & TTY_ON);
+
+ if (t)
+ {
+ if (t->on && !on)
+ {
+ t->on = 0;
+ shutdown_terminal (t);
+ }
+ else if (!t->on && on)
+ {
+ t->on = 1;
+ setup_terminal (t, tt);
+ startup_terminal (t);
+ }
+ }
+ else
+ {
+ t = add_terminal (tt);
+ if (on)
+ startup_terminal (t);
+ }
+
+ t->read = 1;
+ }
+ endttyent ();
+
+ /* Scan tty entries; any that were not found and were on, turn off. */
+ for (i = 0; i < nttys; i++)
+ if (!ttys[i].read && ttys[i].on)
+ {
+ ttys[i].on = 0;
+ shutdown_terminal (&ttys[i]);
+ }
+}