# HG changeset patch
# User luciano@xxxxxxxxxxxxxxxxxxxxxx
# Date 1179848062 -3600
# Node ID 0a3bb46d1d5ee19199f2f7170cfdd16a46cb3553
# Parent 357b7651d6095f5b2e9c5dab1e4cb5c7fb6bc379
Support for reading users and/or passwords from netrc(5)
Extended mutt_account_getuser and mutt_account_getpass in account.c with
netrc_user and netrc_password for retrieving username and password from
~/.netrc.
netrc(5) parsing was added in new files netrc.c and netrc.h.
diff -r 357b7651d609 -r 0a3bb46d1d5e Makefile.am
--- a/Makefile.am Tue May 22 16:11:15 2007 +0100
+++ b/Makefile.am Tue May 22 16:34:22 2007 +0100
@@ -28,7 +28,7 @@ mutt_SOURCES = $(BUILT_SOURCES) \
rfc822.c rfc1524.c rfc2047.c rfc2231.c rfc3676.c \
score.c send.c sendlib.c signal.c sort.c \
status.c system.c thread.c charset.c history.c lib.c \
- muttlib.c editmsg.c mbyte.c \
+ muttlib.c editmsg.c mbyte.c netrc.c \
url.c ascii.c mutt_idna.c crypt-mod.c crypt-mod.h
mutt_LDADD = @MUTT_LIB_OBJECTS@ @LIBOBJS@ $(LIBIMAP) $(MUTTLIBS) \
diff -r 357b7651d609 -r 0a3bb46d1d5e account.c
--- a/account.c Tue May 22 16:11:15 2007 +0100
+++ b/account.c Tue May 22 16:34:22 2007 +0100
@@ -25,6 +25,7 @@
#include "mutt.h"
#include "account.h"
#include "url.h"
+#include "netrc.h"
/* mutt_account_match: compare account info (host/port/user/login) */
int mutt_account_match (const ACCOUNT* a1, const ACCOUNT* a2)
@@ -158,6 +159,10 @@ int mutt_account_getuser (ACCOUNT* accou
else if ((account->type == M_ACCT_TYPE_POP) && PopUser)
strfcpy (account->user, PopUser, sizeof (account->user));
#endif
+ else if (netrc_user (account->host,
+ account->user, sizeof (account->user),
+ account->pass, sizeof (account->pass)))
+ ;
/* prompt (defaults to unix username), copy into account->user */
else
{
@@ -218,6 +223,11 @@ int mutt_account_getpass (ACCOUNT* accou
else if ((account->type == M_ACCT_TYPE_SMTP) && SmtpPass)
strfcpy (account->pass, SmtpPass, sizeof (account->pass));
#endif
+ else if (netrc_password (account->flags & M_ACCT_LOGIN
+ ? account->login : account->user,
+ account->host,
+ account->pass, sizeof (account->pass)))
+ ;
else
{
snprintf (prompt, sizeof (prompt), _("Password for %s@%s: "),
diff -r 357b7651d609 -r 0a3bb46d1d5e netrc.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/netrc.c Tue May 22 16:34:22 2007 +0100
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) 2007 Luciano Rocha <strange@xxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
+ */
+
+/* netrc(5) parsing support */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+/* for isspace(c) */
+#include <ctype.h>
+
+#include "mutt.h"
+#include "netrc.h"
+
+/* token types */
+enum
+{
+ M_NETRC_TOK_DEFAULT,
+ M_NETRC_TOK_MACHINE,
+ M_NETRC_TOK_LOGIN,
+ M_NETRC_TOK_PASSWORD,
+ M_NETRC_TOK_ACCOUNT,
+ M_NETRC_TOK_MACRO,
+ M_NETRC_TOK_UNKNOWN
+};
+
+/* tokens and their values */
+typedef struct {
+ int type;
+ char *value1;
+ int len1;
+ char *value2;
+ int len2;
+} TOKEN;
+
+/* open netrc */
+static FILE *netrc_open (void)
+{
+ char path[_POSIX_PATH_MAX];
+
+ snprintf (path, sizeof (path), "%s/.netrc", NONULL(Homedir));
+ return fopen (path, "r");
+}
+
+/* clean tok structure and free any alloced data */
+static void netrc_free_tok (TOKEN *tok)
+{
+ if (tok->value1)
+ free (tok->value1);
+ if (tok->value2)
+ free (tok->value2);
+ tok->value1 = tok->value2 = NULL;
+ tok->len1 = tok->len2 = 0;
+}
+
+/* read next token from netrc and its values */
+static int netrc_next_tok (FILE *fp, TOKEN *tok)
+{
+ char token[40];
+ char value[256];
+ int c, i;
+
+ netrc_free_tok (tok);
+
+ /* skip whitespace */
+ while ((c = getc (fp)) != EOF && isspace (c));
+ if (c == EOF)
+ return 0;
+
+ /* get token (text till next whitespace) */
+ token[0] = (char) c;
+ i = 1;
+ while ((c = getc (fp)) != EOF && !isspace (c)
+ && i < (sizeof token - 1))
+ token[i++] = (char) c;
+
+ /* abort if EOF or whould exceed token space */
+ if (c == EOF || i == (sizeof token - 1))
+ return 0;
+
+ token[i++] = '\0';
+
+ /* "default" is special, as it doesn't have a value */
+ if (!ascii_strcasecmp ("default", token))
+ {
+ tok->type = M_NETRC_TOK_DEFAULT;
+ return 1;
+ }
+
+ /* has a value, read it */
+
+ /* skip whitespace */
+ while ((c = getc (fp)) != EOF && isspace (c));
+
+ /* no value found if EOF */
+ if (c == EOF)
+ return 0;
+
+ /* get value (text till next whitespace) */
+ value[0] = (char) c;
+ i = 1;
+ while ((c = getc (fp)) != EOF && !isspace (c)
+ && i < (sizeof value - 1))
+ value[i++] = (char) c;
+
+ /* abort if EOF or whould exceed value space */
+ if (c == EOF || i == (sizeof value - 1))
+ return 0;
+ value[i++] = '\0';
+
+ tok->value1 = safe_strdup (value);
+ tok->len1 = i;
+
+ if (!ascii_strcasecmp ("machine", token))
+ tok->type = M_NETRC_TOK_MACHINE;
+ else if (!ascii_strcasecmp ("login", token))
+ tok->type = M_NETRC_TOK_LOGIN;
+ else if (!ascii_strcasecmp ("password", token))
+ tok->type = M_NETRC_TOK_PASSWORD;
+ else if (!ascii_strcasecmp ("account", token))
+ tok->type = M_NETRC_TOK_ACCOUNT;
+ else if (!ascii_strcasecmp ("macdef", token))
+ tok->type = M_NETRC_TOK_MACRO;
+ else
+ tok->type = M_NETRC_TOK_UNKNOWN;
+
+ /* "macdef" next lines till EOF or empty line */
+ if (tok->type == M_NETRC_TOK_MACRO)
+ {
+ char *p = NULL;
+ int l = 0;
+
+ /* skip to end of line */
+ while (c != EOF && c != '\n')
+ c = getc (fp);
+
+ /* while not an empty line, add to value2 */
+ while (fgets (value, sizeof value, fp))
+ {
+ for (i = 0; value[i] && isspace (value[i]); i++);
+ if (value[i] == '\0')
+ /* stopped at '\0': empty line */
+ break;
+
+ /* length of string, excluding \0 */
+ i = i + strlen (value + i);
+
+ /* extend buffer by i and copy new content */
+ safe_realloc (&p, l + i + 1);
+ memcpy (p + l, value, i + 1);
+ l += i;
+ }
+ tok->value2 = p;
+ tok->len2 = l + 1; /* include terminating '\0' */
+ }
+ return 1;
+}
+
+/* get password for user @ host from $HOME/.netrc:
+ * returns true if found, and the password argument is updated with
+ * the value */
+int netrc_password (const char *login, const char *host,
+ char *password, size_t length)
+{
+ TOKEN tok;
+ FILE *nr;
+ char *user = NULL;
+ int in_host = 0;
+ int found = 0;
+
+ nr = netrc_open ();
+ if (!nr) return 0;
+
+ memset (&tok, 0, sizeof tok);
+
+ while (netrc_next_tok (nr, &tok))
+ {
+ /* search for default or "machine" == host */
+ if (tok.type == M_NETRC_TOK_DEFAULT
+ || (tok.type == M_NETRC_TOK_MACHINE
+ && !ascii_strcasecmp (tok.value1,
+ host)))
+ {
+ in_host = 1;
+ if (user)
+ {
+ free (user);
+ user = NULL;
+ }
+ }
+ else if (tok.type == M_NETRC_TOK_MACHINE)
+ in_host = 0;
+ else if (!in_host)
+ /* ignore tokens for other hosts */
+ ;
+ else if (tok.type == M_NETRC_TOK_LOGIN)
+ {
+ /* copy value of user */
+ if (user) free (user);
+ user = safe_strdup (tok.value1);
+ }
+ else if (tok.type == M_NETRC_TOK_PASSWORD
+ && /* password valid if user undefined or
+ user defined to value of login */
+ (!user || !strcmp (login, user)))
+ {
+ /* check if password fits in buffer */
+ if (tok.len1 > length)
+ break;
+ memcpy (password, tok.value1, tok.len1);
+ found = 1;
+ break;
+ }
+ }
+
+ /* clean up */
+ netrc_free_tok (&tok);
+ if (user) free (user);
+ fclose (nr);
+
+ return found;
+}
+
+/* get login and password for host from $HOME/.netrc:
+ * returns true if found, updates arguments if not pointing to NULL */
+int netrc_user (const char *host,
+ char *login, size_t login_length,
+ char *password, size_t password_length)
+{
+ TOKEN tok;
+ FILE *nr;
+ char *user = NULL;
+ int in_host = 0;
+ int i;
+ int found = 0;
+
+ nr = netrc_open ();
+ if (!nr) return 0;
+
+ memset (&tok, 0, sizeof tok);
+
+ while (netrc_next_tok (nr, &tok))
+ {
+ /* search for default or "machine" == host */
+ if (tok.type == M_NETRC_TOK_DEFAULT
+ || (tok.type == M_NETRC_TOK_MACHINE
+ && !ascii_strcasecmp (tok.value1,
+ host)))
+ {
+ in_host = 1;
+ if (user)
+ {
+ free (user);
+ user = NULL;
+ }
+ }
+ else if (tok.type == M_NETRC_TOK_MACHINE)
+ in_host = 0;
+ else if (!in_host)
+ /* ignore tokens for other hosts */
+ ;
+ else if (tok.type == M_NETRC_TOK_LOGIN)
+ {
+ /* copy value of user */
+ if (user) free (user);
+ user = safe_strdup (tok.value1);
+ }
+ else if (tok.type == M_NETRC_TOK_PASSWORD
+ && /* password valid if any user defined */
+ user)
+ {
+ /* check if password fits in buffer */
+ if (tok.len1 > password_length)
+ break;
+
+ /* check if login fits in buffer */
+ i = strlen (user) + 1;
+ if (i > login_length)
+ break;
+
+ memcpy (password, tok.value1, tok.len1);
+ memcpy (login, user, i);
+
+ found = 1;
+ break;
+ }
+ }
+
+ /* if no user + password found, check only user */
+ if (!found && user)
+ {
+ i = strlen (user) + 1;
+ if (i <= login_length)
+ {
+ memcpy (login, user, i);
+ found = 1;
+ }
+ }
+
+ /* clean up */
+ netrc_free_tok (&tok);
+ if (user) free (user);
+ fclose (nr);
+
+ return found;
+}
diff -r 357b7651d609 -r 0a3bb46d1d5e netrc.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/netrc.h Tue May 22 16:34:22 2007 +0100
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2007 Luciano Rocha <strange@xxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
+ */
+
+/* netrc(5) parsing support */
+
+#ifndef _MUTT_NETRC_H_
+#define _MUTT_NETRC_H_ 1
+
+/* get password for user login @ host.
+ * returns true when found and populates password argument to length limit
+ * (including terminating \0) */
+int netrc_password (const char *login, const char *host,
+ char *password, size_t length);
+
+/* get login and password for host.
+ * returns true when found and populates both login and password argument to
+ * their lengths limit (including terminating \0), if not pointing to NULL */
+int netrc_user (const char *host,
+ char *login, size_t login_length,
+ char *password, size_t password_length);
+
+#endif /* _MUTT_NETRC_H_ */
Attachment:
pgpM4d2lxAmue.pgp
Description: PGP signature