1/* Copyright (C) 1992,93,94,95,96,97,98,99,2000, 2001 Free Software Foundation, Inc. 2 This file is part of the GNU C Library. 3 4 This program is free software; you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation; either version 2, or (at your option) 7 any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License along 15 with this program; if not, write to the Free Software Foundation, 16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 17 18#if HAVE_CONFIG_H 19# include <config.h> 20#endif 21 22#include <stdio.h> 23#ifndef SEEK_CUR 24#define SEEK_CUR 1 25#endif 26#include <termios.h> 27#include <unistd.h> 28#include "getline.h" 29 30/* It is desirable to use this bit on systems that have it. 31 The only bit of terminal state we want to twiddle is echoing, which is 32 done in software; there is no need to change the state of the terminal 33 hardware. */ 34 35#ifndef TCSASOFT 36# define TCSASOFT 0 37#endif 38 39char * 40#if __STDC__ 41getpass (const char *prompt) 42#else 43getpass (prompt) 44 const char *prompt; 45#endif 46{ 47 FILE *in, *out; 48 struct termios s, t; 49 int tty_changed; 50 static char *buf; 51 static size_t bufsize; 52 ssize_t nread; 53 54 /* Try to write to and read from the terminal if we can. 55 If we can't open the terminal, use stderr and stdin. */ 56 57 in = fopen ("/dev/tty", "w+"); 58 if (in == NULL) 59 { 60 in = stdin; 61 out = stderr; 62 } 63 else 64 out = in; 65 66 /* Turn echoing off if it is on now. */ 67 68 if (tcgetattr (fileno (in), &t) == 0) 69 { 70 /* Save the old one. */ 71 s = t; 72 /* Tricky, tricky. */ 73 t.c_lflag &= ~(ECHO|ISIG); 74 tty_changed = (tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &t) == 0); 75 } 76 else 77 tty_changed = 0; 78 79 /* Write the prompt. */ 80 fputs (prompt, out); 81 fflush (out); 82 83 /* Read the password. */ 84 nread = getline (&buf, &bufsize, in); 85 if (buf != NULL) 86 { 87 if (nread < 0) 88 buf[0] = '\0'; 89 else if (buf[nread - 1] == '\n') 90 { 91 /* Remove the newline. */ 92 buf[nread - 1] = '\0'; 93 if (tty_changed) 94 { 95 /* Write the newline that was not echoed. */ 96 if (out == in) fseek (out, 0, SEEK_CUR); 97 putc ('\n', out); 98 } 99 } 100 } 101 102 /* Restore the original setting. */ 103 if (tty_changed) 104 (void) tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &s); 105 106 if (in != stdin) 107 /* We opened the terminal; now close it. */ 108 fclose (in); 109 110 return buf; 111} 112