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 = "";
70 * MTS specific variables
73 static char *sm_method = "smtp";
74 int sm_mts = MTS_SMTP;
75 char *hostable = nmhetcdir(/hosts);
76 char *sendmail = SENDMAILPATH;
82 char *clientname = NULL;
83 char *servers = "localhost \01localnet";
87 * BBoards-specific variables
93 * POP BBoards-specific variables
98 char *popbblist = nmhetcdir(/hosts.popbb);
102 * Global MailDelivery file
104 char *maildelivery = nmhetcdir(/maildelivery);
108 * Aliasing Facility (doesn't belong here)
110 int Everyone = NOTOK;
111 static char *everyone = "-1";
115 * Customize the MTS settings for nmh by adjusting
116 * the file mts.conf in the nmh etc directory.
124 static struct bind binds[] = {
125 { "localname", &localname },
126 { "localdomain", &localdomain },
127 { "systemname", &systemname },
128 { "mmdfldir", &mmdfldir },
129 { "mmdflfil", &mmdflfil },
130 { "uucpldir", &uucpldir },
131 { "uucplfil", &uucplfil },
132 { "mmdelim1", &mmdlm1 },
133 { "mmdelim2", &mmdlm2 },
134 { "masquerade", &masquerade },
137 { "mts", &sm_method },
138 { "hostable", &hostable },
139 { "sendmail", &sendmail },
142 { "clientname", &clientname },
143 { "servers", &servers },
144 { "pophost", &pophost },
145 { "bbdomain", &bb_domain },
148 { "popbbhost", &popbbhost },
149 { "popbbuser", &popbbuser },
150 { "popbblist", &popbblist },
154 { "nntphost", &popbbhost },
157 { "maildelivery", &maildelivery },
158 { "everyone", &everyone },
159 { "noshell", &NoShell },
165 * Read the configuration file for the nmh interface
166 * to the mail transport system (MTS).
170 mts_init (char *name)
172 char *bp, *cp, buffer[BUFSIZ];
175 static int inited = 0;
177 if (inited++ || (fp = fopen (mtsconf, "r")) == NULL)
180 while (fgets (buffer, sizeof(buffer), fp)) {
181 if (!(cp = strchr(buffer, '\n')))
184 if (*buffer == '#' || *buffer == '\0')
186 if (!(bp = strchr(buffer, ':')))
189 while (isspace (*bp))
192 for (b = binds; b->keyword; b++)
193 if (!strcmp (buffer, b->keyword))
195 if (b->keyword && (cp = tailor_value (bp)))
201 Everyone = atoi (everyone);
203 if (strstr(masquerade, "draft_from") != NULL)
204 draft_from_masquerading = TRUE;
206 if (strstr(masquerade, "mmailid") != NULL)
207 mmailid_masquerading = TRUE;
209 if (strstr(masquerade, "username_extension") != NULL)
210 username_extension_masquerading = TRUE;
213 if (strcmp(sm_method, "smtp") == 0)
215 else if (strcmp(sm_method, "sendmail") == 0)
216 sm_mts = MTS_SENDMAIL;
218 advise(NULL, "unsupported \"mts\" value in mts.conf: %s", sm_method);
228 * Convert escaped values, malloc some new space,
229 * and copy string to malloc'ed memory.
233 tailor_value (char *s)
240 for (bp = buffer; *s; bp++, s++) {
245 case 'b': *bp = '\b'; break;
246 case 'f': *bp = '\f'; break;
247 case 'n': *bp = '\n'; break;
248 case 't': *bp = '\t'; break;
260 r = *s != '0' ? 10 : 8;
261 for (i = 0; isdigit (*s); s++)
262 i = i * r + *s - '0';
271 len = strlen (buffer) + 1;
272 if ((bp = malloc (len)))
273 memcpy (bp, buffer, len);
279 * Get the fully qualified name of the local host.
285 static char buffer[BUFSIZ] = "";
292 /* check if we have cached the local name */
298 /* check if the mts.conf file specifies a "localname" */
300 strncpy (buffer, localname, sizeof(buffer));
303 /* first get our local name */
305 strncpy (buffer, name.nodename, sizeof(buffer));
307 /* first get our local name */
308 gethostname (buffer, sizeof(buffer));
310 #ifdef HAVE_SETHOSTENT
313 /* now fully qualify our name */
314 if ((hp = gethostbyname (buffer)))
315 strncpy (buffer, hp->h_name, sizeof(buffer));
319 * If the mts.conf file specifies a "localdomain",
320 * we append that now. This should rarely be needed.
323 strcat (buffer, ".");
324 strcat (buffer, localdomain);
332 * This is only for UUCP mail. It gets the hostname
333 * as part of the UUCP "domain".
339 static char buffer[BUFSIZ] = "";
345 /* check if we have cached the system name */
351 /* check if mts.conf file specifies a "systemname" */
353 strncpy (buffer, systemname, sizeof(buffer));
359 strncpy (buffer, name.nodename, sizeof(buffer));
361 gethostname (buffer, sizeof(buffer));
369 * Get the username of current user
375 if (username[0] == '\0')
383 * Get full name of current user (typically from GECOS
384 * field of password file).
390 if (username[0] == '\0')
398 * Find the user's username and full name, and cache them.
399 * Also, handle "mmailid" username masquerading controlled from the GECOS field
400 * of the passwd file.
406 register char *cp, *np;
407 register struct passwd *pw;
413 if (uid == geteuid () && (cp = getenv ("USER")) != NULL
414 && (pw = getpwnam (cp)) != NULL)
415 strncpy (username, cp, sizeof(username));
416 else if ((pw = getpwuid (uid)) == NULL
417 || pw->pw_name == NULL
418 || *pw->pw_name == '\0') {
420 if ((pw = getpwuid (getuid ())) == NULL
421 || pw->pw_name == NULL
422 || *pw->pw_name == '\0') {
424 strncpy (username, "unknown", sizeof(username));
425 snprintf (fullname, sizeof(fullname), "The Unknown User-ID (%d)",
432 /* Get the user's real name from the GECOS field. Stop once we hit a ',',
433 which some OSes use to separate other 'finger' information in the GECOS
434 field, like phone number. Also, if mmailid masquerading is turned on due
435 to "mmailid" appearing on the "masquerade:" line of mts.conf, stop if we
436 hit a '<' (which should precede any ','s). */
438 if (mmailid_masquerading)
439 /* Stop at ',' or '<'. */
440 for (cp = fullname; *np != '\0' && *np != ',' && *np != '<';
444 /* Allow '<' as a legal character of the user's name. This code is
445 basically a duplicate of the code above the "else" -- we don't
446 collapse it down to one copy and put the mmailid_masquerading check
447 inside the loop with "(x ? y : z)" because that's inefficient and the
448 value'll never change while it's in there. */
449 for (cp = fullname; *np != '\0' && *np != ',';
453 /* On BSD(-derived) systems, the system utilities that deal with the GECOS
454 field (finger, mail, sendmail, etc.) translate any '&' character in it to
455 the login name, with the first letter capitalized. So, for instance,
456 fingering a user "bob" with the GECOS field "& Jones" would reveal him to
457 be "In real life: Bob Jones". Surprisingly, though, the OS doesn't do
458 the translation for you, so we have to do it manually here. */
459 if (mmailid_masquerading)
460 /* Stop at ',' or '<'. */
462 *np != '\0' && *np != ',' && *np != '<';) {
463 if (*np == '&') { /* blech! */
464 strcpy (cp, pw->pw_name);
474 /* Allow '<' as a legal character of the user's name. This code is
475 basically a duplicate of the code above the "else" -- we don't
476 collapse it down to one copy and put the mmailid_masquerading check
477 inside the loop with "(x ? y : z)" because that's inefficient and the
478 value'll never change while it's in there. */
480 *np != '\0' && *np != ',';) {
481 if (*np == '&') { /* blech! */
482 strcpy (cp, pw->pw_name);
494 if (mmailid_masquerading) {
495 /* Do mmailid processing. The GECOS field should have the form
496 "Full Name <fakeusername>". For instance,
497 "Dan Harkless <Dan.Harkless>". Naturally, you'll want your MTA to
498 have an alias (e.g. in /etc/aliases) from "fakeusername" to your
502 for (cp = username; *np && *np != '>'; *cp++ = *np++)
506 if (!mmailid_masquerading || *np == '\0')
507 strncpy (username, pw->pw_name, sizeof(username));
509 /* The $SIGNATURE environment variable overrides the GECOS field's idea of
511 if ((cp = getenv ("SIGNATURE")) && *cp)
512 strncpy (fullname, cp, sizeof(fullname));
514 if (strchr(fullname, '.')) { /* quote any .'s */
517 /* should quote "'s too */
518 snprintf (tmp, sizeof(tmp), "\"%s\"", fullname);
519 strncpy (fullname, tmp, sizeof(fullname));