aboutsummaryrefslogtreecommitdiff
path: root/riemann.fmi.uni-sofia.bg/ngetty/ngetty-1.1/ngetty.c
diff options
context:
space:
mode:
authorKlaatu Sverige <[email protected]>2015-08-05 21:31:21 +0000
committerKlaatu Sverige <[email protected]>2015-08-05 21:31:21 +0000
commit86f0721bd904d8163c5f8f2472b78169146cc67d (patch)
treecf9e61bd495c73ece45b96242e6f575af228d01d /riemann.fmi.uni-sofia.bg/ngetty/ngetty-1.1/ngetty.c
parent75a501d32dff3c1c1ee9a2a3dc6d5b704cc7c6d1 (diff)
added website data, because it had heaps of good tutorials and info
Diffstat (limited to 'riemann.fmi.uni-sofia.bg/ngetty/ngetty-1.1/ngetty.c')
-rw-r--r--riemann.fmi.uni-sofia.bg/ngetty/ngetty-1.1/ngetty.c278
1 files changed, 278 insertions, 0 deletions
diff --git a/riemann.fmi.uni-sofia.bg/ngetty/ngetty-1.1/ngetty.c b/riemann.fmi.uni-sofia.bg/ngetty/ngetty-1.1/ngetty.c
new file mode 100644
index 0000000..926e904
--- /dev/null
+++ b/riemann.fmi.uni-sofia.bg/ngetty/ngetty-1.1/ngetty.c
@@ -0,0 +1,278 @@
+/*
+ * ngetty.c - daemon for virtual console terminals
+ *
+ * Copyright 2007 Andre Oliveira
+ * Copyright 2007,2008 Nikola Vladov
+ *
+ * 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.
+ *
+ * This program 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.
+ */
+
+/*
+ * Synopsis: ngetty tty...
+ *
+ * ngetty open()s the virtual console terminals specified as arguments and
+ * poll()s them for user input. Once input is available on one of the
+ * terminals, it fork()s and exec()s the ngetty-helper programs with that
+ * terminal set up as the controlling terminal. ngetty-helper make
+ * utmp/wtmp records, print /etc/issue, ask for user name and then
+ * exec()s login(1) program. When a ngetty session terminates,
+ * the sig_handler() restarts the corresponding terminal.
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <alloca.h>
+#include <errno.h>
+#include <sys/wait.h>
+#include "lib.h"
+#include "sig_action.h"
+
+#ifdef NEED_HELPER_OPTION
+static char *helper;
+#else
+#define helper NGETTY_HELPER
+#endif
+
+struct tty_name {
+ char *tty; /* original ttyname */
+ char tmp[23]; /* expanded ttyname; /dev/ttyX or /dev/vc/X */
+ char st;
+};
+typedef struct tty_name tty_name_;
+typedef struct pollfd pollfd_;
+
+static tty_name_ *tty;
+
+/* Number of managed terminals (argc - 1). */
+static int npfd;
+
+/*
+ * Poll data for the terminals.
+ * When polling for input on a terminal, the fd field stores its
+ * file descriptor, as customary. After fork()ing, though, the parent
+ * process closes the terminal and stores the child's _negative_ pid
+ * in the fd field, so that poll() ignores that entry and
+ * main() knows every child's pid.
+ */
+static pollfd_ *pfd;
+
+static void nano_sleep(int n) { /* sleep n.5 secs */
+ struct timespec ts = { n, 500111222 };
+ nanosleep(&ts, 0);
+}
+
+static void max_copy(char *out,const char *in) {
+ int len;
+ for (len=0; len<10; len++) { if (!(out[len]=in[len])) break; }
+ out[len] = 0;
+}
+
+/*
+ * Exec NGETTY_HELPER.
+ */
+static void exechelper(int i, char *login) {
+ pollfd_ *xx = pfd + i;
+ int pid;
+ while ((pid=fork()) < 0)
+ nano_sleep(0);
+
+ if (pid==0) {
+ tty_name_ *tt = tty + i;
+ char *a1 = (tt->tmp[0]) ? tt->tmp : tt->tty;
+ char *arg[4] = { helper, a1, login, 0 };
+
+#ifndef NGETTY_SELFPIPE
+ if (xx->fd)
+#endif
+ dup2(xx->fd, 0);
+ i = npfd + 8;
+ while (--i) close(i);
+
+ execve(*arg, arg, environ);
+ nano_sleep(5);
+ _exit(127);
+ }
+ close(xx->fd);
+ xx->fd = -pid;
+}
+
+/*
+ * Open virtual console terminal i.
+ *
+ * In case of failure, most likely because the device node does not exist,
+ * poll() will simply ignore this entry and users get a blank screen and
+ * locked keyboard on this console. That's enough error reporting. ;-)
+ * No need to add code to check all syscalls' return values.
+ *
+ * Linux does not implement revoke(); the *BSD do.
+ */
+void opentty(int k) {
+ tty_name_ *tt = tty + k;
+ char *path = tt->tty, *m = tt->tmp, st;
+ int fd;
+
+ if (*path != '/') {
+ max_copy(m, "/dev/vc/");
+ if ('0'<=*path && *path<='9') {
+ max_copy(m+8, path);
+ if (chown(m,0,0))
+ { m[5]='t'; m[6]='t'; m[7]='y'; }
+ } else {
+ if (path[0]==0) { fd = -1; goto do_it; }
+ max_copy(m+5, path);
+ }
+ path = m;
+ } else
+ m[0] = 0;
+
+ chown(path, 0, 0);
+ chmod(path, 0600);
+#ifdef HAVE_REVOKE
+ revoke(path);
+#endif
+
+ fd = open(path, O_RDWR | O_NOCTTY);
+ if (fd > npfd + 4) _exit(100);
+ do_it:
+ pfd[k].fd = fd;
+ if (fd < 0) st = 0;
+ else {
+ st = tt->st ^ 1;
+ if (st) exechelper(k,0);
+ }
+ tt->st = st;
+}
+
+#ifndef NGETTY_SELFPIPE
+static int volatile poll_timeout;
+#endif
+/*
+ * SIG handler.
+ */
+static void sig_handler(int sig) {
+ if (sig == SIGTERM) {
+ int k;
+ again:
+ for (k = 0; k < npfd; k++) {
+ int pid = -pfd[k].fd;
+ if (pid > 1) kill(pid, sig);
+ }
+ nano_sleep(0);
+ if (sig == SIGKILL) _exit(0);
+ sig = SIGKILL;
+ goto again;
+ }
+#ifdef NGETTY_SELFPIPE
+ write(1,"",1);
+#else
+ poll_timeout = 1;
+#endif
+}
+
+static void set_handler() {
+ struct sigaction sa;
+ sigset_t *mask = &sa.sa_mask;
+ sigemptyset(mask);
+ sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
+ sa.sa_handler = sig_handler;
+ sigaction(SIGTERM, &sa, 0);
+ sigaction(SIGCHLD, &sa, 0);
+}
+
+#ifdef NGETTY_SORT
+#include "sortpfd.h"
+#define SORT_x_PFD k = sortpfd()
+#define KK_selfpipe k+1
+#define KK k
+#else
+#define SORT_x_PFD
+#define KK_selfpipe argc
+#define KK npfd
+#endif
+
+#ifdef NGETTY_SELFPIPE
+#define DO_x_POLL poll(pfd-1, KK_selfpipe, -1)
+#else
+#define DO_x_POLL poll(pfd, KK, poll_timeout); poll_timeout = 512*1024
+#endif
+
+/*
+ * Synopsis: ngetty tty...
+ *
+ * Since each terminal's struct pollfd only takes up 8 bytes, just
+ * alloca()te the array on the stack, instead of using the bloated malloc().
+ */
+int main(int argc, char **argv) {
+ int i,k;
+#ifdef NGETTY_SELFPIPE
+ int pi[6];
+#endif
+
+#ifdef NEED_HELPER_OPTION
+ if ((helper=argv[1]) && helper[0] == '-' && helper[1] == 'H') {
+ argv++; argc--; helper += 2;
+ } else helper = NGETTY_HELPER;
+#endif
+
+ npfd = argc - 1;
+ tty = alloca(npfd * sizeof(tty_name_)); if (tty==0) _exit(111);
+ pfd = alloca(argc * sizeof(pollfd_)); if (pfd==0) _exit(111);
+
+#ifdef NGETTY_SELFPIPE
+ pfd->fd = 0;
+ pfd->events = POLLIN;
+ pfd++;
+#endif
+
+ for (k = 0; k < npfd; k++) {
+ tty[k].tty = *++argv;
+ tty[k].st = 0;
+ pfd[k].fd = -1;
+ pfd[k].events = POLLIN;
+ }
+ for (k = 0; k < 127; k++) close(k);
+
+#ifdef NGETTY_SELFPIPE
+ if (pipe(pi) || pi[0] != 0 || pi[1] != 1) _exit(111);
+ for (k=0; k<2; k++)
+ fcntl(k, F_SETFL, fcntl(k,F_GETFL,0) | O_NONBLOCK);
+#endif
+
+ set_handler();
+
+ again:
+ while ((i = waitpid(-1, NULL, WNOHANG)) > 1)
+ for (k = 0; k < npfd; k++)
+ if (pfd[k].fd == -i)
+ { pfd[k].fd = -1; break; }
+
+ for (k = 0; k < npfd; k++)
+ if (pfd[k].fd == -1) opentty(k);
+
+ SORT_x_PFD;
+ i = DO_x_POLL;
+
+ if (i==-1) {
+ if (errno != EINTR)
+ sig_handler(SIGTERM); /* poll failed, what to do? */
+ } else {
+ for (i = 0; i < KK; i++)
+ if (pfd[i].revents)
+ exechelper(i,"login");
+ }
+
+#ifdef NGETTY_SELFPIPE
+ read(0, pi, sizeof pi);
+#endif
+ goto again;
+ return 1;
+}