
/*
 * mts.c -- definitions for the mail transport system
 *
 * $Id$
 */

#include <h/nmh.h>

#define nmhetcdir(file) NMHETCDIR#file

#undef NETWORK
#if defined(BSD41A) || defined(BSD42) || defined(SOCKETS)
# define NETWORK
#endif

#include <ctype.h>
#include <stdio.h>
#include <mts.h>

#ifdef NETWORK
# ifdef SOCKETS
#  include <netdb.h>
# endif
#else	/* NETWORK */
# ifndef SYS5
#  include <whoami.h>
# else
#  include <sys/utsname.h>
# endif /* SYS5 */
#endif /* NETWORK */

#include <pwd.h>

#define	NOTOK	(-1)
#define	OK	0

extern int errno;

/*
 * static prototypes
 */
static char *tailor_value (char *);

/*
 * *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 = "";

#ifdef MF
static char *UUCPchan = "";
#endif

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";

static int MMailids = 0;
static char *mmailid = "0";

#ifdef MF
char *umincproc = nmhetcdir(/uminc);
#else
char *umincproc = NULL;
#endif

int lockstyle = LOK_UNIX;
static char *lkstyle = "0";
char *lockldir = "";

/*
 * MTS specific variables
 */

#ifdef MHMTS
char *Mailqdir = "/usr/spool/netmail";
char *TMailqdir = "/usr/tmp";
int Syscpy = 1;
static char *syscpy = "1";
char *Overseer = "root";
char *Mailer = "root";
char *Fromtmp = "/tmp/rml.f.XXXXXX";
char *Msgtmp = "/tmp/rml.m.XXXXXX";
char *Errtmp = "/tmp/rml.e.XXXXXX";
int Tmpmode = 0600;
static char *tmpmode = "0600";
char *Okhosts = nmhetcdir(/Rmail.OkHosts);
char *Okdests = nmhetcdir(/Rmail.OkDests);
#endif /* MHMTS */

#ifdef MMDFMTS
#endif /* MMDFMTS */

#ifdef SENDMTS
char *hostable = nmhetcdir(/hosts);
char *sendmail = SENDMAILPATH;
#endif /* SENDMTS */

/*
 * 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 },
#ifdef MF
    { "uucpchan", &UUCPchan },
#endif
    { "mmdfldir", &mmdfldir },
    { "mmdflfil", &mmdflfil },
    { "uucpldir", &uucpldir },
    { "uucplfil", &uucplfil },
    { "mmdelim1", &mmdlm1 },
    { "mmdelim2", &mmdlm2 },
    { "mmailid", &mmailid },
    { "umincproc", &umincproc },
    { "lockstyle", &lkstyle },
    { "lockldir", &lockldir },

#ifdef MHMTS
    { "mailqdir", &Mailqdir },
    { "tmailqdir", &TMailqdir },
    { "syscpy", &syscpy },
    { "overseer", &Overseer },
    { "mailer", &Mailer },
    { "fromtmp", &Fromtmp },
    { "msgtmp", &Msgtmp },
    { "errtmp", &Errtmp },
    { "tmpmode", &tmpmode },
    { "okhosts", &Okhosts },
    { "okdests", &Okdests },
#endif

#ifdef MMDFMTS
#endif /* MMDFMTS */

#ifdef SENDMTS
    { "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
};


/*
 * I'd like to use m_getfld() here, but not all programs
 * loading mts.o may be MH-style programs...
 */

/*
 * Read the configuration file for the nmh interface
 * to the mail transport system (MTS).
 */

void
mts_init (char *name)
{
    register char *bp, *cp;
    char buffer[BUFSIZ];
    register struct bind *b;
    register 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);

    MMailids = atoi (mmailid);
    if ((lockstyle = atoi (lkstyle)) < LOK_UNIX || lockstyle > LOK_MMDF)
	lockstyle = LOK_UNIX;

#ifdef MHMTS
    Syscpy = atoi (syscpy);
    sscanf (tmpmode, "0%o", &Tmpmode);
#endif /* MHMTS */

    Everyone = atoi (everyone);
}

#define	QUOTE	'\\'

