]> diplodocus.org Git - nmh/blobdiff - sbr/addrsbr.c
Fix invalid pointer arithmetic.
[nmh] / sbr / addrsbr.c
index 484ec5ef64572c8c6c4f9789aacd429a2241ab2f..eadf1d07443e71a1bc3399e33b4181d3017cd0a5 100644 (file)
@@ -1,6 +1,4 @@
-
-/*
- * addrsbr.c -- parse addresses 822-style
+/* addrsbr.c -- parse addresses 822-style
  *
  * This code is Copyright (c) 2002, by the authors of nmh.  See the
  * COPYRIGHT file in the root directory of the nmh distribution for
@@ -10,6 +8,8 @@
 #include <h/mh.h>
 #include <h/addrsbr.h>
 #include <h/mf.h>
+#include <h/mts.h>
+#include <h/utils.h>
 
 /* High level parsing of addresses:
 
    addresses.  The routines in sbr/addrsbr.c associate semantics with those
    addresses.  
 
+   The comments below are left in for historical purposes; DUMB and
+   REALLYDUMB are now the default in the code.
+
    If #ifdef DUMB is in effect, a full 822-style parser is called
-   for syntax recongition.  This breaks each address into its components.
+   for syntax recognition.  This breaks each address into its components.
    Note however that no semantics are assumed about the parts or their
    totality.  This means that implicit hostnames aren't made explicit,
-   and explicit hostnames aren't expanded to their "official" represenations.
+   and explicit hostnames aren't expanded to their "official" representations.
 
    If DUMB is not in effect, then this module does some
    high-level thinking about what the addresses are.
@@ -44,7 +47,7 @@
 
    If an explicit host is not present, then MH checks for a bang to indicate
    an explicit UUCP-style address.  If so, this is noted.  If not, the host is
-   defaulted, typically to the local host.  The lack of an explict host is
+   defaulted, typically to the local host.  The lack of an explicit host is
    also noted.
 
    If an explicit 822-style host is present, then MH checks to see if it
@@ -71,27 +74,24 @@ static char *grp = NULL;
 static char *note = NULL;
 static char err[BUFSIZ];
 static char adr[BUFSIZ];
+static int eai = 0;
 
-
-extern boolean  username_extension_masquerading;  /* defined in mts.c */
-
-
-/*
- * external prototypes
- */
-char *getusername (void);
+void
+enable_eai(void) {
+    eai = 1;
+}
 
 
 char *
