Annotation of src/usr.bin/sudo/tgetpass.c, Revision 1.1
1.1 ! millert 1: /*
! 2: * Copyright (c) 1996, 1998, 1999 Todd C. Miller <Todd.Miller@courtesan.com>
! 3: * All rights reserved.
! 4: *
! 5: * Redistribution and use in source and binary forms, with or without
! 6: * modification, are permitted provided that the following conditions
! 7: * are met:
! 8: *
! 9: * 1. Redistributions of source code must retain the above copyright
! 10: * notice, this list of conditions and the following disclaimer.
! 11: *
! 12: * 2. Redistributions in binary form must reproduce the above copyright
! 13: * notice, this list of conditions and the following disclaimer in the
! 14: * documentation and/or other materials provided with the distribution.
! 15: *
! 16: * 3. The name of the author may not be used to endorse or promote products
! 17: * derived from this software without specific prior written permission.
! 18: *
! 19: * 4. Products derived from this software may not be called "Sudo" nor
! 20: * may "Sudo" appear in their names without specific prior written
! 21: * permission from the author.
! 22: *
! 23: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
! 24: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
! 25: * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
! 26: * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
! 27: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
! 28: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
! 29: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
! 30: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
! 31: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
! 32: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 33: */
! 34:
! 35: #include "config.h"
! 36:
! 37: #include <stdio.h>
! 38: #ifdef STDC_HEADERS
! 39: #include <stdlib.h>
! 40: #endif /* STDC_HEADERS */
! 41: #ifdef HAVE_UNISTD_H
! 42: #include <unistd.h>
! 43: #endif /* HAVE_UNISTD_H */
! 44: #ifdef HAVE_STRING_H
! 45: #include <string.h>
! 46: #endif /* HAVE_STRING_H */
! 47: #ifdef HAVE_STRINGS_H
! 48: #include <strings.h>
! 49: #endif /* HAVE_STRINGS_H */
! 50: #include <pwd.h>
! 51: #include <sys/param.h>
! 52: #include <sys/types.h>
! 53: #ifdef HAVE_SYS_BSDTYPES_H
! 54: #include <sys/bsdtypes.h>
! 55: #endif /* HAVE_SYS_BSDTYPES_H */
! 56: #ifdef HAVE_SYS_SELECT_H
! 57: #include <sys/select.h>
! 58: #endif /* HAVE_SYS_SELECT_H */
! 59: #include <sys/time.h>
! 60: #include <errno.h>
! 61: #include <signal.h>
! 62: #include <fcntl.h>
! 63: #ifdef HAVE_TERMIOS_H
! 64: #include <termios.h>
! 65: #else
! 66: #ifdef HAVE_TERMIO_H
! 67: #include <termio.h>
! 68: #else
! 69: #include <sgtty.h>
! 70: #include <sys/ioctl.h>
! 71: #endif /* HAVE_TERMIO_H */
! 72: #endif /* HAVE_TERMIOS_H */
! 73:
! 74: #include "sudo.h"
! 75:
! 76: #ifndef TCSASOFT
! 77: #define TCSASOFT 0
! 78: #endif /* TCSASOFT */
! 79:
! 80: #ifndef lint
! 81: static const char rcsid[] = "$Sudo: tgetpass.c,v 1.90 1999/11/01 15:58:46 millert Exp $";
! 82: #endif /* lint */
! 83:
! 84: static char *tgetline __P((int, char *, size_t, int));
! 85:
! 86: /*
! 87: * Like getpass(3) but with timeout and echo flags.
! 88: */
! 89: char *
! 90: tgetpass(prompt, timeout, echo_off)
! 91: const char *prompt;
! 92: int timeout;
! 93: int echo_off;
! 94: {
! 95: #ifdef HAVE_TERMIOS_H
! 96: struct termios term;
! 97: #else
! 98: #ifdef HAVE_TERMIO_H
! 99: struct termio term;
! 100: #else
! 101: struct sgttyb ttyb;
! 102: #endif /* HAVE_TERMIO_H */
! 103: #endif /* HAVE_TERMIOS_H */
! 104: int input, output;
! 105: static char buf[SUDO_PASS_MAX + 1];
! 106:
! 107: /* Open /dev/tty for reading/writing if possible else use stdin/stderr. */
! 108: if ((input = output = open(_PATH_TTY, O_RDWR|O_NOCTTY)) == -1) {
! 109: input = STDIN_FILENO;
! 110: output = STDERR_FILENO;
! 111: }
! 112:
! 113: if (prompt)
! 114: (void) write(output, prompt, strlen(prompt) + 1);
! 115:
! 116: if (echo_off) {
! 117: #ifdef HAVE_TERMIOS_H
! 118: (void) tcgetattr(input, &term);
! 119: if ((echo_off = (term.c_lflag & ECHO))) {
! 120: term.c_lflag &= ~ECHO;
! 121: (void) tcsetattr(input, TCSAFLUSH|TCSASOFT, &term);
! 122: }
! 123: #else
! 124: #ifdef HAVE_TERMIO_H
! 125: (void) ioctl(input, TCGETA, &term);
! 126: if ((echo_off = (term.c_lflag & ECHO))) {
! 127: term.c_lflag &= ~ECHO;
! 128: (void) ioctl(input, TCSETA, &term);
! 129: }
! 130: #else
! 131: (void) ioctl(input, TIOCGETP, &ttyb);
! 132: if ((echo_off = (ttyb.sg_flags & ECHO))) {
! 133: ttyb.sg_flags &= ~ECHO;
! 134: (void) ioctl(input, TIOCSETP, &ttyb);
! 135: }
! 136: #endif /* HAVE_TERMIO_H */
! 137: #endif /* HAVE_TERMIOS_H */
! 138: }
! 139:
! 140: buf[0] = '\0';
! 141: tgetline(input, buf, sizeof(buf), timeout);
! 142:
! 143: #ifdef HAVE_TERMIOS_H
! 144: if (echo_off) {
! 145: term.c_lflag |= ECHO;
! 146: (void) tcsetattr(input, TCSAFLUSH|TCSASOFT, &term);
! 147: }
! 148: #else
! 149: #ifdef HAVE_TERMIO_H
! 150: if (echo_off) {
! 151: term.c_lflag |= ECHO;
! 152: (void) ioctl(input, TCSETA, &term);
! 153: }
! 154: #else
! 155: if (echo_off) {
! 156: ttyb.sg_flags |= ECHO;
! 157: (void) ioctl(input, TIOCSETP, &ttyb);
! 158: }
! 159: #endif /* HAVE_TERMIO_H */
! 160: #endif /* HAVE_TERMIOS_H */
! 161:
! 162: if (echo_off)
! 163: (void) write(output, "\n", 1);
! 164:
! 165: if (input != STDIN_FILENO)
! 166: (void) close(input);
! 167:
! 168: return(buf);
! 169: }
! 170:
! 171: /*
! 172: * Get a line of input (optionally timing out) and place it in buf.
! 173: */
! 174: static char *
! 175: tgetline(fd, buf, bufsiz, timeout)
! 176: int fd;
! 177: char *buf;
! 178: size_t bufsiz;
! 179: int timeout;
! 180: {
! 181: size_t left;
! 182: int n;
! 183: fd_set *readfds = NULL;
! 184: struct timeval tv;
! 185: char c;
! 186: char *cp;
! 187:
! 188: if (bufsiz == 0)
! 189: return(NULL); /* sanity */
! 190:
! 191: /*
! 192: * Timeout of <= 0 means no timeout.
! 193: */
! 194: if (timeout > 0) {
! 195: /* Setup for select(2) */
! 196: n = howmany(fd + 1, NFDBITS) * sizeof(fd_mask);
! 197: readfds = (fd_set *) emalloc(n);
! 198: (void) memset((VOID *)readfds, 0, n);
! 199: FD_SET(fd, readfds);
! 200:
! 201: /* Set timeout for select */
! 202: tv.tv_sec = timeout;
! 203: tv.tv_usec = 0;
! 204:
! 205: /*
! 206: * Make sure there is something to read or timeout
! 207: */
! 208: while ((n = select(fd + 1, readfds, 0, 0, &tv)) == -1 &&
! 209: errno == EINTR)
! 210: ;
! 211: if (n == 0)
! 212: return(NULL); /* timeout */
! 213: }
! 214: if (readfds)
! 215: free(readfds);
! 216:
! 217: /* Keep reading until out of space, EOF, error, or newline */
! 218: cp = buf;
! 219: left = bufsiz;
! 220: while (--left && (n = read(fd, &c, 1)) == 1 && c != '\n')
! 221: *cp++ = c;
! 222: *cp = '\0';
! 223:
! 224: return(cp == buf ? NULL : buf);
! 225: }