| OLD | NEW |
| (Empty) |
| 1 /* Copyright (C) 1992-1998 Free Software Foundation, Inc. | |
| 2 This file is part of the GNU C Library. | |
| 3 | |
| 4 The GNU C Library is free software; you can redistribute it and/or | |
| 5 modify it under the terms of the GNU Lesser General Public License as | |
| 6 published by the Free Software Foundation; either version 3 of the | |
| 7 License, or (at your option) any later version. | |
| 8 | |
| 9 The GNU C Library 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 GNU | |
| 12 Library General Public License for more details. | |
| 13 | |
| 14 You should have received a copy of the GNU Lesser General Public | |
| 15 License along with the GNU C Library; see the file COPYING.LIB. If | |
| 16 not, see <http://www.gnu.org/licenses/>. */ | |
| 17 | |
| 18 /* Modified to use with samba by Jeremy Allison, 8th July 1995. */ | |
| 19 | |
| 20 #include "replace.h" | |
| 21 #include "system/filesys.h" | |
| 22 #include "system/wait.h" | |
| 23 #include "system/terminal.h" | |
| 24 #include "system/passwd.h" | |
| 25 | |
| 26 /* | |
| 27 * Define additional missing types | |
| 28 */ | |
| 29 #ifndef HAVE_SIG_ATOMIC_T_TYPE | |
| 30 typedef int sig_atomic_t; | |
| 31 #endif | |
| 32 | |
| 33 #ifndef SIGCLD | |
| 34 #define SIGCLD SIGCHLD | |
| 35 #endif | |
| 36 | |
| 37 #ifndef SIGNAL_CAST | |
| 38 #define SIGNAL_CAST (RETSIGTYPE (*)(int)) | |
| 39 #endif | |
| 40 | |
| 41 #ifdef SYSV_TERMIO | |
| 42 | |
| 43 /* SYSTEM V TERMIO HANDLING */ | |
| 44 | |
| 45 static struct termio t; | |
| 46 | |
| 47 #define ECHO_IS_ON(t) ((t).c_lflag & ECHO) | |
| 48 #define TURN_ECHO_OFF(t) ((t).c_lflag &= ~ECHO) | |
| 49 #define TURN_ECHO_ON(t) ((t).c_lflag |= ECHO) | |
| 50 | |
| 51 #ifndef TCSAFLUSH | |
| 52 #define TCSAFLUSH 1 | |
| 53 #endif | |
| 54 | |
| 55 #ifndef TCSANOW | |
| 56 #define TCSANOW 0 | |
| 57 #endif | |
| 58 | |
| 59 static int tcgetattr(int fd, struct termio *_t) | |
| 60 { | |
| 61 return ioctl(fd, TCGETA, _t); | |
| 62 } | |
| 63 | |
| 64 static int tcsetattr(int fd, int flags, struct termio *_t) | |
| 65 { | |
| 66 if(flags & TCSAFLUSH) | |
| 67 ioctl(fd, TCFLSH, TCIOFLUSH); | |
| 68 return ioctl(fd, TCSETS, _t); | |
| 69 } | |
| 70 | |
| 71 #elif !defined(TCSAFLUSH) | |
| 72 | |
| 73 /* BSD TERMIO HANDLING */ | |
| 74 | |
| 75 static struct sgttyb t; | |
| 76 | |
| 77 #define ECHO_IS_ON(t) ((t).sg_flags & ECHO) | |
| 78 #define TURN_ECHO_OFF(t) ((t).sg_flags &= ~ECHO) | |
| 79 #define TURN_ECHO_ON(t) ((t).sg_flags |= ECHO) | |
| 80 | |
| 81 #define TCSAFLUSH 1 | |
| 82 #define TCSANOW 0 | |
| 83 | |
| 84 static int tcgetattr(int fd, struct sgttyb *_t) | |
| 85 { | |
| 86 return ioctl(fd, TIOCGETP, (char *)_t); | |
| 87 } | |
| 88 | |
| 89 static int tcsetattr(int fd, int flags, struct sgttyb *_t) | |
| 90 { | |
| 91 return ioctl(fd, TIOCSETP, (char *)_t); | |
| 92 } | |
| 93 | |
| 94 #else /* POSIX TERMIO HANDLING */ | |
| 95 #define ECHO_IS_ON(t) ((t).c_lflag & ECHO) | |
| 96 #define TURN_ECHO_OFF(t) ((t).c_lflag &= ~ECHO) | |
| 97 #define TURN_ECHO_ON(t) ((t).c_lflag |= ECHO) | |
| 98 | |
| 99 static struct termios t; | |
| 100 #endif /* SYSV_TERMIO */ | |
| 101 | |
| 102 static void catch_signal(int signum,void (*handler)(int )) | |
| 103 { | |
| 104 #ifdef HAVE_SIGACTION | |
| 105 struct sigaction act; | |
| 106 struct sigaction oldact; | |
| 107 | |
| 108 memset(&act, 0, sizeof(act)); | |
| 109 | |
| 110 act.sa_handler = handler; | |
| 111 #ifdef SA_RESTART | |
| 112 /* | |
| 113 * We *want* SIGALRM to interrupt a system call. | |
| 114 */ | |
| 115 if(signum != SIGALRM) | |
| 116 act.sa_flags = SA_RESTART; | |
| 117 #endif | |
| 118 sigemptyset(&act.sa_mask); | |
| 119 sigaddset(&act.sa_mask,signum); | |
| 120 sigaction(signum,&act,&oldact); | |
| 121 #else /* !HAVE_SIGACTION */ | |
| 122 /* FIXME: need to handle sigvec and systems with broken signal() */ | |
| 123 signal(signum, handler); | |
| 124 #endif | |
| 125 } | |
| 126 | |
| 127 static sig_atomic_t gotintr; | |
| 128 static int in_fd = -1; | |
| 129 | |
| 130 /*************************************************************** | |
| 131 Signal function to tell us were ^C'ed. | |
| 132 ****************************************************************/ | |
| 133 | |
| 134 static void gotintr_sig(void) | |
| 135 { | |
| 136 gotintr = 1; | |
| 137 if (in_fd != -1) | |
| 138 close(in_fd); /* Safe way to force a return. */ | |
| 139 in_fd = -1; | |
| 140 } | |
| 141 | |
| 142 char *rep_getpass(const char *prompt) | |
| 143 { | |
| 144 FILE *in, *out; | |
| 145 int echo_off; | |
| 146 static char buf[256]; | |
| 147 static size_t bufsize = sizeof(buf); | |
| 148 size_t nread; | |
| 149 | |
| 150 /* Catch problematic signals */ | |
| 151 catch_signal(SIGINT, SIGNAL_CAST gotintr_sig); | |
| 152 | |
| 153 /* Try to write to and read from the terminal if we can. | |
| 154 If we can't open the terminal, use stderr and stdin. */ | |
| 155 | |
| 156 in = fopen ("/dev/tty", "w+"); | |
| 157 if (in == NULL) { | |
| 158 in = stdin; | |
| 159 out = stderr; | |
| 160 } else { | |
| 161 out = in; | |
| 162 } | |
| 163 | |
| 164 setvbuf(in, NULL, _IONBF, 0); | |
| 165 | |
| 166 /* Turn echoing off if it is on now. */ | |
| 167 | |
| 168 if (tcgetattr (fileno (in), &t) == 0) { | |
| 169 if (ECHO_IS_ON(t)) { | |
| 170 TURN_ECHO_OFF(t); | |
| 171 echo_off = tcsetattr (fileno (in), TCSAFLUSH, &t) == 0; | |
| 172 TURN_ECHO_ON(t); | |
| 173 } else { | |
| 174 echo_off = 0; | |
| 175 } | |
| 176 } else { | |
| 177 echo_off = 0; | |
| 178 } | |
| 179 | |
| 180 /* Write the prompt. */ | |
| 181 fputs(prompt, out); | |
| 182 fflush(out); | |
| 183 | |
| 184 /* Read the password. */ | |
| 185 buf[0] = 0; | |
| 186 if (!gotintr) { | |
| 187 in_fd = fileno(in); | |
| 188 if (fgets(buf, bufsize, in) == NULL) { | |
| 189 buf[0] = 0; | |
| 190 } | |
| 191 } | |
| 192 nread = strlen(buf); | |
| 193 if (nread) { | |
| 194 if (buf[nread - 1] == '\n') | |
| 195 buf[nread - 1] = '\0'; | |
| 196 } | |
| 197 | |
| 198 /* Restore echoing. */ | |
| 199 if (echo_off) { | |
| 200 if (gotintr && in_fd == -1) { | |
| 201 in = fopen ("/dev/tty", "w+"); | |
| 202 } | |
| 203 if (in != NULL) | |
| 204 tcsetattr (fileno (in), TCSANOW, &t); | |
| 205 } | |
| 206 | |
| 207 fprintf(out, "\n"); | |
| 208 fflush(out); | |
| 209 | |
| 210 if (in && in != stdin) /* We opened the terminal; now close it. */ | |
| 211 fclose(in); | |
| 212 | |
| 213 /* Catch problematic signals */ | |
| 214 catch_signal(SIGINT, SIGNAL_CAST SIG_DFL); | |
| 215 | |
| 216 if (gotintr) { | |
| 217 printf("Interupted by signal.\n"); | |
| 218 fflush(stdout); | |
| 219 exit(1); | |
| 220 } | |
| 221 return buf; | |
| 222 } | |
| OLD | NEW |