-getname (char *addrs)
+getname (const char *addrs)
 {
     struct adrx *ap;
-
     pers = mbox = host = route = grp = note = NULL;
     err[0] = '\0';
 
-    if ((ap = getadrx (addrs ? addrs : "")) == NULL)
+    if ((ap = getadrx (FENDNULL(addrs), eai)) == NULL) {
        return NULL;
+    }
 
     strncpy (adr, ap->text, sizeof(adr));
     pers = ap->pers;
@@ -109,60 +109,45 @@ getname (char *addrs)
 
 
 struct mailname *
-getm (char *str, char *dfhost, int dftype, int wanthost, char *eresult)
+getm (char *str, char *dfhost, int dftype, char *eresult, size_t eresultsize)
 {
     char *pp;
     struct mailname *mp;
-#ifndef        DUMB
-    char *dp;
-#endif /* not DUMB */
 
     if (err[0]) {
-       if (eresult)
-           strcpy (eresult, err);
-       else
-           if (wanthost == AD_HOST)
-               admonish (NULL, "bad address '%s' - %s", str, err);
+       if (eresult) {
+           strncpy (eresult, err, eresultsize);
+           eresult[eresultsize - 1] = '\0';
+       }
        return NULL;
     }
     if (pers == NULL
            && mbox == NULL && host == NULL && route == NULL
            && grp == NULL) {
-       if (eresult)
-           strcpy (eresult, "null address");
-       else
-           if (wanthost == AD_HOST)
-               admonish (NULL, "null address '%s'", str);
+       if (eresult) {
+           strncpy (eresult, "null address", eresultsize);
+           eresult[eresultsize - 1] = '\0';
+       }
        return NULL;
     }
     if (mbox == NULL && grp == NULL) {
-       if (eresult)
-           strcpy (eresult, "no mailbox in address");
-       else
-           if (wanthost == AD_HOST)
-               admonish (NULL, "no mailbox in address '%s'", str);
+       if (eresult) {
+           strncpy (eresult, "no mailbox in address", eresultsize);
+           eresult[eresultsize - 1] = '\0';
+       }
        return NULL;
     }
 
     if (dfhost == NULL) {
-       dfhost = LocalName ();
+       dfhost = LocalName (0);
        dftype = LOCALHOST;
     }
 
-    mp = (struct mailname *) calloc ((size_t) 1, sizeof(*mp));
-    if (mp == NULL) {
-       if (eresult)
-          strcpy (eresult, "insufficient memory to represent address");
-       else
-           if (wanthost == AD_HOST)
-               adios (NULL, "insufficient memory to represent address");
-       return NULL;
-    }
-
+    NEW0(mp);
     mp->m_next = NULL;
     mp->m_text = getcpy (str);
     if (pers)
-       mp->m_pers = getcpy (pers);
+       mp->m_pers = mh_xstrdup(pers);
 
     if (mbox == NULL) {
        mp->m_type = BADHOST;
@@ -170,72 +155,44 @@ getm (char *str, char *dfhost, int dftype, int wanthost, char *eresult)
        mp->m_ingrp = ingrp;
        mp->m_gname = getcpy (grp);
        if (note)
-           mp->m_note = getcpy (note);
+           mp->m_note = mh_xstrdup(note);
        return mp;
     }
 
     if (host) {
        mp->m_mbox = getcpy (mbox);
-       mp->m_host = getcpy (host);
-    }
-    else {
+       mp->m_host = mh_xstrdup(host);
+       mp->m_type =
+           strcasecmp (LocalName(0), mp->m_host) ? NETHOST : LOCALHOST;
+    } else {
        if ((pp = strchr(mbox, '!'))) {
            *pp++ = '\0';
-           mp->m_mbox = getcpy (pp);
+           mp->m_mbox = mh_xstrdup(pp);
            mp->m_host = getcpy (mbox);
            mp->m_type = UUCPHOST;
-       }
-       else {
+       } else {
            mp->m_nohost = 1;
            mp->m_mbox = getcpy (mbox);
-#ifdef DUMB
            if (route == NULL && dftype == LOCALHOST) {
                mp->m_host = NULL;
                mp->m_type = dftype;
-           }
-           else
-#endif /* DUMB */
-           {
+           } else {
                mp->m_host = route ? NULL : getcpy (dfhost);
                mp->m_type = route ? NETHOST : dftype;
            }
        }
-       goto got_host;
     }
 
-    if (wanthost == AD_NHST)
-       mp->m_type = !mh_strcasecmp (LocalName (), mp->m_host)
-           ? LOCALHOST : NETHOST;
-#ifdef DUMB
-    else
-       mp->m_type = mh_strcasecmp (LocalName(), mp->m_host) ?  NETHOST : LOCALHOST;
-#else /* not DUMB */
-    else
-       if (pp = OfficialName (mp->m_host)) {
-    got_real_host: ;
-           free (mp->m_host);
-           mp->m_host = getcpy (pp);
-           mp->m_type = mh_strcasecmp (LocalName(), mp->m_host) ? NETHOST : LOCALHOST;
-       }
-       else {
-           if (dp = strchr(mp->m_host, '.')) {
-               *dp = NULL;
-               if (pp = OfficialName (mp->m_host))
-                   goto got_real_host;
-               *dp = '.';
-           }
-           mp->m_type = BADHOST;
-       }
-#endif /* not DUMB */
+    /* For alternate mailboxes, m_type gets overwritten in ismymbox ()
+       to support wild-card matching. */
 
-got_host: ;
     if (route)
-       mp->m_path = getcpy (route);
+       mp->m_path = mh_xstrdup(route);
     mp->m_ingrp = ingrp;
     if (grp)
-       mp->m_gname = getcpy (grp);
+       mp->m_gname = mh_xstrdup(grp);
     if (note)
-       mp->m_note = getcpy (note);
+       mp->m_note = mh_xstrdup(note);
 
     return mp;
 }
@@ -247,26 +204,17 @@ mnfree (struct mailname *mp)
     if (!mp)
        return;
 
-    if (mp->m_text)
-       free (mp->m_text);
-    if (mp->m_pers)
-       free (mp->m_pers);
-    if (mp->m_mbox)
-       free (mp->m_mbox);
-    if (mp->m_host)
-       free (mp->m_host);
-    if (mp->m_path)
-       free (mp->m_path);
-    if (mp->m_gname)
-       free (mp->m_gname);
-    if (mp->m_note)
-       free (mp->m_note);
-
-    free ((char *) mp);
-}
+    free(mp->m_text);
+    free(mp->m_pers);
+    free(mp->m_mbox);
+    free(mp->m_host);
+    free(mp->m_path);
+    free(mp->m_gname);
+    free(mp->m_note);
 
