3 * mts.c -- definitions for the mail transport system
8 #include "h/mh.h" /* for snprintf() */
11 #define nmhetcdir(file) NMHETCDIR#file
19 #ifdef HAVE_SYS_UTSNAME_H
20 # include <sys/utsname.h>
31 static char *tailor_value (char *);
32 static void getuserinfo (void);
35 * *mmdfldir and *uucpldir are the maildrop directories. If maildrops
36 * are kept in the user's home directory, then these should be empty
37 * strings. In this case, the appropriate ...lfil array should contain
38 * the name of the file in the user's home directory. Usually, this is
39 * something like ".mail".
43 * nmh mail transport interface customization file
45 static char *mtsconf = nmhetcdir(/mts.conf);
47 static char *localname = "";
48 static char *localdomain = "";
49 static char *systemname = "";
51 char *mmdfldir = MAILSPOOL;
53 char *uucpldir = "/usr/spool/mail";
56 char *mmdlm1 = "\001\001\001\001\n";
57 char *mmdlm2 = "\001\001\001\001\n";
59 /* Cache the username and fullname of the user */
60 static char username[BUFSIZ];
61 static char fullname[BUFSIZ];
63 /* Variables for username masquerading: */
64 boolean draft_from_masquerading = FALSE; /* also used from post.c */
65 static boolean mmailid_masquerading = FALSE;
66 boolean username_extension_masquerading = FALSE; /* " from addrsbr.c */
67 static char* masquerade = "";
71 * MTS specific variables
73 #if defined(SENDMTS) || defined(SMTPMTS)
74 char *hostable = nmhetcdir(/hosts);
75 char *sendmail = SENDMAILPATH;
81 char *clientname = NULL;
82 char *servers = "localhost \01localnet";
86 * BBoards-specific variables
92 * POP BBoards-specific variables
97 char *popbblist = nmhetcdir(/hosts.popbb);
101 * Global MailDelivery file
103 char *maildelivery = nmhetcdir(/maildelivery);
107 * Aliasing Facility (doesn't belong here)
109 int Everyone = NOTOK;
110 static char *everyone = "-1";
114 * Customize the MTS settings for nmh by adjusting
115 * the file mts.conf in the nmh etc directory.
123 static struct bind binds[] = {
124 { "localname", &localname },
125 { "localdomain", &localdomain },
126 { "systemname", &systemname },
127 { "mmdfldir", &mmdfldir },
128 { "mmdflfil", &mmdflfil },
129 { "uucpldir", &uucpldir },
130 { "uucplfil", &uucplfil },
131 { "mmdelim1", &mmdlm1 },
132 { "mmdelim2", &mmdlm2 },
133 { "masquerade", &masquerade },
135 #if defined(SENDMTS) || defined(SMTPMTS)
136 { "hostable", &hostable },
140 { "sendmail", &sendmail },
143 { "clientname", &clientname },
144 { "servers", &servers },
145 { "pophost", &pophost },
146 { "bbdomain", &bb_domain },
149 { "popbbhost", &popbbhost },
150 { "popbbuser", &popbbuser },
151 { "popbblist", &popbblist },
155 { "nntphost", &popbbhost },
158 { "maildelivery", &maildelivery },
159 { "everyone", &everyone },
160 { "noshell", &NoShell },
166 * Read the configuration file for the nmh interface
167 * to the mail transport system (MTS).
171 mts_init (char *name)
173 char *bp, *cp, buffer[BUFSIZ];
176 static int inited = 0;
178 if (inited++ || (fp = fopen (mtsconf, "r")) == NULL)
181 while (fgets (buffer, sizeof(buffer), fp)) {
182 if (!(cp = strchr(buffer, '\n')))
185 if (*buffer == '#' || *buffer == '\0')
187 if (!(bp = strchr(buffer, ':')))
190 while (isspace (*bp))
193 for (b = binds; b->keyword; b++)
194 if (!strcmp (buffer, b->keyword))
196 if (b->keyword && (cp = tailor_value (bp)))
202 Everyone = atoi (everyone);
204 if (strstr(masquerade, "draft_from") != NULL)
205 draft_from_masquerading = TRUE;
207 if (strstr(masquerade, "mmailid") != NULL)
208 mmailid_masquerading = TRUE;
210 if (strstr(masquerade, "username_extension") != NULL)
211 username_extension_masquerading = TRUE;
218 * Convert escaped values, malloc some new space,
219 * and copy string to malloc'ed memory.
223 tailor_value (char *s)
230 for (bp = buffer; *s; bp++, s++) {
235 case 'b': *bp = '\b'; break;
236 case 'f': *bp = '\f'; break;
237 case 'n': *bp = '\n'; break;
238 case 't': *bp = '\t'; break;
250 r = *s != '0' ? 10 : 8;
251 for (i = 0; isdigit (*s); s++)
252 i = i * r + *s - '0';
261 len = strlen (buffer) + 1;
262 if ((bp = malloc (len)))
263 memcpy (bp, buffer, len);
269 * Get the fully qualified name of the local host.
275 static char buffer[BUFSIZ] = "";
282 /* check if we have cached the local name */
288 /* check if the mts.conf file specifies a "localname" */
290 strncpy (buffer, localname, sizeof(buffer));
293 /* first get our local name */
295 strncpy (buffer, name.nodename, sizeof(buffer));
297 /* first get our local name */
298 gethostname (buffer, sizeof(buffer));
300 #ifdef HAVE_SETHOSTENT
303 /* now fully qualify our name */
304 if ((hp = gethostbyname (buffer)))
305 strncpy (buffer, hp->h_name, sizeof(buffer));
309 * If the mts.conf file specifies a "localdomain",
310 * we append that now. This should rarely be needed.
313 strcat (buffer, ".");
314 strcat (buffer, localdomain);
322 * This is only for UUCP mail. It gets the hostname
323 * as part of the UUCP "domain".
329 static char buffer[BUFSIZ] = "";
335 /* check if we have cached the system name */
341 /* check if mts.conf file specifies a "systemname" */
343 strncpy (buffer, systemname, sizeof(buffer));
349 strncpy (buffer, name.nodename, sizeof(buffer));
351 gethostname (buffer, sizeof(buffer));
359 * Get the username of current user
365 if (username[0] == '\0')
373 * Get full name of current user (typically from GECOS
374 * field of password file).
380 if (username[0] == '\0')
388 * Find the user's username and full name, and cache them.
389 * Also, handle "mmailid" username masquerading controlled from the GECOS field
390 * of the passwd file.
396 register char *cp, *np;
397 register struct passwd *pw;
403 if (uid == geteuid () && (cp = getenv ("USER")) != NULL
404 && (pw = getpwnam (cp)) != NULL)
405 strncpy (username, cp, sizeof(username));
406 else if ((pw = getpwuid (uid)) == NULL
407 || pw->pw_name == NULL
408 || *pw->pw_name == '\0') {
410 if ((pw = getpwuid (getuid ())) == NULL
411 || pw->pw_name == NULL
412 || *pw->pw_name == '\0') {
414 strncpy (username, "unknown", sizeof(username));
415 snprintf (fullname, sizeof(fullname), "The Unknown User-ID (%d)",
422 /* Get the user's real name from the GECOS field. Stop once we hit a ',',
423 which some OSes use to separate other 'finger' information in the GECOS
424 field, like phone number. Also, if mmailid masquerading is turned on due
425 to "mmailid" appearing on the "masquerade:" line of mts.conf, stop if we
426 hit a '<' (which should precede any ','s). */
428 if (mmailid_masquerading)
429 /* Stop at ',' or '<'. */
430 for (cp = fullname; *np != '\0' && *np != ',' && *np != '<';
434 /* Allow '<' as a legal character of the user's name. This code is
435 basically a duplicate of the code above the "else" -- we don't
436 collapse it down to one copy and put the mmailid_masquerading check
437 inside the loop with "(x ? y : z)" because that's inefficient and the
438 value'll never change while it's in there. */
439 for (cp = fullname; *np != '\0' && *np != ',';
443 /* On BSD(-derived) systems, the system utilities that deal with the GECOS
444 field (finger, mail, sendmail, etc.) translate any '&' character in it to
445 the login name, with the first letter capitalized. So, for instance,
446 fingering a user "bob" with the GECOS field "& Jones" would reveal him to
447 be "In real life: Bob Jones". Surprisingly, though, the OS doesn't do
448 the translation for you, so we have to do it manually here. */
449 if (mmailid_masquerading)
450 /* Stop at ',' or '<'. */
452 *np != '\0' && *np != ',' && *np != '<';) {
453 if (*np == '&') { /* blech! */
454 strcpy (cp, pw->pw_name);
464 /* Allow '<' as a legal character of the user's name. This code is
465 basically a duplicate of the code above the "else" -- we don't
466 collapse it down to one copy and put the mmailid_masquerading check
467 inside the loop with "(x ? y : z)" because that's inefficient and the
468 value'll never change while it's in there. */
470 *np != '\0' && *np != ',';) {
471 if (*np == '&') { /* blech! */
472 strcpy (cp, pw->pw_name);
484 if (mmailid_masquerading) {
485 /* Do mmailid processing. The GECOS field should have the form
486 "Full Name <fakeusername>". For instance,
487 "Dan Harkless <Dan.Harkless>". Naturally, you'll want your MTA to
488 have an alias (e.g. in /etc/aliases) from "fakeusername" to your
492 for (cp = username; *np && *np != '>'; *cp++ = *np++)
496 if (!mmailid_masquerading || *np == '\0')
497 strncpy (username, pw->pw_name, sizeof(username));
499 /* The $SIGNATURE environment variable overrides the GECOS field's idea of
501 if ((cp = getenv ("SIGNATURE")) && *cp)
502 strncpy (fullname, cp, sizeof(fullname));
504 if (strchr(fullname, '.')) { /* quote any .'s */
507 /* should quote "'s too */
508 snprintf (tmp, sizeof(tmp), "\"%s\"", fullname);
509 strncpy (fullname, tmp, sizeof(fullname));