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