home *** CD-ROM | disk | FTP | other *** search
- /*--------------------------------------------------------------------*/
- /* a d d r e s s . c */
- /* */
- /* Address parsing routines for UUPC/extended */
- /*--------------------------------------------------------------------*/
-
- #include <ctype.h>
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <sys/types.h>
-
- #include "lib.h"
- #include "address.h"
- #include "hostable.h"
- #include "security.h"
-
- /*--------------------------------------------------------------------*/
- /* Global variables */
- /*--------------------------------------------------------------------*/
-
- currentfile();
-
- /*--------------------------------------------------------------------*/
- /* u s e r _ a t _ n o d e */
- /* */
- /* break a UUCP path or RFC-822 address into the basic user and */
- /* node components */
- /* */
- /* Note: This routine assume an address of the form */
- /* path!node1!user@node2 is for a user@node1 routed via */
- /* node2 and then path. */
- /*--------------------------------------------------------------------*/
-
- void user_at_node(const char *raddress,
- char *hispath,
- char *hisnode,
- char *hisuser)
- {
-
- static char *saveaddr = NULL;
- static char *savepath;
- static char *savenode;
- static char *saveuser;
-
- char *uptr; /* Pointer to his user id */
- char *nptr; /* Pointer to his node id */
- char *pptr; /* Pointer to next node in path to him */
- char *tptr; /* Temporary token pointer */
- char *address;
-
- struct HostTable *Hptr = NULL; /* Pointer to host name table */
-
- /*--------------------------------------------------------------------*/
- /* Determine if local address */
- /*--------------------------------------------------------------------*/
-
- if (!strpbrk(raddress,"!@")) /* Any host delimiters? */
- { /* No --> report local data */
- strcpy(hisuser,raddress);
- strcpy(hisnode,nodename);
- strcpy(hispath,nodename);
- strcpy(hisuser,raddress);
- printmsg(5,"user_at_node: Address '%s' is local",raddress);
- return;
- }
-
- /*--------------------------------------------------------------------*/
- /* If the current address is the same as the last processed remote */
- /* address, then return the same information as what we determined */
- /* last time. */
- /*--------------------------------------------------------------------*/
-
- if ((saveaddr != NULL) && equal(raddress,saveaddr))
- {
- strcpy(hispath,savepath);
- strcpy(hisnode,savenode);
- strcpy(hisuser,saveuser);
- return;
- }
-
- /*--------------------------------------------------------------------*/
- /* The address is different; save the new address and then proceed */
- /* to parse it. */
- /*--------------------------------------------------------------------*/
-
- address = strdup(raddress); /* Copy address for parsing */
- checkref(address); /* Verify allocation worked */
-
- if (saveaddr != NULL) /* Was the data previously allocated? */
- { /* Yes --> Free it */
- free(saveaddr);
- free(savepath);
- free(saveuser);
- free(savenode);
- }
-
- saveaddr = strdup(address); /* Remember address for next pass */
-
- nptr = nil(char); /* No known node for user */
- pptr = mailserv; /* Default routing via mail server */
- tptr = address; /* Remember start of address */
-
- /*--------------------------------------------------------------------*/
- /* The address may be RFC-822 syntax; attempt to parse that format */
- /*--------------------------------------------------------------------*/
-
- while (*tptr == '@') /* Explicit RFC 822 path? */
- {
- char *tpath = strtok(++tptr,",:");
- tptr = strtok(NULL,"");
- pptr = HostPath( tpath , pptr );
- printmsg(9,"user_at_node: RFC-822 explicit path: \"%s\" via \"%s\"",
- tptr, pptr);
- } /* while */
-
- /*--------------------------------------------------------------------*/
- /* If the user had an RFC-822 path, then the pointer to the path is */
- /* now initialized, and the remainder of the path has been dropped */
- /* from *tptr; otherwise, the entire address is found via *tptr */
- /*--------------------------------------------------------------------*/
-
- uptr = strtok(tptr,"@"); /* Get user part of userid @node */
- tptr = strtok(NULL,"@"); /* Get node part of userid @node */
-
- if (tptr != NULL) /* Did we get a node? */
- { /* Yes --> Save it */
- nptr = tptr;
- pptr = HostPath( nptr, pptr);
- } /* if */
-
- /*--------------------------------------------------------------------*/
- /* Now, we will try stripping off any uucp path that the address */
- /* may have acquired; we'll assume the last node is the addressee's */
- /* node. */
- /*--------------------------------------------------------------------*/
-
- uptr = strtok(uptr,"!");
- tptr = strtok(NULL,"");
-
- while ( tptr != NULL )
- {
- nptr = uptr;
- uptr = strtok(tptr,"!");
- tptr = strtok(NULL,"");
- pptr = HostPath( nptr, pptr);
- } /* while */
-
- /*--------------------------------------------------------------------*/
- /* Finally, we parse off any internet mail that used the infamous % */
- /* hack (user%node1@gatewayb) */
- /*--------------------------------------------------------------------*/
-
- while ((tptr = strrchr(uptr,'%')) != NULL) /* Get last percent */
- {
- *tptr = '@'; /* Make it an RFC-822 address */
- uptr = strtok(uptr,"@"); /* Get user part of userid @node */
- nptr = strtok(NULL,"@"); /* Get node part of userid @node */
- pptr = HostPath(nptr, pptr); /* Old node is new path */
- } /* while */
-
- /*--------------------------------------------------------------------*/
- /* If the last known hop in the path is via our own system, but the */
- /* target node is not our own system, route the message via our */
- /* default mail server. */
- /*--------------------------------------------------------------------*/
-
- nptr = HostAlias( nptr );
- if (equali(pptr,nodename))
- /* Is mail routed via our local system? */
- { /* Yes --> Determine if destined for us */
- Hptr = checkname(nptr); /* Locate the system */
- if (Hptr == BADHOST) /* System known? */
- { /* No --> Route default */
- printmsg(5,
- "user_at_node: Routing mail for \"%s\" via default mail server",
- nptr);
- pptr = mailserv;
- } /* if */
- } /* if */
-
- /*--------------------------------------------------------------------*/
- /* Print our results */
- /*--------------------------------------------------------------------*/
-
- printmsg(9,
- "user_at_node: Address \"%s\" is \"%s\" at \"%s\" via \"%s\"",
- raddress, uptr, nptr, pptr);
-
- /*--------------------------------------------------------------------*/
- /* We have parsed the address. Fill in the information for caller */
- /*--------------------------------------------------------------------*/
-
- strcpy(hispath,pptr);
- strcpy(hisnode,nptr);
- strcpy(hisuser,uptr);
-
- /*--------------------------------------------------------------------*/
- /* Save the parsed information along with the original address we */
- /* were passed in. This could save breaking it down again. */
- /*--------------------------------------------------------------------*/
-
- savepath = strdup(hispath);
- savenode = strdup(hisnode);
- saveuser = strdup(hisuser);
-
- free(address);
- } /* user_at_node */
-
-
- /*--------------------------------------------------------------------*/
- /* H o s t A l i a s */
- /* */
- /* Resolve a host alias to its real canonized name */
- /*--------------------------------------------------------------------*/
-
- char *HostAlias( char *input)
- {
- size_t loop = 100;
- struct HostTable *Hptr;
- char *host = input;
-
- do {
- Hptr = checkname(host);
- if (Hptr == BADHOST)
- break;
- else {
- if (--loop == 0)
- {
- printmsg(0,"HostAlias: Alias loop of \"%s\" and \"%s\"",
- host , Hptr->via);
- break;
- } /* if */
-
- if (Hptr->hstatus == localhost) /* local system? */
- host = nodename; /* Yes --> Give std. name */
- else if (Hptr->hstatus == aliasof)
- host = Hptr->via;
- else if ( Hptr->hostname[0] != '*') /* Ignore wildcards */
- host = Hptr->hostname;
- } /* if */
- } while( Hptr->hstatus == aliasof);
-
- printmsg((input == host) ? 10: 5 ,
- "HostAlias: \"%s\" is alias of \"%s\"",input,host);
- return host;
- } /* HostAlias */
-
- /*--------------------------------------------------------------------*/
- /* H o s t P a t h */
- /* */
- /* Determine the path to a host */
- /*--------------------------------------------------------------------*/
-
- char *HostPath( char *input, char *best)
- {
- size_t loop = 100;
- struct HostTable *Hptr;
- char *host = input;
-
- do {
- Hptr = checkname(host);
- if (Hptr == BADHOST)
- break;
- else {
- if (--loop == 0)
- {
- printmsg(0,"HostPath: Path loop of \"%s\" and \"%s\"",
- host , Hptr->via);
- break;
- } /* if */
- if (Hptr->hstatus == localhost) /* local system? */
- best = nodename;
- else if (Hptr->hstatus == gatewayed) /* Gatewayed? */
- best = Hptr->hostname; /* Yes --> Use name for path */
- else {
- host = Hptr->via;
- if ( checkreal( host ) != BADHOST )
- best = host;
- } /* else */
- } /* else */
- } while( (Hptr->hstatus == aliasof) ||
- (Hptr->hstatus == routed));
-
- printmsg((best == mailserv) ? 10 : 5 ,
- "HostPath: \"%s\" routed via \"%s\"", input, best);
- return best;
- } /* HostPath */
-
- /*--------------------------------------------------------------------*/
- /* E x t r a c t A d d r e s s */
- /* */
- /* Returns the user name (if available and requested or */
- /* E-mail address of the user */
- /* */
- /* Written by ahd 15 July 1989 */
- /*--------------------------------------------------------------------*/
-
- char *ExtractAddress(char *result,
- const char *input ,
- FULLNAME fullname)
- {
- char *nonblank = NULL;
- char *column = (char *) input;
- char name[BUFSIZ]; /* User full name */
- char *nameptr = name;
- char addr[BUFSIZ]; /* User e-mail address */
- char *addrptr = addr;
-
- char state = 'A'; /* State = skip whitespace */
- char newstate = 'A'; /* Next state to process */
- int bananas = 0; /* No () being processed now */
- boolean quoted = FALSE;
-
- /*--------------------------------------------------------------------*/
- /* Begin loop to copy the input field into the address and or the */
- /* user name. We will begin by copying both (ignoring whitespace */
- /* for addresses) because we won't know if the input field is an */
- /* address or a name until we hit either a special character of */
- /* some sort. */
- /*--------------------------------------------------------------------*/
-
- while ((*column != '\0') && (state != ','))
- {
- switch (state) {
- case 'A':
- if (isspace(*column)) /* Found first non-blank? */
- break; /* No --> keep looking */
- nonblank = column;
- state = 'B';
- /* ... and fall through */
- case 'B':
- case ')':
- newstate = *column;
- switch(*column) {
- case '(':
- bananas++;
- break;
-
- case '"':
- break;
-
- case '<':
- addrptr = addr; /* Start address over */
- nameptr = name; /* Start name over again */
- column = nonblank - 1;
- /* Re-scan in new state */
- newstate = '>'; /* Proc all-non <> as name */
- break; /* Begin addr over again */
- case ',':
- break; /* Terminates address */
- case '>':
- case ')':
- printmsg(0,"Invalid RFC-822 address: %s",nonblank);
- panic(); /* Ooops, funky address */
- break;
-
- default:
- newstate = state; /* stay in this state */
- if (!isspace(*column))
- *(addrptr++) = *column;
- } /* switch(*column) */
- break;
-
- case '<': if (*column == '>')
- newstate = '>';
- else if (!isspace(*column))
- *(addrptr++) = *column;
- break;
-
- case '>': if (*column == '<')
- newstate = '<';
- else switch( *column )
- {
- case ')':
- if (quoted)
- *(nameptr++) = *column;
- else
- bananas--;
- break;
-
- case '(':
- if (quoted)
- *(nameptr++) = *column;
- else
- bananas++;
- break;
-
- case '"':
- if (bananas == 0)
- {
- quoted = !quoted;
- break;
- }
- /* else fall through */
-
- default:
- *(nameptr++) = *column;
- } /* switch */
- break;
-
- case '(': if (*column == '(')
- ++bananas;
- else if (*column == ')')
- {
- if (--bananas == 0)
- {
- newstate = ')';
- break;
- }
- }
- else
- *(nameptr++) = *column;
- break;
-
- case '"': if (*column == '"')
- newstate = ')';
- else
- *(nameptr++) = *column;
-
- break;
-
- default: panic();
- /* Logic error, bad state */
- break;
-
- } /* switch (state) */
- state = newstate;
- column++;
- } /* while */
-
-
- /*--------------------------------------------------------------------*/
- /* Verify we retrieved an address */
- /*--------------------------------------------------------------------*/
-
- if (state == 'A')
- {
- printmsg(0, "ExtractAddress: Could find not address in \"%s\"",
- column);
- panic();
- }
-
- /*--------------------------------------------------------------------*/
- /* Fill in the results for the caller */
- /*--------------------------------------------------------------------*/
-
- *addrptr = '\0';
- *nameptr = '\0';
- *result = '\0';
- if ((fullname == ADDRESSONLY) ||
- ((fullname == FULLADDRESS) && (state == 'B')))
- strcpy(result,addr); /* Return the full address */
- else if (state != 'B')
- {
- while (--nameptr >= name)
- {
- if (isspace(*nameptr))
- *nameptr = '\0';
- else
- break;
- }
-
- /*--------------------------------------------------------------------*/
- /* Strip leading blanks from the address */
- /*--------------------------------------------------------------------*/
-
- nameptr = name;
- while (isspace(*nameptr))
- nameptr++;
- if ( fullname == FULLADDRESS )
- sprintf( result , "\"%s\" <%s>", nameptr, addr );
- else
- strcpy(result,nameptr);
- } /* else */
-
- printmsg(4,"ExtractAddress: %s into <%s> \"%s\"",
- nonblank,addr,(fullname) ? result : name);
-
- /*--------------------------------------------------------------------*/
- /* Return the position of the next address, if any, to the caller */
- /*--------------------------------------------------------------------*/
-
- if ( *column == '\0')
- return NULL;
- else
- return column + 1;
-
- } /*ExtractAddress*/
-