X-Git-Url: http://git.marmaro.de/?a=blobdiff_plain;f=mts%2Fgeneric%2Fmts.c;fp=mts%2Fgeneric%2Fmts.c;h=7d9b718d108cf773777e901735660a64032868c1;hb=75e073ea52a427394690e0c1ef7943a1727c7095;hp=0000000000000000000000000000000000000000;hpb=e2d7f42498f9cb8cb4b0f4ddd7fcd395829157f2;p=mmh diff --git a/mts/generic/mts.c b/mts/generic/mts.c new file mode 100644 index 0000000..7d9b718 --- /dev/null +++ b/mts/generic/mts.c @@ -0,0 +1,523 @@ + +/* + * mts.c -- definitions for the mail transport system + * + * $Id$ + */ + +#include "h/mh.h" /* for snprintf() */ +#include + +#define nmhetcdir(file) NMHETCDIR#file + +#include +#include +#include +#include +#include + +#ifdef HAVE_SYS_UTSNAME_H +# include +#endif + +#define NOTOK (-1) +#define OK 0 + +extern int errno; + +/* + * static prototypes + */ +static char *tailor_value (char *); +static void getuserinfo (void); + +/* + * *mmdfldir and *uucpldir are the maildrop directories. If maildrops + * are kept in the user's home directory, then these should be empty + * strings. In this case, the appropriate ...lfil array should contain + * the name of the file in the user's home directory. Usually, this is + * something like ".mail". + */ + +/* + * nmh mail transport interface customization file + */ +static char *mtsconf = nmhetcdir(/mts.conf); + +static char *localname = ""; +static char *localdomain = ""; +static char *systemname = ""; + +char *mmdfldir = MAILSPOOL; +char *mmdflfil = ""; +char *uucpldir = "/usr/spool/mail"; +char *uucplfil = ""; + +char *mmdlm1 = "\001\001\001\001\n"; +char *mmdlm2 = "\001\001\001\001\n"; + +/* Cache the username and fullname 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 = ""; + +/* + * MTS specific variables + */ +#if defined(SMTPMTS) +static char *sm_method = "smtp"; +int sm_mts = MTS_SMTP; +char *hostable = nmhetcdir(/hosts); +char *sendmail = SENDMAILPATH; +#endif + +/* + * SMTP/POP stuff + */ +char *clientname = NULL; +char *servers = "localhost \01localnet"; +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); + + +/* + * Aliasing Facility (doesn't belong here) + */ +int Everyone = NOTOK; +static char *everyone = "-1"; +char *NoShell = ""; + +/* + * Customize the MTS settings for nmh by adjusting + * the file mts.conf in the nmh etc directory. + */ + +struct bind { + char *keyword; + char **value; +}; + +static struct bind binds[] = { + { "localname", &localname }, + { "localdomain", &localdomain }, + { "systemname", &systemname }, + { "mmdfldir", &mmdfldir }, + { "mmdflfil", &mmdflfil }, + { "uucpldir", &uucpldir }, + { "uucplfil", &uucplfil }, + { "mmdelim1", &mmdlm1 }, + { "mmdelim2", &mmdlm2 }, + { "masquerade", &masquerade }, + +#if defined(SMTPMTS) + { "mts", &sm_method }, + { "hostable", &hostable }, + { "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 }, + { "noshell", &NoShell }, + { NULL, NULL } +}; + + +/* + * Read the configuration file for the nmh interface + * to the mail transport system (MTS). + */ + +void +mts_init (char *name) +{ + char *bp, *cp, buffer[BUFSIZ]; + struct bind *b; + FILE *fp; + static int inited = 0; + + if (inited++ || (fp = fopen (mtsconf, "r")) == NULL) + return; + + 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; + } + + 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 +} + + +#define QUOTE '\\' + +/* + * Convert escaped values, malloc some new space, + * and copy string to malloc'ed memory. + */ + +static char * +tailor_value (char *s) +{ + int i, r; + char *bp; + char buffer[BUFSIZ]; + size_t len; + + for (bp = buffer; *s; bp++, s++) { + if (*s != QUOTE) { + *bp = *s; + } else { + switch (*++s) { + case 'b': *bp = '\b'; break; + case 'f': *bp = '\f'; break; + case 'n': *bp = '\n'; break; + case 't': *bp = '\t'; break; + + case 0: s--; + case QUOTE: + *bp = QUOTE; + break; + + default: + if (!isdigit (*s)) { + *bp++ = QUOTE; + *bp = *s; + } + r = *s != '0' ? 10 : 8; + for (i = 0; isdigit (*s); s++) + i = i * r + *s - '0'; + s--; + *bp = toascii (i); + break; + } + } + } + *bp = 0; + + len = strlen (buffer) + 1; + if ((bp = malloc (len))) + memcpy (bp, buffer, len); + + return bp; +} + +/* + * Get the fully qualified name of the local host. + */ + +char * +LocalName (void) +{ + static char buffer[BUFSIZ] = ""; + struct hostent *hp; + +#ifdef HAVE_UNAME + struct utsname name; +#endif + + /* check if we have cached the local name */ + if (buffer[0]) + return buffer; + + mts_init ("mts"); + + /* check if the mts.conf file specifies a "localname" */ + if (*localname) { + strncpy (buffer, localname, sizeof(buffer)); + } else { +#ifdef HAVE_UNAME + /* first get our local name */ + uname (&name); + strncpy (buffer, name.nodename, sizeof(buffer)); +#else + /* first get our local name */ + gethostname (buffer, sizeof(buffer)); +#endif +#ifdef HAVE_SETHOSTENT + sethostent (1); +#endif + /* now fully qualify our name */ + if ((hp = gethostbyname (buffer))) + strncpy (buffer, hp->h_name, sizeof(buffer)); + } + + /* + * If the mts.conf file specifies a "localdomain", + * we append that now. This should rarely be needed. + */ + if (*localdomain) { + strcat (buffer, "."); + strcat (buffer, localdomain); + } + + return buffer; +} + + +/* + * This is only for UUCP mail. It gets the hostname + * as part of the UUCP "domain". + */ + +char * +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; + + mts_init ("mts"); + + /* check if mts.conf file specifies a "systemname" */ + if (*systemname) { + strncpy (buffer, systemname, sizeof(buffer)); + return buffer; + } + +#ifdef HAVE_UNAME + uname (&name); + strncpy (buffer, name.nodename, sizeof(buffer)); +#else + gethostname (buffer, sizeof(buffer)); +#endif + + return buffer; +} + + +/* + * Get the username of current user + */ + +char * +getusername (void) +{ + if (username[0] == '\0') + getuserinfo(); + + return username; +} + + +/* + * Get full name of current user (typically from GECOS + * field of password file). + */ + +char * +getfullname (void) +{ + if (username[0] == '\0') + getuserinfo(); + + return fullname; +} + + +/* + * 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 +getuserinfo (void) +{ + register char *cp, *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++; + } + } +#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') + strncpy (username, pw->pw_name, sizeof(username)); + + /* The $SIGNATURE environment variable overrides the GECOS field's idea of + your real name. */ + if ((cp = getenv ("SIGNATURE")) && *cp) + strncpy (fullname, cp, sizeof(fullname)); + + if (strchr(fullname, '.')) { /* quote any .'s */ + char tmp[BUFSIZ]; + + /* should quote "'s too */ + snprintf (tmp, sizeof(tmp), "\"%s\"", fullname); + strncpy (fullname, tmp, sizeof(fullname)); + } + + return; +}