summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2010-10-05 21:53:39 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2010-10-05 21:53:39 +0300
commit8575afa0eb3a3f38642e28ec5ab109bc128c62dd (patch)
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.
-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 509a56991..796c4687a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -517,3 +517,3 @@ extern char *strsignal (int);
AC_CHECK_FUNCS(mkstemp sigaction sysconf getdelim setreuid \
- setresuid seteuid setlocale vfork _exit)
+ setresuid seteuid setlocale vfork _exit tcgetattr tcsetattr)
diff --git a/gnulib.modules b/gnulib.modules
index 4368cf7c2..66399597e 100644
--- a/gnulib.modules
+++ b/gnulib.modules
@@ -10,3 +10,2 @@ crypto/des
getline
-getpass-gnu
gettext
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
@@ -159,2 +159,4 @@ extern int mu_parse_stream_perm_string (int *pmode, const char *str,
+extern int mu_getpass (mu_stream_t in, mu_stream_t out, const char *prompt,
+ char **passptr);
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
@@ -76,2 +76,5 @@ enum mu_buffer_type
+#define MU_IOCTL_GET_ECHO 12
+#define MU_IOCTL_SET_ECHO 13
+
#define MU_TRANSPORT_INPUT 0
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
@@ -23,3 +23,4 @@
-#define _MU_FILE_STREAM_TEMP 0x01
+#define _MU_FILE_STREAM_TEMP 0x01
+#define _MU_FILE_STREAM_ECHO_OFF 0x02
@@ -31,2 +32,3 @@ struct _mu_file_stream
char *filename;
+ void *echo_state;
};
diff --git a/libmailutils/Makefile.am b/libmailutils/Makefile.am
index e05edd883..3f083e01d 100644
--- a/libmailutils/Makefile.am
+++ b/libmailutils/Makefile.am
@@ -86,2 +86,3 @@ libmailutils_la_SOURCES = \
gdebug.c\
+ getpass.c\
gocs.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
@@ -25,2 +25,5 @@
#include <sys/stat.h>
+#if HAVE_TERMIOS_H
+# include <termios.h>
+#endif
@@ -185,2 +188,4 @@ fd_done (struct _mu_stream *str)
free (fstr->filename);
+ if (fstr->echo_state)
+ free (fstr->echo_state);
}
@@ -196,2 +201,6 @@ fd_error_string (struct _mu_stream *str, int rc)
+#ifndef TCSASOFT
+# define TCSASOFT 0
+#endif
+
static int
@@ -220,13 +229,82 @@ fd_ioctl (struct _mu_stream *str, int code, void *ptr)
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:
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;
+}
+
diff --git a/mu/mu.h b/mu/mu.h
index 8ae5fc1d2..26d5d59ca 100644
--- a/mu/mu.h
+++ b/mu/mu.h
@@ -40,3 +40,3 @@ 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);
diff --git a/mu/pop.c b/mu/pop.c
index 59fed1517..b3a1592f9 100644
--- a/mu/pop.c
+++ b/mu/pop.c
@@ -456,18 +456,2 @@ com_noop (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
-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
@@ -476,4 +460,3 @@ com_pass (int argc, char **argv)
int status;
- char pass[256];
- char *pwd;
+ char *pwd, *passbuf = NULL;
@@ -481,13 +464,6 @@ com_pass (int argc, char **argv)
{
- 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;
}
@@ -501,2 +477,3 @@ com_pass (int argc, char **argv)
}
+ 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
@@ -35,3 +35,3 @@ mu_vartab_t mutool_prompt_vartab;
int mutool_shell_interactive;
-mu_stream_t mustrout;
+mu_stream_t mustrin, mustrout;
@@ -372,4 +372,9 @@ readline (char *prompt)
}
- 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;
@@ -468,2 +473,11 @@ mutool_shell (const char *name, struct mutool_command *cmd)
+ 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,
@@ -472,6 +486,7 @@ mutool_shell (const char *name, struct mutool_command *cmd)
{
- 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);
@@ -523,2 +538,3 @@ mutool_shell (const char *name, struct mutool_command *cmd)
finish_readline ();
+ mu_stream_destroy (&mustrin);
mu_stream_destroy (&mustrout);
diff --git a/pop3d/popauth.c b/pop3d/popauth.c
index 9f73d60ed..f8505f949 100644
--- a/pop3d/popauth.c
+++ b/pop3d/popauth.c
@@ -76,3 +76,3 @@ static struct argp_option options[] =
" For the file owner: --list\n"
- " For a user: --modify --username <username>\n"), 2 },
+ " For a user: --modify --user <username>\n"), 2 },
@@ -107,3 +107,3 @@ set_db_perms (struct argp_state *astate, char *opt, int *pperm)
- if (mu_isdigit(opt[0]))
+ if (mu_isdigit (opt[0]))
{
@@ -448,17 +448,53 @@ fill_pass (struct action_data *ap)
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.