X-Git-Url: http://git.marmaro.de/?a=blobdiff_plain;f=sbr%2Fmts.c;h=bf7d42b1a1c5025117ebf3dabe38e9ca19d41a79;hb=374ece2e88368afd6e0a29c4ee4b75ffa9e28b39;hp=de7518c017387ee36448416d90fdbbe5c72789c7;hpb=7b98850d3b8b2453b473fdfb6db52f4aa3fe39b6;p=mmh diff --git a/sbr/mts.c b/sbr/mts.c index de7518c..bf7d42b 100644 --- a/sbr/mts.c +++ b/sbr/mts.c @@ -2,8 +2,6 @@ /* * mts.c -- definitions for the mail transport system * - * $Id$ - * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. @@ -19,20 +17,17 @@ #include #include #include +#include #include -#ifdef HAVE_SYS_UTSNAME_H -# include -#endif - -#define NOTOK (-1) -#define OK 0 - /* * static prototypes */ static char *tailor_value (unsigned char *); static void getuserinfo (void); +static const char *get_mtsconf_pathname(void); +static const char *get_mtsuserconf_pathname(void); +static void mts_read_conf_file (FILE *fp); /* * *mmdfldir and *uucpldir are the maildrop directories. If maildrops @@ -59,49 +54,26 @@ char *uucplfil = ""; char *mmdlm1 = "\001\001\001\001\n"; char *mmdlm2 = "\001\001\001\001\n"; -/* Cache the username and fullname of the user */ +/* Cache the username, fullname, and mailbox of the user */ static char username[BUFSIZ]; static char fullname[BUFSIZ]; - -/* Variables for username masquerading: */ - boolean draft_from_masquerading = FALSE; /* also used from post.c */ -static boolean mmailid_masquerading = FALSE; - boolean username_extension_masquerading = FALSE; /* " from addrsbr.c */ -static char* masquerade = ""; +static char localmbox[BUFSIZ]; /* * MTS specific variables */ -#if defined(SMTPMTS) -static char *sm_method = "smtp"; -int sm_mts = MTS_SMTP; -char *hostable = nmhetcdir(/hosts); +static char *mts_method = "smtp"; +int sm_mts = MTS_SENDMAIL_SMTP; char *sendmail = SENDMAILPATH; -#endif /* * SMTP/POP stuff */ char *clientname = NULL; -char *servers = "localhost \01localnet"; +char *servers = "localhost"; char *pophost = ""; /* - * BBoards-specific variables - */ -char *bb_domain = ""; - - -/* - * POP BBoards-specific variables - */ -#ifdef BPOP -char *popbbhost = ""; -char *popbbuser = ""; -char *popbblist = nmhetcdir(/hosts.popbb); -#endif /* BPOP */ - -/* * Global MailDelivery file */ char *maildelivery = nmhetcdir(/maildelivery); @@ -134,28 +106,11 @@ static struct bind binds[] = { { "uucplfil", &uucplfil }, { "mmdelim1", &mmdlm1 }, { "mmdelim2", &mmdlm2 }, - { "masquerade", &masquerade }, - -#if defined(SMTPMTS) - { "mts", &sm_method }, - { "hostable", &hostable }, + { "mts", &mts_method }, { "sendmail", &sendmail }, -#endif - { "clientname", &clientname }, { "servers", &servers }, { "pophost", &pophost }, - { "bbdomain", &bb_domain }, - -#ifdef BPOP - { "popbbhost", &popbbhost }, - { "popbbuser", &popbbuser }, - { "popbblist", &popbblist }, -#endif - -#ifdef NNTP - { "nntphost", &popbbhost }, -#endif { "maildelivery", &maildelivery }, { "everyone", &everyone }, @@ -164,6 +119,25 @@ static struct bind binds[] = { }; +/* Convert name of mts method to integer value and store it. */ +void +save_mts_method (const char *value) { + if (! mh_strcasecmp (value, "smtp")) { + mts_method = "smtp"; + sm_mts = MTS_SMTP; + } else if (! mh_strcasecmp (value, "sendmail/smtp") || + ! mh_strcasecmp (value, "sendmail")) { + mts_method = "sendmail/smtp"; + sm_mts = MTS_SENDMAIL_SMTP; + } else if (! mh_strcasecmp (value, "sendmail/pipe")) { + mts_method = "sendmail/pipe"; + sm_mts = MTS_SENDMAIL_PIPE; + } else { + adios (NULL, "unsupported mts selection \"%s\"", value); + } +} + + /* * Read the configuration file for the nmh interface * to the mail transport system (MTS). @@ -172,57 +146,26 @@ static struct bind binds[] = { void mts_init (char *name) { - unsigned char *bp; - char *cp, buffer[BUFSIZ]; - struct bind *b; + const char *cp; FILE *fp; static int inited = 0; + NMH_UNUSED (name); - if (inited++ || (fp = fopen (mtsconf, "r")) == NULL) + if (inited++ || (fp = fopen (get_mtsconf_pathname(), "r")) == NULL) return; + mts_read_conf_file(fp); + fclose (fp); - while (fgets (buffer, sizeof(buffer), fp)) { - if (!(cp = strchr(buffer, '\n'))) - break; - *cp = 0; - if (*buffer == '#' || *buffer == '\0') - continue; - if (!(bp = strchr(buffer, ':'))) - break; - *bp++ = 0; - while (isspace (*bp)) - *bp++ = 0; - - for (b = binds; b->keyword; b++) - if (!strcmp (buffer, b->keyword)) - break; - if (b->keyword && (cp = tailor_value (bp))) - *b->value = cp; + cp = get_mtsuserconf_pathname(); + if (cp != NULL && + ((fp = fopen (get_mtsuserconf_pathname(), "r")) != NULL)) { + mts_read_conf_file(fp); + fclose (fp); } - fclose (fp); - Everyone = atoi (everyone); - if (strstr(masquerade, "draft_from") != NULL) - draft_from_masquerading = TRUE; - - if (strstr(masquerade, "mmailid") != NULL) - mmailid_masquerading = TRUE; - - if (strstr(masquerade, "username_extension") != NULL) - username_extension_masquerading = TRUE; - -#ifdef SMTPMTS - if (strcmp(sm_method, "smtp") == 0) - sm_mts = MTS_SMTP; - else if (strcmp(sm_method, "sendmail") == 0) - sm_mts = MTS_SENDMAIL; - else { - advise(NULL, "unsupported \"mts\" value in mts.conf: %s", sm_method); - sm_mts = MTS_SMTP; - } -#endif + save_mts_method (mts_method); } @@ -281,43 +224,45 @@ tailor_value (unsigned char *s) /* * Get the fully qualified name of the local host. + * + * If flag is 0, then use anything out of mts.conf (like localname). + * If flag is 1, then only use the "proper" local hostname. */ char * -LocalName (void) +LocalName (int flag) { - static char buffer[BUFSIZ] = ""; + static char buffer0[BUFSIZ] = ""; + static char buffer1[BUFSIZ] = ""; + static char *buffer[] = { buffer0, buffer1 }; + char *buf; struct addrinfo hints, *res; -#ifdef HAVE_UNAME - struct utsname name; -#endif + + if (flag < 0 || flag > 1) + return NULL; + + buf = buffer[flag]; /* check if we have cached the local name */ - if (buffer[0]) - return buffer; + if (buf[0]) + return buf; mts_init ("mts"); /* check if the mts.conf file specifies a "localname" */ - if (*localname) { - strncpy (buffer, localname, sizeof(buffer)); + if (*localname && flag == 0) { + strncpy (buf, localname, sizeof(buffer0)); } else { - memset(buffer, 0, sizeof(buffer)); -#ifdef HAVE_UNAME - /* first get our local name */ - uname (&name); - strncpy (buffer, name.nodename, sizeof(buffer) - 1); -#else + memset(buf, 0, sizeof(buffer0)); /* first get our local name */ - gethostname (buffer, sizeof(buffer) - 1); -#endif + gethostname (buf, sizeof(buffer0) - 1); /* now fully qualify our name */ memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_CANONNAME; hints.ai_family = PF_UNSPEC; - if (getaddrinfo(buffer, NULL, &hints, &res) == 0) { - strncpy(buffer, res->ai_canonname, sizeof(buffer) - 1); + if (getaddrinfo(buf, NULL, &hints, &res) == 0) { + strncpy(buf, res->ai_canonname, sizeof(buffer0) - 1); freeaddrinfo(res); } } @@ -327,11 +272,11 @@ LocalName (void) * we append that now. This should rarely be needed. */ if (*localdomain) { - strcat (buffer, "."); - strcat (buffer, localdomain); + strcat (buf, "."); + strcat (buf, localdomain); } - return buffer; + return buf; } @@ -345,10 +290,6 @@ SystemName (void) { static char buffer[BUFSIZ] = ""; -#ifdef HAVE_UNAME - struct utsname name; -#endif - /* check if we have cached the system name */ if (buffer[0]) return buffer; @@ -361,12 +302,7 @@ SystemName (void) return buffer; } -#ifdef HAVE_UNAME - uname (&name); - strncpy (buffer, name.nodename, sizeof(buffer)); -#else gethostname (buffer, sizeof(buffer)); -#endif return buffer; } @@ -402,9 +338,22 @@ getfullname (void) /* + * Get the full local mailbox name. This is in the form: + * + * User Name + */ + +char * +getlocalmbox (void) +{ + if (username[0] == '\0') + getuserinfo(); + + return localmbox; +} + +/* * Find the user's username and full name, and cache them. - * Also, handle "mmailid" username masquerading controlled from the GECOS field - * of the passwd file. */ static void @@ -414,118 +363,124 @@ getuserinfo (void) register char *np; register struct passwd *pw; -#ifdef KPOP - uid_t uid; - - uid = getuid (); - if (uid == geteuid () && (cp = getenv ("USER")) != NULL - && (pw = getpwnam (cp)) != NULL) - strncpy (username, cp, sizeof(username)); - else if ((pw = getpwuid (uid)) == NULL - || pw->pw_name == NULL - || *pw->pw_name == '\0') { -#else /* KPOP */ if ((pw = getpwuid (getuid ())) == NULL || pw->pw_name == NULL || *pw->pw_name == '\0') { -#endif /* KPOP */ strncpy (username, "unknown", sizeof(username)); snprintf (fullname, sizeof(fullname), "The Unknown User-ID (%d)", (int) getuid ()); return; } - np = pw->pw_gecos; - /* Get the user's real name from the GECOS field. Stop once we hit a ',', - which some OSes use to separate other 'finger' information in the GECOS - field, like phone number. Also, if mmailid masquerading is turned on due - to "mmailid" appearing on the "masquerade:" line of mts.conf, stop if we - hit a '<' (which should precede any ','s). */ -#ifndef BSD42 - if (mmailid_masquerading) - /* Stop at ',' or '<'. */ - for (cp = fullname; *np != '\0' && *np != ',' && *np != '<'; - *cp++ = *np++) - continue; - else - /* Allow '<' as a legal character of the user's name. This code is - basically a duplicate of the code above the "else" -- we don't - collapse it down to one copy and put the mmailid_masquerading check - inside the loop with "(x ? y : z)" because that's inefficient and the - value'll never change while it's in there. */ - for (cp = fullname; *np != '\0' && *np != ','; - *cp++ = *np++) - continue; -#else /* BSD42 */ - /* On BSD(-derived) systems, the system utilities that deal with the GECOS - field (finger, mail, sendmail, etc.) translate any '&' character in it to - the login name, with the first letter capitalized. So, for instance, - fingering a user "bob" with the GECOS field "& Jones" would reveal him to - be "In real life: Bob Jones". Surprisingly, though, the OS doesn't do - the translation for you, so we have to do it manually here. */ - if (mmailid_masquerading) - /* Stop at ',' or '<'. */ - for (cp = fullname; - *np != '\0' && *np != ',' && *np != '<';) { - if (*np == '&') { /* blech! */ - strcpy (cp, pw->pw_name); - *cp = toupper(*cp); - while (*cp) - cp++; - np++; - } else { - *cp++ = *np++; - } - } - else - /* Allow '<' as a legal character of the user's name. This code is - basically a duplicate of the code above the "else" -- we don't - collapse it down to one copy and put the mmailid_masquerading check - inside the loop with "(x ? y : z)" because that's inefficient and the - value'll never change while it's in there. */ - for (cp = fullname; - *np != '\0' && *np != ',';) { - if (*np == '&') { /* blech! */ - strcpy (cp, pw->pw_name); - *cp = toupper(*cp); - while (*cp) - cp++; - np++; - } else { - *cp++ = *np++; + /* username */ + /* If there's a Local-Mailbox profile component, try to extract + the username from it. But don't try very hard, this assumes + the very simple User Name form. + Note that post(8) and whom(1) use context_foil (), so they + won't see the profile component. */ + if ((np = context_find("Local-Mailbox")) != NULL) { + char *left_angle_bracket = strchr (np, '<'); + char *at_sign = strchr (np, '@'); + char *right_angle_bracket = strchr (np, '>'); + + strncpy(localmbox, np, sizeof(localmbox)); + + if (left_angle_bracket && at_sign && right_angle_bracket) { + if (at_sign > left_angle_bracket && + at_sign - left_angle_bracket < BUFSIZ) { + strncpy(username, left_angle_bracket + 1, + at_sign - left_angle_bracket - 1); } } -#endif /* BSD42 */ - *cp = '\0'; - - if (mmailid_masquerading) { - /* Do mmailid processing. The GECOS field should have the form - "Full Name ". For instance, - "Dan Harkless ". Naturally, you'll want your MTA to - have an alias (e.g. in /etc/aliases) from "fakeusername" to your - account name. */ - if (*np) - np++; - for (cp = username; *np && *np != '>'; *cp++ = *np++) - continue; - *cp = '\0'; } - if (!mmailid_masquerading || *np == '\0') + + if (username[0] == '\0') { strncpy (username, pw->pw_name, sizeof(username)); + } + + username[sizeof(username) - 1] = '\0'; + + escape_local_part(username, sizeof(username)); + + + /* fullname */ + np = pw->pw_gecos; + + /* Get the user's real name from the GECOS field. Stop once we hit a ',', + which some OSes use to separate other 'finger' information in the GECOS + field, like phone number. */ + for (cp = fullname; *np != '\0' && *np != ','; *cp++ = *np++) + continue; + *cp = '\0'; /* The $SIGNATURE environment variable overrides the GECOS field's idea of - your real name. */ + your real name. If SIGNATURE isn't set, use the Signature profile + setting if it exists. + Note that post(8) and whom(1) use context_foil (), so they + won't see the profile component. */ if ((cp = getenv ("SIGNATURE")) && *cp) strncpy (fullname, cp, sizeof(fullname)); + else if ((cp = context_find("Signature"))) + strncpy (fullname, cp, sizeof(fullname)); + + fullname[sizeof(fullname) - 1] = '\0'; - if (strchr(fullname, '.')) { /* quote any .'s */ - char tmp[BUFSIZ]; + escape_display_name(fullname, sizeof(fullname)); - /* should quote "'s too */ - snprintf (tmp, sizeof(tmp), "\"%s\"", fullname); - strncpy (fullname, tmp, sizeof(fullname)); + + /* localmbox, if not using Local-Mailbox */ + if (localmbox[0] == '\0') { + snprintf(localmbox, sizeof(localmbox), "%s <%s@%s>", fullname, + username, LocalName(0)); } - return; + localmbox[sizeof(localmbox) - 1] = '\0'; +} + +static const char* +get_mtsconf_pathname (void) +{ + const char *cp = getenv ( "MHMTSCONF" ); + if (cp != NULL && *cp != '\0') { + return cp; + } + return mtsconf; +} + +static const char* +get_mtsuserconf_pathname (void) +{ + const char *cp = getenv ( "MHMTSUSERCONF" ); + if (cp != NULL && *cp != '\0') { + return cp; + } + return NULL; +} + +static void +mts_read_conf_file (FILE *fp) +{ + unsigned char *bp; + char *cp, buffer[BUFSIZ]; + struct bind *b; + + while (fgets (buffer, sizeof(buffer), fp)) { + if (!(cp = strchr(buffer, '\n'))) + break; + *cp = 0; + if (*buffer == '#' || *buffer == '\0') + continue; + if (!(bp = strchr(buffer, ':'))) + break; + *bp++ = 0; + while (isspace (*bp)) + *bp++ = 0; + + for (b = binds; b->keyword; b++) + if (!strcmp (buffer, b->keyword)) + break; + if (b->keyword && (cp = tailor_value (bp))) + *b->value = cp; + } }