1 /* netrc.c -- parse the .netrc file to get hosts, accounts, and passwords
3 Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
5 For license terms, see the file COPYING in this directory.
7 Compile with -DSTANDALONE to test this module. */
15 #include "fetchmail.h"
20 /* Normally defined in xstrdup.c. */
21 # define xstrdup strdup
23 /* Normally defined in xmalloc.c */
24 # define xmalloc malloc
25 # define xrealloc realloc
28 /* Maybe add NEWENTRY to the account information list, LIST. NEWENTRY is
29 set to a ready-to-use netrc_entry, in any event. */
31 maybe_add_to_list (netrc_entry **newentry, netrc_entry **list)
37 /* We need an account name in order to add the entry to the list. */
38 if (a && ! a->account)
40 /* Free any allocated space. */
50 /* Add the current machine into our list. */
55 /* Allocate a new netrc_entry structure. */
56 a = (netrc_entry *) xmalloc (sizeof (netrc_entry));
59 /* Zero the structure, so that it is ready to use. */
60 memset (a, 0, sizeof(*a));
62 /* Return the new pointers. */
69 /* Parse FILE as a .netrc file (as described in ftp(1)), and return a
70 list of entries. NULL is returned if the file could not be
77 char buf[POPBUFSIZE+1], *p, *tok;
78 const char *premature_token;
79 netrc_entry *current, *retval;
82 /* The latest token we've seen in the file. */
85 tok_nothing, tok_account, tok_login, tok_macdef, tok_machine, tok_password
86 } last_token = tok_nothing;
88 current = retval = NULL;
90 fp = fopen (file, "r");
93 /* Just return NULL if we can't open the file. */
97 /* Initialize the file data. */
99 premature_token = NULL;
101 /* While there are lines in the file... */
102 while (fgets(buf, POPBUFSIZE, fp))
106 /* Strip trailing CRLF */
107 for (p = buf + strlen(buf) - 1; (p >= buf) && isspace(*p); p--)
110 /* Parse the line. */
113 /* If the line is empty... */
115 if (last_token == tok_macdef) /* end of macro */
116 last_token = tok_nothing;
118 continue; /* otherwise ignore it */
120 /* If we are defining macros, then skip parsing the line. */
121 while (*p && last_token != tok_macdef)
126 /* Skip any whitespace. */
127 while (*p && isspace (*p))
130 /* Discard end-of-line comments. */
136 /* Find the end of the token. */
137 while (*p && (quote_char || !isspace (*p)))
141 if (quote_char == *p)
155 if (*p == '"' || *p == '\'')
165 /* Null-terminate the token, if it isn't already. */
174 current->account = (char *) xstrdup (tok);
176 premature_token = "login";
180 /* Start a new machine entry. */
181 maybe_add_to_list (¤t, &retval);
182 current->host = (char *) xstrdup (tok);
187 current->password = (char *) xstrdup (tok);
189 premature_token = "password";
192 /* We handle most of tok_macdef above. */
195 premature_token = "macdef";
198 /* We don't handle the account keyword at all. */
201 premature_token = "account";
204 /* We handle tok_nothing below this switch. */
212 error_at_line (0, file, ln,
213 _("warning: found \"%s\" before any host names"),
217 _("%s:%d: warning: found \"%s\" before any host names\n"),
218 file, ln, premature_token);
220 premature_token = NULL;
223 if (last_token != tok_nothing)
224 /* We got a value, so reset the token state. */
225 last_token = tok_nothing;
228 /* Fetch the next token. */
229 if (!strcmp (tok, "default"))
231 maybe_add_to_list (¤t, &retval);
233 else if (!strcmp (tok, "login"))
234 last_token = tok_login;
236 else if (!strcmp (tok, "user"))
237 last_token = tok_login;
239 else if (!strcmp (tok, "macdef"))
240 last_token = tok_macdef;
242 else if (!strcmp (tok, "machine"))
243 last_token = tok_machine;
245 else if (!strcmp (tok, "password"))
246 last_token = tok_password;
248 else if (!strcmp (tok, "passwd"))
249 last_token = tok_password;
251 else if (!strcmp (tok, "account"))
252 last_token = tok_account;
256 fprintf (stderr, _("%s:%d: warning: unknown token \"%s\"\n"),
265 /* Finalize the last machine entry we found. */
266 maybe_add_to_list (¤t, &retval);
269 /* Reverse the order of the list so that it appears in file order. */
274 netrc_entry *saved_reference;
276 /* Change the direction of the pointers. */
277 saved_reference = current->next;
278 current->next = retval;
280 /* Advance to the next node. */
282 current = saved_reference;
289 /* Return the netrc entry from LIST corresponding to HOST. NULL is
290 returned if no such entry exists. */
292 search_netrc (list, host)
296 /* Look for the HOST in LIST. */
300 /* We hit the default entry. */
303 else if (!strcmp (list->host, host))
304 /* We found a matching entry. */
310 /* Return the matching entry, or NULL. */
316 #include <sys/types.h>
317 #include <sys/stat.h>
327 char *program_name, *file, *target;
328 netrc_entry *head, *a;
332 fprintf (stderr, "Usage: %s NETRC [HOSTNAME]...\n", argv[0]);
336 program_name = argv[0];
340 if (stat (file, &sb))
342 fprintf (stderr, "%s: cannot stat %s: %s\n", argv[0], file,
347 head = parse_netrc (file);
350 fprintf (stderr, "%s: no entries found in %s\n", argv[0], file);
358 for (i = 2; i < argc; i++)
360 /* Print out the host that we are checking for. */
361 fputs (argv[i], stdout);
363 a = search_netrc (head, argv[i]);
366 /* Print out the account and password (if any). */
368 fputs (a->account, stdout);
372 fputs (a->password, stdout);
378 fputc ('\n', stdout);
383 /* Print out the entire contents of the netrc. */
387 /* Print the host name. */
389 fputs (a->host, stdout);
391 fputs ("DEFAULT", stdout);
395 /* Print the account name. */
396 fputs (a->account, stdout);
400 /* Print the password, if there is any. */
402 fputs (a->password, stdout);
405 fputc ('\n', stdout);
411 #endif /* STANDALONE */