X-Git-Url: http://sjero.net/git/?p=wget;a=blobdiff_plain;f=src%2Fnetrc.c;h=1e12d1deddba24c73086e2abd841a598b1200037;hp=9777e9e261a5d4eb5dc9e996e81dc661040c6089;hb=38a7829dcb4eb5dba28dbf0f05c6a80fea9217f8;hpb=1810f7a442eb746d625f183c7349c68ec17ee800 diff --git a/src/netrc.c b/src/netrc.c index 9777e9e2..1e12d1de 100644 --- a/src/netrc.c +++ b/src/netrc.c @@ -1,53 +1,58 @@ /* Read and parse the .netrc file to get hosts, accounts, and passwords. - Copyright (C) 1996, Free Software Foundation, Inc. + Copyright (C) 1996, 2007, 2008, 2009, 2010, 2011 Free Software + Foundation, Inc. -This file is part of Wget. +This file is part of GNU Wget. -This program is free software; you can redistribute it and/or modify +GNU Wget 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 +the Free Software Foundation; either version 3 of the License, or (at your option) any later version. -This program is distributed in the hope that it will be useful, +GNU Wget 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. */ +along with Wget. If not, see . + +Additional permission under GNU GPL version 3 section 7 + +If you modify this program, or any covered work, by linking or +combining it with the OpenSSL project's OpenSSL library (or a +modified version of that library), containing parts covered by the +terms of the OpenSSL or SSLeay licenses, the Free Software Foundation +grants you additional permission to convey the resulting work. +Corresponding Source for a non-source form of such a combination +shall include the source code for the parts of OpenSSL used as well +as that of the covered work. */ /* This file used to be kept in synch with the code in Fetchmail, but the latter has diverged since. */ -#ifdef HAVE_CONFIG_H -# include -#endif +#include "wget.h" #include #include -#ifdef HAVE_STRING_H -# include -#else -# include -#endif -#include +#include #include -#include "wget.h" #include "utils.h" #include "netrc.h" #include "init.h" -#ifndef errno -extern int errno; -#endif - #define NETRC_FILE_NAME ".netrc" -acc_t *netrc_list; +static acc_t *netrc_list; -static acc_t *parse_netrc PARAMS ((const char *)); +static acc_t *parse_netrc (const char *); + +void +netrc_cleanup(void) +{ + free_netrc (netrc_list); +} /* Return the correct user and password, given the host, user (as given in the URL), and password (as given in the URL). May return @@ -57,7 +62,7 @@ static acc_t *parse_netrc PARAMS ((const char *)); You will typically turn it off for HTTP. */ void search_netrc (const char *host, const char **acc, const char **passwd, - int slack_default) + int slack_default) { acc_t *l; static int processed_netrc; @@ -67,22 +72,39 @@ search_netrc (const char *host, const char **acc, const char **passwd, /* Find ~/.netrc. */ if (!processed_netrc) { - char *home = home_dir(); +#ifdef __VMS + + int err; + struct_stat buf; + char *path = "SYS$LOGIN:.netrc"; + + netrc_list = NULL; + processed_netrc = 1; + + err = stat (path, &buf); + if (err == 0) + netrc_list = parse_netrc (path); + +#else /* def __VMS */ + + char *home = home_dir (); netrc_list = NULL; processed_netrc = 1; if (home) - { - int err; - struct stat buf; - char *path = (char *)alloca (strlen (home) + 1 - + strlen (NETRC_FILE_NAME) + 1); - sprintf (path, "%s/%s", home, NETRC_FILE_NAME); - xfree (home); - err = stat (path, &buf); - if (err == 0) - netrc_list = parse_netrc (path); - } + { + int err; + struct_stat buf; + char *path = (char *)alloca (strlen (home) + 1 + + strlen (NETRC_FILE_NAME) + 1); + sprintf (path, "%s/%s", home, NETRC_FILE_NAME); + xfree (home); + err = stat (path, &buf); + if (err == 0) + netrc_list = parse_netrc (path); + } + +#endif /* def __VMS [else] */ } /* If nothing to do... */ if (!netrc_list) @@ -90,100 +112,63 @@ search_netrc (const char *host, const char **acc, const char **passwd, /* Acc and password found; all OK. */ if (*acc && *passwd) return; - if (!*acc && !slack_default) - return; /* Some data not given -- try finding the host. */ for (l = netrc_list; l; l = l->next) { if (!l->host) - continue; + continue; else if (!strcasecmp (l->host, host)) - break; + break; } if (l) { if (*acc) - { - /* Looking for password in .netrc. */ - if (!strcmp (l->acc, *acc)) - *passwd = l->passwd; /* usernames match; password OK */ - else - *passwd = NULL; /* usernames don't match */ - } - else /* NOT *acc */ - { - /* If password was given, use it. The account is l->acc. */ - *acc = l->acc; - if (l->passwd) - *passwd = l->passwd; - } + { + /* Looking for password in .netrc. */ + if (!strcmp (l->acc, *acc)) + *passwd = l->passwd; /* usernames match; password OK */ + else + *passwd = NULL; /* usernames don't match */ + } + else /* NOT *acc */ + { + /* If password was given, use it. The account is l->acc. */ + *acc = l->acc; + if (l->passwd) + *passwd = l->passwd; + } return; } else { if (!slack_default) - return; + return; if (*acc) - return; + return; /* Try looking for the default account. */ for (l = netrc_list; l; l = l->next) - if (!l->host) - break; + if (!l->host) + break; if (!l) - return; + return; *acc = l->acc; if (!*passwd) - *passwd = l->passwd; + *passwd = l->passwd; return; } } #ifdef STANDALONE + +#include + /* Normally, these functions would be defined by your package. */ # define xmalloc malloc # define xfree free # define xstrdup strdup -/* The function reads a whole line. It reads the line realloc-ing the - storage exponentially, doubling the storage after each overflow to - minimize the number of calls to realloc(). - - It is not an exemplary of correctness, since it kills off the - newline (and no, there is no way to know if there was a newline at - EOF). */ # define xrealloc realloc -# define DYNAMIC_LINE_BUFFER 40 - -char * -read_whole_line (FILE *fp) -{ - char *line; - int i, bufsize, c; - - i = 0; - bufsize = DYNAMIC_LINE_BUFFER; - line = xmalloc(bufsize); - /* Construct the line. */ - while ((c = getc(fp)) != EOF && c != '\n') - { - if (i > bufsize - 1) - line = (char *)xrealloc(line, (bufsize <<= 1)); - line[i++] = c; - } - if (c == EOF && !i) - { - xfree(line); - return NULL; - } - - /* Check for overflow at zero-termination (no need to double the - buffer in this case. */ - if (i == bufsize) - line = (char *)xrealloc(line, i + 1); - line[i] = '\0'; - return line; -} #endif /* STANDALONE */ @@ -200,21 +185,21 @@ maybe_add_to_list (acc_t **newentry, acc_t **list) if (a && ! a->acc) { /* Free any allocated space. */ - xfree (a->host); - xfree (a->acc); - xfree (a->passwd); + xfree_null (a->host); + xfree_null (a->acc); + xfree_null (a->passwd); } else { 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 acc_t structure. */ - a = (acc_t *)xmalloc (sizeof (acc_t)); + a = xmalloc (sizeof (acc_t)); } /* Zero the structure, so that it is ready to use. */ @@ -230,9 +215,10 @@ maybe_add_to_list (acc_t **newentry, acc_t **list) null-terminated string once character to the left. Used in processing \ and " constructs in the netrc file */ static void -shift_left(char *string){ +shift_left(char *string) +{ char *p; - + for (p=string; *p; ++p) *p = *(p+1); } @@ -242,9 +228,11 @@ static acc_t * parse_netrc (const char *path) { FILE *fp; - char *line, *p, *tok, *premature_token; + char *line = NULL, *p, *tok; + const char *premature_token; acc_t *current, *retval; - int ln, quote; + int ln, qmark; + size_t bufsize = 0; /* The latest token we've seen in the file. */ enum @@ -258,7 +246,7 @@ parse_netrc (const char *path) if (!fp) { fprintf (stderr, _("%s: Cannot read %s (%s).\n"), exec_name, - path, strerror (errno)); + path, strerror (errno)); return retval; } @@ -267,135 +255,142 @@ parse_netrc (const char *path) premature_token = NULL; /* While there are lines in the file... */ - while ((line = read_whole_line (fp))) + while (getline (&line, &bufsize, fp) > 0) { ln ++; /* Parse the line. */ p = line; - quote = 0; + qmark = 0; + + /* Skip leading whitespace. */ + while (*p && c_isspace (*p)) + p ++; /* 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; + /* End of macro if the line is empty. */ + last_token = tok_nothing; /* If we are defining macros, then skip parsing the line. */ while (*p && last_token != tok_macdef) - { - /* Skip any whitespace. */ - while (*p && ISSPACE (*p)) - p ++; - - /* Discard end-of-line comments; also, stop processing if - the above `while' merely skipped trailing whitespace. */ - if (*p == '#' || !*p) - break; - - /* If the token starts with quotation mark, note this fact, - and squash the quotation character */ - if (*p == '"'){ - quote = 1; - shift_left (p); - } - - tok = p; - - /* Find the end of the token, handling quotes and escapes. */ - while (*p && (quote ? *p != '"' : !ISSPACE (*p))){ - if (*p == '\\') - shift_left (p); - p ++; - } - - /* if field was quoted, squash the trailing quotation mark */ - if (quote) - shift_left(p); - - /* Null-terminate the token, if it isn't already. */ - if (*p) - *p ++ = '\0'; - - switch (last_token) - { - case tok_login: - if (current) - current->acc = xstrdup (tok); - else - premature_token = "login"; - break; - - case tok_machine: - /* Start a new machine entry. */ - maybe_add_to_list (¤t, &retval); - current->host = xstrdup (tok); - break; - - case tok_password: - if (current) - current->passwd = xstrdup (tok); - else - premature_token = "password"; - break; - - /* We handle most of tok_macdef above. */ - case tok_macdef: - if (!current) - premature_token = "macdef"; - break; - - /* We don't handle the account keyword at all. */ - case tok_account: - if (!current) - premature_token = "account"; - break; - - /* We handle tok_nothing below this switch. */ - case tok_nothing: - break; - } - - if (premature_token) - { - fprintf (stderr, _("\ -%s: %s:%d: warning: \"%s\" token appears before any machine name\n"), - exec_name, path, 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 - { - /* Fetch the next token. */ - if (!strcmp (tok, "account")) - last_token = tok_account; - else if (!strcmp (tok, "default")) - { - maybe_add_to_list (¤t, &retval); - } - else if (!strcmp (tok, "login")) - 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, "password")) - last_token = tok_password; - - else - fprintf (stderr, _("%s: %s:%d: unknown token \"%s\"\n"), - exec_name, path, ln, tok); - } - } - - xfree (line); + { + /* Skip any whitespace. */ + while (*p && c_isspace (*p)) + p ++; + + /* Discard end-of-line comments; also, stop processing if + the above `while' merely skipped trailing whitespace. */ + if (*p == '#' || !*p) + break; + + /* If the token starts with quotation mark, note this fact, + and squash the quotation character */ + if (*p == '"'){ + qmark = 1; + shift_left (p); + } + + tok = p; + + /* Find the end of the token, handling quotes and escapes. */ + while (*p && (qmark ? *p != '"' : !c_isspace (*p))){ + if (*p == '\\') + shift_left (p); + p ++; + } + + /* If field was quoted, squash the trailing quotation mark + and reset qmark flag. */ + if (qmark) + { + shift_left (p); + qmark = 0; + } + + /* Null-terminate the token, if it isn't already. */ + if (*p) + *p ++ = '\0'; + + switch (last_token) + { + case tok_login: + if (current) + current->acc = xstrdup (tok); + else + premature_token = "login"; + break; + + case tok_machine: + /* Start a new machine entry. */ + maybe_add_to_list (¤t, &retval); + current->host = xstrdup (tok); + break; + + case tok_password: + if (current) + current->passwd = xstrdup (tok); + else + premature_token = "password"; + break; + + /* We handle most of tok_macdef above. */ + case tok_macdef: + if (!current) + premature_token = "macdef"; + break; + + /* We don't handle the account keyword at all. */ + case tok_account: + if (!current) + premature_token = "account"; + break; + + /* We handle tok_nothing below this switch. */ + case tok_nothing: + break; + } + + if (premature_token) + { + fprintf (stderr, _("\ +%s: %s:%d: warning: %s token appears before any machine name\n"), + exec_name, path, ln, quote (premature_token)); + premature_token = NULL; + } + + 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; + else if (!strcmp (tok, "default")) + { + maybe_add_to_list (¤t, &retval); + } + else if (!strcmp (tok, "login")) + 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, "password")) + last_token = tok_password; + + else + fprintf (stderr, _("%s: %s:%d: unknown token \"%s\"\n"), + exec_name, path, ln, tok); + } + } } + xfree (line); fclose (fp); /* Finalize the last machine entry we found. */ @@ -431,9 +426,9 @@ free_netrc(acc_t *l) while (l) { t = l->next; - FREE_MAYBE (l->acc); - FREE_MAYBE (l->passwd); - FREE_MAYBE (l->host); + xfree_null (l->acc); + xfree_null (l->passwd); + xfree_null (l->host); xfree (l); l = t; } @@ -446,7 +441,7 @@ free_netrc(acc_t *l) int main (int argc, char **argv) { - struct stat sb; + struct_stat sb; char *program_name, *file, *target; acc_t *head, *a; @@ -463,7 +458,7 @@ main (int argc, char **argv) if (stat (file, &sb)) { fprintf (stderr, _("%s: cannot stat %s: %s\n"), argv[0], file, - strerror (errno)); + strerror (errno)); exit (1); } @@ -473,37 +468,37 @@ main (int argc, char **argv) { /* Skip if we have a target and this isn't it. */ if (target && a->host && strcmp (target, a->host)) - { - a = a->next; - continue; - } + { + a = a->next; + continue; + } if (!target) - { - /* Print the host name if we have no target. */ - if (a->host) - fputs (a->host, stdout); - else - fputs ("DEFAULT", stdout); + { + /* Print the host name if we have no target. */ + if (a->host) + fputs (a->host, stdout); + else + fputs ("DEFAULT", stdout); - fputc (' ', stdout); - } + fputc (' ', stdout); + } /* Print the account name. */ fputs (a->acc, stdout); if (a->passwd) - { - /* Print the password, if there is any. */ - fputc (' ', stdout); - fputs (a->passwd, stdout); - } + { + /* Print the password, if there is any. */ + fputc (' ', stdout); + fputs (a->passwd, stdout); + } fputc ('\n', stdout); /* Exit if we found the target. */ if (target) - exit (0); + exit (0); a = a->next; }