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 : #ifdef SYSV_TERMIO
38 :
39 : /* SYSTEM V TERMIO HANDLING */
40 :
41 : static struct termio t;
42 :
43 : #define ECHO_IS_ON(t) ((t).c_lflag & ECHO)
44 : #define TURN_ECHO_OFF(t) ((t).c_lflag &= ~ECHO)
45 : #define TURN_ECHO_ON(t) ((t).c_lflag |= ECHO)
46 :
47 : #ifndef TCSAFLUSH
48 : #define TCSAFLUSH 1
49 : #endif
50 :
51 : #ifndef TCSANOW
52 : #define TCSANOW 0
53 : #endif
54 :
55 : static int tcgetattr(int fd, struct termio *_t)
56 : {
57 : return ioctl(fd, TCGETA, _t);
58 : }
59 :
60 : static int tcsetattr(int fd, int flags, struct termio *_t)
61 : {
62 : if(flags & TCSAFLUSH)
63 : ioctl(fd, TCFLSH, TCIOFLUSH);
64 : return ioctl(fd, TCSETS, _t);
65 : }
66 :
67 : #elif !defined(TCSAFLUSH)
68 :
69 : /* BSD TERMIO HANDLING */
70 :
71 : static struct sgttyb t;
72 :
73 : #define ECHO_IS_ON(t) ((t).sg_flags & ECHO)
74 : #define TURN_ECHO_OFF(t) ((t).sg_flags &= ~ECHO)
75 : #define TURN_ECHO_ON(t) ((t).sg_flags |= ECHO)
76 :
77 : #define TCSAFLUSH 1
78 : #define TCSANOW 0
79 :
80 : static int tcgetattr(int fd, struct sgttyb *_t)
81 : {
82 : return ioctl(fd, TIOCGETP, (char *)_t);
83 : }
84 :
85 : static int tcsetattr(int fd, int flags, struct sgttyb *_t)
86 : {
87 : return ioctl(fd, TIOCSETP, (char *)_t);
88 : }
89 :
90 : #else /* POSIX TERMIO HANDLING */
91 : #define ECHO_IS_ON(t) ((t).c_lflag & ECHO)
92 : #define TURN_ECHO_OFF(t) ((t).c_lflag &= ~ECHO)
93 : #define TURN_ECHO_ON(t) ((t).c_lflag |= ECHO)
94 :
95 : static struct termios t;
96 : #endif /* SYSV_TERMIO */
97 :
98 : static void catch_signal(int signum, void (*handler)(int ))
99 0 : {
100 : #ifdef HAVE_SIGACTION
101 : struct sigaction act;
102 : struct sigaction oldact;
103 :
104 0 : memset(&act, 0, sizeof(act));
105 :
106 0 : act.sa_handler = handler;
107 : #ifdef SA_RESTART
108 : /*
109 : * We *want* SIGALRM to interrupt a system call.
110 : */
111 0 : if(signum != SIGALRM)
112 0 : act.sa_flags = SA_RESTART;
113 : #endif
114 0 : sigemptyset(&act.sa_mask);
115 0 : sigaddset(&act.sa_mask,signum);
116 0 : sigaction(signum,&act,&oldact);
117 : #else /* !HAVE_SIGACTION */
118 : /* FIXME: need to handle sigvec and systems with broken signal() */
119 : signal(signum, handler);
120 : #endif
121 0 : }
122 :
123 : static sig_atomic_t gotintr;
124 : static int in_fd = -1;
125 :
126 : /***************************************************************
127 : Signal function to tell us were ^C'ed.
128 : ****************************************************************/
129 :
130 : static void gotintr_sig(int signum)
131 0 : {
132 0 : gotintr = 1;
133 0 : if (in_fd != -1)
134 0 : close(in_fd); /* Safe way to force a return. */
135 0 : in_fd = -1;
136 0 : }
137 :
138 : char *rep_getpass(const char *prompt)
139 0 : {
140 : FILE *in, *out;
141 : int echo_off;
142 : static char buf[256];
143 : static size_t bufsize = sizeof(buf);
144 : size_t nread;
145 :
146 : /* Catch problematic signals */
147 0 : catch_signal(SIGINT, gotintr_sig);
148 :
149 : /* Try to write to and read from the terminal if we can.
150 : If we can't open the terminal, use stderr and stdin. */
151 :
152 0 : in = fopen ("/dev/tty", "w+");
153 0 : if (in == NULL) {
154 0 : in = stdin;
155 0 : out = stderr;
156 : } else {
157 0 : out = in;
158 : }
159 :
160 0 : setvbuf(in, NULL, _IONBF, 0);
161 :
162 : /* Turn echoing off if it is on now. */
163 :
164 0 : if (tcgetattr (fileno (in), &t) == 0) {
165 0 : if (ECHO_IS_ON(t)) {
166 0 : TURN_ECHO_OFF(t);
167 0 : echo_off = tcsetattr (fileno (in), TCSAFLUSH, &t) == 0;
168 0 : TURN_ECHO_ON(t);
169 : } else {
170 0 : echo_off = 0;
171 : }
172 : } else {
173 0 : echo_off = 0;
174 : }
175 :
176 : /* Write the prompt. */
177 0 : fputs(prompt, out);
178 0 : fflush(out);
179 :
180 : /* Read the password. */
181 0 : buf[0] = 0;
182 0 : if (!gotintr) {
183 0 : in_fd = fileno(in);
184 0 : if (fgets(buf, bufsize, in) == NULL) {
185 0 : buf[0] = 0;
186 : }
187 : }
188 0 : nread = strlen(buf);
189 0 : if (nread) {
190 0 : if (buf[nread - 1] == '\n')
191 0 : buf[nread - 1] = '\0';
192 : }
193 :
194 : /* Restore echoing. */
195 0 : if (echo_off) {
196 0 : if (gotintr && in_fd == -1) {
197 0 : in = fopen ("/dev/tty", "w+");
198 : }
199 0 : if (in != NULL)
200 0 : tcsetattr (fileno (in), TCSANOW, &t);
201 : }
202 :
203 0 : fprintf(out, "\n");
204 0 : fflush(out);
205 :
206 0 : if (in && in != stdin) /* We opened the terminal; now close it. */
207 0 : fclose(in);
208 :
209 : /* Catch problematic signals */
210 0 : catch_signal(SIGINT, SIG_DFL);
211 :
212 0 : if (gotintr) {
213 0 : printf("Interrupted by signal.\n");
214 0 : fflush(stdout);
215 0 : exit(1);
216 : }
217 0 : return buf;
218 : }
|