static char *
tailor_value (char *s)
{
    register int i, r;
    register char *bp;
    char buffer[BUFSIZ];
    size_t len;

    for (bp = buffer; *s; bp++, s++)
	if (*s != QUOTE)
	    *bp = *s;
	else
	    switch (*++s) {
#define	grot(y,z) case y: *bp = z; break;
		grot ('b', '\b');
		grot ('f', '\f');
		grot ('n', '\n');
		grot ('t', '\t');
#undef	grot

		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;
}

char *
LocalName (void)
{
#ifdef BSD41A
    char  *myname;
#endif /* BSD41A */
#if defined(BSD42) || defined(SOCKETS)
    register struct hostent *hp;
#endif /* BSD42 or SOCKETS */
#if defined(SYS5) && !defined(NETWORK)
    struct utsname name;
#endif /* SYS5 and not NETWORK */
    static char buffer[BUFSIZ] = "";

    if (buffer[0])
	return buffer;

    mts_init ("mts");
    if (*localname)
	strcpy (buffer, localname);
    else {

#ifdef locname
    strcpy (buffer, locname);
#else /* not locname */
#ifdef NETWORK
#ifdef BSD41A
    myname = "myname";
    if (rhost (&myname) == -1)
	gethostname (buffer, sizeof(buffer));
    else {
	strcpy (buffer, myname);
	free (myname);
    }
#endif /* BSD41A */
#if defined(BSD42) || defined(SOCKETS)
    gethostname (buffer, sizeof(buffer));
#ifndef	BIND
    sethostent (1);
#endif
    if ((hp = gethostbyname (buffer)))
	strcpy (buffer, hp->h_name);
#endif /* BSD42 or SOCKETS */
#else /* not NETWORK */
#ifndef	SYS5
    strcpy (buffer, SystemName ());
#else /* SYS5 */
    uname (&name);
    strcpy (buffer, name.nodename);
#endif /* SYS5 */
#endif /* not NETWORK */
#endif /* not locname */
    }
    if (*localdomain) {
	strcat (buffer, ".");
	strcat (buffer, localdomain);
    }
    return buffer;
}

char *
SystemName (void)
{
#if defined(SYS5) && !defined(NETWORK)
    struct utsname name;
#endif /* SYS5 and not NETWORK */
    static char buffer[BUFSIZ] = "";

    if (buffer[0])
	return buffer;

    mts_init ("mts");
    if (*systemname)
	return strcpy (buffer, systemname);

#ifdef sysname
    strcpy (buffer, sysname);
#else /* sysname */
#if !defined(SYS5) || defined(NETWORK)
    gethostname (buffer, sizeof(buffer));
#else /* SYS5 and not NETWORK */
#ifdef SYS5
    uname (&name);
    strcpy (buffer, name.nodename);
#endif /* SYS5 */
#endif /* SYS5 and not NETWORK */
#endif /* sysname */

    return buffer;
}

char *
UucpChan (void)
{
#ifdef	MF
    static char buffer[BUFSIZ] = "";
#endif /* MF */

#ifndef	MF
    return NULL;
#else /* MF */
    if (buffer[0])
	return buffer;

    mts_init ("mts");
    if (*UUCPchan)
	return strcpy (buffer, UUCPchan);

#ifdef	uucpchan
    strcpy (buffer, uucpchan);
#else /* uucpchan */
    strcpy (buffer, "uucp");
#endif /* uucpchan */
    return buffer;
#endif /* MF */
}

static char username[BUFSIZ];
static char fullname[BUFSIZ];


char *
getusr (void)
{
    register char *cp, *np;
#ifdef KPOP
    uid_t uid;
#endif /* KPOP */
    register struct passwd *pw;

    if (username[0])
	return username;

#ifndef KPOP
    if ((pw = getpwuid (getuid ())) == NULL
	    || pw->pw_name == NULL
	    || *pw->pw_name == NULL) {
#else /* KPOP */
    uid = getuid ();
    if (uid == geteuid () && (cp = getenv ("USER")) != NULL
	&& (pw = getpwnam (cp)) != NULL)
      strcpy (username, cp);
    else if ((pw = getpwuid (uid)) == NULL
	     || pw->pw_name == NULL
	     || *pw->pw_name == '\0') {
#endif /* KPOP */
	strcpy (username, "unknown");
	sprintf (fullname, "The Unknown User-ID (%d)", getuid ());
	return username;
    }

    np = pw->pw_gecos;
#ifndef	GCOS_HACK
    for (cp = fullname; *np && *np != (MMailids ? '<' : ','); *cp++ = *np++)
	continue;
#else
    for (cp = fullname; *np && *np != (MMailids ? '<' : ','); )
	if (*np == '&')	{	/* blech! */
	    strcpy(cp, pw->pw_name);
	    *cp = toupper(*cp);
	    while (*cp)
		cp++;
	    np++;
	}
	else
	    *cp++ = *np++;
#endif
    *cp = '\0';
    if (MMailids) {
	if (*np)
	    np++;
	for (cp = username; *np && *np != '>'; *cp++ = *np++)
	    continue;
	*cp = '\0';
    }
    if (MMailids == 0 || *np == '\0')
	strcpy (username, pw->pw_name);

    if ((cp = getenv ("SIGNATURE")) && *cp)
	strcpy (fullname, cp);
    if (strchr(fullname, '.')) {		/*  quote any .'s */
	  char tmp[BUFSIZ];
      sprintf (tmp, "\"%s\"", fullname);/* should quote "'s too */
      strcpy (fullname, tmp);
    }

    return username;
}


char *
getfullname (void)
{
    if (username[0] == '\0')
	getusr ();

    return fullname;
}

