From 75e073ea52a427394690e0c1ef7943a1727c7095 Mon Sep 17 00:00:00 2001 From: Shantonu Sen Date: Fri, 8 Sep 2000 00:30:58 +0000 Subject: [PATCH] Moved code from zotnet/mts to mts/generic. Also, unified generic mts code and smtp/sendmail into libmts.a as an intermediate, instead of having two static libs. --- mts/Makefile.in | 35 +++- mts/generic/Makefile.in | 101 +++++++++ mts/generic/client.c | 479 +++++++++++++++++++++++++++++++++++++++++++ mts/generic/mts.c | 523 +++++++++++++++++++++++++++++++++++++++++++++++ mts/generic/mts.h | 88 ++++++++ mts/mmdf/hosts.c | 2 +- mts/sendmail/hosts.c | 2 +- mts/sendmail/sendmail.c | 2 +- mts/smtp/Makefile.in | 18 +- mts/smtp/hosts.c | 2 +- mts/smtp/smtp.c | 4 +- 11 files changed, 1227 insertions(+), 29 deletions(-) create mode 100644 mts/generic/Makefile.in create mode 100644 mts/generic/client.c create mode 100644 mts/generic/mts.c create mode 100644 mts/generic/mts.h diff --git a/mts/Makefile.in b/mts/Makefile.in index a8c5ee5..08b4754 100644 --- a/mts/Makefile.in +++ b/mts/Makefile.in @@ -17,6 +17,15 @@ etcdir='$(etcdir)' libdir='$(libdir)' mandir='$(mandir)' \ mailspool='$(mailspool)' sendmailpath='$(sendmailpath)' \ default_editor='$(default_editor)' default_pager='$(default_pager)' +LORDER = @LORDER@ +TSORT = @TSORT@ +RANLIB = @RANLIB@ +LIBTOOL = @LIBTOOL@ +GNU_LIBTOOL = @GNU_LIBTOOL@ + +# object files that go into libmts.a +OBJS = generic/client.o generic/mts.o smtp/hosts.o smtp/smtp.o + # auxiliary files AUX = Makefile.in @@ -24,18 +33,32 @@ AUX = Makefile.in DIST = $(AUX) # subdirectories -SUBDIRS = smtp sendmail mmdf +SUBDIRS = smtp generic # mail transport agent we are using (currently always smtp) -MTS = smtp +# MTS = smtp +# DEPRECATED: smtp/sendmail functionality handled by mts.conf # ========= DEPENDENCIES FOR BUILDING AND INSTALLING ========== -all install uninstall: - for subdir in $(MTS); do \ - (cd $$subdir && $(MAKE) $(MAKEDEFS) $@) || exit 1; \ +all: all-recursive libmts.a + +all-recursive: + for subdir in $(SUBDIRS); do \ + (cd $$subdir && $(MAKE) $(MAKEDEFS) all) || exit 1; \ done +libmts.a: $(OBJS) + rm -f $@ + if test x$(LIBTOOL) != x -a x$(GNU_LIBTOOL) = x ; then \ + $(LIBTOOL) -static -c $(OBJS) -o $@ ; \ + else \ + ar cr $@ `$(LORDER) $(OBJS) | $(TSORT)` ; \ + $(RANLIB) $@ ; \ + fi + +install uninstall: + # ========== DEPENDENCIES FOR CLEANUP ========== mostlyclean: mostlyclean-recursive mostlyclean-local @@ -48,7 +71,7 @@ mostlyclean-local: rm -f *~ clean-local: mostlyclean-local - + rm -f libmts.a distclean-local: clean-local rm -f Makefile diff --git a/mts/generic/Makefile.in b/mts/generic/Makefile.in new file mode 100644 index 0000000..97dca02 --- /dev/null +++ b/mts/generic/Makefile.in @@ -0,0 +1,101 @@ +# +# Makefile for mts/generic subdirectory +# +# $Id$ +# + +SHELL = /bin/sh + +top_srcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +libdir = @libdir@ +etcdir = @sysconfdir@ + +mailspool = @mailspool@ +sendmailpath = @sendmailpath@ + +CC = @CC@ +CFLAGS = @CFLAGS@ +DEFS = @DEFS@ +KRB4_INCLUDES = @KRB4_INCLUDES@ +HESIOD_INCLUDES = @HESIOD_INCLUDES@ +INCLUDES = -I../.. -I$(srcdir) -I$(top_srcdir) $(KRB4_INCLUDES) $(HESIOD_INCLUDES) +CONFIGDEFS = -DNMHETCDIR='"$(etcdir)"' -DMAILSPOOL='"$(mailspool)"' -DSENDMAILPATH='"$(sendmailpath)"' +LINT = @LINT@ +LINTFLAGS = @LINTFLAGS@ + +COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CFLAGS) +COMPILE2 = $(CC) -c $(DEFS) $(CONFIGDEFS) $(INCLUDES) $(CFLAGS) + +SED = sed + +.SUFFIXES: +.SUFFIXES: .c .o + +.c.o: + $(COMPILE) $< + +# header files +HDRS = mts.h + +# source files +SRCS = mts.c client.c + +# object files +OBJS = mts.o client.o + +# auxiliary files +AUX = Makefile.in + +# all files in this directory included in the distribution +DIST = $(HDRS) $(SRCS) $(AUX) + +# ========= DEPENDENCIES FOR BUILDING AND INSTALLING ========== + +all: $(OBJS) + +mts.o: mts.c + $(COMPILE2) $< + +install: + +uninstall: + +# ========== DEPENDENCIES FOR CLEANUP ========== + +mostlyclean: + rm -f *.o *~ + +clean: mostlyclean + +distclean: clean + rm -f Makefile + +realclean: distclean + +superclean: realclean + +# ========== DEPENDENCIES FOR LINT ================ + +lint: + $(LINT) $(LINTFLAGS) $(INCLUDES) $(DEFS) $(SRCS) + +# ========== DEPENDENCIES FOR MAINTENANCE ========== + +subdir = mts/generic + +Makefile: Makefile.in ../../config.status + cd ../.. && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= ./config.status + +distdir = ../../`cat ../../distname`/$(subdir) +nmhdist: $(DIST) + @echo "Copying distribution files in $(subdir)" + @for file in $(DIST); do \ + cp -p $(srcdir)/$$file $(distdir); \ + done + diff --git a/mts/generic/client.c b/mts/generic/client.c new file mode 100644 index 0000000..0095959 --- /dev/null +++ b/mts/generic/client.c @@ -0,0 +1,479 @@ + +/* + * client.c -- connect to a server + * + * $Id$ + */ + +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_ARPA_INET_H +# include +#endif + +#ifdef HESIOD +# include +#endif + +#ifdef KPOP +# include +# include +#endif /* KPOP */ + +#define TRUE 1 +#define FALSE 0 + +#define OOPS1 (-2) +#define OOPS2 (-3) + +#define MAXARGS 1000 +#define MAXNETS 5 +#define MAXHOSTS 25 + +struct addrent { + int a_addrtype; /* assumes AF_INET for inet_netof () */ + union { + int un_net; + char un_addr[14]; + } un; +}; + +#define a_net un.un_net +#define a_addr un.un_addr + +static struct addrent *n1, *n2; +static struct addrent nets[MAXNETS]; +static struct addrent *h1, *h2; +static struct addrent hosts[MAXHOSTS]; + +#ifdef KPOP +static CREDENTIALS cred; +static MSG_DAT msg_data; +static KTEXT ticket = (KTEXT) NULL; +static Key_schedule schedule; +static char *kservice; /* "pop" if using kpop */ +char krb_realm[REALM_SZ]; +char *PrincipalHostname(); +#endif /* KPOP */ + +#if !defined(h_addr) +# define h_addr h_addr_list[0] +#endif + +#define inaddr_copy(hp,sin) \ + memcpy(&((sin)->sin_addr), (hp)->h_addr, (hp)->h_length) + +/* + * static prototypes + */ +static int rcaux (struct servent *, struct hostent *, int, char *, int); +static int getport (int, int, char *, int); +static int inet (struct hostent *, int); +struct hostent *gethostbystring (char *s); + +/* client's own static version of several nmh subroutines */ +static char **client_brkstring (char *, char *, char *); +static int client_brkany (char, char *); +static char **client_copyip (char **, char **, int); +static char *client_getcpy (char *); + + +int +client (char *args, char *protocol, char *service, int rproto, + char *response, int len_response) +{ + int sd; + register char **ap; + char *arguments[MAXARGS]; + register struct hostent *hp; + register struct servent *sp; +#ifndef HAVE_GETHOSTBYNAME + register struct netent *np; +#endif + +#ifdef KPOP + char *cp; + + kservice = service; + if (cp = strchr (service, '/')) { /* "pop/kpop" */ + *cp++ = '\0'; /* kservice = "pop" */ + service = cp; /* service = "kpop" */ + } else { + kservice = NULL; /* not using KERBEROS */ + } +#endif /* KPOP */ + + + if ((sp = getservbyname (service, protocol)) == NULL) { +#ifdef HESIOD + if ((sp = hes_getservbyname (service, protocol)) == NULL) { + snprintf (response, len_response, "%s/%s: unknown service", protocol, service); + return NOTOK; + } +#else + snprintf (response, len_response, "%s/%s: unknown service", protocol, service); + return NOTOK; +#endif + } + + ap = arguments; + if (args != NULL && *args != 0) { + ap = client_copyip (client_brkstring (client_getcpy (args), " ", "\n"), + ap, MAXARGS); + } else { + if (servers != NULL && *servers != 0) + ap = client_copyip (client_brkstring (client_getcpy (servers), " ", "\n"), + ap, MAXARGS); + } + if (ap == arguments) { + *ap++ = client_getcpy ("localhost"); + *ap = NULL; + } + + n1 = nets; + n2 = nets + sizeof(nets) / sizeof(nets[0]); + + h1 = hosts; + h2 = hosts + sizeof(hosts) / sizeof(hosts[0]); + + for (ap = arguments; *ap; ap++) { + if (**ap == '\01') { +/* + * the assumption here is that if the system doesn't have a + * gethostbyname() function, it must not use DNS. So we need to look + * into the /etc/hosts using gethostent(). There probablly aren't any + * systems still like this, but you never know. On every system I have + * access to, this section is ignored. + */ +#ifndef HAVE_GETHOSTBYNAME + if ((np = getnetbyname (*ap + 1))) { +#ifdef HAVE_SETHOSTENT + sethostent (1); +#endif /* HAVE_SETHOSTENT */ + while ((hp = gethostent())) + if (np->n_addrtype == hp->h_addrtype + && inet (hp, np->n_net)) { + switch (sd = rcaux (sp, hp, rproto, response, len_response)) { + case NOTOK: + continue; + case OOPS1: + break; + case OOPS2: + return NOTOK; + + default: + return sd; + } + break; + } + } +#endif /* don't HAVE_GETHOSTBYNAME */ + continue; + } + + if ((hp = gethostbystring (*ap))) { + switch (sd = rcaux (sp, hp, rproto, response, len_response)) { + case NOTOK: + case OOPS1: + break; + case OOPS2: + return NOTOK; + + default: + return sd; + } + continue; + } + } + + strncpy (response, "no servers available", len_response); + return NOTOK; +} + + +static int +rcaux (struct servent *sp, struct hostent *hp, int rproto, + char *response, int len_response) +{ + int sd; + struct in_addr in; + register struct addrent *ap; + struct sockaddr_in in_socket; + register struct sockaddr_in *isock = &in_socket; + +#ifdef KPOP + int rem; + struct hostent *hp2; +#endif /* KPOP */ + + for (ap = nets; ap < n1; ap++) + if (ap->a_addrtype == hp->h_addrtype && inet (hp, ap->a_net)) + return NOTOK; + + for (ap = hosts; ap < h1; ap++) + if (ap->a_addrtype == hp->h_addrtype + && memcmp(ap->a_addr, hp->h_addr, hp->h_length) == 0) + return NOTOK; + + if ((sd = getport (rproto, hp->h_addrtype, response, len_response)) == NOTOK) + return OOPS2; + + memset (isock, 0, sizeof(*isock)); + isock->sin_family = hp->h_addrtype; + inaddr_copy (hp, isock); + isock->sin_port = sp->s_port; + + if (connect (sd, (struct sockaddr *) isock, sizeof(*isock)) == NOTOK) + switch (errno) { + case ENETDOWN: + case ENETUNREACH: + close (sd); + if (n1 < n2) { + n1->a_addrtype = hp->h_addrtype; + memcpy(&in, hp->h_addr, sizeof(in)); + n1->a_net = inet_netof (in); + n1++; + } + return OOPS1; + + case ETIMEDOUT: + case ECONNREFUSED: + default: + close (sd); + if (h1 < h2) { + h1->a_addrtype = hp->h_addrtype; + memcpy(h1->a_addr, hp->h_addr, hp->h_length); + h1++; + } + return NOTOK; + } + +#ifdef KPOP + if (kservice) { /* "pop" */ + char *instance; + + if (( hp2 = gethostbyaddr( hp->h_addr, hp->h_length, hp->h_addrtype )) + == NULL ) { + return NOTOK; + } + if ((instance = strdup (hp2->h_name)) == NULL) { + close (sd); + strncpy (response, "Out of memory.", len_response); + return OOPS2; + } + ticket = (KTEXT) malloc (sizeof(KTEXT_ST)); + rem = krb_sendauth (0L, sd, ticket, kservice, instance, + (char *) krb_realmofhost (instance), + (unsigned long) 0, &msg_data, &cred, schedule, + (struct sockaddr_in *) NULL, + (struct sockaddr_in *) NULL, + "KPOPV0.1"); + free (instance); + if (rem != KSUCCESS) { + close (sd); + strncpy (response, "Post office refused connection: ", len_response); + strncat (response, krb_err_txt[rem], len_response - strlen(response)); + return OOPS2; + } + } +#endif /* KPOP */ + + return sd; +} + + +static int +getport (int rproto, int addrtype, char *response, int len_response) +{ + int sd, port; + struct sockaddr_in in_socket, *isock; + + isock = &in_socket; + if (rproto && addrtype != AF_INET) { + snprintf (response, len_response, "reserved ports not supported for af=%d", addrtype); + errno = ENOPROTOOPT; + return NOTOK; + } + + if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == NOTOK) { + char *s; + + if ((s = strerror (errno))) + snprintf (response, len_response, "unable to create socket: %s", s); + else + snprintf (response, len_response, "unable to create socket: unknown error"); + return NOTOK; + } +#ifdef KPOP + if (kservice) /* "pop" */ + return(sd); +#endif /* KPOP */ + if (!rproto) + return sd; + + memset(isock, 0, sizeof(*isock)); + isock->sin_family = addrtype; + for (port = IPPORT_RESERVED - 1;;) { + isock->sin_port = htons ((unsigned short) port); + if (bind (sd, (struct sockaddr *) isock, sizeof(*isock)) != NOTOK) + return sd; + + switch (errno) { + char *s; + + case EADDRINUSE: + case EADDRNOTAVAIL: + if (--port <= IPPORT_RESERVED / 2) { + strncpy (response, "ports available", len_response); + return NOTOK; + } + break; + + default: + if ((s = strerror (errno))) + snprintf (response, len_response, "unable to bind socket: %s", s); + else + snprintf (response, len_response, "unable to bind socket: unknown error"); + return NOTOK; + } + } +} + + +static int +inet (struct hostent *hp, int net) +{ + struct in_addr in; + + memcpy(&in, hp->h_addr, sizeof(in)); + return (inet_netof (in) == net); +} + + +/* + * taken from ISODE's compat/internet.c + */ + +static char *empty = NULL; + +#ifdef h_addr +static char *addrs[2] = { NULL }; +#endif + +struct hostent * +gethostbystring (char *s) +{ + register struct hostent *h; + static struct hostent hs; +#ifdef DG + static struct in_addr iaddr; +#else + static unsigned long iaddr; +#endif + + iaddr = inet_addr (s); +#ifdef DG + if (iaddr.s_addr == NOTOK && strcmp (s, "255.255.255.255")) +#else + if (((int) iaddr == NOTOK) && strcmp (s, "255.255.255.255")) +#endif + return gethostbyname (s); + + h = &hs; + h->h_name = s; + h->h_aliases = ∅ + h->h_addrtype = AF_INET; + h->h_length = sizeof(iaddr); +#ifdef h_addr + h->h_addr_list = addrs; + memset(addrs, 0, sizeof(addrs)); +#endif + h->h_addr = (char *) &iaddr; + + return h; +} + + +/* + * static copies of three nmh subroutines + */ + +static char *broken[MAXARGS + 1]; + +static char ** +client_brkstring (char *strg, char *brksep, char *brkterm) +{ + register int bi; + register char c, *sp; + + sp = strg; + + for (bi = 0; bi < MAXARGS; bi++) { + while (client_brkany (c = *sp, brksep)) + *sp++ = 0; + if (!c || client_brkany (c, brkterm)) { + *sp = 0; + broken[bi] = 0; + return broken; + } + + broken[bi] = sp; + while ((c = *++sp) && !client_brkany (c, brksep) && !client_brkany (c, brkterm)) + continue; + } + broken[MAXARGS] = 0; + + return broken; +} + + +/* + * returns 1 if chr in strg, 0 otherwise + */ +static int +client_brkany (char chr, char *strg) +{ + register char *sp; + + if (strg) + for (sp = strg; *sp; sp++) + if (chr == *sp) + return 1; + return 0; +} + + +/* + * copy a string array and return pointer to end + */ +static char ** +client_copyip (char **p, char **q, int len_q) +{ + while (*p && --len_q > 0) + *q++ = *p++; + + *q = NULL; + + return q; +} + + +static char * +client_getcpy (char *str) +{ + char *cp; + size_t len; + + len = strlen(str) + 1; + if (!(cp = malloc(len))) + return NULL; + + memcpy (cp, str, len); + return cp; +} + 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; +} diff --git a/mts/generic/mts.h b/mts/generic/mts.h new file mode 100644 index 0000000..ce063d9 --- /dev/null +++ b/mts/generic/mts.h @@ -0,0 +1,88 @@ + +/* + * mts.h -- definitions for the mail system + * + * $Id$ + */ + +/* + * Local and UUCP Host Name + */ +char *LocalName(void); +char *SystemName(void); + +/* + * Mailboxes + */ +extern char *mmdfldir; +extern char *mmdflfil; +extern char *uucpldir; +extern char *uucplfil; + +#define MAILDIR (mmdfldir && *mmdfldir ? mmdfldir : getenv ("HOME")) +#define MAILFIL (mmdflfil && *mmdflfil ? mmdflfil : getusername ()) +#define UUCPDIR (uucpldir && *uucpldir ? uucpldir : getenv ("HOME")) +#define UUCPFIL (uucplfil && *uucplfil ? uucplfil : getusername ()) + +char *getusername(void); +char *getfullname(void); + +/* + * Separators + */ +extern char *mmdlm1; +extern char *mmdlm2; + +#define isdlm1(s) (strcmp (s, mmdlm1) == 0) +#define isdlm2(s) (strcmp (s, mmdlm2) == 0) + +/* + * Read mts.conf file + */ +void mts_init (char *); + +/* + * MTS specific variables + */ +#if defined (SMTPMTS) + +/* whether to speak SMTP to localhost:25 or to /usr/sbin/sendmail */ +#define MTS_SMTP 0 +#define MTS_SENDMAIL 1 +extern int sm_mts; + +extern char *hostable; +extern char *sendmail; +#endif + +/* + * SMTP/POP stuff + */ +extern char *clientname; +extern char *servers; +extern char *pophost; + +/* + * BBoards-specific variables + */ +extern char *bb_domain; + +/* + * POP BBoards-specific variables + */ +#ifdef BPOP +extern char *popbbhost; +extern char *popbbuser; +extern char *popbblist; +#endif /* BPOP */ + +/* + * Global MailDelivery File + */ +extern char *maildelivery; + +/* + * Aliasing Facility (doesn't belong here) + */ +extern int Everyone; +extern char *NoShell; diff --git a/mts/mmdf/hosts.c b/mts/mmdf/hosts.c index 748d8d6..a6d3139 100644 --- a/mts/mmdf/hosts.c +++ b/mts/mmdf/hosts.c @@ -14,7 +14,7 @@ # include "dm.h" #endif /* MMDFII */ -#include "../../zotnet/mts.h" +#include /* * We really should be careful with the number of fd's that this routine diff --git a/mts/sendmail/hosts.c b/mts/sendmail/hosts.c index 83727d5..40697ce 100644 --- a/mts/sendmail/hosts.c +++ b/mts/sendmail/hosts.c @@ -13,7 +13,7 @@ */ #include -#include +#include #include static struct host { diff --git a/mts/sendmail/sendmail.c b/mts/sendmail/sendmail.c index 9a9c725..00fe825 100644 --- a/mts/sendmail/sendmail.c +++ b/mts/sendmail/sendmail.c @@ -7,7 +7,7 @@ #include #include -#include +#include #include #include "h/signals.h" /* for SIGNAL() */ #ifdef MPOP diff --git a/mts/smtp/Makefile.in b/mts/smtp/Makefile.in index 4a726b9..341f0b1 100644 --- a/mts/smtp/Makefile.in +++ b/mts/smtp/Makefile.in @@ -21,12 +21,6 @@ CFLAGS = @CFLAGS@ DEFS = @DEFS@ SASL_INCLUDES = @SASL_INCLUDES@ INCLUDES = -I../.. -I$(srcdir) -I$(top_srcdir) $(SASL_INCLUDES) - -LORDER = @LORDER@ -TSORT = @TSORT@ -RANLIB = @RANLIB@ -LIBTOOL = @LIBTOOL@ -GNU_LIBTOOL = @GNU_LIBTOOL@ LINT = @LINT@ LINTFLAGS = @LINTFLAGS@ @@ -55,16 +49,7 @@ DIST = $(HDRS) $(SRCS) $(AUX) # ========= DEPENDENCIES FOR BUILDING AND INSTALLING ========== -all: libsmtp.a - -libsmtp.a: $(OBJS) - rm -f $@ - if test x$(LIBTOOL) != x -a x$(GNU_LIBTOOL) = x ; then \ - $(LIBTOOL) -static -c $(OBJS) -o $@ ; \ - else \ - ar cr $@ `$(LORDER) $(OBJS) | $(TSORT)` ; \ - $(RANLIB) $@ ; \ - fi +all: $(OBJS) install: @@ -76,7 +61,6 @@ mostlyclean: rm -f *.o *~ clean: mostlyclean - rm -f libsmtp.a distclean: clean rm -f Makefile diff --git a/mts/smtp/hosts.c b/mts/smtp/hosts.c index 83727d5..40697ce 100644 --- a/mts/smtp/hosts.c +++ b/mts/smtp/hosts.c @@ -13,7 +13,7 @@ */ #include -#include +#include #include static struct host { diff --git a/mts/smtp/smtp.c b/mts/smtp/smtp.c index f2390b8..e596680 100644 --- a/mts/smtp/smtp.c +++ b/mts/smtp/smtp.c @@ -6,7 +6,7 @@ #include #include "smtp.h" -#include +#include #include #include #ifdef MPOP @@ -150,7 +150,7 @@ char **smail_copyip (char **, char **, int); static int sm_auth_sasl(char *, char *, char *); #endif /* CYRUS_SASL */ -/* from zotnet/mts/client.c */ +/* from mts/generic/client.c */ int client (char *, char *, char *, int, char *, int); int -- 1.7.10.4