+    free(mp);
+}
 
-#define empty(s) ((s) ? (s) : "")
 
 char *
 auxformat (struct mailname *mp, int extras)
@@ -274,18 +222,15 @@ auxformat (struct mailname *mp, int extras)
     static char addr[BUFSIZ];
     static char buffer[BUFSIZ];
 
-#ifdef DUMB
        if (mp->m_nohost)
-           strncpy (addr, mp->m_mbox ? mp->m_mbox : "", sizeof(addr));
-       else
-#endif /* DUMB */
-
-#ifndef        BANG
-       if (mp->m_type != UUCPHOST)
-           snprintf (addr, sizeof(addr), mp->m_host ? "%s%s@%s" : "%s%s",
-               empty(mp->m_path), empty(mp->m_mbox), mp->m_host);
-       else
-#endif /* not BANG */
+           strncpy (addr, FENDNULL(mp->m_mbox), sizeof(addr));
+       else if (mp->m_type != UUCPHOST) {
+           if (mp->m_host)
+               snprintf (addr, sizeof(addr), "%s%s@%s", FENDNULL(mp->m_path),
+                         FENDNULL(mp->m_mbox), mp->m_host);
+           else snprintf (addr, sizeof(addr), "%s%s", FENDNULL(mp->m_path),
+                          FENDNULL(mp->m_mbox));
+       } else
            snprintf (addr, sizeof(addr), "%s!%s", mp->m_host, mp->m_mbox);
 
     if (!extras)
@@ -300,75 +245,15 @@ auxformat (struct mailname *mp, int extras)
            snprintf (buffer, sizeof(buffer), "%s <%s>",
                    legal_person (mp->m_pers ? mp->m_pers : mp->m_mbox),
                    addr);
-    }
+    } else if (mp->m_note)
+        snprintf (buffer, sizeof(buffer), "%s %s", addr, mp->m_note);
     else
-       if (mp->m_note)
-           snprintf (buffer, sizeof(buffer), "%s %s", addr, mp->m_note);
-       else
-           strncpy (buffer, addr, sizeof(buffer));
+        strncpy (buffer, addr, sizeof(buffer));
 
     return buffer;
 }
 
 
