* sulogin - add the possibility to reset the terminal io

This commit is contained in:
Werner Fink 2010-03-12 18:18:28 +00:00
parent d80bb06fec
commit b98dd2505c
2 changed files with 114 additions and 47 deletions

View File

@ -17,6 +17,7 @@
* init - initialize console by using the macros from ttydefaults.h * init - initialize console by using the macros from ttydefaults.h
* init - add the possiblity to ignore further interrupts from keyboard * init - add the possiblity to ignore further interrupts from keyboard
* init - add the possiblity to set sane terminal line settings * init - add the possiblity to set sane terminal line settings
* sulogin - add the possibility to reset the terminal io
sysvinit (2.88dsf) UNRELEASED; urgency=low sysvinit (2.88dsf) UNRELEASED; urgency=low

View File

@ -39,6 +39,7 @@
#include <pwd.h> #include <pwd.h>
#include <shadow.h> #include <shadow.h>
#include <termios.h> #include <termios.h>
#include <sys/ttydefaults.h>
#include <errno.h> #include <errno.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#if defined(__GLIBC__) #if defined(__GLIBC__)
@ -60,49 +61,83 @@
char *Version = "@(#)sulogin 2.85-3 23-Apr-2003 miquels@cistron.nl"; char *Version = "@(#)sulogin 2.85-3 23-Apr-2003 miquels@cistron.nl";
int timeout = 0; static int timeout;
int profile = 0; static int profile;
static void (*saved_sigint) = SIG_DFL;
static void (*saved_sigtstp) = SIG_DFL;
static void (*saved_sigquit) = SIG_DFL;
#ifndef IUCLC #ifndef IUCLC
# define IUCLC 0 # define IUCLC 0
#endif #endif
#if 0 #if defined(SANE_TIO) && (SANE_TIO == 1)
/* /*
* Fix the tty modes and set reasonable defaults. * Fix the tty modes and set reasonable defaults.
* (I'm not sure if this is needed under Linux, but..) * (I'm not sure if this is needed under Linux, but..)
*/ */
static
void fixtty(void) void fixtty(void)
{ {
struct termios tty; struct termios tty;
int serial;
/* Skip serial console */
if (ioctl (0, TIOCMGET, (char*)&serial) == 0)
goto out;
/* Expected error */
serial = errno = 0;
tcgetattr(0, &tty); tcgetattr(0, &tty);
/* /* Use defaults of <sys/ttydefaults.h> for base settings */
* Set or adjust tty modes. tty.c_iflag |= TTYDEF_IFLAG;
*/ tty.c_oflag |= TTYDEF_OFLAG;
tty.c_iflag &= ~(INLCR|IGNCR|IUCLC); tty.c_lflag |= TTYDEF_LFLAG;
tty.c_iflag |= ICRNL; tty.c_cflag |= (TTYDEF_SPEED | TTYDEF_CFLAG);
tty.c_oflag &= ~(OCRNL|OLCUC|ONOCR|ONLRET|OFILL);
tty.c_oflag |= OPOST|ONLCR;
tty.c_cflag |= CLOCAL;
tty.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE;
/* /* Sane setting, allow eight bit characters, no carriage return delay
* Set the most important characters */ * the same result as `stty sane cr0 pass8'
*/ */
tty.c_cc[VINTR] = 3; tty.c_iflag |= (BRKINT | ICRNL | IMAXBEL);
tty.c_cc[VQUIT] = 28; #ifdef IUTF8 /* Not defined on FreeBSD */
tty.c_cc[VERASE] = 127; tty.c_iflag |= IUTF8;
tty.c_cc[VKILL] = 24; #endif /* IUTF8 */
tty.c_cc[VEOF] = 4; tty.c_iflag &= ~(IGNBRK | INLCR | IGNCR | IXOFF | IUCLC | IXANY | ISTRIP);
tty.c_cc[VTIME] = 0; tty.c_oflag |= (OPOST | ONLCR | NL0 | CR0 | TAB0 | BS0 | VT0 | FF0);
tty.c_cc[VMIN] = 1; tty.c_oflag &= ~(OLCUC | OCRNL | ONOCR | ONLRET | OFILL | OFDEL |\
tty.c_cc[VSTART] = 17; NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY);
tty.c_cc[VSTOP] = 19; tty.c_lflag |= (ISIG | ICANON | IEXTEN | ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE);
tty.c_cc[VSUSP] = 26; tty.c_lflag &= ~(ECHONL | NOFLSH | XCASE | TOSTOP | ECHOPRT);
tty.c_cflag |= (CREAD | CS8 | B9600);
tty.c_cflag &= ~(PARENB);
/* VTIME and VMIN can overlap with VEOF and VEOL since they are
* only used for non-canonical mode. We just set the at the
* beginning, so nothing bad should happen.
*/
tty.c_cc[VTIME] = 0;
tty.c_cc[VMIN] = 1;
tty.c_cc[VINTR] = CINTR;
tty.c_cc[VQUIT] = CQUIT;
tty.c_cc[VERASE] = CERASE; /* ASCII DEL (0177) */
tty.c_cc[VKILL] = CKILL;
tty.c_cc[VEOF] = CEOF;
tty.c_cc[VSWTC] = _POSIX_VDISABLE;
tty.c_cc[VSTART] = CSTART;
tty.c_cc[VSTOP] = CSTOP;
tty.c_cc[VSUSP] = CSUSP;
tty.c_cc[VEOL] = _POSIX_VDISABLE;
tty.c_cc[VREPRINT] = CREPRINT;
tty.c_cc[VDISCARD] = CDISCARD;
tty.c_cc[VWERASE] = CWERASE;
tty.c_cc[VLNEXT] = CLNEXT;
tty.c_cc[VEOL2] = _POSIX_VDISABLE;
tcsetattr(0, TCSANOW, &tty); tcsetattr(0, TCSANOW, &tty);
out:
return;
} }
#endif #endif
@ -110,7 +145,12 @@ void fixtty(void)
/* /*
* Called at timeout. * Called at timeout.
*/ */
void alrm_handler() static
# ifdef __GNUC__
void alrm_handler(int sig __attribute__((unused)))
# else
void alrm_handler(int sig)
# endif
{ {
} }
@ -119,6 +159,7 @@ void alrm_handler()
* password is checked for traditional-style DES and * password is checked for traditional-style DES and
* FreeBSD-style MD5 encryption. * FreeBSD-style MD5 encryption.
*/ */
static
int valid(char *pass) int valid(char *pass)
{ {
char *s; char *s;
@ -157,6 +198,7 @@ int valid(char *pass)
/* /*
* Set a variable if the value is not NULL. * Set a variable if the value is not NULL.
*/ */
static
void set(char **var, char *val) void set(char **var, char *val)
{ {
if (val) *var = val; if (val) *var = val;
@ -165,6 +207,7 @@ void set(char **var, char *val)
/* /*
* Get the root password entry. * Get the root password entry.
*/ */
static
struct passwd *getrootpwent(int try_manually) struct passwd *getrootpwent(int try_manually)
{ {
static struct passwd pwd; static struct passwd pwd;
@ -267,6 +310,7 @@ struct passwd *getrootpwent(int try_manually)
* Ask for the password. Note that there is no * Ask for the password. Note that there is no
* default timeout as we normally skip this during boot. * default timeout as we normally skip this during boot.
*/ */
static
char *getpasswd(char *crypted) char *getpasswd(char *crypted)
{ {
struct sigaction sa; struct sigaction sa;
@ -275,11 +319,10 @@ char *getpasswd(char *crypted)
char *ret = pass; char *ret = pass;
int i; int i;
if (crypted[0]) if (crypted[0]) {
printf("Give root password for maintenance\n"); printf("Give root password for login: ");
else } else
printf("Press enter for maintenance\n"); printf("Press enter for login: ");
printf("(or type Control-D to continue): ");
fflush(stdout); fflush(stdout);
tcgetattr(0, &old); tcgetattr(0, &old);
@ -314,6 +357,7 @@ char *getpasswd(char *crypted)
/* /*
* Password was OK, execute a shell. * Password was OK, execute a shell.
*/ */
static
void sushell(struct passwd *pwd) void sushell(struct passwd *pwd)
{ {
char shell[128]; char shell[128];
@ -355,9 +399,9 @@ void sushell(struct passwd *pwd)
* Try to execute a shell. * Try to execute a shell.
*/ */
setenv("SHELL", sushell, 1); setenv("SHELL", sushell, 1);
signal(SIGINT, SIG_DFL); signal(SIGINT, saved_sigint);
signal(SIGTSTP, SIG_DFL); signal(SIGTSTP, saved_sigtstp);
signal(SIGQUIT, SIG_DFL); signal(SIGQUIT, saved_sigquit);
#ifdef WITH_SELINUX #ifdef WITH_SELINUX
if (is_selinux_enabled > 0) { if (is_selinux_enabled > 0) {
security_context_t scon=NULL; security_context_t scon=NULL;
@ -387,6 +431,7 @@ void sushell(struct passwd *pwd)
perror(STATICSH); perror(STATICSH);
} }
static
void usage(void) void usage(void)
{ {
fprintf(stderr, "Usage: sulogin [-e] [-p] [-t timeout] [tty device]\n"); fprintf(stderr, "Usage: sulogin [-e] [-p] [-t timeout] [tty device]\n");
@ -429,14 +474,19 @@ int main(int argc, char **argv)
/* /*
* See if we need to open an other tty device. * See if we need to open an other tty device.
*/ */
signal(SIGINT, SIG_IGN); saved_sigint = signal(SIGINT, SIG_IGN);
signal(SIGQUIT, SIG_IGN); saved_sigtstp = signal(SIGQUIT, SIG_IGN);
signal(SIGTSTP, SIG_IGN); saved_sigquit = signal(SIGTSTP, SIG_IGN);
if (optind < argc) tty = argv[optind]; if (optind < argc) tty = argv[optind];
if (tty) {
if (tty || (tty = getenv("CONSOLE"))) {
if ((fd = open(tty, O_RDWR)) < 0) { if ((fd = open(tty, O_RDWR)) < 0) {
perror(tty); perror(tty);
} else if (!isatty(fd)) { fd = dup(0);
}
if (!isatty(fd)) {
fprintf(stderr, "%s: not a tty\n", tty); fprintf(stderr, "%s: not a tty\n", tty);
close(fd); close(fd);
} else { } else {
@ -448,7 +498,7 @@ int main(int argc, char **argv)
pid = getpid(); pid = getpid();
pgrp = getpgid(0); pgrp = getpgid(0);
ppgrp = getpgid(getppid()); ppgrp = getpgid(getppid());
ioctl(fd, TIOCGPGRP, &ttypgrp); ttypgrp = tcgetpgrp(fd);
if (pgrp != ttypgrp && ppgrp != ttypgrp) { if (pgrp != ttypgrp && ppgrp != ttypgrp) {
if (pid != getsid(0)) { if (pid != getsid(0)) {
@ -458,18 +508,28 @@ int main(int argc, char **argv)
} }
signal(SIGHUP, SIG_IGN); signal(SIGHUP, SIG_IGN);
ioctl(0, TIOCNOTTY, (char *)1); if (ttypgrp > 0)
ioctl(0, TIOCNOTTY, (char *)1);
signal(SIGHUP, SIG_DFL); signal(SIGHUP, SIG_DFL);
close(0); close(0);
close(1); close(1);
close(2); close(2);
close(fd); if (fd > 2)
fd = open(tty, O_RDWR); close(fd);
ioctl(0, TIOCSCTTY, (char *)1); if ((fd = open(tty, O_RDWR)) < 0) {
dup(fd); perror(tty);
dup(fd); } else {
ioctl(0, TIOCSCTTY, (char *)1);
tcsetpgrp(fd, ppgrp);
dup2(fd, 0);
dup2(fd, 1);
dup2(fd, 2);
if (fd > 2)
close(fd);
}
} else } else
close(fd); if (fd > 2)
close(fd);
} }
} else if (getpid() == 1) { } else if (getpid() == 1) {
/* We are init. We hence need to set a session anyway */ /* We are init. We hence need to set a session anyway */
@ -478,6 +538,10 @@ int main(int argc, char **argv)
perror("ioctl(TIOCSCTTY)"); perror("ioctl(TIOCSCTTY)");
} }
#if defined(SANE_TIO) && (SANE_TIO == 1)
fixtty();
#endif
/* /*
* Get the root password. * Get the root password.
*/ */
@ -494,6 +558,9 @@ int main(int argc, char **argv)
if (pwd->pw_passwd[0] == 0 || if (pwd->pw_passwd[0] == 0 ||
strcmp(crypt(p, pwd->pw_passwd), pwd->pw_passwd) == 0) strcmp(crypt(p, pwd->pw_passwd), pwd->pw_passwd) == 0)
sushell(pwd); sushell(pwd);
saved_sigquit = signal(SIGQUIT, SIG_IGN);
saved_sigtstp = signal(SIGTSTP, SIG_IGN);
saved_sigint = signal(SIGINT, SIG_IGN);
printf("Login incorrect.\n"); printf("Login incorrect.\n");
} }
@ -502,4 +569,3 @@ int main(int argc, char **argv)
*/ */
return 0; return 0;
} }