"Fossies" - the Fresh Open Source Software Archive

Member "msmtp-1.8.5/src/netrc.c" (12 Dec 2018, 8409 Bytes) of package /linux/privat/msmtp-1.8.5.tar.xz:


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 and the last Fossies "Diffs" side-by-side code changes report: 1.8.1_vs_1.8.2.

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