"Fossies" - the Fresh Open Source Software Archive

Member "sitecopy-0.16.6/lib/netrc.c" (2 Jan 2005, 8690 Bytes) of archive /linux/www/sitecopy-0.16.6.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "netrc.c" see the Fossies "Dox" file reference documentation.

    1 /* netrc.c -- parse the .netrc file to get hosts, accounts, and passwords
    2 
    3    Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
    4 
    5    This program is free software; you can redistribute it and/or modify
    6    it under the terms of the GNU General Public License as published by
    7    the Free Software Foundation; either version 2 of the License, or
    8    (at your option) any later version.
    9   
   10    This program is distributed in the hope that it will be useful,
   11    but WITHOUT ANY WARRANTY; without even the implied warranty of
   12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13    GNU General Public License for more details.
   14   
   15    You should have received a copy of the GNU General Public License
   16    along with this program; if not, write to the Free Software
   17    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   18 
   19    For license terms, see the file COPYING in this directory.
   20 
   21    Compile with -DSTANDALONE to test this module. */
   22 
   23 #include <stdio.h>
   24 #include <ctype.h>
   25 #include <stdlib.h>
   26 #include <string.h>
   27 
   28 #include <config.h>
   29 #include "netrc.h"
   30 
   31 #include <ne_alloc.h>
   32 
   33 #define POPBUFSIZE BUFSIZ
   34 
   35 /* Maybe add NEWENTRY to the account information list, LIST.  NEWENTRY is
   36    set to a ready-to-use netrc_entry, in any event. */
   37 static void
   38 maybe_add_to_list (netrc_entry **newentry, netrc_entry **list)
   39 {
   40     netrc_entry *a, *l;
   41     a = *newentry;
   42     l = *list;
   43 
   44     /* We need an account name in order to add the entry to the list. */
   45     if (a && ! a->account)
   46     {
   47     /* Free any allocated space. */
   48     if (a->host)
   49         free (a->host);
   50     if (a->password)
   51         free (a->password);
   52     }
   53     else
   54     {
   55     if (a)
   56     {
   57         /* Add the current machine into our list. */
   58         a->next = l;
   59         l = a;
   60     }
   61 
   62     /* Allocate a new netrc_entry structure. */
   63     a = (netrc_entry *) ne_malloc (sizeof (netrc_entry));
   64     }
   65 
   66     /* Zero the structure, so that it is ready to use. */
   67     memset (a, 0, sizeof(*a));
   68 
   69     /* Return the new pointers. */
   70     *newentry = a;
   71     *list = l;
   72     return;
   73 }
   74 
   75 
   76 /* Parse FILE as a .netrc file (as described in ftp(1)), and return a
   77    list of entries.  NULL is returned if the file could not be
   78    parsed. */
   79 netrc_entry *
   80 parse_netrc (file)
   81      char *file;
   82 {
   83     FILE *fp;
   84     char buf[POPBUFSIZE+1], *p, *tok;
   85     const char *premature_token;
   86     netrc_entry *current, *retval;
   87     int ln;
   88 
   89     /* The latest token we've seen in the file. */
   90     enum
   91     {
   92     tok_nothing, tok_account, tok_login, tok_macdef, tok_machine, tok_password
   93     } last_token = tok_nothing;
   94 
   95     current = retval = NULL;
   96 
   97     fp = fopen (file, "r");
   98     if (!fp)
   99     {
  100     /* Just return NULL if we can't open the file. */
  101     return NULL;
  102     }
  103 
  104     /* Initialize the file data. */
  105     ln = 0;
  106     premature_token = NULL;
  107 
  108     /* While there are lines in the file... */
  109     while (fgets(buf, POPBUFSIZE, fp))
  110     {
  111     ln++;
  112 
  113     /* Strip trailing CRLF */
  114     for (p = buf + strlen(buf) - 1; (p >= buf) && isspace((unsigned)*p); p--)
  115         *p = '\0';
  116 
  117     /* Parse the line. */
  118     p = buf;
  119 
  120     /* If the line is empty... */
  121     if (!*p) {
  122         if (last_token == tok_macdef) { /* end of macro */
  123         last_token = tok_nothing;
  124         } else {
  125         continue;           /* otherwise ignore it */
  126         }
  127     }
  128 
  129     /* If we are defining macros, then skip parsing the line. */
  130     while (*p && last_token != tok_macdef)
  131     {
  132         char quote_char = 0;
  133         char *pp;
  134 
  135         /* Skip any whitespace. */
  136         while (*p && isspace ((unsigned)*p))
  137         p++;
  138 
  139         /* Discard end-of-line comments. */
  140         if (*p == '#')
  141         break;
  142 
  143         tok = pp = p;
  144 
  145         /* Find the end of the token. */
  146         while (*p && (quote_char || !isspace ((unsigned)*p)))
  147         {
  148         if (quote_char)
  149         {
  150             if (quote_char == *p)
  151             {
  152             quote_char = 0;
  153             p ++;
  154             }
  155             else
  156             {
  157             *pp = *p;
  158             p ++;
  159             pp ++;
  160             }
  161         }
  162         else
  163         {
  164             if (*p == '"' || *p == '\'')
  165             quote_char = *p;
  166             else
  167             {
  168             *pp = *p;
  169             pp ++;
  170             }
  171             p ++;
  172         }
  173         }
  174         /* Null-terminate the token, if it isn't already. */
  175         if (*p)
  176         *p ++ = '\0';
  177         *pp = 0;
  178 
  179         switch (last_token)
  180         {
  181         case tok_login:
  182         if (current)
  183             current->account = (char *) ne_strdup (tok);
  184         else
  185             premature_token = "login";
  186         break;
  187 
  188         case tok_machine:
  189         /* Start a new machine entry. */
  190         maybe_add_to_list (&current, &retval);
  191         current->host = (char *) ne_strdup (tok);
  192         break;
  193 
  194         case tok_password:
  195         if (current)
  196             current->password = (char *) ne_strdup (tok);
  197         else
  198             premature_token = "password";
  199         break;
  200 
  201         /* We handle most of tok_macdef above. */
  202         case tok_macdef:
  203         if (!current)
  204             premature_token = "macdef";
  205         break;
  206 
  207         /* We don't handle the account keyword at all. */
  208         case tok_account:
  209         if (!current)
  210             premature_token = "account";
  211         break;
  212 
  213         /* We handle tok_nothing below this switch. */
  214         case tok_nothing:
  215         break;
  216         }
  217 
  218         if (premature_token)
  219         {
  220 #ifdef HAVE_ERROR
  221         error_at_line (0, file, ln,
  222                    "warning: found \"%s\" before any host names",
  223                    premature_token);
  224 #else
  225         fprintf (stderr,
  226              "%s:%d: warning: found \"%s\" before any host names\n",
  227              file, ln, premature_token);
  228 #endif
  229         premature_token = NULL;
  230         }
  231 
  232         if (last_token != tok_nothing)
  233         /* We got a value, so reset the token state. */
  234         last_token = tok_nothing;
  235         else
  236         {
  237         /* Fetch the next token. */
  238         if (!strcmp (tok, "default"))
  239         {
  240             maybe_add_to_list (&current, &retval);
  241         }
  242         else if (!strcmp (tok, "login"))
  243             last_token = tok_login;
  244 
  245         else if (!strcmp (tok, "user"))
  246             last_token = tok_login;
  247 
  248         else if (!strcmp (tok, "macdef"))
  249             last_token = tok_macdef;
  250 
  251         else if (!strcmp (tok, "machine"))
  252             last_token = tok_machine;
  253 
  254         else if (!strcmp (tok, "password"))
  255             last_token = tok_password;
  256 
  257         else if (!strcmp (tok, "passwd"))
  258             last_token = tok_password;
  259 
  260         else if (!strcmp (tok, "account"))
  261             last_token = tok_account;
  262 
  263         else
  264         {
  265             fprintf (stderr, "%s:%d: warning: unknown token \"%s\"\n",
  266                  file, ln, tok);
  267         }
  268         }
  269     }
  270     }
  271 
  272     fclose (fp);
  273 
  274     /* Finalize the last machine entry we found. */
  275     maybe_add_to_list (&current, &retval);
  276     free (current);
  277 
  278     /* Reverse the order of the list so that it appears in file order. */
  279     current = retval;
  280     retval = NULL;
  281     while (current)
  282     {
  283     netrc_entry *saved_reference;
  284 
  285     /* Change the direction of the pointers. */
  286     saved_reference = current->next;
  287     current->next = retval;
  288 
  289     /* Advance to the next node. */
  290     retval = current;
  291     current = saved_reference;
  292     }
  293 
  294     return retval;
  295 }
  296 
  297 
  298 /* Return the netrc entry from LIST corresponding to HOST.  NULL is
  299    returned if no such entry exists. */
  300 netrc_entry *
  301 search_netrc (list, host)
  302      netrc_entry *list;
  303      const char *host;
  304 {
  305     /* Look for the HOST in LIST. */
  306     while (list)
  307     {
  308     if (!list->host)
  309         /* We hit the default entry. */
  310         break;
  311 
  312     else if (!strcmp (list->host, host))
  313         /* We found a matching entry. */
  314         break;
  315 
  316     list = list->next;
  317     }
  318 
  319     /* Return the matching entry, or NULL. */
  320     return list;
  321 }
  322 
  323 
  324 #ifdef STANDALONE
  325 #include <sys/types.h>
  326 #include <sys/stat.h>
  327 
  328 extern int errno;
  329 
  330 int
  331 main (argc, argv)
  332      int argc;
  333      char **argv;
  334 {
  335     struct stat sb;
  336     char *program_name, *file, *target;
  337     netrc_entry *head, *a;
  338 
  339     if (argc < 2)
  340     {
  341     fprintf (stderr, "Usage: %s NETRC [HOSTNAME]...\n", argv[0]);
  342     exit (1);
  343     }
  344 
  345     program_name = argv[0];
  346     file = argv[1];
  347     target = argv[2];
  348 
  349     if (stat (file, &sb))
  350     {
  351     fprintf (stderr, "%s: cannot stat %s: %s\n", argv[0], file,
  352          strerror (errno));
  353     exit (1);
  354     }
  355 
  356     head = parse_netrc (file);
  357     if (!head)
  358     {
  359     fprintf (stderr, "%s: no entries found in %s\n", argv[0], file);
  360     exit (1);
  361     }
  362 
  363     if (argc > 2)
  364     {
  365     int i, status;
  366     status = 0;
  367     for (i = 2; i < argc; i++)
  368     {
  369         /* Print out the host that we are checking for. */
  370         fputs (argv[i], stdout);
  371 
  372         a = search_netrc (head, argv[i]);
  373         if (a)
  374         {
  375         /* Print out the account and password (if any). */
  376         fputc (' ', stdout);
  377         fputs (a->account, stdout);
  378         if (a->password)
  379         {
  380             fputc (' ', stdout);
  381             fputs (a->password, stdout);
  382         }
  383         }
  384         else
  385         status = 1;
  386 
  387         fputc ('\n', stdout);
  388     }
  389     exit (status);
  390     }
  391 
  392     /* Print out the entire contents of the netrc. */
  393     a = head;
  394     while (a)
  395     {
  396     /* Print the host name. */
  397     if (a->host)
  398         fputs (a->host, stdout);
  399     else
  400         fputs ("DEFAULT", stdout);
  401 
  402     fputc (' ', stdout);
  403 
  404     /* Print the account name. */
  405     fputs (a->account, stdout);
  406 
  407     if (a->password)
  408     {
  409         /* Print the password, if there is any. */
  410         fputc (' ', stdout);
  411         fputs (a->password, stdout);
  412     }
  413 
  414     fputc ('\n', stdout);
  415     a = a->next;
  416     }
  417 
  418     exit (0);
  419 }
  420 #endif /* STANDALONE */