]> Pileus Git - ~andy/fetchmail/blob - getpass.c
Progress messages now go to stdout.
[~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 #if defined(HAVE_UNISTD_H)
21 #include <unistd.h>
22 #endif
23 #include "fetchmail.h"
24 #include "i18n.h"
25
26 #define INPUT_BUF_SIZE  PASSWORDLEN
27
28 #if defined(HAVE_TERMIOS_H) && defined(HAVE_TCSETATTR)
29 #  include <termios.h>
30 #else
31 #if defined(HAVE_TERMIO_H)
32 #  include <sys/ioctl.h>
33 #  include <termio.h>
34 #else
35 #if defined(HAVE_SGTTY_H)
36 #  include <sgtty.h>
37 #endif
38 #endif
39 #endif
40
41 static int ttyfd;
42
43 #if defined(HAVE_TCSETATTR)
44   static struct termios termb;
45   static tcflag_t flags;
46 #else
47 #if defined(HAVE_TERMIO_H)
48   static struct termio termb;
49   static unsigned short flags;
50 #else
51 #if defined(HAVE_STTY)
52   static struct sgttyb ttyb;
53   static int flags;
54 #endif
55 #endif
56 #endif
57
58 void static save_tty_state(void);
59 void static disable_tty_echo(void);
60 void static restore_tty_state(void);
61 static RETSIGTYPE sigint_handler(int);
62
63 char *getpassword(prompt)
64 char *prompt;
65 {
66 #if !(defined(HAVE_TCSETATTR) || defined(HAVE_TERMIO_H) || defined(HAVE_STTY))
67 #if defined(HAVE_GETPASS) 
68     char *getpass();
69     return getpass(prompt);
70 #else
71     fputs(_("ERROR: no support for getpassword() routine\n"),stderr);
72     exit(1);
73 #endif
74 #else
75     register char *p;
76     register int c;
77     FILE *fi;
78     static char pbuf[INPUT_BUF_SIZE];
79     RETSIGTYPE (*sig)(int) = 0; /* initialization pacifies -Wall */
80     RETSIGTYPE sigint_handler(int);
81
82     int istty = isatty(0);
83
84     /* get the file descriptor for the actual input device if it's a tty */
85     if (istty)
86     {
87         if ((fi = fdopen(open("/dev/tty", 2), "r")) == NULL)
88             fi = stdin;
89         else
90             setbuf(fi, (char *)NULL);
91     }
92     else
93         fi = stdin;
94
95     /* store descriptor for the tty */
96     ttyfd = fileno(fi);
97
98     if (istty)
99     {
100         /* preserve tty state before turning off echo */
101         save_tty_state();
102
103         /* now that we have the current tty state, we can catch SIGINT and  
104            exit gracefully */
105         sig = signal(SIGINT, sigint_handler);
106
107         /* turn off echo on the tty */
108         disable_tty_echo();
109
110         /* display the prompt and get the input string */
111         fprintf(stderr, "%s", prompt);
112     }
113
114     for (p = pbuf; (c = getc(fi))!='\n' && c!=EOF;)
115     {
116         if (p < &pbuf[INPUT_BUF_SIZE - 1])
117             *p++ = c;
118     }
119     *p = '\0';
120
121     /* write a newline so cursor won't appear to hang */
122     if (fi != stdin)
123         fprintf(stderr, "\n");
124
125     if (istty)
126     {
127         /* restore previous state of the tty */
128         restore_tty_state();
129
130         /* restore previous state of SIGINT */
131         signal(SIGINT, sig);
132     }
133     if (fi != stdin)
134         fclose(fi);
135
136     return(pbuf);
137 #endif /* !(defined(HAVE_TCSETATTR) || ... */
138 }
139
140 static void save_tty_state (void)
141 {
142 #if defined(HAVE_TCSETATTR)
143     tcgetattr(ttyfd, &termb);
144     flags = termb.c_lflag;
145 #else
146 #if defined(HAVE_TERMIO_H)
147     ioctl(ttyfd, TCGETA, (char *) &termb);
148     flags = termb.c_lflag;
149 #else  /* we HAVE_STTY */
150     gtty(ttyfd, &ttyb);
151     flags = ttyb.sg_flags;
152 #endif
153 #endif
154 }
155
156 static void disable_tty_echo(void) 
157 {
158     /* turn off echo on the tty */
159 #if defined(HAVE_TCSETATTR)
160     termb.c_lflag &= ~ECHO;
161     tcsetattr(ttyfd, TCSAFLUSH, &termb);
162 #else
163 #if defined(HAVE_TERMIO_H)
164     termb.c_lflag &= ~ECHO;
165     ioctl(ttyfd, TCSETA, (char *) &termb);
166 #else  /* we HAVE_STTY */
167     ttyb.sg_flags &= ~ECHO;
168     stty(ttyfd, &ttyb);
169 #endif
170 #endif
171 }
172
173 static void restore_tty_state(void)
174 {
175     /* restore previous tty echo state */
176 #if defined(HAVE_TCSETATTR)
177     termb.c_lflag = flags;
178     tcsetattr(ttyfd, TCSAFLUSH, &termb);
179 #else
180 #if defined(HAVE_TERMIO_H)
181     termb.c_lflag = flags;
182     ioctl(ttyfd, TCSETA, (char *) &termb);
183 #else  /* we HAVE_STTY */
184     ttyb.sg_flags = flags;
185     stty(ttyfd, &ttyb);
186 #endif
187 #endif
188 }
189
190 static RETSIGTYPE sigint_handler(int signum)
191 {
192     restore_tty_state();
193     report(stderr, 1, 0, _("\nCaught signal... bailing out."));
194 }
195
196 /* getpass.c ends here */