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