]> Pileus Git - ~andy/fetchmail/blob - getpass.c
c5fe4829adb490608d7db9975faf5606cbca79fd
[~andy/fetchmail] / getpass.c
1 /* Copyright 1993-95 by Carl Harris, Jr.
2  * All rights reserved
3  *
4  * Distribute freely, except: don't remove my name from the source or
5  * documentation (don't take credit for my work), mark your changes (don't
6  * get me blamed for your possible bugs), don't alter or remove this
7  * notice.  May be sold if buildable source is provided to buyer.  No
8  * warrantee of any kind, express or implied, is included with this
9  * software; use at your own risk, responsibility for damages (if any) to
10  * anyone resulting from the use of this software rests entirely with the
11  * user.
12  *
13  * Send bug reports, bug fixes, enhancements, requests, flames, etc., and
14  * I'll try to keep a version up to date.  I can be reached as follows:
15  * Carl Harris <ceharris@mal.com>
16  */
17
18
19 /***********************************************************************
20   module:       getpass.c
21   project:      popclient
22   programmer:   Carl Harris, ceharris@mal.com
23   description:  getpass() replacement which allows for long passwords.
24
25   $Log: getpass.c,v $
26   Revision 1.1  1996/06/28 14:33:54  esr
27   Initial revision
28
29   Revision 1.4  1995/08/10 00:32:27  ceharris
30   Preparation for 3.0b3 beta release:
31   -     added code for --kill/--keep, --limit, --protocol, --flush
32         options; --pop2 and --pop3 options now obsoleted by --protocol.
33   -     added support for APOP authentication, including --with-APOP
34         argument for configure.
35   -     provisional and broken support for RPOP
36   -     added buffering to SockGets and SockRead functions.
37   -     fixed problem of command-line options not being correctly
38         carried into the merged options record.
39
40   Revision 1.3  1995/08/08 01:01:19  ceharris
41   Added GNU-style long options processing.
42   Fixed password in 'ps' output problem.
43   Fixed various RCS tag blunders.
44   Integrated .poprc parser, lexer, etc into Makefile processing.
45
46  ***********************************************************************/
47
48 #include <config.h>
49
50 #if defined(STDC_HEADERS)
51 #include <stdio.h>
52 #endif
53
54 #include <signal.h>
55
56 #define INPUT_BUF_SIZE  MAX_PASSWORD_LENGTH
57
58 #if defined(HAVE_TERMIOS_H) && defined(HAVE_TCSETATTR)
59 #  include <termios.h>
60 #else
61 #if defined(HAVE_TERMIO_H)
62 #  include <sys/ioctl.h>
63 #  include <termio.h>
64 #else
65 #if defined(HAVE_SGTTY_H)
66 #  include <sgtty.h>
67 #endif
68 #endif
69 #endif
70
71 static int ttyfd;
72
73 #if defined(HAVE_TCSETATTR)
74   static struct termios termb;
75   static tcflag_t flags;
76 #else
77 #if defined(HAVE_TERMIO_H)
78   static struct termio termb;
79   static unsigned short flags;
80 #else
81 #if defined(HAVE_STTY)
82   static struct sgttyb ttyb;
83   static int flags;
84 #endif
85 #endif
86 #endif
87
88 void save_tty_state();
89 void disable_tty_echo();
90 void restore_tty_state();
91
92 char *
93 getpassword(prompt)
94 char *prompt;
95 {
96
97 #if !(defined(HAVE_TCSETATTR) || defined(HAVE_TERMIO_H) || defined(HAVE_STTY))
98
99 #if defined(HAVE_GETPASS) 
100   char *getpass();
101   return getpass(prompt);
102 #else
103   fputs("ERROR: no support for getpassword() routine\n",stderr);
104   exit(1);
105 #endif
106
107 #endif /* !(defined(HAVE_TCSETATTR) || ... */
108
109   register char *p;
110   register c;
111   FILE *fi;
112   static char pbuf[INPUT_BUF_SIZE];
113   RETSIGTYPE (*sig)();
114   RETSIGTYPE sigint_handler();
115
116
117   /* get the file descriptor for the input device */
118   if ((fi = fdopen(open("/dev/tty", 2), "r")) == NULL)
119     fi = stdin;
120   else
121     setbuf(fi, (char *)NULL);
122
123   /* store descriptor for the tty */
124   ttyfd = fileno(fi);
125
126   /* preserve tty state before turning off echo */
127   save_tty_state();
128
129   /* now that we have the current tty state, we can catch SIGINT and  
130      exit gracefully */
131   sig = signal(SIGINT, sigint_handler);
132
133   /* turn off echo on the tty */
134   disable_tty_echo();
135
136   /* display the prompt and get the input string */
137   fprintf(stderr, "%s", prompt); fflush(stderr);
138   for (p=pbuf; (c = getc(fi))!='\n' && c!=EOF;) {
139     if (p < &pbuf[INPUT_BUF_SIZE - 1])
140       *p++ = c;
141   }
142   *p = '\0';
143
144   /* write a newline so cursor won't appear to hang */
145   fprintf(stderr, "\n"); fflush(stderr);
146
147   /* restore previous state of the tty */
148   restore_tty_state();
149
150   /* restore previous state of SIGINT */
151   signal(SIGINT, sig);
152
153   if (fi != stdin)
154     fclose(fi);
155
156   return(pbuf);
157
158 }
159
160
161 void
162 save_tty_state ()
163 {
164 #if defined(HAVE_TCSETATTR)
165   tcgetattr(ttyfd, &termb);
166   flags = termb.c_lflag;
167 #else
168 #if defined(HAVE_TERMIO_H)
169   ioctl(ttyfd, TCGETA, (char *) &termb);
170   flags = termb.c_lflag;
171 #else  /* we HAVE_STTY */
172   gtty(ttyfd, &ttyb);
173   flags = ttyb.sg_flags;
174 #endif
175 #endif
176 }
177
178
179 void
180 disable_tty_echo() 
181 {
182   /* turn off echo on the tty */
183 #if defined(HAVE_TCSETATTR)
184   termb.c_lflag &= ~ECHO;
185   tcsetattr(ttyfd, TCSAFLUSH, &termb);
186 #else
187 #if defined(HAVE_TERMIO_H)
188   termb.c_lflag &= ~ECHO;
189   ioctl(ttyfd, TCSETA, (char *) &termb);
190 #else  /* we HAVE_STTY */
191   ttyb.sg_flags &= ~ECHO;
192   stty(ttyfd, &ttyb);
193 #endif
194 #endif
195 }
196
197
198
199 void
200 restore_tty_state()
201 {
202   /* restore previous tty echo state */
203 #if defined(HAVE_TCSETATTR)
204   termb.c_lflag = flags;
205   tcsetattr(ttyfd, TCSAFLUSH, &termb);
206 #else
207 #if defined(HAVE_TERMIO_H)
208   termb.c_lflag = flags;
209   ioctl(ttyfd, TCSETA, (char *) &termb);
210 #else  /* we HAVE_STTY */
211   ttyb.sg_flags = flags;
212   stty(ttyfd, &ttyb);
213 #endif
214 #endif
215 }
216
217
218 RETSIGTYPE sigint_handler ()
219 {
220   restore_tty_state();
221   fputs("\nCaught signal... bailing out.\n", stderr);
222   exit(1);
223 }