summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org.ua>2010-10-05 18:53:39 (GMT)
committer Sergey Poznyakoff <gray@gnu.org.ua>2010-10-05 18:53:39 (GMT)
commit8575afa0eb3a3f38642e28ec5ab109bc128c62dd (patch) (side-by-side diff)
tree29539bcff711fbc5b4142422404aea282c82a7d9
parent63d1c19652942be6b600a5855880667f16fdb8a3 (diff)
downloadmailutils-8575afa0eb3a3f38642e28ec5ab109bc128c62dd.tar.gz
mailutils-8575afa0eb3a3f38642e28ec5ab109bc128c62dd.tar.bz2
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.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--configure.ac2
-rw-r--r--gnulib.modules1
-rw-r--r--include/mailutils/mutil.h2
-rw-r--r--include/mailutils/stream.h3
-rw-r--r--include/mailutils/sys/file_stream.h4
-rw-r--r--libmailutils/Makefile.am1
-rw-r--r--libmailutils/file_stream.c94
-rw-r--r--libmailutils/getpass.c59
-rw-r--r--mu/mu.h2
-rw-r--r--mu/pop.c35
-rw-r--r--mu/shell.c28
-rw-r--r--pop3d/popauth.c68
12 files changed, 236 insertions, 63 deletions
diff --git a/configure.ac b/configure.ac
index 509a569..796c468 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 4368cf7..6639959 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 7acc021..86d2243 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 c076ade..d951f34 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 70c576a..581d289 100644
--- a/include/mailutils/sys/file_stream.h
+++ b/include/mailutils/sys/file_stream.h
@@ -21,7 +21,8 @@
#include <mailutils/stream.h>
#include <mailutils/sys/stream.h>
-#define _MU_FILE_STREAM_TEMP 0x01
+#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 e05edd8..3f083e0 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 247768c..578f482 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:
- {
- struct mu_buffer_query *qp = ptr;
- return mu_stream_get_buffer (str, qp);
- }
+ if (!ptr)
+ return EINVAL;
+ else
+ {
+ struct mu_buffer_query *qp = ptr;
+ return mu_stream_get_buffer (str, qp);
+ }
case MU_IOCTL_SET_TRANSPORT_BUFFER:
- {
- struct mu_buffer_query *qp = ptr;
- return mu_stream_set_buffer (str, qp->buftype, qp->bufsize);
- }
+ 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 0000000..8a37c52
--- a/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;
+}
+
diff --git a/mu/mu.h b/mu/mu.h
index 8ae5fc1..26d5d59 100644
--- a/mu/mu.h
+++ b/mu/mu.h
@@ -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);
diff --git a/mu/pop.c b/mu/pop.c
index 59fed15..b3a1592 100644
--- a/mu/pop.c
+++ b/mu/pop.c
@@ -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 4abaef4..1ca73e7 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)
- return NULL;
+ if (mu_stream_getline (mustrin, &buf, &size, &n) || n == 0)
+ {
+ free (buf);
+ buf = NULL;
+ size = 0;
+ return NULL;
+ }
return buf;
}
@@ -466,14 +471,24 @@ 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;
- }
-
+ }
+
mutool_shell_interactive = isatty (0);
input_line = mutool_shell_interactive ?
input_line_interactive : input_line_script;
@@ -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 9f73d60..f8505f9 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 },
@@ -105,7 +105,7 @@ set_db_perms (struct argp_state *astate, char *opt, int *pperm)
{
int perm = 0;
- if (mu_isdigit(opt[0]))
+ if (mu_isdigit (opt[0]))
{
char *p;
perm = strtoul (opt, &p, 8);
@@ -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) {
- if (ap->passwd)
- free (ap->passwd);
- p = getpass (_("Password:"));
- 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 :"));
- if (strcmp (ap->passwd, p) == 0)
- break;
- mu_error (_("Passwords differ. Please retry."));
- }
+ while (1)
+ {
+ if (ap->passwd)
+ free (ap->passwd);
+ 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 */
+ 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);
}
}

Return to:

Send suggestions and report system problems to the System administrator.