3 * mts.c -- definitions for the mail transport system
7 * This code is Copyright (c) 2002, by the authors of nmh. See the
8 * COPYRIGHT file in the root directory of the nmh distribution for
9 * complete copyright information.
12 #include <h/mh.h> /* for snprintf() */
16 #define nmhetcdir(file) NMHETCDIR#file
24 #ifdef HAVE_SYS_UTSNAME_H
25 # include <sys/utsname.h>
34 static char *tailor_value (char *);
35 static void getuserinfo (void);
38 * *mmdfldir and *uucpldir are the maildrop directories. If maildrops
39 * are kept in the user's home directory, then these should be empty
40 * strings. In this case, the appropriate ...lfil array should contain
41 * the name of the file in the user's home directory. Usually, this is
42 * something like ".mail".
46 * nmh mail transport interface customization file
48 static char *mtsconf = nmhetcdir(/mts.conf);
50 static char *localname = "";
51 static char *localdomain = "";
52 static char *systemname = "";
54 char *mmdfldir = MAILSPOOL;
56 char *uucpldir = "/usr/spool/mail";
59 char *mmdlm1 = "\001\001\001\001\n";
60 char *mmdlm2 = "\001\001\001\001\n";
62 /* Cache the username and fullname of the user */
63 static char username[BUFSIZ];
64 static char fullname[BUFSIZ];
66 /* Variables for username masquerading: */
67 boolean draft_from_masquerading = FALSE; /* also used from post.c */
68 static boolean mmailid_masquerading = FALSE;
69 boolean username_extension_masquerading = FALSE; /* " from addrsbr.c */
70 static char* masquerade = "";
73 * MTS specific variables
76 static char *sm_method = "smtp";
77 int sm_mts = MTS_SMTP;
78 char *hostable = nmhetcdir(/hosts);
79 char *sendmail = SENDMAILPATH;
85 char *clientname = NULL;
86 char *servers = "localhost \01localnet";
90 * BBoards-specific variables
96 * POP BBoards-specific variables
100 char *popbbuser = "";
101 char *popbblist = nmhetcdir(/hosts.popbb);
105 * Global MailDelivery file
107 char *maildelivery = nmhetcdir(/maildelivery);
111 * Aliasing Facility (doesn't belong here)
113 int Everyone = NOTOK;
114 static char *everyone = "-1";
118 * Customize the MTS settings for nmh by adjusting
119 * the file mts.conf in the nmh etc directory.
127 static struct bind binds[] = {
128 { "localname", &localname },
129 { "localdomain", &localdomain },
130 { "systemname", &systemname },
131 { "mmdfldir", &mmdfldir },
132 { "mmdflfil", &mmdflfil },
133 { "uucpldir", &uucpldir },
134 { "uucplfil", &uucplfil },
135 { "mmdelim1", &mmdlm1 },
136 { "mmdelim2", &mmdlm2 },
137 { "masquerade", &masquerade },
140 { "mts", &sm_method },
141 { "hostable", &hostable },
142 { "sendmail", &sendmail },
145 { "clientname", &clientname },
146 { "servers", &servers },
147 { "pophost", &pophost },
148 { "bbdomain", &bb_domain },
151 { "popbbhost", &popbbhost },
152 { "popbbuser", &popbbuser },
153 { "popbblist", &popbblist },
157 { "nntphost", &popbbhost },
160 { "maildelivery", &maildelivery },
161 { "everyone", &everyone },
162 { "noshell", &NoShell },
168 * Read the configuration file for the nmh interface
169 * to the mail transport system (MTS).
173 mts_init (char *name)
175 char *bp, *cp, buffer[BUFSIZ];
178 static int inited = 0;
180 if (inited++ || (fp = fopen (mtsconf, "r")) == NULL)
183 while (fgets (buffer, sizeof(buffer), fp)) {
184 if (!(cp = strchr(buffer, '\n')))
187 if (*buffer == '#' || *buffer == '\0')
189 if (!(bp = strchr(buffer, ':')))
192 while (isspace (*bp))
195 for (b = binds; b->keyword; b++)
196 if (!strcmp (buffer, b->keyword))
198 if (b->keyword && (cp = tailor_value (bp)))
204 Everyone = atoi (everyone);
206 if (strstr(masquerade, "draft_from") != NULL)
207 draft_from_masquerading = TRUE;
209 if (strstr(masquerade, "mmailid") != NULL)
210 mmailid_masquerading = TRUE;
212 if (strstr(masquerade, "username_extension") != NULL)
213 username_extension_masquerading = TRUE;
216 if (strcmp(sm_method, "smtp") == 0)
218 else if (strcmp(sm_method, "sendmail") == 0)
219 sm_mts = MTS_SENDMAIL;
221 advise(NULL, "unsupported \"mts\" value in mts.conf: %s", sm_method);
231 * Convert escaped values, malloc some new space,
232 * and copy string to malloc'ed memory.
236 tailor_value (char *s)
243 for (bp = buffer; *s; bp++, s++) {
248 case 'b': *bp = '\b'; break;
249 case 'f': *bp = '\f'; break;
250 case 'n': *bp = '\n'; break;
251 case 't': *bp = '\t'; break;
263 r = *s != '0' ? 10 : 8;
264 for (i = 0; isdigit (*s); s++)
265 i = i * r + *s - '0';
274 len = strlen (buffer) + 1;
275 bp = mh_xmalloc (len);
276 memcpy (bp, buffer, len);
282 * Get the fully qualified name of the local host.
288 static char buffer[BUFSIZ] = "";
295 /* check if we have cached the local name */
301 /* check if the mts.conf file specifies a "localname" */
303 strncpy (buffer, localname, sizeof(buffer));
306 /* first get our local name */
308 strncpy (buffer, name.nodename, sizeof(buffer));
310 /* first get our local name */
311 gethostname (buffer, sizeof(buffer));
313 #ifdef HAVE_SETHOSTENT
316 /* now fully qualify our name */
317 if ((hp = gethostbyname (buffer)))
318 strncpy (buffer, hp->h_name, sizeof(buffer));
322 * If the mts.conf file specifies a "localdomain",
323 * we append that now. This should rarely be needed.
326 strcat (buffer, ".");
327 strcat (buffer, localdomain);
335 * This is only for UUCP mail. It gets the hostname
336 * as part of the UUCP "domain".
342 static char buffer[BUFSIZ] = "";
348 /* check if we have cached the system name */
354 /* check if mts.conf file specifies a "systemname" */
356 strncpy (buffer, systemname, sizeof(buffer));
362 strncpy (buffer, name.nodename, sizeof(buffer));
364 gethostname (buffer, sizeof(buffer));
372 * Get the username of current user
378 if (username[0] == '\0')
386 * Get full name of current user (typically from GECOS
387 * field of password file).
393 if (username[0] == '\0')
401 * Find the user's username and full name, and cache them.
402 * Also, handle "mmailid" username masquerading controlled from the GECOS field
403 * of the passwd file.
409 register char *cp, *np;
410 register struct passwd *pw;
416 if (uid == geteuid () && (cp = getenv ("USER")) != NULL
417 && (pw = getpwnam (cp)) != NULL)
418 strncpy (username, cp, sizeof(username));
419 else if ((pw = getpwuid (uid)) == NULL
420 || pw->pw_name == NULL
421 || *pw->pw_name == '\0') {
423 if ((pw = getpwuid (getuid ())) == NULL
424 || pw->pw_name == NULL
425 || *pw->pw_name == '\0') {
427 strncpy (username, "unknown", sizeof(username));
428 snprintf (fullname, sizeof(fullname), "The Unknown User-ID (%d)",
435 /* Get the user's real name from the GECOS field. Stop once we hit a ',',
436 which some OSes use to separate other 'finger' information in the GECOS
437 field, like phone number. Also, if mmailid masquerading is turned on due
438 to "mmailid" appearing on the "masquerade:" line of mts.conf, stop if we
439 hit a '<' (which should precede any ','s). */
441 if (mmailid_masquerading)
442 /* Stop at ',' or '<'. */
443 for (cp = fullname; *np != '\0' && *np != ',' && *np != '<';
447 /* Allow '<' as a legal character of the user's name. This code is
448 basically a duplicate of the code above the "else" -- we don't
449 collapse it down to one copy and put the mmailid_masquerading check
450 inside the loop with "(x ? y : z)" because that's inefficient and the
451 value'll never change while it's in there. */
452 for (cp = fullname; *np != '\0' && *np != ',';
456 /* On BSD(-derived) systems, the system utilities that deal with the GECOS
457 field (finger, mail, sendmail, etc.) translate any '&' character in it to
458 the login name, with the first letter capitalized. So, for instance,
459 fingering a user "bob" with the GECOS field "& Jones" would reveal him to
460 be "In real life: Bob Jones". Surprisingly, though, the OS doesn't do
461 the translation for you, so we have to do it manually here. */
462 if (mmailid_masquerading)
463 /* Stop at ',' or '<'. */
465 *np != '\0' && *np != ',' && *np != '<';) {
466 if (*np == '&') { /* blech! */
467 strcpy (cp, pw->pw_name);
477 /* Allow '<' as a legal character of the user's name. This code is
478 basically a duplicate of the code above the "else" -- we don't
479 collapse it down to one copy and put the mmailid_masquerading check
480 inside the loop with "(x ? y : z)" because that's inefficient and the
481 value'll never change while it's in there. */
483 *np != '\0' && *np != ',';) {
484 if (*np == '&') { /* blech! */
485 strcpy (cp, pw->pw_name);
497 if (mmailid_masquerading) {
498 /* Do mmailid processing. The GECOS field should have the form
499 "Full Name <fakeusername>". For instance,
500 "Dan Harkless <Dan.Harkless>". Naturally, you'll want your MTA to
501 have an alias (e.g. in /etc/aliases) from "fakeusername" to your
505 for (cp = username; *np && *np != '>'; *cp++ = *np++)
509 if (!mmailid_masquerading || *np == '\0')
510 strncpy (username, pw->pw_name, sizeof(username));
512 /* The $SIGNATURE environment variable overrides the GECOS field's idea of
514 if ((cp = getenv ("SIGNATURE")) && *cp)
515 strncpy (fullname, cp, sizeof(fullname));
517 if (strchr(fullname, '.')) { /* quote any .'s */
520 /* should quote "'s too */
521 snprintf (tmp, sizeof(tmp), "\"%s\"", fullname);
522 strncpy (fullname, tmp, sizeof(fullname));