-/*
- * address specific "sprintf"
- */
-
-char *
-adrsprintf (char *username, char *domain)
-{
-    int          snprintf_return;
-    static char  addr[BUFSIZ];
-
-    if (username == NULL)
-       username = getusername();
-
-    if (username_extension_masquerading) {
-       /* mts.conf contains "masquerade:[...]username_extension[...]", so tack
-          on the value of the $USERNAME_EXTENSION environment variable, if set,
-          to username. */
-       char*        extension = getenv("USERNAME_EXTENSION");
-       static char  username_with_extension[BUFSIZ];
-
-       if (extension != NULL && *extension != '\0') {
-           snprintf_return = snprintf(username_with_extension,
-                                      sizeof(username_with_extension),
-                                      "%s%s", username, extension);
-           
-           if (snprintf_return < 0 ||
-               snprintf_return >= sizeof(username_with_extension))
-               adios(NULL, "snprintf() error writing username (%d chars) and"
-                     " $USERNAME_EXTENSION (%d chars) to array of BUFSIZ (%d)"
-                     " chars",
-                     strlen(username), strlen(extension), BUFSIZ);
-           
-           username = username_with_extension;
-       }
-    }
-
-#ifdef REALLYDUMB
-    return username;
-#endif
-
-    if (domain == NULL)
-       domain = LocalName();
-
-#ifndef        BANG
-    snprintf_return = snprintf (addr, sizeof(addr), "%s@%s", username, domain);
-#else /* BANG */
-    snprintf_return = snprintf (addr, sizeof(addr), "%s!%s", domain, username);
-#endif /* BANG */
-
-    if (snprintf_return < 0 || snprintf_return >= sizeof(addr))
-       adios(NULL, "snprintf() error writing username (%d chars), domain (%d"
-             " chars), and 1 separator char to array of BUFSIZ (%d) chars",
-             strlen(username), strlen(domain), BUFSIZ);
-    
-    return addr;
-}
-
-
 #define        W_NIL   0x0000
 #define        W_MBEG  0x0001
 #define        W_MEND  0x0002
@@ -382,17 +267,18 @@ adrsprintf (char *username, char *domain)
  * Check if this is my address
  */
 
-int
+bool
 ismymbox (struct mailname *np)
 {
     int oops;
-    register int len, i;
-    register char *cp;
-    register char *pp;
+    int len, i;
+    char *cp;
+    char *pp;
     char buffer[BUFSIZ];
     struct mailname *mp;
     static char *am = NULL;
-    static struct mailname mq={NULL};
+    static struct mailname mq;
+    static int localmailbox = 0;
 
     /*
      * If this is the first call, initialize
@@ -401,14 +287,35 @@ ismymbox (struct mailname *np)
     if (am == NULL) {
        mq.m_next = NULL;
        mq.m_mbox = getusername ();
+
+       if ((am = context_find ("local-mailbox"))) {
+
+           localmailbox++;
+
+           if ((cp = getname(am)) == NULL) {
+               inform("Unable to find address in local-mailbox, continuing...");
+               return false;
+           }
+
+           if ((mq.m_next = getm (cp, NULL, 0, NULL, 0)) == NULL) {
+                inform("invalid entry in local-mailbox: %s, continuing...", cp);
+               return false;
+           }
+
+           /* Sigh, it turns out that the address parser gets messed up
+            * if you don't call getname() until it returns NULL. */
+           while (getname(am) != NULL)
+               ;
+       }
+
        if ((am = context_find ("alternate-mailboxes")) == NULL)
            am = getusername();
        else {
-           mp = &mq;
+           mp = mq.m_next ? mq.m_next : &mq;
            oops = 0;
            while ((cp = getname (am))) {
-               if ((mp->m_next = getm (cp, NULL, 0, AD_NAME, NULL)) == NULL) {
-                   admonish (NULL, "illegal address: %s", cp);
+               if ((mp->m_next = getm (cp, NULL, 0, NULL, 0)) == NULL) {
+                   inform("illegal address: %s, continuing...", cp);
                    oops++;
                } else {
                    mp = mp->m_next;
@@ -431,40 +338,53 @@ ismymbox (struct mailname *np)
                            *cp = '\0';
                        }
                    }
-                   if ((cp = getenv ("MHWDEBUG")) && *cp)
-                       fprintf (stderr, "mbox=\"%s\" host=\"%s\" %s\n",
-                           mp->m_mbox, mp->m_host,
-                           snprintb (buffer, sizeof(buffer), (unsigned) mp->m_type, WBITS));
                }
            }
            if (oops)
