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