1 /* netrc.c -- parse the .netrc file to get hosts, accounts, and passwords
2 Copyright (C) 1996, Free Software Foundation, Inc.
3 Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
5 i18n by Arnaldo Carvalho de Melo <acme@conectiva.com.br> 7-Nov-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
21 /* Compile with -DSTANDALONE to test this module. */
29 #include "fetchmail.h"
34 /* Normally defined in xstrdup.c. */
35 # define xstrdup strdup
37 /* Normally defined in xmalloc.c */
38 # define xmalloc malloc
39 # define xrealloc realloc
42 /* Maybe add NEWENTRY to the account information list, LIST. NEWENTRY is
43 set to a ready-to-use netrc_entry, in any event. */
45 maybe_add_to_list (netrc_entry **newentry, netrc_entry **list)
51 /* We need an account name in order to add the entry to the list. */
52 if (a && ! a->account)
54 /* Free any allocated space. */
64 /* Add the current machine into our list. */
69 /* Allocate a new netrc_entry structure. */
70 a = (netrc_entry *) xmalloc (sizeof (netrc_entry));
73 /* Zero the structure, so that it is ready to use. */
74 memset (a, 0, sizeof(*a));
76 /* Return the new pointers. */
83 /* Parse FILE as a .netrc file (as described in ftp(1)), and return a
84 list of entries. NULL is returned if the file could not be
91 char buf[POPBUFSIZE+1], *p, *tok;
92 const char *premature_token;
93 netrc_entry *current, *retval;
96 /* The latest token we've seen in the file. */
99 tok_nothing, tok_account, tok_login, tok_macdef, tok_machine, tok_password
100 } last_token = tok_nothing;
102 current = retval = NULL;
104 fp = fopen (file, "r");
107 /* Just return NULL if we can't open the file. */
111 /* Initialize the file data. */
113 premature_token = NULL;
115 /* While there are lines in the file... */
116 while (fgets(buf, POPBUFSIZE, fp))
120 /* Strip trailing CRLF */
121 p = buf + strlen(buf) - 1;
122 while (*p && isspace(*p))
125 /* Parse the line. */
128 /* If the line is empty... */
130 if (last_token == tok_macdef) /* end of macro */
131 last_token = tok_nothing;
133 continue; /* otherwise ignore it */
135 /* If we are defining macros, then skip parsing the line. */
136 while (*p && last_token != tok_macdef)
141 /* Skip any whitespace. */
142 while (*p && isspace (*p))
145 /* Discard end-of-line comments. */
151 /* Find the end of the token. */
152 while (*p && (quote_char || !isspace (*p)))
156 if (quote_char == *p)
170 if (*p == '"' || *p == '\'')
180 /* Null-terminate the token, if it isn't already. */
189 current->account = (char *) xstrdup (tok);
191 premature_token = "login";
195 /* Start a new machine entry. */
196 maybe_add_to_list (¤t, &retval);
197 current->host = (char *) xstrdup (tok);
202 current->password = (char *) xstrdup (tok);
204 premature_token = "password";
207 /* We handle most of tok_macdef above. */
210 premature_token = "macdef";
213 /* We don't handle the account keyword at all. */
216 premature_token = "account";
219 /* We handle tok_nothing below this switch. */
227 error_at_line (0, 0, file, ln,
228 _("warning: found \"%s\" before any host names"),
232 _("%s:%d: warning: found \"%s\" before any host names\n"),
233 file, ln, premature_token);
235 premature_token = NULL;
238 if (last_token != tok_nothing)
239 /* We got a value, so reset the token state. */
240 last_token = tok_nothing;
243 /* Fetch the next token. */
244 if (!strcmp (tok, "default"))
246 maybe_add_to_list (¤t, &retval);
248 else if (!strcmp (tok, "login"))
249 last_token = tok_login;
251 else if (!strcmp (tok, "user"))
252 last_token = tok_login;
254 else if (!strcmp (tok, "macdef"))
255 last_token = tok_macdef;
257 else if (!strcmp (tok, "machine"))
258 last_token = tok_machine;
260 else if (!strcmp (tok, "password"))
261 last_token = tok_password;
263 else if (!strcmp (tok, "account"))
264 last_token = tok_account;
268 fprintf (stderr, _("%s:%d: warning: unknown token \"%s\"\n"),
277 /* Finalize the last machine entry we found. */
278 maybe_add_to_list (¤t, &retval);
281 /* Reverse the order of the list so that it appears in file order. */
286 netrc_entry *saved_reference;
288 /* Change the direction of the pointers. */
289 saved_reference = current->next;
290 current->next = retval;
292 /* Advance to the next node. */
294 current = saved_reference;
301 /* Return the netrc entry from LIST corresponding to HOST. NULL is
302 returned if no such entry exists. */
304 search_netrc (list, host)
308 /* Look for the HOST in LIST. */
312 /* We hit the default entry. */
315 else if (!strcmp (list->host, host))
316 /* We found a matching entry. */
322 /* Return the matching entry, or NULL. */
328 #include <sys/types.h>
329 #include <sys/stat.h>
339 char *program_name, *file, *target;
340 netrc_entry *head, *a;
344 fprintf (stderr, "Usage: %s NETRC [HOSTNAME]...\n", argv[0]);
348 program_name = argv[0];
352 if (stat (file, &sb))
354 fprintf (stderr, "%s: cannot stat %s: %s\n", argv[0], file,
359 head = parse_netrc (file);
362 fprintf (stderr, "%s: no entries found in %s\n", argv[0], file);
370 for (i = 2; i < argc; i++)
372 /* Print out the host that we are checking for. */
373 fputs (argv[i], stdout);
375 a = search_netrc (head, argv[i]);
378 /* Print out the account and password (if any). */
380 fputs (a->account, stdout);
384 fputs (a->password, stdout);
390 fputc ('\n', stdout);
395 /* Print out the entire contents of the netrc. */
399 /* Print the host name. */
401 fputs (a->host, stdout);
403 fputs ("DEFAULT", stdout);
407 /* Print the account name. */
408 fputs (a->account, stdout);
412 /* Print the password, if there is any. */
414 fputs (a->password, stdout);
417 fputc ('\n', stdout);
423 #endif /* STANDALONE */