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