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