/* mingetty.c * * Copyright (C) 1996 Florian La Roche * Copyright (C) 2002, 2003 Red Hat, Inc * * This getty can only be used as a small console getty. Look at mgetty * for a real modem getty. * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* name of this program (argv[0]) */ static char *progname; /* on which tty line are we sitting? (e.g. tty1) */ static char *tty; /* process and session ID of this program */ static pid_t pid, sid; /* Do not call vhangup() on the tty. */ static int nohangup = 0; /* error() - output error messages */ static void error(const char *fmt, ...) { va_list va_alist; va_start(va_alist, fmt); openlog(progname, LOG_PID, LOG_AUTH); vsyslog(LOG_ERR, fmt, va_alist); /* no need, we exit anyway: closelog (); */ va_end(va_alist); sleep(5); exit(EXIT_FAILURE); } /* open_tty - set up tty as standard { input, output, error } */ static void open_tty(void) { struct sigaction sa, sa_old; char buf[40]; int fd; /* Set up new standard input. */ strcpy(buf, "/dev/"); strcat(buf, tty); /* There is always a race between this reset and the call to vhangup() that s.o. can use to get access to your tty. */ if (chown(buf, 0, 0) || chmod(buf, 0600)) if (errno != EROFS) error("%s: %s", tty, strerror(errno)); sa.sa_handler = SIG_IGN; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); sigaction(SIGHUP, &sa, &sa_old); /* vhangup() will replace all open file descriptors in the kernel that point to our controlling tty by a dummy that will deny further reading/writing to our device. It will also reset the tty to sane defaults, so we don't have to modify the tty device for sane settings. We also get a SIGHUP/SIGCONT. */ if ((fd = open(buf, O_RDWR, 0)) < 0) error("%s: cannot open tty: %s", tty, strerror(errno)); if (!isatty(fd)) error("%s: not a tty", tty); if (nohangup == 0) { if (vhangup()) error("%s: vhangup() failed", tty); /* Get rid of the present stdout/stderr. */ close(2); close(1); close(0); close(fd); if ((fd = open(buf, O_RDWR, 0)) != 0) error("%s: cannot open tty: %s", tty, strerror(errno)); } /* Set up stdin/stdout/stderr. */ if (dup2(fd, 0) != 0 || dup2(fd, 1) != 1 || dup2(fd, 2) != 2) error("%s: dup2(): %s", tty, strerror(errno)); if (fd > 2) close(fd); sigaction(SIGHUP, &sa_old, NULL); } void get_logname(void) { unsigned char c; struct termios org_opts, new_opts; int res = 0; tcflush(0, TCIFLUSH); /* flush pending input */ res = tcgetattr(STDIN_FILENO, &org_opts); memcpy(&new_opts, &org_opts, sizeof(new_opts)); new_opts.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | ECHOPRT | ECHOKE | ICRNL); new_opts.c_cc[VMIN] = 1; tcsetattr(STDIN_FILENO, TCSANOW, &new_opts); if (read(0, &c, 1) < 1) { if (errno == EINTR || errno == EIO || errno == ENOENT) exit(EXIT_SUCCESS); error("%s: read: %s", tty, strerror(errno)); } exit(c); } int main(int argc, char **argv) { progname = argv[0]; if (!progname) progname = "mingetty"; pid = getpid(); sid = getsid(0); putenv("TERM=linux"); tty = strdup("tty1"); open_tty(); get_logname(); return argc; }