home *** CD-ROM | disk | FTP | other *** search
/ ftp.wwiv.com / ftp.wwiv.com.zip / ftp.wwiv.com / pub / INTERNET / UPC2S1.ZIP / ADDRESS.C < prev    next >
C/C++ Source or Header  |  1993-06-21  |  28KB  |  694 lines

  1. /*--------------------------------------------------------------------*/
  2. /*    a d d r e s s . c                                               */
  3. /*                                                                    */
  4. /*    Address parsing routines for UUPC/extended                      */
  5. /*--------------------------------------------------------------------*/
  6.  
  7. /*--------------------------------------------------------------------*/
  8. /*    Changes Copyright (c) 1990-1993 by Kendra Electronic            */
  9. /*    Wonderworks.                                                    */
  10. /*                                                                    */
  11. /*    All rights reserved except those explicitly granted by the      */
  12. /*    UUPC/extended license agreement.                                */
  13. /*--------------------------------------------------------------------*/
  14.  
  15. /*--------------------------------------------------------------------*/
  16. /*                          RCS Information                           */
  17. /*--------------------------------------------------------------------*/
  18.  
  19. /*
  20.  *    $Id: address.c 1.7 1993/06/22 00:55:45 ahd Exp $
  21.  *
  22.  *    Revision history:
  23.  *    $Log: address.c $
  24.  * Revision 1.7  1993/06/22  00:55:45  ahd
  25.  * Trap routing entries when aliasing systems
  26.  *
  27.  * Revision 1.6  1993/06/21  04:04:04  ahd
  28.  * Don't fail routing loops from aliased systems with no route
  29.  *
  30.  * Revision 1.5  1993/06/21  02:17:31  ahd
  31.  * Correct errors in mail routing via HOSTPATH
  32.  *
  33.  */
  34.  
  35. /*--------------------------------------------------------------------*/
  36. /*                        System include files                        */
  37. /*--------------------------------------------------------------------*/
  38.  
  39. #include <ctype.h>
  40. #include <stdio.h>
  41. #include <string.h>
  42. #include <stdlib.h>
  43. #include <sys/types.h>
  44.  
  45. /*--------------------------------------------------------------------*/
  46. /*                    UUPC/extended include files                     */
  47. /*--------------------------------------------------------------------*/
  48.  
  49. #include "lib.h"
  50. #include "hlib.h"
  51. #include "address.h"
  52. #include "hostable.h"
  53. #include "security.h"
  54.  
  55. /*--------------------------------------------------------------------*/
  56. /*                          Global variables                          */
  57. /*--------------------------------------------------------------------*/
  58.  
  59. currentfile();
  60.  
  61. /*--------------------------------------------------------------------*/
  62. /*                     Local function prototypes                      */
  63. /*--------------------------------------------------------------------*/
  64.  
  65. static char *rfc_route( char *tptr, char **nptr, char **pptr );
  66.  
  67. /*--------------------------------------------------------------------*/
  68. /*    u s e r _ a t _ n o d e                                         */
  69. /*                                                                    */
  70. /*    break a UUCP path or RFC-822 address into the basic user and    */
  71. /*    node components                                                 */
  72. /*                                                                    */
  73. /*    Note:    This routine assume an address of the form             */
  74. /*             path!node1!user@node2 is for a user@node1 routed via   */
  75. /*             node2 and then path.                                   */
  76. /*--------------------------------------------------------------------*/
  77.  
  78. void user_at_node(const char *raddress,
  79.                   char *hispath,
  80.                   char *hisnode,
  81.                   char *hisuser)
  82. {
  83.  
  84.    static char *saveaddr = NULL;
  85.    static char *savepath;
  86.    static char *savenode;
  87.    static char *saveuser;
  88.  
  89.    char *uptr;                      /* Pointer to his user id              */
  90.    char *nptr;                      /* Pointer to his node id              */
  91.    char *pptr;                      /* Pointer to next node in path to him */
  92.    char *tptr;                      /* Temporary token pointer             */
  93.    char *wptr;                      /* Work pointer (not used between
  94.                                        steps                               */
  95.    char *address;
  96.  
  97.    struct HostTable *Hptr = NULL;   /* Pointer to host name table          */
  98.  
  99.  
  100.    if ( strlen( raddress ) >= MAXADDR )
  101.    {
  102.       printmsg(0,"Unable to process %d length address: %s",
  103.             strlen(raddress) , raddress );
  104.       panic();
  105.    }
  106.  
  107. /*--------------------------------------------------------------------*/
  108. /*                     Determine if local address                     */
  109. /*--------------------------------------------------------------------*/
  110.  
  111.    if (!strpbrk(raddress,"%!@"))    /* Any host delimiters?                */
  112.    {                                /* No --> report local data            */
  113.       strcpy(hisuser,raddress);
  114.       strcpy(hisnode,E_nodename);
  115.       strcpy(hispath,E_nodename);
  116.       strcpy(hisuser,raddress);
  117.       printmsg(5,"user_at_node: Address '%s' is local",raddress);
  118.       return;
  119.    }
  120.  
  121. /*--------------------------------------------------------------------*/
  122. /*    If the current address is the same as the last processed remote */
  123. /*    address, then return the same information as what we determined */
  124. /*    last time.                                                      */
  125. /*--------------------------------------------------------------------*/
  126.  
  127.    if ((saveaddr != NULL) && equal(raddress,saveaddr))
  128.    {
  129.       strcpy(hispath,savepath);
  130.       strcpy(hisnode,savenode);
  131.       strcpy(hisuser,saveuser);
  132.       return;
  133.    }
  134.  
  135. /*--------------------------------------------------------------------*/
  136. /*   The address is different; save the new address and then proceed  */
  137. /*   to parse it.                                                     */
  138. /*--------------------------------------------------------------------*/
  139.  
  140.    address = strdup(raddress);   /* Copy address for parsing         */
  141.    checkref(address);            /* Verify allocation worked         */
  142.  
  143.    if (saveaddr != NULL)         /* Was the data previously allocated?  */
  144.    {                             /* Yes --> Free it                     */
  145.       free(saveaddr);
  146.    }
  147.  
  148.    saveaddr = strdup(address);   /* Remember address for next pass   */
  149.  
  150. /*--------------------------------------------------------------------*/
  151. /*    If the address has no at sign (@), but does have a percent      */
  152. /*    sign (%), replace the last percent sign with an at sign.        */
  153. /*--------------------------------------------------------------------*/
  154.  
  155.    if ( strchr(address,'@') == NULL )  // Any at signs?
  156.    {                                // No --> Look further for %
  157.       wptr = strrchr(address,'%');  // Locate any percent signs
  158.  
  159.       if ( wptr != NULL )           // Got one?
  160.          *wptr = '@';               // Yup --> Make it an at sign at
  161.    }
  162.  
  163. /*--------------------------------------------------------------------*/
  164. /*                   Initialize routing information                   */
  165. /*--------------------------------------------------------------------*/
  166.  
  167.    nptr = nil(char);             /* No known node for user           */
  168.    pptr = E_mailserv;            /* Default routing via mail server  */
  169.    tptr = address;               /* Remember start of address        */
  170.  
  171. /*--------------------------------------------------------------------*/
  172. /*  The address may be RFC-822 syntax; attempt to parse that format   */
  173. /*--------------------------------------------------------------------*/
  174.  
  175.    uptr = tptr = rfc_route( tptr, &nptr, &pptr );
  176.  
  177. /*--------------------------------------------------------------------*/
  178. /*   If the user had an RFC-822 path, then the pointer to the path is */
  179. /*   now initialized, and the remainder of the path has been dropped  */
  180. /*   from *tptr; otherwise, the entire address is found via *tptr     */
  181. /*--------------------------------------------------------------------*/
  182.  
  183.    wptr  = strrchr(tptr,'@');  /* Get last at sign, since it's right
  184.                                   to left scan (more or less)         */
  185.  
  186. /*--------------------------------------------------------------------*/
  187. /*    Translation of following:  If the at-sign (@) is not the        */
  188. /*    first character and the character preceding the at-sign is      */
  189. /*    not a bang (!), then break the address down into user and       */
  190. /*    node.                                                           */
  191. /*--------------------------------------------------------------------*/
  192.  
  193.    if (( wptr > tptr ) && ( strchr("!:",*(wptr-1)) == NULL))
  194.    {
  195.       uptr  = tptr;               /* Get user part of userid @node    */
  196.       *wptr++ = '\0';             /* Terminate user portion           */
  197.       tptr  = wptr;               /* Get node part of userid @node    */
  198.    }
  199.  
  200.    if (tptr != NULL)           /* Did we get a node?                  */
  201.    {                           /* Yes --> Save it                     */
  202.       nptr = tptr;
  203.       pptr = HostPath( nptr, pptr);
  204.    } /* if */
  205.  
  206. /*--------------------------------------------------------------------*/
  207. /*   Now, we will try stripping off any uucp path that the address    */
  208. /*   may have acquired; we'll assume the last node is the addressee's */
  209. /*   node.                                                            */
  210. /*--------------------------------------------------------------------*/
  211.  
  212.    uptr = strtok(uptr,"!");
  213.    tptr = strtok(NULL,"");
  214.  
  215.    while ( tptr != NULL )
  216.    {
  217.       nptr = uptr;                  /* First token is node           */
  218.       if (*tptr == '@')             /* Explicit RFC-822 route?       */
  219.       {                             /* Yes --> Examine in detail     */
  220.          uptr = strtok( rfc_route( tptr, &nptr, &pptr ), "!");
  221.                                     /* Second token, or what's
  222.                                        left of it, is user id        */
  223.          tptr = strtok(NULL,"");    /* Save rest of string           */
  224.       } /* if (*tptr == '@') */
  225.       else {
  226.          uptr = strtok(tptr,"!");   /* Second token is user id       */
  227.          tptr = strtok(NULL,"");    /* Save rest of string           */
  228.          pptr = HostPath( nptr, pptr);
  229.       } /* else */
  230.    } /* while */
  231.  
  232. /*--------------------------------------------------------------------*/
  233. /*   Finally, we parse off any internet mail that used the infamous % */
  234. /*   hack (user%node1@gatewayb)                                       */
  235. /*--------------------------------------------------------------------*/
  236.  
  237.    while ((tptr = strrchr(uptr,'%')) != NULL)   /* Get last percent  */
  238.    {
  239.       *tptr = '@';               /* Make it an RFC-822 address       */
  240.       uptr  = strtok(uptr,"@");  /* Get user part of userid @node    */
  241.       nptr  = strtok(NULL,"@");  /* Get node part of userid @node    */
  242.       pptr  = HostPath(nptr, pptr); /* Old node is new path          */
  243.    } /* while */
  244.  
  245. /*--------------------------------------------------------------------*/
  246. /*   If the last known hop in the path is via our own system, but the */
  247. /*   target node is not our own system, route the message via our     */
  248. /*   default mail server.                                             */
  249. /*--------------------------------------------------------------------*/
  250.  
  251.    nptr = HostAlias( nptr );
  252.    if (equali(pptr,E_nodename))
  253.                               /* Is mail routed via our local system? */
  254.    {                          /* Yes --> Determine if destined for us */
  255.       Hptr = checkname(nptr);          /* Locate the system       */
  256.       if (Hptr == BADHOST)             /* System known?           */
  257.       {                                /* No --> Route default    */
  258.          printmsg(5,
  259.             "user_at_node: Routing mail for \"%s\" via default mail server",
  260.                   nptr);
  261.          pptr = E_mailserv;
  262.       } /* if */
  263.    }  /* if */
  264.  
  265. /*--------------------------------------------------------------------*/
  266. /*                         Print our results                          */
  267. /*--------------------------------------------------------------------*/
  268.  
  269.    printmsg(9,
  270.          "user_at_node: Address \"%s\" is \"%s\" at \"%s\" via \"%s\"",
  271.             raddress, uptr, nptr, pptr);
  272.  
  273. /*--------------------------------------------------------------------*/
  274. /*  We have parsed the address.  Fill in the information for caller   */
  275. /*--------------------------------------------------------------------*/
  276.  
  277.    strcpy(hispath,pptr);
  278.    strcpy(hisnode,nptr);
  279.    strcpy(hisuser,uptr);
  280.  
  281. /*--------------------------------------------------------------------*/
  282. /*   Save the parsed information along with the original address we   */
  283. /*   were passed in.  This could save breaking it down again.         */
  284. /*--------------------------------------------------------------------*/
  285.  
  286.    savepath = newstr(hispath);
  287.    savenode = newstr(hisnode);
  288.    saveuser = newstr(hisuser);
  289.  
  290.    free(address);
  291. }  /* user_at_node */
  292.  
  293. /*--------------------------------------------------------------------*/
  294. /*    r f c _ r o u t e                                               */
  295. /*                                                                    */
  296. /*    Strip off explicit RFC-822 routing from an address              */
  297. /*--------------------------------------------------------------------*/
  298.  
  299. static char *rfc_route( char *tptr, char **nptr, char **pptr )
  300. {
  301.  
  302. /*--------------------------------------------------------------------*/
  303. /*          Loop as long as we have an explicit RFC-822 path          */
  304. /*--------------------------------------------------------------------*/
  305.  
  306.    while (*tptr == '@')        /* Explicit RFC 822 path?             */
  307.    {
  308.       *nptr = strtok(++tptr,",:");  /* First token is path/node      */
  309.       tptr = strtok(NULL,""); /* Second has rest, including user id  */
  310.       *pptr = HostPath( *nptr , *pptr );
  311.                               /* Determine actual path               */
  312.       printmsg(9,"rfc_route: RFC-822 explicit path: "
  313.                   "\"%s\" routed via \"%s\" is via \"%s\"",
  314.          tptr, *nptr, *pptr);
  315.    } /* while */
  316.  
  317. /*--------------------------------------------------------------------*/
  318. /*    At this point, *nptr is last node in list, *pptr is path to     */
  319. /*    *nptr, and *tptr is the rest of the string (userid?)            */
  320. /*--------------------------------------------------------------------*/
  321.  
  322.    return tptr;
  323. } /* rfc_route */
  324.  
  325. /*--------------------------------------------------------------------*/
  326. /*    H o s t A l i a s                                               */
  327. /*                                                                    */
  328. /*    Resolve a host alias to its real canonized name                 */
  329. /*--------------------------------------------------------------------*/
  330.  
  331. char *HostAlias( char *input)
  332. {
  333.    struct HostTable *hostp;
  334.  
  335.    hostp = checkname(input);
  336.  
  337. /*--------------------------------------------------------------------*/
  338. /*     If nothing else to look at, return original data to caller     */
  339. /*--------------------------------------------------------------------*/
  340.  
  341.    if (hostp == BADHOST)
  342.       return input;
  343.  
  344. /*--------------------------------------------------------------------*/
  345. /*       If the entry has no alias and is not a real system, it's     */
  346. /*       a routing entry and we should ignore it.                     */
  347. /*--------------------------------------------------------------------*/
  348.  
  349.    if ((hostp->hstatus == phantom) && ( hostp->realname == NULL ))
  350.       return input;
  351.  
  352. /*--------------------------------------------------------------------*/
  353. /*      If we already chased this chain, return result to caller      */
  354. /*--------------------------------------------------------------------*/
  355.  
  356.    if (hostp->aliased)
  357.    {
  358.       if ( hostp->realname  == NULL )
  359.       {
  360.          printmsg(0,"Alias table loop detected with host %s",
  361.                hostp->hostname);
  362.       }
  363.  
  364.       return hostp->realname;
  365.    } /* if */
  366.  
  367.    hostp->aliased = TRUE;        /* Prevent limitless recursion      */
  368.  
  369. /*--------------------------------------------------------------------*/
  370. /*                  Determine next host in the chain                  */
  371. /*--------------------------------------------------------------------*/
  372.  
  373.    if ( hostp->realname == NULL)  /* End of the line?        */
  374.       hostp->realname = hostp->hostname;
  375.    else
  376.       hostp->realname = HostAlias(hostp->realname);
  377.  
  378. /*--------------------------------------------------------------------*/
  379. /*                        Announce our results                        */
  380. /*--------------------------------------------------------------------*/
  381.  
  382.    printmsg( 5 , "HostAlias: \"%s\" is alias of \"%s\"",
  383.                   input,
  384.                   hostp->realname);
  385.  
  386.    return hostp->realname;
  387.  
  388. } /* HostAlias */
  389.  
  390. /*--------------------------------------------------------------------*/
  391. /*    H o s t P a t h                                                 */
  392. /*                                                                    */
  393. /*    Determine the path to a host                                    */
  394. /*--------------------------------------------------------------------*/
  395.  
  396. char *HostPath( char *input, char *best)
  397. {
  398.    struct HostTable *hostp;
  399.  
  400.    hostp = checkname( input );
  401.  
  402. /*--------------------------------------------------------------------*/
  403. /*     If nothing else to look at, return original data to caller     */
  404. /*--------------------------------------------------------------------*/
  405.  
  406.    if (hostp == BADHOST)
  407.       return best;
  408.  
  409.    if (hostp->hstatus == gatewayed)  /* Gatewayed?                    */
  410.       return hostp->hostname;      /* Yes --> Use name for path       */
  411.  
  412.  
  413. /*--------------------------------------------------------------------*/
  414. /*      If we already chased this chain, return result to caller      */
  415. /*--------------------------------------------------------------------*/
  416.  
  417.    if (hostp->routed)
  418.    {
  419.       if ( hostp->via == NULL )
  420.       {
  421.          if ( hostp->aliased &&
  422.               ! equali(hostp->hostname,hostp->realname))
  423.             hostp->via = best;
  424.          else {
  425.             printmsg(0,"Routing table loop discovered at host %s",
  426.                      hostp->hostname);
  427.             panic();
  428.          }
  429.  
  430.       } /* if ( hostp->via == NULL ) */
  431.  
  432.       return hostp->via;
  433.  
  434.    } /* if (hostp->routed) */
  435.  
  436.    hostp->routed  = TRUE;        /* Prevent limitless recursion      */
  437.  
  438. /*--------------------------------------------------------------------*/
  439. /*                  Determine next host in the chain                  */
  440. /*--------------------------------------------------------------------*/
  441.  
  442.    if ( hostp->via == NULL )
  443.    {
  444.       char *alias = HostAlias( hostp->hostname );
  445.  
  446.       if (equal(hostp->hostname,alias))
  447.       {
  448.          if (hostp->hstatus == localhost) /* Ourself?                */
  449.             hostp->via = E_nodename;      /* Yes --> Deliver local   */
  450.          else if ( checkreal( hostp->hostname ) == BADHOST )
  451.                                           /* Unknown system?         */
  452.             hostp->via = best;            /* Yes --> Use default     */
  453.          else
  454.             hostp->via = hostp->hostname; /* Known --> route to it   */
  455.       } /* if ( hostp->via == NULL ) */
  456.       else
  457.          hostp->via = HostPath( alias, best);
  458.  
  459.    } /* if ( hostp->via == NULL ) */
  460.  
  461.    hostp->via = HostPath( hostp->via, best );
  462.  
  463.    printmsg( 5 ,"HostPath: \"%s\" routed via \"%s\"", input, hostp->via);
  464.  
  465.    return hostp->via;
  466.  
  467. } /* HostPath */
  468.  
  469. /*--------------------------------------------------------------------*/
  470. /*    E x t r a c t A d d r e s s                                     */
  471. /*                                                                    */
  472. /*    Returns the user name (if available and requested or            */
  473. /*    E-mail address of the user                                      */
  474. /*--------------------------------------------------------------------*/
  475.  
  476. char *ExtractAddress(char *result,
  477.                     const char *input ,
  478.                     FULLNAME fullname)
  479. {
  480.    char *nonblank = NULL;
  481.    char *column  = (char *) input;
  482.    char name[BUFSIZ];      /* User full name             */
  483.    char *nameptr = name;
  484.    char addr[BUFSIZ];      /* User e-mail address        */
  485.    char *addrptr  = addr;
  486.  
  487.    char state = 'A';                /* State = skip whitespace    */
  488.    char newstate = 'A';             /* Next state to process      */
  489.    int bananas = 0;                 /* No () being processed now  */
  490.    int len;
  491.    boolean quoted = FALSE;
  492.  
  493. /*--------------------------------------------------------------------*/
  494. /*   Begin loop to copy the input field into the address and or the   */
  495. /*   user name.  We will begin by copying both (ignoring whitespace   */
  496. /*   for addresses) because we won't know if the input field is an    */
  497. /*   address or a name until we hit either a special character of     */
  498. /*   some sort.                                                       */
  499. /*--------------------------------------------------------------------*/
  500.  
  501.    while ((*column != '\0') && (state != ','))
  502.    {
  503.       switch (state) {
  504.          case 'A':
  505.             if (isspace(*column))   /* Found first non-blank? */
  506.                break;               /* No --> keep looking    */
  507.             nonblank = column;
  508.             state = 'B';
  509.                                     /* ... and fall through          */
  510.          case 'B':
  511.          case ')':
  512.             newstate = *column;
  513.             switch(*column) {
  514.                case '(':
  515.                   bananas++;
  516.                   break;
  517.  
  518.                case '"':
  519.                   break;
  520.  
  521.                case '<':
  522.                   addrptr = addr;   /* Start address over      */
  523.                   nameptr = name;   /* Start name over again   */
  524.                   column  = nonblank - 1;
  525.                                     /* Re-scan in new state    */
  526.                   newstate = '>';   /* Proc all-non <> as name */
  527.                   break;            /* Begin addr over again   */
  528.                case ',':
  529.                   break;            /* Terminates address      */
  530.                case '>':
  531.                case ')':
  532.                   printmsg(0,"Invalid RFC-822 address: %s",nonblank);
  533.                   panic();          /* Ooops, funky address    */
  534.                   break;
  535.  
  536.                default:
  537.                   newstate = state; /* stay in this state            */
  538.                   if (!isspace(*column))
  539.                      *(addrptr++) = *column;
  540.             }  /* switch(*column) */
  541.             break;
  542.  
  543.          case '<':   if (*column == '>')
  544.                         newstate = '>';
  545.                      else if (!isspace(*column))
  546.                         *(addrptr++) = *column;
  547.                      break;
  548.  
  549.          case '>':   if (*column == '<')
  550.                         newstate = '<';
  551.                      else switch( *column )
  552.                      {
  553.                         case ')':
  554.                            if (quoted)
  555.                               *(nameptr++) = *column;
  556.                            else
  557.                               bananas--;
  558.                            break;
  559.  
  560.                         case '(':
  561.                            if (quoted)
  562.                               *(nameptr++) = *column;
  563.                            else
  564.                               bananas++;
  565.                            break;
  566.  
  567.                         case '"':
  568.                            if (bananas == 0)
  569.                            {
  570.                               quoted = !quoted;
  571.                               break;
  572.                            }
  573.                            /* else fall through */
  574.  
  575.                         default:
  576.                            *(nameptr++) = *column;
  577.                      } /* switch */
  578.                      break;
  579.  
  580.          case '(':   if (*column == '(')
  581.                         ++bananas;
  582.                      else if (*column == ')')
  583.                      {
  584.                         if (--bananas == 0)
  585.                         {
  586.                            newstate = ')';
  587.                            break;
  588.                         }
  589.                      }
  590.                      else
  591.                         *(nameptr++) = *column;
  592.                      break;
  593.  
  594.          case '"':   if (*column == '"')
  595.                         newstate = ')';
  596.                      else
  597.                         *(nameptr++) = *column;
  598.  
  599.                      break;
  600.  
  601.          default:    panic();
  602.                                  /* Logic error, bad state        */
  603.                      break;
  604.  
  605.       }  /* switch (state) */
  606.       state = newstate;
  607.       column++;
  608.    } /* while */
  609.  
  610. /*--------------------------------------------------------------------*/
  611. /*                   Verify we retrieved an address                   */
  612. /*--------------------------------------------------------------------*/
  613.  
  614.    if (state == 'A')
  615.    {
  616.       printmsg(0, "ExtractAddress: Could not find address in \"%s\"",
  617.                column);
  618.       panic();
  619.    }
  620.  
  621. /*--------------------------------------------------------------------*/
  622. /*                 Fill in the results for the caller                 */
  623. /*--------------------------------------------------------------------*/
  624.  
  625.    *addrptr = '\0';
  626.    *nameptr = '\0';
  627.    *result  = '\0';
  628.    len = strlen( addr );
  629.  
  630.    if ((fullname == ADDRESSONLY) ||
  631.        ((fullname == FULLADDRESS) && (state == 'B')))
  632.    {
  633.       if ( len >= MAXADDR )
  634.       {
  635.          printmsg(0,"ExtractAddress: Address exceeds %d characters: %s",
  636.                      MAXADDR, addr );
  637.          panic();
  638.       }
  639.       strcpy(result,addr);         /* Return the full address    */
  640.    }
  641.    else if (state != 'B')
  642.    {
  643.       while (--nameptr >= name)
  644.       {
  645.          if (isspace(*nameptr))
  646.             *nameptr = '\0';
  647.          else
  648.             break;
  649.       }
  650.  
  651. /*--------------------------------------------------------------------*/
  652. /*               Strip leading blanks from the address                */
  653. /*--------------------------------------------------------------------*/
  654.  
  655.       nameptr = name;
  656.       while (isspace(*nameptr))
  657.          nameptr++;
  658.  
  659.       if ( strlen( nameptr ) >= MAXADDR )
  660.       {
  661.          printmsg(0,"ExtractAddress: Truncating name %s" , nameptr);
  662.          nameptr[ MAXADDR - 1 ] = '\0';
  663.       }
  664.  
  665.       if ( fullname == FULLADDRESS )
  666.       {
  667.          if ( len >= (MAXADDR-6) )
  668.          {
  669.             printmsg(0,"ExtractAddress: Address exceeds %d characters: %s",
  670.                         MAXADDR-6, addr );
  671.             panic();
  672.          }
  673.          nameptr[ MAXADDR - len - 6] = '\0';
  674.          sprintf( result , "\"%s\" <%s>", nameptr, addr );
  675.       }
  676.       else
  677.          strncpy(result,nameptr, MAXADDR);
  678.  
  679.    } /* else */
  680.  
  681.    printmsg(4,"ExtractAddress: %s into <%s> \"%s\"",
  682.             nonblank,addr,(fullname) ? result : name);
  683.  
  684. /*--------------------------------------------------------------------*/
  685. /*   Return the position of the next address, if any, to the caller   */
  686. /*--------------------------------------------------------------------*/
  687.  
  688.    if ( *column == '\0')
  689.       return NULL;
  690.    else
  691.       return column + 1;
  692.  
  693. } /*ExtractAddress*/
  694.