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