Implement echo control on fd streams. Implement mu_getpass function.
* configure.ac: Test for tcgetattr and tcsetattr. * gnulib.modules (getpass-gnu): Remove. * include/mailutils/mutil.h (mu_getpass): New proto. * include/mailutils/stream.h (MU_IOCTL_GET_ECHO) (MU_IOCTL_SET_ECHO): New ioctls. * include/mailutils/sys/file_stream.h (_MU_FILE_STREAM_ECHO_OFF): New flag. (_mu_file_stream) <echo_state>: New member. * libmailutils/getpass.c: New file. * libmailutils/Makefile.am (libmailutils_la_SOURCES): Add getpass.c. * libmailutils/file_stream.c (fd_done): Free echo_state. (fd_ioctl): Implement MU_IOCTL_GET_ECHO and MU_IOCTL_SET_ECHO. * mu/mu.h (mustrin): New extern. * mu/pop.c (com_pass): Use mu_getpass. * mu/shell.c (mustrin): New variable. (readline): Use mu_stream_getline instead of getline. (mutool_shell): Create mustrin. * pop3d/popauth.c (options): Fix typo. (fill_pass): Use mu_getpass.
Showing
12 changed files
with
236 additions
and
63 deletions
... | @@ -515,7 +515,7 @@ extern char *strsignal (int); | ... | @@ -515,7 +515,7 @@ extern char *strsignal (int); |
515 | ]) | 515 | ]) |
516 | 516 | ||
517 | AC_CHECK_FUNCS(mkstemp sigaction sysconf getdelim setreuid \ | 517 | AC_CHECK_FUNCS(mkstemp sigaction sysconf getdelim setreuid \ |
518 | setresuid seteuid setlocale vfork _exit) | 518 | setresuid seteuid setlocale vfork _exit tcgetattr tcsetattr) |
519 | 519 | ||
520 | AC_FUNC_FSEEKO | 520 | AC_FUNC_FSEEKO |
521 | AC_FUNC_SETVBUF_REVERSED | 521 | AC_FUNC_SETVBUF_REVERSED | ... | ... |
... | @@ -157,6 +157,8 @@ extern int mu_stream_flags_to_mode (int flags, int isdir); | ... | @@ -157,6 +157,8 @@ extern int mu_stream_flags_to_mode (int flags, int isdir); |
157 | extern int mu_parse_stream_perm_string (int *pmode, const char *str, | 157 | extern int mu_parse_stream_perm_string (int *pmode, const char *str, |
158 | const char **endp); | 158 | const char **endp); |
159 | 159 | ||
160 | extern int mu_getpass (mu_stream_t in, mu_stream_t out, const char *prompt, | ||
161 | char **passptr); | ||
160 | 162 | ||
161 | #ifdef __cplusplus | 163 | #ifdef __cplusplus |
162 | } | 164 | } | ... | ... |
... | @@ -74,6 +74,9 @@ enum mu_buffer_type | ... | @@ -74,6 +74,9 @@ enum mu_buffer_type |
74 | #define MU_IOCTL_GET_TRANSPORT_BUFFER 10 | 74 | #define MU_IOCTL_GET_TRANSPORT_BUFFER 10 |
75 | #define MU_IOCTL_SET_TRANSPORT_BUFFER 11 | 75 | #define MU_IOCTL_SET_TRANSPORT_BUFFER 11 |
76 | 76 | ||
77 | #define MU_IOCTL_GET_ECHO 12 | ||
78 | #define MU_IOCTL_SET_ECHO 13 | ||
79 | |||
77 | #define MU_TRANSPORT_INPUT 0 | 80 | #define MU_TRANSPORT_INPUT 0 |
78 | #define MU_TRANSPORT_OUTPUT 1 | 81 | #define MU_TRANSPORT_OUTPUT 1 |
79 | #define MU_TRANSPORT_VALID_TYPE(n) \ | 82 | #define MU_TRANSPORT_VALID_TYPE(n) \ | ... | ... |
... | @@ -21,7 +21,8 @@ | ... | @@ -21,7 +21,8 @@ |
21 | #include <mailutils/stream.h> | 21 | #include <mailutils/stream.h> |
22 | #include <mailutils/sys/stream.h> | 22 | #include <mailutils/sys/stream.h> |
23 | 23 | ||
24 | #define _MU_FILE_STREAM_TEMP 0x01 | 24 | #define _MU_FILE_STREAM_TEMP 0x01 |
25 | #define _MU_FILE_STREAM_ECHO_OFF 0x02 | ||
25 | 26 | ||
26 | struct _mu_file_stream | 27 | struct _mu_file_stream |
27 | { | 28 | { |
... | @@ -29,6 +30,7 @@ struct _mu_file_stream | ... | @@ -29,6 +30,7 @@ struct _mu_file_stream |
29 | int fd; | 30 | int fd; |
30 | int flags; | 31 | int flags; |
31 | char *filename; | 32 | char *filename; |
33 | void *echo_state; | ||
32 | }; | 34 | }; |
33 | 35 | ||
34 | int _mu_file_stream_create (struct _mu_file_stream **pstream, size_t size, | 36 | int _mu_file_stream_create (struct _mu_file_stream **pstream, size_t size, | ... | ... |
... | @@ -23,6 +23,9 @@ | ... | @@ -23,6 +23,9 @@ |
23 | #include <unistd.h> | 23 | #include <unistd.h> |
24 | #include <fcntl.h> | 24 | #include <fcntl.h> |
25 | #include <sys/stat.h> | 25 | #include <sys/stat.h> |
26 | #if HAVE_TERMIOS_H | ||
27 | # include <termios.h> | ||
28 | #endif | ||
26 | 29 | ||
27 | #include <mailutils/types.h> | 30 | #include <mailutils/types.h> |
28 | #include <mailutils/alloc.h> | 31 | #include <mailutils/alloc.h> |
... | @@ -183,6 +186,8 @@ fd_done (struct _mu_stream *str) | ... | @@ -183,6 +186,8 @@ fd_done (struct _mu_stream *str) |
183 | fd_close (str); | 186 | fd_close (str); |
184 | if (fstr->filename) | 187 | if (fstr->filename) |
185 | free (fstr->filename); | 188 | free (fstr->filename); |
189 | if (fstr->echo_state) | ||
190 | free (fstr->echo_state); | ||
186 | } | 191 | } |
187 | 192 | ||
188 | const char * | 193 | const char * |
... | @@ -194,6 +199,10 @@ fd_error_string (struct _mu_stream *str, int rc) | ... | @@ -194,6 +199,10 @@ fd_error_string (struct _mu_stream *str, int rc) |
194 | return mu_strerror (rc); | 199 | return mu_strerror (rc); |
195 | } | 200 | } |
196 | 201 | ||
202 | #ifndef TCSASOFT | ||
203 | # define TCSASOFT 0 | ||
204 | #endif | ||
205 | |||
197 | static int | 206 | static int |
198 | fd_ioctl (struct _mu_stream *str, int code, void *ptr) | 207 | fd_ioctl (struct _mu_stream *str, int code, void *ptr) |
199 | { | 208 | { |
... | @@ -218,17 +227,86 @@ fd_ioctl (struct _mu_stream *str, int code, void *ptr) | ... | @@ -218,17 +227,86 @@ fd_ioctl (struct _mu_stream *str, int code, void *ptr) |
218 | break; | 227 | break; |
219 | 228 | ||
220 | case MU_IOCTL_GET_TRANSPORT_BUFFER: | 229 | case MU_IOCTL_GET_TRANSPORT_BUFFER: |
221 | { | 230 | if (!ptr) |
222 | struct mu_buffer_query *qp = ptr; | 231 | return EINVAL; |
223 | return mu_stream_get_buffer (str, qp); | 232 | else |
224 | } | 233 | { |
234 | struct mu_buffer_query *qp = ptr; | ||
235 | return mu_stream_get_buffer (str, qp); | ||
236 | } | ||
225 | 237 | ||
226 | case MU_IOCTL_SET_TRANSPORT_BUFFER: | 238 | case MU_IOCTL_SET_TRANSPORT_BUFFER: |
227 | { | 239 | if (!ptr) |
228 | struct mu_buffer_query *qp = ptr; | 240 | return EINVAL; |
229 | return mu_stream_set_buffer (str, qp->buftype, qp->bufsize); | 241 | else |
230 | } | 242 | { |
243 | struct mu_buffer_query *qp = ptr; | ||
244 | return mu_stream_set_buffer (str, qp->buftype, qp->bufsize); | ||
245 | } | ||
246 | |||
247 | case MU_IOCTL_SET_ECHO: | ||
248 | if (!ptr) | ||
249 | return EINVAL; | ||
250 | else | ||
251 | { | ||
252 | int status; | ||
253 | struct termios t; | ||
254 | int state = *(int*)ptr; | ||
255 | #if HAVE_TCGETATTR | ||
256 | if (state == 0) | ||
257 | { | ||
258 | if (fstr->flags & _MU_FILE_STREAM_ECHO_OFF) | ||
259 | return 0; | ||
260 | status = tcgetattr (fstr->fd, &t); | ||
261 | if (status == 0) | ||
262 | { | ||
263 | fstr->echo_state = malloc (sizeof (t)); | ||
264 | if (!fstr->echo_state) | ||
265 | return ENOMEM; | ||
266 | memcpy (fstr->echo_state, &t, sizeof (t)); | ||
267 | |||
268 | t.c_lflag &= ~(ECHO | ISIG); | ||
269 | status = tcsetattr (fstr->fd, TCSAFLUSH | TCSASOFT, &t); | ||
270 | if (status == 0) | ||
271 | fstr->flags |= _MU_FILE_STREAM_ECHO_OFF; | ||
272 | } | ||
273 | if (status) | ||
274 | { | ||
275 | status = errno; | ||
276 | if (fstr->echo_state) | ||
277 | { | ||
278 | free (fstr->echo_state); | ||
279 | fstr->echo_state = NULL; | ||
280 | } | ||
281 | } | ||
282 | } | ||
283 | else | ||
284 | { | ||
285 | if (!(fstr->flags & _MU_FILE_STREAM_ECHO_OFF)) | ||
286 | return 0; | ||
287 | if (tcsetattr (fstr->fd, TCSAFLUSH | TCSASOFT, fstr->echo_state)) | ||
288 | status = errno; | ||
289 | else | ||
290 | { | ||
291 | status = 0; | ||
292 | free (fstr->echo_state); | ||
293 | fstr->echo_state = NULL; | ||
294 | fstr->flags &= ~_MU_FILE_STREAM_ECHO_OFF; | ||
295 | } | ||
296 | } | ||
297 | return status; | ||
298 | #else | ||
299 | return ENOSYS; | ||
300 | #endif | ||
301 | } | ||
231 | 302 | ||
303 | case MU_IOCTL_GET_ECHO: | ||
304 | if (!ptr) | ||
305 | return EINVAL; | ||
306 | else | ||
307 | *(int*)ptr = fstr->flags & _MU_FILE_STREAM_ECHO_OFF; | ||
308 | break; | ||
309 | |||
232 | default: | 310 | default: |
233 | return ENOSYS; | 311 | return ENOSYS; |
234 | } | 312 | } | ... | ... |
libmailutils/getpass.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999, 2000, 2001, 2002, 2004, | ||
3 | 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. | ||
4 | |||
5 | This library is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU Lesser General Public License as published by | ||
7 | the Free Software Foundation; either version 3, or (at your option) | ||
8 | any later version. | ||
9 | |||
10 | This library is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU Lesser General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Lesser General Public License | ||
16 | along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ | ||
17 | |||
18 | #ifdef HAVE_CONFIG_H | ||
19 | # include <config.h> | ||
20 | #endif | ||
21 | |||
22 | #include <stdlib.h> | ||
23 | #include <string.h> | ||
24 | |||
25 | #include <mailutils/types.h> | ||
26 | #include <mailutils/stream.h> | ||
27 | #include <mailutils/mutil.h> | ||
28 | #include <mailutils/cstr.h> | ||
29 | |||
30 | int | ||
31 | mu_getpass (mu_stream_t in, mu_stream_t out, const char *prompt, | ||
32 | char **passptr) | ||
33 | { | ||
34 | int status; | ||
35 | int echo_state = 0; | ||
36 | size_t size = 0; | ||
37 | char *buf = NULL; | ||
38 | |||
39 | status = mu_stream_write (out, prompt, strlen (prompt), NULL); | ||
40 | if (status) | ||
41 | return status; | ||
42 | mu_stream_flush (out); | ||
43 | status = mu_stream_ioctl (in, MU_IOCTL_SET_ECHO, &echo_state); | ||
44 | if (status == 0) | ||
45 | echo_state = 1; | ||
46 | status = mu_stream_getline (in, &buf, &size, NULL); | ||
47 | if (echo_state) | ||
48 | { | ||
49 | mu_stream_ioctl (in, MU_IOCTL_SET_ECHO, &echo_state); | ||
50 | mu_stream_write (out, "\n", 1, NULL); | ||
51 | } | ||
52 | if (status == 0) | ||
53 | { | ||
54 | mu_rtrim_cset (buf, "\n"); | ||
55 | *passptr = buf; | ||
56 | } | ||
57 | return 0; | ||
58 | } | ||
59 |
... | @@ -38,6 +38,6 @@ int mutool_acl (int argc, char **argv); | ... | @@ -38,6 +38,6 @@ int mutool_acl (int argc, char **argv); |
38 | extern char *mutool_shell_prompt; | 38 | extern char *mutool_shell_prompt; |
39 | extern mu_vartab_t mutool_prompt_vartab; | 39 | extern mu_vartab_t mutool_prompt_vartab; |
40 | extern int mutool_shell_interactive; | 40 | extern int mutool_shell_interactive; |
41 | extern mu_stream_t mustrout; | 41 | extern mu_stream_t mustrin, mustrout; |
42 | int mutool_shell (const char *name, struct mutool_command *cmd); | 42 | int mutool_shell (const char *name, struct mutool_command *cmd); |
43 | mu_stream_t mutool_open_pager (void); | 43 | mu_stream_t mutool_open_pager (void); | ... | ... |
... | @@ -454,42 +454,18 @@ com_noop (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED) | ... | @@ -454,42 +454,18 @@ com_noop (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED) |
454 | return mu_pop3_noop (pop3); | 454 | return mu_pop3_noop (pop3); |
455 | } | 455 | } |
456 | 456 | ||
457 | static void | ||
458 | echo_off (struct termios *stored_settings) | ||
459 | { | ||
460 | struct termios new_settings; | ||
461 | tcgetattr (0, stored_settings); | ||
462 | new_settings = *stored_settings; | ||
463 | new_settings.c_lflag &= (~ECHO); | ||
464 | tcsetattr (0, TCSANOW, &new_settings); | ||
465 | } | ||
466 | |||
467 | static void | ||
468 | echo_on (struct termios *stored_settings) | ||
469 | { | ||
470 | tcsetattr (0, TCSANOW, stored_settings); | ||
471 | } | ||
472 | |||
473 | static int | 457 | static int |
474 | com_pass (int argc, char **argv) | 458 | com_pass (int argc, char **argv) |
475 | { | 459 | { |
476 | int status; | 460 | int status; |
477 | char pass[256]; | 461 | char *pwd, *passbuf = NULL; |
478 | char *pwd; | ||
479 | 462 | ||
480 | if (argc == 1) | 463 | if (argc == 1) |
481 | { | 464 | { |
482 | struct termios stored_settings; | 465 | status = mu_getpass (mustrin, mustrout, "Password:", &passbuf); |
483 | 466 | if (status) | |
484 | printf ("passwd:"); | 467 | return status; |
485 | fflush (stdout); | 468 | pwd = passbuf; |
486 | echo_off (&stored_settings); | ||
487 | fgets (pass, sizeof pass, stdin); | ||
488 | echo_on (&stored_settings); | ||
489 | putchar ('\n'); | ||
490 | fflush (stdout); | ||
491 | pass[strlen (pass) - 1] = '\0'; /* nuke the trailing line. */ | ||
492 | pwd = pass; | ||
493 | } | 469 | } |
494 | else | 470 | else |
495 | pwd = argv[1]; | 471 | pwd = argv[1]; |
... | @@ -499,6 +475,7 @@ com_pass (int argc, char **argv) | ... | @@ -499,6 +475,7 @@ com_pass (int argc, char **argv) |
499 | pop_session_status = pop_session_logged_in; | 475 | pop_session_status = pop_session_logged_in; |
500 | pop_prompt_vartab (); | 476 | pop_prompt_vartab (); |
501 | } | 477 | } |
478 | free (passbuf); | ||
502 | return status; | 479 | return status; |
503 | } | 480 | } |
504 | 481 | ... | ... |
... | @@ -33,7 +33,7 @@ | ... | @@ -33,7 +33,7 @@ |
33 | char *mutool_shell_prompt; | 33 | char *mutool_shell_prompt; |
34 | mu_vartab_t mutool_prompt_vartab; | 34 | mu_vartab_t mutool_prompt_vartab; |
35 | int mutool_shell_interactive; | 35 | int mutool_shell_interactive; |
36 | mu_stream_t mustrout; | 36 | mu_stream_t mustrin, mustrout; |
37 | 37 | ||
38 | static char * | 38 | static char * |
39 | expand_prompt () | 39 | expand_prompt () |
... | @@ -370,8 +370,13 @@ readline (char *prompt) | ... | @@ -370,8 +370,13 @@ readline (char *prompt) |
370 | mu_stream_printf (mustrout, "%s", prompt); | 370 | mu_stream_printf (mustrout, "%s", prompt); |
371 | fflush (stdout); | 371 | fflush (stdout); |
372 | } | 372 | } |
373 | if (getline (&buf, &size, stdin) <= 0) | 373 | if (mu_stream_getline (mustrin, &buf, &size, &n) || n == 0) |
374 | return NULL; | 374 | { |
375 | free (buf); | ||
376 | buf = NULL; | ||
377 | size = 0; | ||
378 | return NULL; | ||
379 | } | ||
375 | return buf; | 380 | return buf; |
376 | } | 381 | } |
377 | 382 | ||
... | @@ -466,14 +471,24 @@ mutool_shell (const char *name, struct mutool_command *cmd) | ... | @@ -466,14 +471,24 @@ mutool_shell (const char *name, struct mutool_command *cmd) |
466 | size_t n; | 471 | size_t n; |
467 | char *(*input_line) (); | 472 | char *(*input_line) (); |
468 | 473 | ||
474 | rc = mu_stdio_stream_create (&mustrin, MU_STDIN_FD, | ||
475 | MU_STREAM_READ); | ||
476 | if (rc) | ||
477 | { | ||
478 | mu_diag_funcall (MU_DIAG_ERROR, "mu_stdio_stream_create", | ||
479 | "MU_STDIN_FD", rc); | ||
480 | return 1; | ||
481 | } | ||
482 | |||
469 | rc = mu_stdio_stream_create (&mustrout, MU_STDOUT_FD, | 483 | rc = mu_stdio_stream_create (&mustrout, MU_STDOUT_FD, |
470 | MU_STREAM_WRITE); | 484 | MU_STREAM_WRITE); |
471 | if (rc) | 485 | if (rc) |
472 | { | 486 | { |
473 | mu_diag_funcall (MU_DIAG_ERROR, "mu_stdio_stream_create", "1", rc); | 487 | mu_diag_funcall (MU_DIAG_ERROR, "mu_stdio_stream_create", |
488 | "MU_STDOUT_FD", rc); | ||
474 | return 1; | 489 | return 1; |
475 | } | 490 | } |
476 | 491 | ||
477 | mutool_shell_interactive = isatty (0); | 492 | mutool_shell_interactive = isatty (0); |
478 | input_line = mutool_shell_interactive ? | 493 | input_line = mutool_shell_interactive ? |
479 | input_line_interactive : input_line_script; | 494 | input_line_interactive : input_line_script; |
... | @@ -521,6 +536,7 @@ mutool_shell (const char *name, struct mutool_command *cmd) | ... | @@ -521,6 +536,7 @@ mutool_shell (const char *name, struct mutool_command *cmd) |
521 | } | 536 | } |
522 | if (mutool_shell_interactive) | 537 | if (mutool_shell_interactive) |
523 | finish_readline (); | 538 | finish_readline (); |
539 | mu_stream_destroy (&mustrin); | ||
524 | mu_stream_destroy (&mustrout); | 540 | mu_stream_destroy (&mustrout); |
525 | return 0; | 541 | return 0; |
526 | } | 542 | } | ... | ... |
... | @@ -74,7 +74,7 @@ static struct argp_option options[] = | ... | @@ -74,7 +74,7 @@ static struct argp_option options[] = |
74 | { NULL, 0, NULL, 0, | 74 | { NULL, 0, NULL, 0, |
75 | N_("Default action is:\n" | 75 | N_("Default action is:\n" |
76 | " For the file owner: --list\n" | 76 | " For the file owner: --list\n" |
77 | " For a user: --modify --username <username>\n"), 2 }, | 77 | " For a user: --modify --user <username>\n"), 2 }, |
78 | 78 | ||
79 | { NULL, 0, NULL, 0, N_("Options are:"), 3 }, | 79 | { NULL, 0, NULL, 0, N_("Options are:"), 3 }, |
80 | { "file", 'f', N_("FILE"), 0, N_("read input from FILE (default stdin)"), 3 }, | 80 | { "file", 'f', N_("FILE"), 0, N_("read input from FILE (default stdin)"), 3 }, |
... | @@ -105,7 +105,7 @@ set_db_perms (struct argp_state *astate, char *opt, int *pperm) | ... | @@ -105,7 +105,7 @@ set_db_perms (struct argp_state *astate, char *opt, int *pperm) |
105 | { | 105 | { |
106 | int perm = 0; | 106 | int perm = 0; |
107 | 107 | ||
108 | if (mu_isdigit(opt[0])) | 108 | if (mu_isdigit (opt[0])) |
109 | { | 109 | { |
110 | char *p; | 110 | char *p; |
111 | perm = strtoul (opt, &p, 8); | 111 | perm = strtoul (opt, &p, 8); |
... | @@ -446,21 +446,57 @@ fill_pass (struct action_data *ap) | ... | @@ -446,21 +446,57 @@ fill_pass (struct action_data *ap) |
446 | if (!ap->passwd) | 446 | if (!ap->passwd) |
447 | { | 447 | { |
448 | char *p; | 448 | char *p; |
449 | mu_stream_t in, out; | ||
450 | int rc; | ||
451 | |||
452 | rc = mu_stdio_stream_create (&in, MU_STDIN_FD, MU_STREAM_READ); | ||
453 | if (rc) | ||
454 | { | ||
455 | mu_diag_funcall (MU_DIAG_ERROR, "mu_stdio_stream_create", | ||
456 | "MU_STDIN_FD", rc); | ||
457 | return; | ||
458 | } | ||
459 | |||
460 | rc = mu_stdio_stream_create (&out, MU_STDOUT_FD, MU_STREAM_WRITE); | ||
461 | if (rc) | ||
462 | { | ||
463 | mu_diag_funcall (MU_DIAG_ERROR, "mu_stdio_stream_create", | ||
464 | "MU_STDOUT_FD", rc); | ||
465 | return; | ||
466 | } | ||
449 | 467 | ||
450 | while (1) { | 468 | while (1) |
451 | if (ap->passwd) | 469 | { |
452 | free (ap->passwd); | 470 | if (ap->passwd) |
453 | p = getpass (_("Password:")); | 471 | free (ap->passwd); |
454 | if (!p) | 472 | rc = mu_getpass (in, out, _("Password:"), &p); |
455 | exit (EX_DATAERR); | 473 | if (rc) |
456 | ap->passwd = strdup (p); | 474 | { |
457 | /* TRANSLATORS: Please try to format this string so that it has | 475 | mu_diag_funcall (MU_DIAG_ERROR, "mu_getpass", NULL, rc); |
458 | the same length as the translation of 'Password:' above */ | 476 | exit (EX_DATAERR); |
459 | p = getpass (_("Confirm :")); | 477 | } |
460 | if (strcmp (ap->passwd, p) == 0) | 478 | |
461 | break; | 479 | if (!p) |
462 | mu_error (_("Passwords differ. Please retry.")); | 480 | exit (EX_DATAERR); |
463 | } | 481 | |
482 | ap->passwd = strdup (p); | ||
483 | /* TRANSLATORS: Please try to format this string so that it has | ||
484 | the same length as the translation of 'Password:' above */ | ||
485 | rc = mu_getpass (in, out, _("Confirm :"), &p); | ||
486 | if (rc) | ||
487 | { | ||
488 | mu_diag_funcall (MU_DIAG_ERROR, "mu_getpass", NULL, rc); | ||
489 | exit (EX_DATAERR); | ||
490 | } | ||
491 | |||
492 | if (!p) | ||
493 | exit (EX_DATAERR); | ||
494 | if (strcmp (ap->passwd, p) == 0) | ||
495 | break; | ||
496 | mu_error (_("Passwords differ. Please retry.")); | ||
497 | } | ||
498 | mu_stream_destroy (&in); | ||
499 | mu_stream_destroy (&out); | ||
464 | } | 500 | } |
465 | } | 501 | } |
466 | 502 | ... | ... |
-
Please register or sign in to post a comment