]> granicus.if.org Git - sudo/commitdiff
Use SA_INTERRUPT so SunOS works correctly, avoid stdio and just use read/write
authorTodd C. Miller <Todd.Miller@courtesan.com>
Fri, 28 May 2004 22:06:50 +0000 (22:06 +0000)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Fri, 28 May 2004 22:06:50 +0000 (22:06 +0000)
as it is simpler.

tgetpass.c

index fb3d5ed0a6c979978f153123ac64a90062e98a8a..c3771c73a6e442fc123152c4a6dcede06736f02f 100644 (file)
@@ -115,6 +115,7 @@ static const char rcsid[] = "$Sudo$";
 static volatile sig_atomic_t signo;
 
 static void handler __P((int));
+static char *getln __P((int, char *, size_t));
 
 /*
  * Like getpass(3) but with timeout and echo flags.
@@ -127,29 +128,26 @@ tgetpass(prompt, timeout, flags)
 {
     sigaction_t sa, savealrm, saveint, savehup, savequit, saveterm;
     sigaction_t savetstp, savettin, savettou;
-    FILE *input, *output;
     struct TERM term, oterm;
-    char *pass, *ep;
+    char *pass;
     static char buf[SUDO_PASS_MAX + 1];
-    int fd, save_errno;
+    int input, output, save_errno;
 
+    (void) fflush(stdout);
 restart:
     /* Open /dev/tty for reading/writing if possible else use stdin/stderr. */
     if (ISSET(flags, TGP_STDIN) ||
-       (fd = open(_PATH_TTY, O_RDWR|O_NOCTTY)) == -1 ||
-       (input = output = fdopen(fd, "r+")) == NULL) {
-       input = stdin;
-       output = stderr;
-       (void) fflush(output);
+       (input = output = open(_PATH_TTY, O_RDWR|O_NOCTTY)) == -1) {
+       input = STDIN_FILENO;
+       output = STDERR_FILENO;
     }
 
     /*
      * Catch signals that would otherwise cause the user to end
-     * up with echo turned off in the shell.  Don't worry about
-     * things like SIGALRM and SIGPIPE for now.
+     * up with echo turned off in the shell.
      */
     sigemptyset(&sa.sa_mask);
-    sa.sa_flags = 0;           /* don't restart system calls */
+    sa.sa_flags = SA_INTERRUPT;        /* don't restart system calls */
     sa.sa_handler = handler;
     (void) sigaction(SIGALRM, &sa, &savealrm);
     (void) sigaction(SIGINT, &sa, &saveint);
@@ -161,43 +159,34 @@ restart:
     (void) sigaction(SIGTTOU, &sa, &savettou);
 
     /* Turn echo off/on as specified by flags.  */
-    if (term_getattr(fileno(input), &oterm) == 0) {
+    if (term_getattr(input, &oterm) == 0) {
        (void) memcpy(&term, &oterm, sizeof(term));
        if (!ISSET(flags, TGP_ECHO))
            CLR(term.tflags, (ECHO | ECHONL));
 #ifdef VSTATUS
        term.c_cc[VSTATUS] = _POSIX_VDISABLE;
 #endif
-       (void) term_setattr(fileno(input), &term);
+       (void) term_setattr(input, &term);
     } else {
        memset(&term, 0, sizeof(term));
        memset(&oterm, 0, sizeof(oterm));
     }
 
-    if (prompt) {
-       (void) fputs(prompt, output);
-       (void) fflush(output);
-       if (input == output)
-           (void) rewind(input);
-    }
+    if (prompt)
+       (void) write(output, prompt, strlen(prompt));
 
     if (timeout > 0)
        alarm(timeout);
-    pass = fgets(buf, sizeof(buf), input);
+    pass = getln(input, buf, sizeof(buf));
     alarm(0);
-    if (pass != NULL) {
-       ep = pass + strlen(pass);
-       while (ep > pass && (*--ep == '\n' || *ep == '\r'))
-               *ep = '\0';
-    }
     save_errno = errno;
 
     if (!ISSET(term.tflags, ECHO))
-       fputc('\n', output);
+       (void) write(output, "\n", 1);
 
     /* Restore old tty settings and signals. */
     if (memcmp(&term, &oterm, sizeof(term)) != 0)
-       (void) term_setattr(fileno(input), &oterm);
+       (void) term_setattr(input, &oterm);
     (void) sigaction(SIGALRM, &savealrm, NULL);
     (void) sigaction(SIGINT, &saveint, NULL);
     (void) sigaction(SIGHUP, &savehup, NULL);
@@ -206,8 +195,8 @@ restart:
     (void) sigaction(SIGTSTP, &savetstp, NULL);
     (void) sigaction(SIGTTIN, &savettin, NULL);
     (void) sigaction(SIGTTOU, &savettou, NULL);
-    if (input != stdin)
-       (void) fclose(input);
+    if (input != STDIN_FILENO)
+       (void) close(input);
 
     /*
      * If we were interrupted by a signal, resend it to ourselves
@@ -228,6 +217,28 @@ restart:
     return(pass);
 }
 
+static char *
+getln(fd, buf, bufsiz)
+    int fd;
+    char *buf;
+    size_t bufsiz;
+{
+    char c, *cp;
+    ssize_t nr;
+
+    if (bufsiz == 0) {
+       errno = EINVAL;
+       return(NULL);                   /* sanity */
+    }
+
+    cp = buf;
+    nr = -1;
+    while (--bufsiz && (nr = read(fd, &c, 1)) == 1 && c != '\n' && c != '\r')
+       *cp++ = c;
+    *cp = '\0';
+    return(nr == -1 ? NULL : buf);
+}
+
 static void
 handler(s)
     int s;