diff --git a/us.c b/us.c index e2d507c..25b06c4 100644 --- a/us.c +++ b/us.c @@ -97,6 +97,17 @@ static int get_config(struct config **, int *); extern char **environ; char *config_file = "/etc/us.conf"; +int tty_fd = STDOUT_FILENO; +struct termios tio_before = {0}; + +void int_handler(int signum) +{ + (void)signum; + if (tio_before.c_iflag || tio_before.c_oflag || tio_before.c_iflag) + tcsetattr(tty_fd, TCSANOW, &tio_before); + putchar('\n'); + exit(signum); +} int main(int argc, char *argv[]) { @@ -106,6 +117,24 @@ int main(int argc, char *argv[]) struct user_info t_gr_info = {0}, t_pw_info = {0}; int opt, err; int shellflag = 0, envflag = 0, askpass = 0; + + /* Save the terminal setup, don't fail since we don't know if we'll + * need it, save it because some shells don't reset termios upon + * program exit, if we don't reset it after a SIGINT or SIGTERM then + * the controlling terminal will be stuck in no echo */ + if (tcgetattr(tty_fd, &tio_before) == -1) { + tio_before.c_iflag = 0; + tio_before.c_oflag = 0; + tio_before.c_cflag = 0; + } + struct sigaction action; + memset(&action, 0, sizeof(action)); + action.sa_handler = int_handler; + if (sigaction(SIGINT, &action, NULL) == -1) + die("Error setting interrupt handler:"); + if (sigaction(SIGTERM, &action, NULL) == -1) + die("Error setting interrupt handler:"); + while ((opt = getopt(argc, argv, "Au:g:C:seh")) != -1) { switch (opt) { case 'A': @@ -487,7 +516,6 @@ static int authenticate(uid_t uid, int ask, int persist) struct passwd *pw = getpwuid(uid); char *hash_p, hash[MAX_HASH]; char *p = pw->pw_passwd; - int tty_fd = STDOUT_FILENO; if (!strcmp(p, "x") || *p == '*' || *p == '!') { #if defined(__linux__) @@ -519,7 +547,7 @@ static int authenticate(uid_t uid, int ask, int persist) int fd = STDIN_FILENO; char *askpass = getenv("US_ASKPASS"); char pass[PASS_MAX] = {0}; - struct termios tio_before, tio_pass; + struct termios tio_pass; if (ask && askpass) { pid_t pid, parent = getpid(); int pipefd[2];