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