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