netrc.c
上传用户:xxcykj
上传日期:2007-01-04
资源大小:727k
文件大小:8k
源码类别:

Email客户端

开发平台:

Unix_Linux

  1. /* netrc.c -- parse the .netrc file to get hosts, accounts, and passwords
  2.    Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
  3.    For license terms, see the file COPYING in this directory.
  4.    Compile with -DSTANDALONE to test this module. */
  5. #include <stdio.h>
  6. #include <ctype.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include "config.h"
  10. #include "fetchmail.h"
  11. #include "netrc.h"
  12. #include "i18n.h"
  13. #ifdef STANDALONE
  14. /* Normally defined in xstrdup.c. */
  15. # define xstrdup strdup
  16. /* Normally defined in xmalloc.c */
  17. # define xmalloc malloc
  18. # define xrealloc realloc
  19. char *program_name = "netrc";
  20. #endif
  21. /* Maybe add NEWENTRY to the account information list, LIST.  NEWENTRY is
  22.    set to a ready-to-use netrc_entry, in any event. */
  23. static void
  24. maybe_add_to_list (netrc_entry **newentry, netrc_entry **list)
  25. {
  26.     netrc_entry *a, *l;
  27.     a = *newentry;
  28.     l = *list;
  29.     /* We need an account name in order to add the entry to the list. */
  30.     if (a && ! a->account)
  31.     {
  32. /* Free any allocated space. */
  33. if (a->host)
  34.     free (a->host);
  35. if (a->password)
  36.     free (a->password);
  37.     }
  38.     else
  39.     {
  40. if (a)
  41. {
  42.     /* Add the current machine into our list. */
  43.     a->next = l;
  44.     l = a;
  45. }
  46. /* Allocate a new netrc_entry structure. */
  47. a = (netrc_entry *) xmalloc (sizeof (netrc_entry));
  48.     }
  49.     /* Zero the structure, so that it is ready to use. */
  50.     memset (a, 0, sizeof(*a));
  51.     /* Return the new pointers. */
  52.     *newentry = a;
  53.     *list = l;
  54.     return;
  55. }
  56. /* Parse FILE as a .netrc file (as described in ftp(1)), and return a
  57.    list of entries.  NULL is returned if the file could not be
  58.    parsed. */
  59. netrc_entry *
  60. parse_netrc (file)
  61.      char *file;
  62. {
  63.     FILE *fp;
  64.     char buf[POPBUFSIZE+1], *p, *tok;
  65.     const char *premature_token;
  66.     netrc_entry *current, *retval;
  67.     int ln;
  68.     /* The latest token we've seen in the file. */
  69.     enum
  70.     {
  71. tok_nothing, tok_account, tok_login, tok_macdef, tok_machine, tok_password
  72.     } last_token = tok_nothing;
  73.     current = retval = NULL;
  74.     fp = fopen (file, "r");
  75.     if (!fp)
  76.     {
  77. /* Just return NULL if we can't open the file. */
  78. return NULL;
  79.     }
  80.     /* Initialize the file data. */
  81.     ln = 0;
  82.     premature_token = NULL;
  83.     /* While there are lines in the file... */
  84.     while (fgets(buf, POPBUFSIZE, fp))
  85.     {
  86. ln++;
  87. /* Strip trailing CRLF */
  88. for (p = buf + strlen(buf) - 1; (p >= buf) && isspace(*p); p--)
  89.     *p = '';
  90. /* Parse the line. */
  91. p = buf;
  92. /* If the line is empty... */
  93. if (!*p)
  94. {
  95.     if (last_token == tok_macdef) /* end of macro */
  96. last_token = tok_nothing;
  97.     else
  98. continue; /* otherwise ignore it */
  99. }
  100. /* If we are defining macros, then skip parsing the line. */
  101. while (*p && last_token != tok_macdef)
  102. {
  103.     char quote_char = 0;
  104.     char *pp;
  105.     /* Skip any whitespace. */
  106.     while (*p && isspace (*p))
  107. p++;
  108.     /* Discard end-of-line comments. */
  109.     if (*p == '#')
  110. break;
  111.     tok = pp = p;
  112.     /* Find the end of the token. */
  113.     while (*p && (quote_char || !isspace (*p)))
  114.     {
  115. if (quote_char)
  116. {
  117.     if (quote_char == *p)
  118.     {
  119. quote_char = 0;
  120. p ++;
  121.     }
  122.     else
  123.     {
  124. *pp = *p;
  125. p ++;
  126. pp ++;
  127.     }
  128. }
  129. else
  130. {
  131.     if (*p == '"' || *p == ''')
  132. quote_char = *p;
  133.     else
  134.     {
  135. *pp = *p;
  136. pp ++;
  137.     }
  138.     p ++;
  139. }
  140.     }
  141.     /* Null-terminate the token, if it isn't already. */
  142.     if (*p)
  143. *p ++ = '';
  144.     *pp = 0;
  145.     switch (last_token)
  146.     {
  147.     case tok_login:
  148. if (current)
  149.     current->account = (char *) xstrdup (tok);
  150. else
  151.     premature_token = "login";
  152. break;
  153.     case tok_machine:
  154. /* Start a new machine entry. */
  155. maybe_add_to_list (&current, &retval);
  156. current->host = (char *) xstrdup (tok);
  157. break;
  158.     case tok_password:
  159. if (current)
  160.     current->password = (char *) xstrdup (tok);
  161. else
  162.     premature_token = "password";
  163. break;
  164. /* We handle most of tok_macdef above. */
  165.     case tok_macdef:
  166. if (!current)
  167.     premature_token = "macdef";
  168. break;
  169. /* We don't handle the account keyword at all. */
  170.     case tok_account:
  171. if (!current)
  172.     premature_token = "account";
  173. break;
  174. /* We handle tok_nothing below this switch. */
  175.     case tok_nothing:
  176. break;
  177.     }
  178.     if (premature_token)
  179.     {
  180. #ifdef HAVE_ERROR
  181. error_at_line (0, file, ln,
  182.        _("warning: found "%s" before any host names"),
  183.        premature_token);
  184. #else
  185. fprintf (stderr,
  186.  _("%s:%d: warning: found "%s" before any host namesn"),
  187.  file, ln, premature_token);
  188. #endif
  189. premature_token = NULL;
  190.     }
  191.     if (last_token != tok_nothing)
  192. /* We got a value, so reset the token state. */
  193. last_token = tok_nothing;
  194.     else
  195.     {
  196. /* Fetch the next token. */
  197. if (!strcmp (tok, "default"))
  198. {
  199.     maybe_add_to_list (&current, &retval);
  200. }
  201. else if (!strcmp (tok, "login"))
  202.     last_token = tok_login;
  203. else if (!strcmp (tok, "user"))
  204.     last_token = tok_login;
  205. else if (!strcmp (tok, "macdef"))
  206.     last_token = tok_macdef;
  207. else if (!strcmp (tok, "machine"))
  208.     last_token = tok_machine;
  209. else if (!strcmp (tok, "password"))
  210.     last_token = tok_password;
  211. else if (!strcmp (tok, "passwd"))
  212.     last_token = tok_password;
  213. else if (!strcmp (tok, "account"))
  214.     last_token = tok_account;
  215. else
  216. {
  217.     fprintf (stderr, _("%s:%d: warning: unknown token "%s"n"),
  218.      file, ln, tok);
  219. }
  220.     }
  221. }
  222.     }
  223.     fclose (fp);
  224.     /* Finalize the last machine entry we found. */
  225.     maybe_add_to_list (&current, &retval);
  226.     free (current);
  227.     /* Reverse the order of the list so that it appears in file order. */
  228.     current = retval;
  229.     retval = NULL;
  230.     while (current)
  231.     {
  232. netrc_entry *saved_reference;
  233. /* Change the direction of the pointers. */
  234. saved_reference = current->next;
  235. current->next = retval;
  236. /* Advance to the next node. */
  237. retval = current;
  238. current = saved_reference;
  239.     }
  240.     return retval;
  241. }
  242. /* Return the netrc entry from LIST corresponding to HOST.  NULL is
  243.    returned if no such entry exists. */
  244. netrc_entry *
  245. search_netrc (list, host, account)
  246.      netrc_entry *list;
  247.      char *host, *account;
  248. {
  249.     /* Look for the HOST in LIST. */
  250.     while (list)
  251.     {
  252. if (list->host && !strcmp(list->host, host))
  253.     if (!list->account || !strcmp(list->account, account))
  254. /* We found a matching entry. */
  255. break;
  256. list = list->next;
  257.     }
  258.     /* Return the matching entry, or NULL. */
  259.     return list;
  260. }
  261. #ifdef STANDALONE
  262. #include <sys/types.h>
  263. #include <sys/stat.h>
  264. extern int errno;
  265. int
  266. main (argc, argv)
  267.      int argc;
  268.      char **argv;
  269. {
  270.     struct stat sb;
  271.     char *program_name, *file, *host, *account;
  272.     netrc_entry *head, *a;
  273.     program_name = argv[0];
  274.     file = argv[1];
  275.     host = argv[2];
  276.     account = argv[3];
  277.     if (stat (file, &sb))
  278.     {
  279. fprintf (stderr, "%s: cannot stat %s: %sn", argv[0], file,
  280.  strerror (errno));
  281. exit (1);
  282.     }
  283.     head = parse_netrc (file);
  284.     if (!head)
  285.     {
  286. fprintf (stderr, "%s: no entries found in %sn", argv[0], file);
  287. exit (1);
  288.     }
  289.     if (host && account)
  290.     {
  291. int i, status;
  292. status = 0;
  293. printf("Host: %s, Account: %sn", host, account);
  294.     
  295. a = search_netrc (head, host, account);
  296. if (a)
  297. {
  298.     /* Print out the password (if any). */
  299.     if (a->password)
  300.     {
  301. fputc (' ', stdout);
  302. fputs (a->password, stdout);
  303.     }
  304. }
  305. fputc ('n', stdout);
  306. exit (status);
  307.     }
  308.     /* Print out the entire contents of the netrc. */
  309.     a = head;
  310.     while (a)
  311.     {
  312. /* Print the host name. */
  313. if (a->host)
  314.     fputs (a->host, stdout);
  315. else
  316.     fputs ("DEFAULT", stdout);
  317. fputc (' ', stdout);
  318. /* Print the account name. */
  319. fputs (a->account, stdout);
  320. if (a->password)
  321. {
  322.     /* Print the password, if there is any. */
  323.     fputc (' ', stdout);
  324.     fputs (a->password, stdout);
  325. }
  326. fputc ('n', stdout);
  327. a = a->next;
  328.     }
  329.     exit (0);
  330. }
  331. #endif /* STANDALONE */