initial-freebsd-port-work-20010414
[openafs.git] / src / des / read_pssword.c
1 /*
2  *
3  * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
4  * of Technology.
5  *
6  * For copying and distribution information, please see the file
7  * <mit-cpyright.h>.
8  *
9  * This routine prints the supplied string to standard
10  * output as a prompt, and reads a password string without
11  * echoing.
12  */
13
14 #include <afs/param.h>
15 #include <mit-cpyright.h>
16 #include <des.h>
17 #include "conf.h"
18
19 #include <stdio.h>
20
21 #if defined(AFS_SUN5_ENV) || defined(AFS_NT40_ENV)
22 #include <string.h>
23 #else
24 #include <strings.h>
25 #endif
26
27 #ifdef  BSDUNIX
28 #ifdef  AFS_SUN5_ENV
29 #define BSD_COMP
30 #endif
31 #if defined(AFS_FBSD_ENV)
32 #define USE_OLD_TTY
33 #endif
34 #include <sys/ioctl.h>
35 #include <signal.h>
36 #include <setjmp.h>
37 #endif
38
39 #if defined(AFS_SGI_ENV) || defined(AFS_LINUX20_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
40 #include <signal.h>
41 #endif
42
43 #ifdef  AFS_HPUX_ENV
44 #include <bsdtty.h>
45 #include <sys/ttold.h>
46 #include <termios.h>
47 static int intrupt;
48 #endif
49
50 #if defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV)
51 #include <termios.h>
52 #endif
53
54 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
55 #include <termios.h>
56 #endif
57 #ifdef AFS_NT40_ENV
58 #include <windows.h>
59 #endif
60
61 static int intrupt;
62 #if defined(AFS_SGI_ENV) || defined (AFS_AIX_ENV) /*|| defined (AFS_HPUX_ENV) || defined(AFS_SUN5_ENV)*/
63 #undef  BSDUNIX
64 #endif
65
66 #ifdef  BSDUNIX
67 static jmp_buf env;
68 #endif
69
70 #ifdef BSDUNIX
71 #define POSIX
72 #ifdef POSIX
73 typedef void sigtype;
74 #else
75 typedef int sigtype;
76 #endif
77 static sigtype sig_restore();
78 static push_signals(), pop_signals();
79 int des_read_pw_string();
80 #endif
81
82 /*** Routines ****************************************************** */
83 int
84 des_read_password(k,prompt,verify)
85     des_cblock *k;
86     char *prompt;
87     int verify;
88 {
89     int ok;
90     char key_string[BUFSIZ];
91
92 #ifdef BSDUNIX
93     if (setjmp(env)) {
94         ok = -1;
95         goto lose;
96     }
97 #endif
98
99     ok = des_read_pw_string(key_string, BUFSIZ, prompt, verify);
100     if (ok == 0)
101         des_string_to_key(key_string, k);
102
103 lose:
104     bzero(key_string, sizeof (key_string));
105     return ok;
106 }
107
108 #if     defined (AFS_AIX_ENV) || defined (AFS_HPUX_ENV) || defined(AFS_SGI_ENV) || defined(AFS_SUN_ENV) || defined(AFS_LINUX20_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
109 static void catch(int);
110 #endif
111
112 #if     !defined(BSDUNIX) && (defined(AFS_AIX_ENV) || defined (AFS_HPUX_ENV) || defined(AFS_SGI_ENV) || defined(AFS_LINUX20_ENV))
113 #include <termio.h>
114 #endif
115
116 /*
117  * This version just returns the string, doesn't map to key.
118  *
119  * Returns 0 on success, non-zero on failure.
120  */
121 int
122 des_read_pw_string(s,maxa,prompt,verify)
123     char *s;
124     int maxa;
125     char *prompt;
126     int verify;
127 {
128     int ok = 0, cnt1=0;
129     char *ptr;
130 #if defined(AFS_HPUX_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
131     register int fno;
132     struct sigaction newsig, oldsig;
133     struct termios save_ttyb, ttyb;
134 #endif
135 #if defined(AFS_DARWIN_ENV)
136     FILE *fi;
137 #endif
138 #if     defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV)
139     struct termios ttyb;
140     struct sigaction osa, sa;
141 #endif
142 #ifdef BSDUNIX
143     jmp_buf old_env;
144     unsigned long flags;
145     struct sgttyb tty_state, echo_off_tty_state;
146     FILE *fi;
147 #else
148 #if     defined (AFS_AIX_ENV) || defined (AFS_HPUX_ENV) || defined(AFS_SGI_ENV) || defined(AFS_LINUX20_ENV)
149     struct termio ttyb;
150     FILE *fi;
151     char savel, flags;
152     void (*sig)();
153     extern void setbuf();
154     extern int kill(), fclose();
155 #endif
156 #endif
157 #ifdef AFS_NT40_ENV
158     HANDLE hConStdin;
159     DWORD oldConMode, newConMode;
160     BOOL resetConMode = FALSE;
161 #endif
162     char key_string[BUFSIZ];
163
164     if (maxa > BUFSIZ) {
165         return -1;
166     }
167
168 #if defined(AFS_HPUX_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
169     if ((fi = fopen("/dev/tty", "r")) == NULL)
170         return -1;
171     setbuf(fi, (char *)NULL);                   /* We don't want any buffering for our i/o. */
172     /*
173      * Install signal handler for SIGINT so that we can restore
174      * the tty settings after we change them.  The handler merely
175      * increments the variable "intrupt" to tell us that an
176      * interrupt signal was received.
177      */
178     newsig.sa_handler = catch;
179     sigemptyset(&newsig.sa_mask);
180     newsig.sa_flags = 0;
181     sigaction(SIGINT, &newsig, &oldsig);
182     intrupt = 0;
183  
184     /*
185      * Get the terminal characters (save for later restoration) and
186      * reset them so that echo is off
187      */
188     fno = fileno(fi);
189     tcgetattr(fno, &ttyb);
190     save_ttyb = ttyb;
191     ttyb.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
192     tcsetattr(fno, TCSAFLUSH, &ttyb);
193 #else
194 #if     defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV)
195     if((fi = fopen("/dev/tty", "r")) == NULL) {
196                 return(-1);
197             }
198     else
199         setbuf(fi, (char*)NULL);
200     sa.sa_handler = catch;
201     sa.sa_mask = 0;
202     sa.sa_flags = SA_INTERRUPT;
203     (void) sigaction(SIGINT, &sa, &osa);
204     intrupt = 0;
205     (void) ioctl(fileno(fi), TCGETS, &ttyb);
206     flags = ttyb.c_lflag;
207     ttyb.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
208     (void) ioctl(fileno(fi), TCSETSF, &ttyb);
209 #else
210 #ifdef  BSDUNIX
211     /* XXX assume jmp_buf is typedef'ed to an array */
212     bcopy((char *)old_env, (char *)env, sizeof(env));
213     if (setjmp(env))
214         goto lose;
215     /* save terminal state*/
216     if (ioctl(0,TIOCGETP,(char *)&tty_state) == -1)
217         return -1;
218     push_signals();
219     /* Turn off echo */
220     bcopy (&tty_state, &echo_off_tty_state, sizeof (tty_state));
221     echo_off_tty_state.sg_flags &= ~ECHO;
222     if (ioctl(0,TIOCSETP,(char *)&echo_off_tty_state) == -1)
223         return -1;
224 #else
225 #if     defined (AFS_AIX_ENV) || defined (AFS_HPUX_ENV) || defined(AFS_SGI_ENV) || defined(AFS_LINUX20_ENV)
226         if((fi = fopen("/dev/tty", "r+")) == NULL)
227                 return(-1);
228         else
229                 setbuf(fi, (char*)NULL);
230         sig = signal(SIGINT, catch);
231         intrupt = 0;
232         (void) ioctl(fileno(fi), TCGETA, &ttyb);
233         savel = ttyb.c_line;
234         ttyb.c_line = 0;
235         flags = ttyb.c_lflag;
236         ttyb.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
237         (void) ioctl(fileno(fi), TCSETAF, &ttyb);
238 #else
239 #ifdef AFS_NT40_ENV
240     /* turn off console input echoing */
241     if ((hConStdin = GetStdHandle(STD_INPUT_HANDLE)) != INVALID_HANDLE_VALUE) {
242         if (GetConsoleMode(hConStdin, &oldConMode)) {
243             newConMode = (oldConMode & ~(ENABLE_ECHO_INPUT));
244             if (SetConsoleMode(hConStdin, newConMode)) {
245                 resetConMode = TRUE;
246             }
247         }
248     }
249 #endif
250 #endif
251 #endif
252 #endif
253 #endif
254     while (!ok) {
255         (void) printf(prompt);
256         (void) fflush(stdout);
257 #ifdef  CROSSMSDOS
258         h19line(s,sizeof(s),0);
259         if (!strlen(s))
260             continue;
261 #else
262         if (!fgets(s, maxa, stdin)) {
263             clearerr(stdin);
264             printf("\n");
265             if (cnt1++ > 1) {
266                 /*
267                  * Otherwise hitting ctrl-d will always leave us inside this loop forever!
268                  */
269                 break;
270             }
271             continue;
272         }
273         if ((ptr = index(s, '\n')))
274             *ptr = '\0';
275 #endif
276         if (verify) {
277             printf("\nVerifying, please re-enter %s",prompt);
278             (void) fflush(stdout);
279 #ifdef CROSSMSDOS
280             h19line(key_string,sizeof(key_string),0);
281             if (!strlen(key_string))
282                 continue;
283 #else
284             if (!fgets(key_string, sizeof(key_string), stdin)) {
285                 clearerr(stdin);
286                 continue;
287             }
288             if ((ptr = index(key_string, '\n')))
289             *ptr = '\0';
290 #endif
291             if (strcmp(s,key_string)) {
292                 printf("\n\07\07Mismatch - try again\n");
293                 (void) fflush(stdout);
294                 continue;
295             }
296         }
297         ok = 1;
298     }
299
300 lose:
301     if (!ok)
302         bzero(s, maxa);
303     printf("\n");
304 #ifdef  AFS_HPUX_ENV
305     /*
306      * Restore the terminal to its previous characteristics.
307      * Restore the old signal handler for SIGINT.
308      */
309     tcsetattr(fno, TCSANOW, &save_ttyb);
310     sigaction(SIGINT, &oldsig, (struct sigaction *)0);
311     if (fi != stdin)
312         fclose(fi);
313  
314     /*
315      * If we got a SIGINT while we were doing things, send the SIGINT
316      * to ourselves so that the calling program receives it (since we
317      * were intercepting it for a period of time.)
318      */
319     if (intrupt)
320         kill(getpid(), SIGINT);
321 #else
322 #if     defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV)
323     ttyb.c_lflag = flags;
324     (void) ioctl(fileno(fi), TCSETSW, &ttyb);
325     (void) sigaction(SIGINT, &osa, (struct sigaction *)NULL);
326     if(fi != stdin)
327         (void) fclose(fi);
328 #else
329 #ifdef  BSDUNIX
330     if (ioctl(0,TIOCSETP,(char *)&tty_state))
331         ok = 0;
332     pop_signals();
333     bcopy((char *)env, (char *)old_env, sizeof(env));
334 #else
335 #if     defined (AFS_AIX_ENV) /*|| defined (AFS_HPUX_ENV)*/ || defined(AFS_SGI_ENV) || defined(AFS_LINUX20_ENV)
336     ttyb.c_lflag = flags;
337     ttyb.c_line = savel;
338     (void) ioctl(fileno(fi), TCSETAW, &ttyb);
339     (void) signal(SIGINT, sig);
340     if(fi != stdin)
341         (void) fclose(fi);
342     if(intrupt)
343         (void) kill(getpid(), SIGINT);
344 #else
345 #ifdef AFS_NT40_ENV
346     /* restore console to original mode settings */
347     if (resetConMode) {
348         (void)SetConsoleMode(hConStdin, oldConMode);
349     }
350 #endif
351 #endif
352 #endif
353 #endif
354 #endif
355     if (verify)
356         bzero(key_string, sizeof (key_string));
357     s[maxa-1] = 0;              /* force termination */
358     return !ok;                 /* return nonzero if not okay */
359 }
360
361 #ifdef  BSDUNIX
362 /*
363  * this can be static since we should never have more than
364  * one set saved....
365  */
366 #ifdef mips
367 void static (*old_sigfunc[NSIG])();
368 #else
369 static sigtype (*old_sigfunc[NSIG])();
370 #endif
371
372 static push_signals()
373 {
374     register i;
375     for (i = 0; i < NSIG; i++)
376         old_sigfunc[i] = signal(i,sig_restore);
377 }
378
379 static pop_signals()
380 {
381     register i;
382     for (i = 0; i < NSIG; i++)
383         (void) signal(i,old_sigfunc[i]);
384 }
385
386 static sigtype
387 sig_restore()
388 {
389     longjmp(env,1);
390 }
391 #endif
392
393
394 #if     defined (AFS_AIX_ENV) || defined (AFS_HPUX_ENV) || defined(AFS_SGI_ENV) || defined(AFS_SUN_ENV) || defined(AFS_LINUX20_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
395 static void
396 catch(int junk)
397 {
398         ++intrupt;
399 }
400 #endif