X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=netrc.c;h=a585e1a0be37c236336713b949f15e7f9b3926e6;hb=fb3286d03c35f4ccfdeb89669adf47d7ce7aeebe;hp=92adfa77c2be4e0fb64998ecb45eb3d4061d81f2;hpb=6c847c7569654682cc3d14e4a14d3afbf207f63c;p=~andy%2Ffetchmail diff --git a/netrc.c b/netrc.c index 92adfa77..a585e1a0 100644 --- a/netrc.c +++ b/netrc.c @@ -1,61 +1,25 @@ -/* netrc.c -- parse the .netrc file to get hosts, accounts, and passwords - Copyright (C) 1996, Free Software Foundation, Inc. +/* + * netrc.c -- parse the .netrc file to get hosts, accounts, and passwords + * Gordon Matzigkeit , 1996 + Copyright assigned to Eric S. Raymond, October 2001. - 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -/* Compile with -DSTANDALONE to test this module. */ - -#ifdef HAVE_CONFIG_H -# include -#endif /* HAVE_CONFIG_H */ - -/* If SYSTEM_WGETRC is defined in config.h, then we assume we are being - compiled as a part of Wget. That means we make special Wget-specific - modifications to the code (at least until we settle on a cleaner - library interface). */ -/* FIXME - eliminate all WGET_HACKS conditionals by massaging Wget. */ -#ifdef SYSTEM_WGETRC -# define WGET_HACKS 1 -#endif + For license terms, see the file COPYING in this directory. -/* If CLIENT_TIMEOUT is defined in config.h, then we assume we are being - compiled as a part of fetchmail. */ -/* FIXME - eliminate all FETCHMAIL_HACKS conditionals by fixing fetchmail. */ -#ifdef CLIENT_TIMEOUT -# define FETCHMAIL_HACKS 1 -#endif + Compile with -DSTANDALONE to test this module. + (Makefile.am should have a rule so you can just type "make netrc") +*/ + +#include "config.h" #include #include #include -#ifdef HAVE_STRING_H -# include -#else -# include -#endif - -#if ENABLE_NLS -# include -# define _(Text) gettext (Text) -#else -# define textdomain(Domain) -# define _(Text) Text -#endif +#include +#include "fetchmail.h" #include "netrc.h" +#include "i18n.h" #ifdef STANDALONE /* Normally defined in xstrdup.c. */ @@ -64,183 +28,48 @@ /* Normally defined in xmalloc.c */ # define xmalloc malloc # define xrealloc realloc -#endif -#if defined(STANDALONE) || defined(WGET_HACKS) || defined(FETCHMAIL_HACKS) -/* We need to implement our own dynamic strings. */ -typedef struct -{ - int ds_length; - char *ds_string; -} dynamic_string; -#else -/* We must be part of libit, or another GNU program, so assume that we have - the ERROR function */ -# define HAVE_ERROR 1 -# include "error.h" -# include "dstring.h" +const char *program_name = "netrc"; #endif -#define DS_INIT_LENGTH 40 - -#ifdef WGET_HACKS -/* Wget uses different naming conventions. */ -# define xmalloc nmalloc -# define xstrdup nstrdup -# define xrealloc nrealloc - -/* Wget has read_whole_line defined in utils.c */ -# include "utils.h" - -/* Temporary dynamic string (dstring.c from libit)-like interface to - using read_whole_line. */ -#define ds_init(string, size) ((string)->ds_string = NULL) -#define ds_destroy(string) free ((string)->ds_string) - -/* We use read_whole_line to implement ds_fgets. */ -static char * -ds_fgets (FILE *f, dynamic_string *s) -{ - free (s->ds_string); - s->ds_string = read_whole_line (f); - return s->ds_string; -} -#endif /* WGET_HACKS */ - -#ifdef FETCHMAIL_HACKS -/* fetchmail, too, is not consistent with the xmalloc functions. */ -# define xrealloc realloc -# define xstrdup strdup -#endif - -#if defined(STANDALONE) || defined(FETCHMAIL_HACKS) -/* Bits and pieces of Tom Tromey's dstring.c, taken from libit-0.2. */ - -/* Initialize dynamic string STRING with space for SIZE characters. */ - -void -ds_init (string, size) - dynamic_string *string; - int size; -{ - string->ds_length = size; - string->ds_string = (char *) xmalloc (size); -} - -/* Expand dynamic string STRING, if necessary, to hold SIZE characters. */ - -void -ds_resize (string, size) - dynamic_string *string; - int size; -{ - if (size > string->ds_length) - { - string->ds_length = size; - string->ds_string = (char *) xrealloc ((char *) string->ds_string, size); - } -} - -/* Delete dynamic string. */ - -void -ds_destroy (string) - dynamic_string *string; -{ - free (string->ds_string); - string->ds_string = NULL; -} - -/* Dynamic string S gets a string terminated by the EOS character - (which is removed) from file F. S will increase - in size during the function if the string from F is longer than - the current size of S. - Return NULL if end of file is detected. Otherwise, - Return a pointer to the null-terminated string in S. */ - -char * -ds_fgetstr (f, s, eos) - FILE *f; - dynamic_string *s; - char eos; -{ - int insize; /* Amount needed for line. */ - int strsize; /* Amount allocated for S. */ - int next_ch; - - /* Initialize. */ - insize = 0; - strsize = s->ds_length; - - /* Read the input string. */ - next_ch = getc (f); - while (next_ch != eos && next_ch != EOF) - { - if (insize >= strsize - 1) - { - ds_resize (s, strsize * 2 + 2); - strsize = s->ds_length; - } - s->ds_string[insize++] = next_ch; - next_ch = getc (f); - } - s->ds_string[insize++] = '\0'; - - if (insize == 1 && next_ch == EOF) - return NULL; - else - return s->ds_string; -} - -char * -ds_fgets (f, s) - FILE *f; - dynamic_string *s; -{ - return ds_fgetstr (f, s, '\n'); -} -#endif /* !STANDALONE */ - - /* Maybe add NEWENTRY to the account information list, LIST. NEWENTRY is set to a ready-to-use netrc_entry, in any event. */ static void -maybe_add_to_list (newentry, list) - netrc_entry **newentry; - netrc_entry **list; +maybe_add_to_list (netrc_entry **newentry, netrc_entry **list) { - netrc_entry *a, *l; - a = *newentry; - l = *list; + netrc_entry *a, *l; + a = *newentry; + l = *list; - /* We need an account name in order to add the entry to the list. */ - if (a && ! a->account) + /* We need a login name in order to add the entry to the list. */ + if (a && ! a->login) { - /* Free any allocated space. */ - free (a->host); - free (a->account); - free (a->password); + /* Free any allocated space. */ + if (a->host) + free (a->host); + if (a->password) + free (a->password); } - else + else { - if (a) + if (a) { - /* Add the current machine into our list. */ - a->next = l; - l = a; + /* Add the current machine into our list. */ + a->next = l; + l = a; } - /* Allocate a new netrc_entry structure. */ - a = (netrc_entry *) xmalloc (sizeof (netrc_entry)); + /* Allocate a new netrc_entry structure. */ + a = (netrc_entry *) xmalloc (sizeof (netrc_entry)); } - /* Zero the structure, so that it is ready to use. */ - memset (a, 0, sizeof(*a)); + /* Zero the structure, so that it is ready to use. */ + memset (a, 0, sizeof(*a)); - /* Return the new pointers. */ - *newentry = a; - *list = l; - return; + /* Return the new pointers. */ + *newentry = a; + *list = l; + return; } @@ -248,303 +77,342 @@ maybe_add_to_list (newentry, list) list of entries. NULL is returned if the file could not be parsed. */ netrc_entry * -parse_netrc (file) - char *file; +parse_netrc (char *file) { - FILE *fp; - char *p, *tok, *premature_token; - netrc_entry *current, *retval; - dynamic_string line; - int ln; - - /* The latest token we've seen in the file. */ - enum - { - tok_nothing, tok_account, tok_login, tok_macdef, tok_machine, tok_password - } last_token = tok_nothing; - - current = retval = NULL; - - fp = fopen (file, "r"); - if (!fp) + FILE *fp; + char buf[POPBUFSIZE+1], *p, *tok; + const char *premature_token; + netrc_entry *current, *retval; + int ln; + + /* The latest token we've seen in the file. */ + enum { - /* Just return NULL if we can't open the file. */ - return NULL; + tok_nothing, tok_account, tok_login, tok_macdef, tok_machine, tok_password + } last_token = tok_nothing; + + current = retval = NULL; + + fp = fopen (file, "r"); + if (!fp) + { + /* Just return NULL if we can't open the file. */ + return NULL; } - /* Initialize the file data. */ - ln = 0; - premature_token = NULL; + /* Initialize the file data. */ + ln = 0; + premature_token = NULL; - /* While there are lines in the file... */ - ds_init (&line, DS_INIT_LENGTH); - while (ds_fgets (fp, &line)) + /* While there are lines in the file... */ + while (fgets(buf, sizeof(buf) - 1, fp)) { - ln ++; + ln++; - /* Parse the line. */ - p = line.ds_string; + /* Strip trailing CRLF */ + for (p = buf + strlen(buf) - 1; (p >= buf) && isspace((unsigned char)*p); p--) + *p = '\0'; - /* If the line is empty, then end any macro definition. */ - if (last_token == tok_macdef && !*p) - /* End of macro if the line is empty. */ - last_token = tok_nothing; + /* Parse the line. */ + p = buf; - /* If we are defining macros, then skip parsing the line. */ - while (*p && last_token != tok_macdef) + /* If the line is empty... */ + if (!*p) { - /* Skip any whitespace. */ - while (*p && isspace (*p)) - p ++; + if (last_token == tok_macdef) /* end of macro */ + last_token = tok_nothing; + else + continue; /* otherwise ignore it */ + } - /* Discard end-of-line comments. */ - if (*p == '#') - break; + /* If we are defining macros, then skip parsing the line. */ + while (*p && last_token != tok_macdef) + { + char quote_char = 0; + char *pp; + + /* Skip any whitespace. */ + while (*p && isspace ((unsigned char)*p)) + p++; - tok = p; + /* Discard end-of-line comments. */ + if (*p == '#') + break; - /* Find the end of the token. */ - while (*p && !isspace (*p)) - p ++; + tok = pp = p; - /* Null-terminate the token, if it isn't already. */ - if (*p) - *p ++ = '\0'; + /* Find the end of the token. */ + while (*p && (quote_char || !isspace ((unsigned char)*p))) + { + if (quote_char) + { + if (quote_char == *p) + { + quote_char = 0; + p ++; + } + else + { + *pp = *p; + p ++; + pp ++; + } + } + else + { + if (*p == '"' || *p == '\'') + quote_char = *p; + else + { + *pp = *p; + pp ++; + } + p ++; + } + } + /* Null-terminate the token, if it isn't already. */ + if (*p) + *p ++ = '\0'; + *pp = 0; - switch (last_token) + switch (last_token) { case tok_login: - if (current) - current->account = (char *) xstrdup (tok); - else - premature_token = "login"; - break; + if (current) + current->login = (char *) xstrdup (tok); + else + premature_token = "login"; + break; case tok_machine: - /* Start a new machine entry. */ - maybe_add_to_list (¤t, &retval); - current->host = (char *) xstrdup (tok); - break; + /* Start a new machine entry. */ + maybe_add_to_list (¤t, &retval); + current->host = (char *) xstrdup (tok); + break; case tok_password: - if (current) - current->password = (char *) xstrdup (tok); - else - premature_token = "password"; - break; + if (current) + current->password = (char *) xstrdup (tok); + else + premature_token = "password"; + break; - /* We handle most of tok_macdef above. */ + /* We handle most of tok_macdef above. */ case tok_macdef: - if (!current) - premature_token = "macdef"; - break; + if (!current) + premature_token = "macdef"; + break; - /* We don't handle the account keyword at all. */ + /* We don't handle the account keyword at all. */ case tok_account: - if (!current) - premature_token = "account"; - break; + if (!current) + premature_token = "account"; + break; - /* We handle tok_nothing below this switch. */ + /* We handle tok_nothing below this switch. */ case tok_nothing: - break; + break; } - if (premature_token) + if (premature_token) { -#ifdef HAVE_ERROR - error_at_line (0, 0, file, ln, - _("warning: found \"%s\" before any host names"), - premature_token); -#else - fprintf (stderr, - "%s:%d: warning: found \"%s\" before any host names\n", - file, ln, premature_token); -#endif - premature_token = NULL; + fprintf (stderr, + GT_("%s:%d: warning: found \"%s\" before any host names\n"), + file, ln, premature_token); + premature_token = NULL; } - if (last_token != tok_nothing) - /* We got a value, so reset the token state. */ - last_token = tok_nothing; - else + if (last_token != tok_nothing) + /* We got a value, so reset the token state. */ + last_token = tok_nothing; + else { - /* Fetch the next token. */ - if (!strcmp (tok, "account")) - last_token = tok_account; - - if (!strcmp (tok, "default")) + /* Fetch the next token. */ + if (!strcmp (tok, "default")) { - maybe_add_to_list (¤t, &retval); + maybe_add_to_list (¤t, &retval); } - else if (!strcmp (tok, "login")) - last_token = tok_login; + else if (!strcmp (tok, "login")) + last_token = tok_login; + + else if (!strcmp (tok, "user")) + last_token = tok_login; + + else if (!strcmp (tok, "macdef")) + last_token = tok_macdef; + + else if (!strcmp (tok, "machine")) + last_token = tok_machine; - else if (!strcmp (tok, "macdef")) - last_token = tok_macdef; + else if (!strcmp (tok, "password")) + last_token = tok_password; - else if (!strcmp (tok, "machine")) - last_token = tok_machine; + else if (!strcmp (tok, "passwd")) + last_token = tok_password; - else if (!strcmp (tok, "password")) - last_token = tok_password; + else if (!strcmp (tok, "account")) + last_token = tok_account; - else + else { - fprintf (stderr, _("%s:%d: warning: unknown token \"%s\"\n"), - file, ln, tok); + fprintf (stderr, GT_("%s:%d: warning: unknown token \"%s\"\n"), + file, ln, tok); } } } } - ds_destroy (&line); - fclose (fp); + fclose (fp); - /* Finalize the last machine entry we found. */ - maybe_add_to_list (¤t, &retval); - free (current); + /* Finalize the last machine entry we found. */ + maybe_add_to_list (¤t, &retval); + free (current); - /* Reverse the order of the list so that it appears in file order. */ - current = retval; - retval = NULL; - while (current) + /* Reverse the order of the list so that it appears in file order. */ + current = retval; + retval = NULL; + while (current) { - netrc_entry *saved_reference; + netrc_entry *saved_reference; - /* Change the direction of the pointers. */ - saved_reference = current->next; - current->next = retval; + /* Change the direction of the pointers. */ + saved_reference = current->next; + current->next = retval; - /* Advance to the next node. */ - retval = current; - current = saved_reference; + /* Advance to the next node. */ + retval = current; + current = saved_reference; } - return retval; + return retval; } /* Return the netrc entry from LIST corresponding to HOST. NULL is returned if no such entry exists. */ netrc_entry * -search_netrc (list, host) - netrc_entry *list; - char *host; +search_netrc (netrc_entry *list, char *host, char *login) { - /* Look for the HOST in LIST. */ - while (list) + /* Look for the HOST in LIST. */ + while (list) { - if (!list->host) - /* We hit the default entry. */ - break; + if (list->host && !strcmp(list->host, host)) + if (!list->login || !strcmp(list->login, login)) + /* We found a matching entry. */ + break; - else if (!strcmp (list->host, host)) - /* We found a matching entry. */ - break; - - list = list->next; + list = list->next; } - /* Return the matching entry, or NULL. */ - return list; + /* Return the matching entry, or NULL. */ + return list; } +void +free_netrc(netrc_entry *a) { + while(a) { + netrc_entry *n = a->next; + if (a->password != NULL) { + memset(a->password, 0x55, strlen(a->password)); + free(a->password); + } + xfree(a->login); + xfree(a->host); + xfree(a); + a = n; + } +} #ifdef STANDALONE #include #include -extern int errno; +#include -int -main (argc, argv) - int argc; - char **argv; +int main (int argc, char **argv) { - struct stat sb; - char *program_name, *file, *target; - netrc_entry *head, *a; - - if (argc < 2) - { - fprintf (stderr, "Usage: %s NETRC [HOSTNAME]...\n", argv[0]); - exit (1); + struct stat sb; + char *file, *host, *login; + netrc_entry *head, *a; + + program_name = argv[0]; + file = argv[1]; + host = argv[2]; + login = argv[3]; + + switch (argc) { + case 2: + case 4: + break; + default: + fprintf (stderr, "Usage: %s [ ]\n", argv[0]); + exit(EXIT_FAILURE); } - program_name = argv[0]; - file = argv[1]; - target = argv[2]; - - if (stat (file, &sb)) + if (stat (file, &sb)) { - fprintf (stderr, "%s: cannot stat %s: %s\n", argv[0], file, - strerror (errno)); - exit (1); + fprintf (stderr, "%s: cannot stat %s: %s\n", argv[0], file, + strerror (errno)); + exit (1); } - head = parse_netrc (file); - if (!head) + head = parse_netrc (file); + if (!head) { - fprintf (stderr, "%s: no entries found in %s\n", argv[0], file); - exit (1); + fprintf (stderr, "%s: no entries found in %s\n", argv[0], file); + exit (1); } - if (argc > 2) + if (host && login) { - int i, status; - status = 0; - for (i = 2; i < argc; i++) - { - /* Print out the host that we are checking for. */ - fputs (argv[i], stdout); + int status; + status = EXIT_SUCCESS; - a = search_netrc (head, argv[i]); - if (a) + printf("Host: %s, Login: %s\n", host, login); + + a = search_netrc (head, host, login); + if (a) + { + /* Print out the password (if any). */ + if (a->password) { - /* Print out the account and password (if any). */ - fputc (' ', stdout); - fputs (a->account, stdout); - if (a->password) - { - fputc (' ', stdout); - fputs (a->password, stdout); - } + printf("Password: %s\n", a->password); } - else - status = 1; + } else + status = EXIT_FAILURE; + fputc ('\n', stdout); - fputc ('\n', stdout); - } - exit (status); + exit (status); } - /* Print out the entire contents of the netrc. */ - a = head; - while (a) + /* Print out the entire contents of the netrc. */ + a = head; + while (a) { - /* Print the host name. */ - if (a->host) - fputs (a->host, stdout); - else - fputs ("DEFAULT", stdout); + /* Print the host name. */ + if (a->host) + fputs (a->host, stdout); + else + fputs ("DEFAULT", stdout); - fputc (' ', stdout); + fputc (' ', stdout); - /* Print the account name. */ - fputs (a->account, stdout); + /* Print the login name. */ + fputs (a->login, stdout); - if (a->password) + if (a->password) { - /* Print the password, if there is any. */ - fputc (' ', stdout); - fputs (a->password, stdout); + /* Print the password, if there is any. */ + fputc (' ', stdout); + fputs (a->password, stdout); } - fputc ('\n', stdout); - a = a->next; + fputc ('\n', stdout); + a = a->next; } - exit (0); + free_netrc(head); + + exit (0); } #endif /* STANDALONE */