diff options
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | gnulib.modules | 1 | ||||
-rw-r--r-- | include/mailutils/mutil.h | 2 | ||||
-rw-r--r-- | include/mailutils/stream.h | 3 | ||||
-rw-r--r-- | include/mailutils/sys/file_stream.h | 2 | ||||
-rw-r--r-- | libmailutils/Makefile.am | 1 | ||||
-rw-r--r-- | libmailutils/file_stream.c | 78 | ||||
-rw-r--r-- | libmailutils/getpass.c | 59 | ||||
-rw-r--r-- | mu/mu.h | 2 | ||||
-rw-r--r-- | mu/pop.c | 35 | ||||
-rw-r--r-- | mu/shell.c | 22 | ||||
-rw-r--r-- | pop3d/popauth.c | 44 |
12 files changed, 212 insertions, 39 deletions
diff --git a/configure.ac b/configure.ac index 509a56991..796c4687a 100644 --- a/configure.ac +++ b/configure.ac @@ -515,7 +515,7 @@ extern char *strsignal (int); ]) AC_CHECK_FUNCS(mkstemp sigaction sysconf getdelim setreuid \ - setresuid seteuid setlocale vfork _exit) + setresuid seteuid setlocale vfork _exit tcgetattr tcsetattr) AC_FUNC_FSEEKO AC_FUNC_SETVBUF_REVERSED diff --git a/gnulib.modules b/gnulib.modules index 4368cf7c2..66399597e 100644 --- a/gnulib.modules +++ b/gnulib.modules @@ -8,7 +8,6 @@ autobuild argp crypto/des getline -getpass-gnu gettext gitlog-to-changelog intprops diff --git a/include/mailutils/mutil.h b/include/mailutils/mutil.h index 7acc021cf..86d2243e7 100644 --- a/include/mailutils/mutil.h +++ b/include/mailutils/mutil.h @@ -157,6 +157,8 @@ extern int mu_stream_flags_to_mode (int flags, int isdir); extern int mu_parse_stream_perm_string (int *pmode, const char *str, const char **endp); +extern int mu_getpass (mu_stream_t in, mu_stream_t out, const char *prompt, + char **passptr); #ifdef __cplusplus } diff --git a/include/mailutils/stream.h b/include/mailutils/stream.h index c076ade11..d951f3425 100644 --- a/include/mailutils/stream.h +++ b/include/mailutils/stream.h @@ -74,6 +74,9 @@ enum mu_buffer_type #define MU_IOCTL_GET_TRANSPORT_BUFFER 10 #define MU_IOCTL_SET_TRANSPORT_BUFFER 11 +#define MU_IOCTL_GET_ECHO 12 +#define MU_IOCTL_SET_ECHO 13 + #define MU_TRANSPORT_INPUT 0 #define MU_TRANSPORT_OUTPUT 1 #define MU_TRANSPORT_VALID_TYPE(n) \ diff --git a/include/mailutils/sys/file_stream.h b/include/mailutils/sys/file_stream.h index 70c576ab7..581d28941 100644 --- a/include/mailutils/sys/file_stream.h +++ b/include/mailutils/sys/file_stream.h @@ -22,6 +22,7 @@ #include <mailutils/sys/stream.h> #define _MU_FILE_STREAM_TEMP 0x01 +#define _MU_FILE_STREAM_ECHO_OFF 0x02 struct _mu_file_stream { @@ -29,6 +30,7 @@ struct _mu_file_stream int fd; int flags; char *filename; + void *echo_state; }; int _mu_file_stream_create (struct _mu_file_stream **pstream, size_t size, diff --git a/libmailutils/Makefile.am b/libmailutils/Makefile.am index e05edd883..3f083e01d 100644 --- a/libmailutils/Makefile.am +++ b/libmailutils/Makefile.am @@ -84,6 +84,7 @@ libmailutils_la_SOURCES = \ folder.c\ freeitem.c\ gdebug.c\ + getpass.c\ gocs.c\ hdritr.c\ header.c\ diff --git a/libmailutils/file_stream.c b/libmailutils/file_stream.c index 247768c25..578f4829e 100644 --- a/libmailutils/file_stream.c +++ b/libmailutils/file_stream.c @@ -23,6 +23,9 @@ #include <unistd.h> #include <fcntl.h> #include <sys/stat.h> +#if HAVE_TERMIOS_H +# include <termios.h> +#endif #include <mailutils/types.h> #include <mailutils/alloc.h> @@ -183,6 +186,8 @@ fd_done (struct _mu_stream *str) fd_close (str); if (fstr->filename) free (fstr->filename); + if (fstr->echo_state) + free (fstr->echo_state); } const char * @@ -194,6 +199,10 @@ fd_error_string (struct _mu_stream *str, int rc) return mu_strerror (rc); } +#ifndef TCSASOFT +# define TCSASOFT 0 +#endif + static int fd_ioctl (struct _mu_stream *str, int code, void *ptr) { @@ -218,17 +227,86 @@ fd_ioctl (struct _mu_stream *str, int code, void *ptr) break; case MU_IOCTL_GET_TRANSPORT_BUFFER: + if (!ptr) + return EINVAL; + else { struct mu_buffer_query *qp = ptr; return mu_stream_get_buffer (str, qp); } case MU_IOCTL_SET_TRANSPORT_BUFFER: + if (!ptr) + return EINVAL; + else { struct mu_buffer_query *qp = ptr; return mu_stream_set_buffer (str, qp->buftype, qp->bufsize); } + case MU_IOCTL_SET_ECHO: + if (!ptr) + return EINVAL; + else + { + int status; + struct termios t; + int state = *(int*)ptr; +#if HAVE_TCGETATTR + if (state == 0) + { + if (fstr->flags & _MU_FILE_STREAM_ECHO_OFF) + return 0; + status = tcgetattr (fstr->fd, &t); + if (status == 0) + { + fstr->echo_state = malloc (sizeof (t)); + if (!fstr->echo_state) + return ENOMEM; + memcpy (fstr->echo_state, &t, sizeof (t)); + + t.c_lflag &= ~(ECHO | ISIG); + status = tcsetattr (fstr->fd, TCSAFLUSH | TCSASOFT, &t); + if (status == 0) + fstr->flags |= _MU_FILE_STREAM_ECHO_OFF; + } + if (status) + { + status = errno; + if (fstr->echo_state) + { + free (fstr->echo_state); + fstr->echo_state = NULL; + } + } + } + else + { + if (!(fstr->flags & _MU_FILE_STREAM_ECHO_OFF)) + return 0; + if (tcsetattr (fstr->fd, TCSAFLUSH | TCSASOFT, fstr->echo_state)) + status = errno; + else + { + status = 0; + free (fstr->echo_state); + fstr->echo_state = NULL; + fstr->flags &= ~_MU_FILE_STREAM_ECHO_OFF; + } + } + return status; +#else + return ENOSYS; +#endif + } + + case MU_IOCTL_GET_ECHO: + if (!ptr) + return EINVAL; + else + *(int*)ptr = fstr->flags & _MU_FILE_STREAM_ECHO_OFF; + break; + default: return ENOSYS; } diff --git a/libmailutils/getpass.c b/libmailutils/getpass.c new file mode 100644 index 000000000..8a37c52cc --- /dev/null +++ b/libmailutils/getpass.c @@ -0,0 +1,59 @@ +/* GNU Mailutils -- a suite of utilities for electronic mail + Copyright (C) 1999, 2000, 2001, 2002, 2004, + 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + + This library is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdlib.h> +#include <string.h> + +#include <mailutils/types.h> +#include <mailutils/stream.h> +#include <mailutils/mutil.h> +#include <mailutils/cstr.h> + +int +mu_getpass (mu_stream_t in, mu_stream_t out, const char *prompt, + char **passptr) +{ + int status; + int echo_state = 0; + size_t size = 0; + char *buf = NULL; + + status = mu_stream_write (out, prompt, strlen (prompt), NULL); + if (status) + return status; + mu_stream_flush (out); + status = mu_stream_ioctl (in, MU_IOCTL_SET_ECHO, &echo_state); + if (status == 0) + echo_state = 1; + status = mu_stream_getline (in, &buf, &size, NULL); + if (echo_state) + { + mu_stream_ioctl (in, MU_IOCTL_SET_ECHO, &echo_state); + mu_stream_write (out, "\n", 1, NULL); + } + if (status == 0) + { + mu_rtrim_cset (buf, "\n"); + *passptr = buf; + } + return 0; +} + @@ -38,6 +38,6 @@ int mutool_acl (int argc, char **argv); extern char *mutool_shell_prompt; extern mu_vartab_t mutool_prompt_vartab; extern int mutool_shell_interactive; -extern mu_stream_t mustrout; +extern mu_stream_t mustrin, mustrout; int mutool_shell (const char *name, struct mutool_command *cmd); mu_stream_t mutool_open_pager (void); @@ -454,42 +454,18 @@ com_noop (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED) return mu_pop3_noop (pop3); } -static void -echo_off (struct termios *stored_settings) -{ - struct termios new_settings; - tcgetattr (0, stored_settings); - new_settings = *stored_settings; - new_settings.c_lflag &= (~ECHO); - tcsetattr (0, TCSANOW, &new_settings); -} - -static void -echo_on (struct termios *stored_settings) -{ - tcsetattr (0, TCSANOW, stored_settings); -} - static int com_pass (int argc, char **argv) { int status; - char pass[256]; - char *pwd; + char *pwd, *passbuf = NULL; if (argc == 1) { - struct termios stored_settings; - - printf ("passwd:"); - fflush (stdout); - echo_off (&stored_settings); - fgets (pass, sizeof pass, stdin); - echo_on (&stored_settings); - putchar ('\n'); - fflush (stdout); - pass[strlen (pass) - 1] = '\0'; /* nuke the trailing line. */ - pwd = pass; + status = mu_getpass (mustrin, mustrout, "Password:", &passbuf); + if (status) + return status; + pwd = passbuf; } else pwd = argv[1]; @@ -499,6 +475,7 @@ com_pass (int argc, char **argv) pop_session_status = pop_session_logged_in; pop_prompt_vartab (); } + free (passbuf); return status; } diff --git a/mu/shell.c b/mu/shell.c index 4abaef4dc..1ca73e79a 100644 --- a/mu/shell.c +++ b/mu/shell.c @@ -33,7 +33,7 @@ char *mutool_shell_prompt; mu_vartab_t mutool_prompt_vartab; int mutool_shell_interactive; -mu_stream_t mustrout; +mu_stream_t mustrin, mustrout; static char * expand_prompt () @@ -370,8 +370,13 @@ readline (char *prompt) mu_stream_printf (mustrout, "%s", prompt); fflush (stdout); } - if (getline (&buf, &size, stdin) <= 0) + if (mu_stream_getline (mustrin, &buf, &size, &n) || n == 0) + { + free (buf); + buf = NULL; + size = 0; return NULL; + } return buf; } @@ -466,11 +471,21 @@ mutool_shell (const char *name, struct mutool_command *cmd) size_t n; char *(*input_line) (); + rc = mu_stdio_stream_create (&mustrin, MU_STDIN_FD, + MU_STREAM_READ); + if (rc) + { + mu_diag_funcall (MU_DIAG_ERROR, "mu_stdio_stream_create", + "MU_STDIN_FD", rc); + return 1; + } + rc = mu_stdio_stream_create (&mustrout, MU_STDOUT_FD, MU_STREAM_WRITE); if (rc) { - mu_diag_funcall (MU_DIAG_ERROR, "mu_stdio_stream_create", "1", rc); + mu_diag_funcall (MU_DIAG_ERROR, "mu_stdio_stream_create", + "MU_STDOUT_FD", rc); return 1; } @@ -521,6 +536,7 @@ mutool_shell (const char *name, struct mutool_command *cmd) } if (mutool_shell_interactive) finish_readline (); + mu_stream_destroy (&mustrin); mu_stream_destroy (&mustrout); return 0; } diff --git a/pop3d/popauth.c b/pop3d/popauth.c index 9f73d60ed..f8505f949 100644 --- a/pop3d/popauth.c +++ b/pop3d/popauth.c @@ -74,7 +74,7 @@ static struct argp_option options[] = { NULL, 0, NULL, 0, N_("Default action is:\n" " For the file owner: --list\n" - " For a user: --modify --username <username>\n"), 2 }, + " For a user: --modify --user <username>\n"), 2 }, { NULL, 0, NULL, 0, N_("Options are:"), 3 }, { "file", 'f', N_("FILE"), 0, N_("read input from FILE (default stdin)"), 3 }, @@ -446,21 +446,57 @@ fill_pass (struct action_data *ap) if (!ap->passwd) { char *p; + mu_stream_t in, out; + int rc; + + rc = mu_stdio_stream_create (&in, MU_STDIN_FD, MU_STREAM_READ); + if (rc) + { + mu_diag_funcall (MU_DIAG_ERROR, "mu_stdio_stream_create", + "MU_STDIN_FD", rc); + return; + } + + rc = mu_stdio_stream_create (&out, MU_STDOUT_FD, MU_STREAM_WRITE); + if (rc) + { + mu_diag_funcall (MU_DIAG_ERROR, "mu_stdio_stream_create", + "MU_STDOUT_FD", rc); + return; + } - while (1) { + while (1) + { if (ap->passwd) free (ap->passwd); - p = getpass (_("Password:")); + rc = mu_getpass (in, out, _("Password:"), &p); + if (rc) + { + mu_diag_funcall (MU_DIAG_ERROR, "mu_getpass", NULL, rc); + exit (EX_DATAERR); + } + if (!p) exit (EX_DATAERR); + ap->passwd = strdup (p); /* TRANSLATORS: Please try to format this string so that it has the same length as the translation of 'Password:' above */ - p = getpass (_("Confirm :")); + rc = mu_getpass (in, out, _("Confirm :"), &p); + if (rc) + { + mu_diag_funcall (MU_DIAG_ERROR, "mu_getpass", NULL, rc); + exit (EX_DATAERR); + } + + if (!p) + exit (EX_DATAERR); if (strcmp (ap->passwd, p) == 0) break; mu_error (_("Passwords differ. Please retry.")); } + mu_stream_destroy (&in); + mu_stream_destroy (&out); } } |