]> Pileus Git - ~andy/fetchmail/blob - getpass.c
Merge branch 'legacy_63'
[~andy/fetchmail] / getpass.c
1 /*
2  * For license terms, see the file COPYING in this directory.
3  */
4
5 /***********************************************************************
6   module:       getpass.c
7   project:      fetchmail
8   programmer:   Carl Harris, ceharris@mal.com
9   description:  getpass() replacement which allows for long passwords.
10                 This version hacked by Wilfred Teiken, allowing the
11                 password to be piped to fetchmail.
12  
13  ***********************************************************************/
14
15 #include "config.h"
16
17 #include <stdio.h>
18 #include <signal.h>
19 #include <fcntl.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include "fetchmail.h"
23 #include "gettext.h"
24
25 #define INPUT_BUF_SIZE  PASSWORDLEN
26
27 #include <termios.h>
28
29 static int ttyfd;
30
31 static struct termios termb;
32 static tcflag_t flags;
33
34 static void save_tty_state(void);
35 static void disable_tty_echo(void);
36 static void restore_tty_state(void);
37 static void sigint_handler(int);
38
39 char *fm_getpassword(char *prompt)
40 {
41     register char *p;
42     register int c;
43     FILE *fi;
44     static char pbuf[INPUT_BUF_SIZE];
45     SIGHANDLERTYPE sig = 0;     /* initialization pacifies -Wall */
46
47     int istty = isatty(0);
48
49     /* get the file descriptor for the actual input device if it's a tty */
50     if (istty)
51     {
52         if ((fi = fdopen(open("/dev/tty", 2), "r")) == NULL)
53             fi = stdin;
54         else
55             setbuf(fi, (char *)NULL);
56     }
57     else
58         fi = stdin;
59
60     /* store descriptor for the tty */
61     ttyfd = fileno(fi);
62
63     if (istty)
64     {
65         /* preserve tty state before turning off echo */
66         save_tty_state();
67
68         /* now that we have the current tty state, we can catch SIGINT and  
69            exit gracefully */
70         sig = set_signal_handler(SIGINT, sigint_handler);
71
72         /* turn off echo on the tty */
73         disable_tty_echo();
74
75         /* display the prompt and get the input string */
76         fprintf(stderr, "%s", prompt);
77     }
78
79     for (p = pbuf; (c = getc(fi))!='\n' && c!=EOF;)
80     {
81         if (p < &pbuf[INPUT_BUF_SIZE - 1])
82             *p++ = c;
83     }
84     *p = '\0';
85
86     /* write a newline so cursor won't appear to hang */
87     if (fi != stdin)
88         fprintf(stderr, "\n");
89
90     if (istty)
91     {
92         /* restore previous state of the tty */
93         restore_tty_state();
94
95         /* restore previous state of SIGINT */
96         set_signal_handler(SIGINT, sig);
97     }
98     if (fi != stdin)
99         fclose(fi);     /* not checking should be safe, file mode was "r" */
100
101     return(pbuf);
102 }
103
104 static void save_tty_state (void)
105 {
106     tcgetattr(ttyfd, &termb);
107     flags = termb.c_lflag;
108 }
109
110 static void disable_tty_echo(void) 
111 {
112     /* turn off echo on the tty */
113     termb.c_lflag &= ~ECHO;
114     tcsetattr(ttyfd, TCSAFLUSH, &termb);
115 }
116
117 static void restore_tty_state(void)
118 {
119     /* restore previous tty echo state */
120     termb.c_lflag = flags;
121     tcsetattr(ttyfd, TCSAFLUSH, &termb);
122 }
123
124 static void sigint_handler(int signum)
125 {
126     (void)signum;
127     restore_tty_state();
128     report(stderr, GT_("\nCaught SIGINT... bailing out.\n"));
129     exit(1);
130 }
131
132 /* getpass.c ends here */