#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#ifdef HAVE_STRING_H
# include <string.h>
#else
# include <strings.h>
#endif
#include <sys/types.h>
#include <errno.h>
#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 *parse_netrc PARAMS ((const char *));
void
search_netrc (const char *host, const char **acc, const char **passwd,
int slack_default)
{
acc_t *l;
static int processed_netrc;
if (!opt.netrc)
return;
if (!processed_netrc)
{
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);
free (home);
err = stat (path, &buf);
if (err == 0)
netrc_list = parse_netrc (path);
}
}
if (!netrc_list)
return;
if (*acc && *passwd)
return;
if (!*acc && !slack_default)
return;
for (l = netrc_list; l; l = l->next)
{
if (!l->host)
continue;
else if (!strcasecmp (l->host, host))
break;
}
if (l)
{
if (*acc)
{
if (!strcmp (l->acc, *acc))
*passwd = l->passwd;
else
*passwd = NULL;
}
else
{
*acc = l->acc;
if (l->passwd)
*passwd = l->passwd;
}
return;
}
else
{
if (!slack_default)
return;
if (*acc)
return;
for (l = netrc_list; l; l = l->next)
if (!l->host)
break;
if (!l)
return;
*acc = l->acc;
if (!*passwd)
*passwd = l->passwd;
return;
}
}
#ifdef STANDALONE
# define xmalloc malloc
# define xstrdup strdup
# 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);
while ((c = getc(fp)) != EOF && c != '\n')
{
if (i > bufsize - 1)
line = (char *)xrealloc(line, (bufsize <<= 1));
line[i++] = c;
}
if (c == EOF && !i)
{
free(line);
return NULL;
}
if (i == bufsize)
line = (char *)xrealloc(line, i + 1);
line[i] = '\0';
return line;
}
#endif
static void
maybe_add_to_list (acc_t **newentry, acc_t **list)
{
acc_t *a, *l;
a = *newentry;
l = *list;
if (a && ! a->acc)
{
free (a->host);
free (a->acc);
free (a->passwd);
}
else
{
if (a)
{
a->next = l;
l = a;
}
a = (acc_t *)xmalloc (sizeof (acc_t));
}
memset (a, 0, sizeof(*a));
*newentry = a;
*list = l;
return;
}
static acc_t *
parse_netrc (const char *path)
{
FILE *fp;
char *line, *p, *tok, *premature_token;
acc_t *current, *retval;
int ln;
enum
{
tok_nothing, tok_account, tok_login, tok_macdef, tok_machine, tok_password
} last_token = tok_nothing;
current = retval = NULL;
fp = fopen (path, "r");
if (!fp)
{
fprintf (stderr, _("%s: Cannot read %s (%s).\n"), exec_name,
path, strerror (errno));
return retval;
}
ln = 0;
premature_token = NULL;
while ((line = read_whole_line (fp)))
{
ln ++;
p = line;
if (last_token == tok_macdef && !*p)
last_token = tok_nothing;
while (*p && last_token != tok_macdef)
{
while (*p && ISSPACE (*p))
p ++;
if (*p == '#')
break;
tok = p;
while (*p && !ISSPACE (*p))
p ++;
if (*p)
*p ++ = '\0';
switch (last_token)
{
case tok_login:
if (current)
current->acc = xstrdup (tok);
else
premature_token = "login";
break;
case tok_machine:
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;
case tok_macdef:
if (!current)
premature_token = "macdef";
break;
case tok_account:
if (!current)
premature_token = "account";
break;
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)
last_token = tok_nothing;
else
{
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);
}
}
free (line);
}
fclose (fp);
maybe_add_to_list (¤t, &retval);
free (current);
current = retval;
retval = NULL;
while (current)
{
acc_t *saved_reference;
saved_reference = current->next;
current->next = retval;
retval = current;
current = saved_reference;
}
return retval;
}
void
free_netrc(acc_t *l)
{
acc_t *t;
while (l)
{
t = l->next;
FREE_MAYBE (l->acc);
FREE_MAYBE (l->passwd);
FREE_MAYBE (l->host);
free(l);
l = t;
}
}
#ifdef STANDALONE
#include <sys/types.h>
#include <sys/stat.h>
int
main (int argc, char **argv)
{
struct stat sb;
char *program_name, *file, *target;
acc_t *head, *a;
if (argc < 2 || argc > 3)
{
fprintf (stderr, _("Usage: %s NETRC [HOSTNAME]\n"), argv[0]);
exit (1);
}
program_name = argv[0];
file = argv[1];
target = argv[2];
if (stat (file, &sb))
{
fprintf (stderr, _("%s: cannot stat %s: %s\n"), argv[0], file,
strerror (errno));
exit (1);
}
head = parse_netrc (file);
a = head;
while (a)
{
if (target && a->host && strcmp (target, a->host))
{
a = a->next;
continue;
}
if (!target)
{
if (a->host)
fputs (a->host, stdout);
else
fputs ("DEFAULT", stdout);
fputc (' ', stdout);
}
fputs (a->acc, stdout);
if (a->passwd)
{
fputc (' ', stdout);
fputs (a->passwd, stdout);
}
fputc ('\n', stdout);
if (target)
exit (0);
a = a->next;
}
if (target)
exit (1);
exit (0);
}
#endif