1 /* netrc.c -- parse the .netrc file to get hosts, accounts, and passwords
3 Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
4 Copyright assigned to Eric S. Raymond, October 2001.
6 For license terms, see the file COPYING in this directory.
8 Compile with -DSTANDALONE to test this module. */
16 #include "fetchmail.h"
21 /* Normally defined in xstrdup.c. */
22 # define xstrdup strdup
24 /* Normally defined in xmalloc.c */
25 # define xmalloc malloc
26 # define xrealloc realloc
28 char *program_name = "netrc";
31 /* Maybe add NEWENTRY to the account information list, LIST. NEWENTRY is
32 set to a ready-to-use netrc_entry, in any event. */
34 maybe_add_to_list (netrc_entry **newentry, netrc_entry **list)
40 /* We need an account name in order to add the entry to the list. */
41 if (a && ! a->account)
43 /* Free any allocated space. */
53 /* Add the current machine into our list. */
58 /* Allocate a new netrc_entry structure. */
59 a = (netrc_entry *) xmalloc (sizeof (netrc_entry));
62 /* Zero the structure, so that it is ready to use. */
63 memset (a, 0, sizeof(*a));
65 /* Return the new pointers. */
72 /* Parse FILE as a .netrc file (as described in ftp(1)), and return a
73 list of entries. NULL is returned if the file could not be
80 char buf[POPBUFSIZE+1], *p, *tok;
81 const char *premature_token;
82 netrc_entry *current, *retval;
85 /* The latest token we've seen in the file. */
88 tok_nothing, tok_account, tok_login, tok_macdef, tok_machine, tok_password
89 } last_token = tok_nothing;
91 current = retval = NULL;
93 fp = fopen (file, "r");
96 /* Just return NULL if we can't open the file. */
100 /* Initialize the file data. */
102 premature_token = NULL;
104 /* While there are lines in the file... */
105 while (fgets(buf, POPBUFSIZE, fp))
109 /* Strip trailing CRLF */
110 for (p = buf + strlen(buf) - 1; (p >= buf) && isspace(*p); p--)
113 /* Parse the line. */
116 /* If the line is empty... */
119 if (last_token == tok_macdef) /* end of macro */
120 last_token = tok_nothing;
122 continue; /* otherwise ignore it */
125 /* If we are defining macros, then skip parsing the line. */
126 while (*p && last_token != tok_macdef)
131 /* Skip any whitespace. */
132 while (*p && isspace (*p))
135 /* Discard end-of-line comments. */
141 /* Find the end of the token. */
142 while (*p && (quote_char || !isspace (*p)))
146 if (quote_char == *p)
160 if (*p == '"' || *p == '\'')
170 /* Null-terminate the token, if it isn't already. */
179 current->account = (char *) xstrdup (tok);
181 premature_token = "login";
185 /* Start a new machine entry. */
186 maybe_add_to_list (¤t, &retval);
187 current->host = (char *) xstrdup (tok);
192 current->password = (char *) xstrdup (tok);
194 premature_token = "password";
197 /* We handle most of tok_macdef above. */
200 premature_token = "macdef";
203 /* We don't handle the account keyword at all. */
206 premature_token = "account";
209 /* We handle tok_nothing below this switch. */
217 error_at_line (0, file, ln,
218 GT_("warning: found \"%s\" before any host names"),
222 GT_("%s:%d: warning: found \"%s\" before any host names\n"),
223 file, ln, premature_token);
225 premature_token = NULL;
228 if (last_token != tok_nothing)
229 /* We got a value, so reset the token state. */
230 last_token = tok_nothing;
233 /* Fetch the next token. */
234 if (!strcmp (tok, "default"))
236 maybe_add_to_list (¤t, &retval);
238 else if (!strcmp (tok, "login"))
239 last_token = tok_login;
241 else if (!strcmp (tok, "user"))
242 last_token = tok_login;
244 else if (!strcmp (tok, "macdef"))
245 last_token = tok_macdef;
247 else if (!strcmp (tok, "machine"))
248 last_token = tok_machine;
250 else if (!strcmp (tok, "password"))
251 last_token = tok_password;
253 else if (!strcmp (tok, "passwd"))
254 last_token = tok_password;
256 else if (!strcmp (tok, "account"))
257 last_token = tok_account;
261 fprintf (stderr, GT_("%s:%d: warning: unknown token \"%s\"\n"),
270 /* Finalize the last machine entry we found. */
271 maybe_add_to_list (¤t, &retval);
274 /* Reverse the order of the list so that it appears in file order. */
279 netrc_entry *saved_reference;
281 /* Change the direction of the pointers. */
282 saved_reference = current->next;
283 current->next = retval;
285 /* Advance to the next node. */
287 current = saved_reference;
294 /* Return the netrc entry from LIST corresponding to HOST. NULL is
295 returned if no such entry exists. */
297 search_netrc (list, host, account)
299 char *host, *account;
301 /* Look for the HOST in LIST. */
304 if (list->host && !strcmp(list->host, host))
305 if (!list->account || !strcmp(list->account, account))
306 /* We found a matching entry. */
312 /* Return the matching entry, or NULL. */
318 #include <sys/types.h>
319 #include <sys/stat.h>
329 char *program_name, *file, *host, *account;
330 netrc_entry *head, *a;
332 program_name = argv[0];
337 if (stat (file, &sb))
339 fprintf (stderr, "%s: cannot stat %s: %s\n", argv[0], file,
344 head = parse_netrc (file);
347 fprintf (stderr, "%s: no entries found in %s\n", argv[0], file);
356 printf("Host: %s, Account: %s\n", host, account);
358 a = search_netrc (head, host, account);
361 /* Print out the password (if any). */
365 fputs (a->password, stdout);
368 fputc ('\n', stdout);
373 /* Print out the entire contents of the netrc. */
377 /* Print the host name. */
379 fputs (a->host, stdout);
381 fputs ("DEFAULT", stdout);
385 /* Print the account name. */
386 fputs (a->account, stdout);
390 /* Print the password, if there is any. */
392 fputs (a->password, stdout);
395 fputc ('\n', stdout);
401 #endif /* STANDALONE */