bottleneck testcase based on rubbos
[bottlenecks.git] / rubbos / app / httpd-2.0.64 / srclib / apr / passwd / apr_getpass.c
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements.  See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (the "License"); you may not use this file except in compliance with
6  * the License.  You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /* apr_password_get.c: abstraction to provide for obtaining a password from the
18  * command line in whatever way the OS supports.  In the best case, it's a
19  * wrapper for the system library's getpass() routine; otherwise, we
20  * use one we define ourselves.
21  */
22 #include "apr_private.h"
23 #include "apr_strings.h"
24 #include "apr_lib.h"
25 #include "apr_errno.h"
26 #if APR_HAVE_SYS_TYPES_H
27 #include <sys/types.h>
28 #endif
29 #if APR_HAVE_ERRNO_H
30 #include <errno.h>
31 #endif
32
33 #if APR_HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
36 #if APR_HAVE_CONIO_H
37 #pragma warning(disable: 4032)
38 #include <conio.h>
39 #pragma warning(default: 4032)
40 #endif
41 #if APR_HAVE_STDLIB_H
42 #include <stdlib.h>
43 #endif
44 #if APR_HAVE_STRING_H
45 #include <string.h>
46 #endif
47 #if APR_HAVE_STRINGS_H
48 #include <strings.h>
49 #endif
50
51 #if defined(HAVE_TERMIOS_H) && !defined(HAVE_GETPASS)
52 #include <termios.h>
53 #endif
54
55 #if !APR_CHARSET_EBCDIC
56 #define LF 10
57 #define CR 13
58 #else /* APR_CHARSET_EBCDIC */
59 #define LF '\n'
60 #define CR '\r'
61 #endif /* APR_CHARSET_EBCDIC */
62
63 #define MAX_STRING_LEN 256
64
65 #define ERR_OVERFLOW 5
66
67 #ifndef HAVE_GETPASS
68
69 /* MPE, Win32, NetWare and BeOS all lack a native getpass() */
70
71 #if !defined(HAVE_TERMIOS_H) && !defined(WIN32) && !defined(NETWARE)
72 /*
73  * MPE lacks getpass() and a way to suppress stdin echo.  So for now, just
74  * issue the prompt and read the results with echo.  (Ugh).
75  */
76
77 static char *getpass(const char *prompt)
78 {
79     static char password[MAX_STRING_LEN];
80
81     fputs(prompt, stderr);
82     fgets((char *) &password, sizeof(password), stdin);
83
84     return (char *) &password;
85 }
86
87 #elif defined (HAVE_TERMIOS_H)
88 #include <stdio.h>
89
90 static char *getpass(const char *prompt)
91 {
92     struct termios attr;
93     static char password[MAX_STRING_LEN];
94     int n=0;
95     fputs(prompt, stderr);
96     fflush(stderr);
97         
98     if (tcgetattr(STDIN_FILENO, &attr) != 0)
99         return NULL;
100     attr.c_lflag &= ~(ECHO);
101
102     if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &attr) != 0)
103             return NULL;
104     while ((password[n] = getchar()) != '\n') {
105         if (n < sizeof(password) - 1 && password[n] >= ' ' && password[n] <= '~') {
106             n++;
107         } else {
108             fprintf(stderr,"\n");
109             fputs(prompt, stderr);
110             fflush(stderr);
111             n = 0;
112         }
113     }
114  
115     password[n] = '\0';
116     printf("\n");
117     if (n > (MAX_STRING_LEN - 1)) {
118         password[MAX_STRING_LEN - 1] = '\0';
119     }
120
121     attr.c_lflag |= ECHO;
122     tcsetattr(STDIN_FILENO, TCSANOW, &attr);
123     return (char*) &password;
124 }
125
126 #else
127
128 /*
129  * Windows lacks getpass().  So we'll re-implement it here.
130  */
131
132 static char *getpass(const char *prompt)
133 {
134 /* WCE lacks console. So the getpass is unsuported
135  * The only way is to use the GUI so the getpass should be implemented
136  * on per-application basis.
137  */ 
138 #ifdef _WIN32_WCE
139     return NULL;
140 #else
141     static char password[128];
142     int n = 0;
143     int ch;
144
145     fputs(prompt, stderr);
146     
147     while ((ch = _getch()) != '\r') {
148         if (ch == EOF) /* EOF */ {
149             fputs("[EOF]\n", stderr);
150             return NULL;
151         }
152         else if (ch == 0 || ch == 0xE0) {
153             /* FN Keys (0 or E0) are a sentinal for a FN code */ 
154             ch = (ch << 4) | _getch();
155             /* Catch {DELETE}, {<--}, Num{DEL} and Num{<--} */
156             if ((ch == 0xE53 || ch == 0xE4B || ch == 0x053 || ch == 0x04b) && n) {
157                 password[--n] = '\0';
158                 fputs("\b \b", stderr);
159             }
160             else {
161                 fputc('\a', stderr);
162             }
163         }
164         else if ((ch == '\b' || ch == 127) && n) /* BS/DEL */ {
165             password[--n] = '\0';
166             fputs("\b \b", stderr);
167         }
168         else if (ch == 3) /* CTRL+C */ {
169             /* _getch() bypasses Ctrl+C but not Ctrl+Break detection! */
170             fputs("^C\n", stderr);
171             exit(-1);
172         }
173         else if (ch == 26) /* CTRL+Z */ {
174             fputs("^Z\n", stderr);
175             return NULL;
176         }
177         else if (ch == 27) /* ESC */ {
178             fputc('\n', stderr);
179             fputs(prompt, stderr);
180             n = 0;
181         }
182         else if ((n < sizeof(password) - 1) && !apr_iscntrl(ch)) {
183             password[n++] = ch;
184             fputc('*', stderr);
185         }
186         else {
187             fputc('\a', stderr);
188         }
189     }
190  
191     fputc('\n', stderr);
192     password[n] = '\0';
193     return password;
194 #endif
195 }
196
197 #endif /* no getchar or _getch */
198
199 #endif /* no getpass */
200
201 /*
202  * Use the OS getpass() routine (or our own) to obtain a password from
203  * the input stream.
204  *
205  * Exit values:
206  *  0: Success
207  *  5: Partial success; entered text truncated to the size of the
208  *     destination buffer
209  *
210  * Restrictions: Truncation also occurs according to the host system's
211  * getpass() semantics, or at position 255 if our own version is used,
212  * but the caller is *not* made aware of it unless their own buffer is
213  * smaller than our own.
214  */
215
216 APR_DECLARE(apr_status_t) apr_password_get(const char *prompt, char *pwbuf, apr_size_t *bufsiz)
217 {
218 #ifdef HAVE_GETPASSPHRASE
219     char *pw_got = getpassphrase(prompt);
220 #else
221     char *pw_got = getpass(prompt);
222 #endif
223     if (!pw_got)
224         return APR_EINVAL;
225     apr_cpystrn(pwbuf, pw_got, *bufsiz);
226     memset(pw_got, 0, strlen(pw_got));
227     if (strlen(pw_got) >= *bufsiz) {
228         return APR_ENAMETOOLONG;
229     }
230     return APR_SUCCESS; 
231 }