/*
* mts.c -- definitions for the mail transport system
*
* $Id: mts.c,v 1.3 2003/09/30 16:58:43 gbburkhardt Exp $
*
* 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.
*/
#include <h/mh.h> /* for snprintf() */
#include <h/nmh.h>
#define nmhetcdir(file) NMHETCDIR#file
#include <ctype.h>
#include <stdio.h>
#include <h/mts.h>
#include <pwd.h>
#include <netdb.h>
#ifdef HAVE_SYS_UTSNAME_H
# include <sys/utsname.h>
#endif
#define NOTOK (-1)
#define OK 0
/*
* 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 <fakeusername>". For instance,
"Dan Harkless <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;
}
syntax highlighted by Code2HTML, v. 0.9.1