-               advise (NULL, "please fix the %s: entry in your %s file",
+               inform("please fix the %s: entry in your %s file",
                        "alternate-mailboxes", mh_profile);
        }
+
+       if ((cp = getenv ("MHWDEBUG")) && *cp) {
+           for (mp = &mq; mp; mp = mp->m_next) {
+             fprintf (stderr, "Local- or Alternate-Mailbox: text=\"%s\" "
+                      "mbox=\"%s\" host=\"%s\" %s\n",
+                      FENDNULL(mp->m_text), mp->m_mbox,
+                      FENDNULL(mp->m_host),
+                      snprintb (buffer, sizeof(buffer), (unsigned) mp->m_type,
+                                WBITS));
+           }
+       }
     }
 
     if (np == NULL) /* XXX */
-       return 0;
+       return false;
     
-    switch (np->m_type) {
-       case NETHOST:
-           len = strlen (cp = LocalName ());
-           if (!uprf (np->m_host, cp) || np->m_host[len] != '.')
-               break;
-           goto local_test;
+    /*
+     * Don't perform this "local" test if we have a Local-Mailbox set
+     */
 
-       case UUCPHOST:
-           if (mh_strcasecmp (np->m_host, SystemName()))
-               break;          /* fall */
-       case LOCALHOST:
+    if (! localmailbox)
+       switch (np->m_type) {
+           case NETHOST:
+               len = strlen (cp = LocalName (0));
+               if (!uprf (np->m_host, cp) || np->m_host[len] != '.')
+                   break;
+               goto local_test;
+
+           case UUCPHOST:
+               if (strcasecmp (np->m_host, SystemName()))
+                   break;
+                   /* FALLTHRU */
+           case LOCALHOST:
 local_test: ;
-           if (!mh_strcasecmp (np->m_mbox, mq.m_mbox))
-               return 1;
-           break;
+               if (!strcasecmp (np->m_mbox, mq.m_mbox))
+                   return true;
+               break;
 
-       default:
-           break;
-    }
+           default:
+               break;
+       }
 
     /*
      * Now scan through list of alternate
@@ -474,16 +394,16 @@ local_test: ;
        mp = mp->m_next;
        if (!np->m_mbox)
            continue;
-       if ((len = strlen (cp = np->m_mbox))
+        if ((len = strlen (cp = np->m_mbox))
                < (i = strlen (pp = mp->m_mbox)))
            continue;
        switch (mp->m_type & W_MBOX) {
            case W_NIL: 
-               if (mh_strcasecmp (cp, pp))
+               if (strcasecmp (cp, pp))
                    continue;
                break;
            case W_MBEG: 
-               if (mh_strcasecmp (cp + len - i, pp))
+               if (strcasecmp (cp + len - i, pp))
                    continue;
                break;
            case W_MEND: 
@@ -497,19 +417,19 @@ local_test: ;
        }
 
        if (mp->m_nohost)
-           return 1;
-       if (np->m_host == NULL)
+           return true;
+       if (np->m_host == NULL || mp->m_host == NULL)
            continue;
        if ((len = strlen (cp = np->m_host))
                < (i = strlen (pp = mp->m_host)))
            continue;
        switch (mp->m_type & W_HOST) {
            case W_NIL: 
-               if (mh_strcasecmp (cp, pp))
+               if (strcasecmp (cp, pp))
                    continue;
                break;
            case W_HBEG: 
-               if (mh_strcasecmp (cp + len - i, pp))
+               if (strcasecmp (cp + len - i, pp))
                    continue;
                break;
            case W_HEND: 
@@ -521,8 +441,8 @@ local_test: ;
                    continue;
                break;
        }
-       return 1;
+       return true;
     }
 
-    return 0;
+    return false;
 }