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 |