3 * mts.c -- definitions for the mail transport system
5 * This code is Copyright (c) 2002, by the authors of nmh. See the
6 * COPYRIGHT file in the root directory of the nmh distribution for
7 * complete copyright information.
10 #include <h/mh.h> /* for snprintf() */
14 #define nmhetcdir(file) NMHETCDIR#file
20 #include <sys/socket.h>
26 static char *tailor_value (unsigned char *);
27 static void getuserinfo (void);
28 static const char *get_mtsconf_pathname(void);
29 static const char *get_mtsuserconf_pathname(void);
30 static void mts_read_conf_file (FILE *fp);
33 * *mmdfldir and *uucpldir are the maildrop directories. If maildrops
34 * are kept in the user's home directory, then these should be empty
35 * strings. In this case, the appropriate ...lfil array should contain
36 * the name of the file in the user's home directory. Usually, this is
37 * something like ".mail".
41 * nmh mail transport interface customization file
43 static char *mtsconf = nmhetcdir(/mts.conf);
45 static char *localname = "";
46 static char *localdomain = "";
47 static char *systemname = "";
49 char *mmdfldir = MAILSPOOL;
51 char *uucpldir = "/usr/spool/mail";
54 char *mmdlm1 = "\001\001\001\001\n";
55 char *mmdlm2 = "\001\001\001\001\n";
57 /* Cache the username, fullname, and mailbox of the user */
58 static char username[BUFSIZ];
59 static char fullname[BUFSIZ];
60 static char localmbox[BUFSIZ];
62 /* Variables for username masquerading: */
63 boolean draft_from_masquerading = FALSE; /* also used from post.c */
64 static boolean mmailid_masquerading = FALSE;
65 boolean username_extension_masquerading = FALSE; /* " from addrsbr.c */
66 static char* masquerade = "";
69 * MTS specific variables
71 static char *sm_method = "smtp";
72 int sm_mts = MTS_SMTP;
73 char *hostable = nmhetcdir(/hosts);
74 char *sendmail = SENDMAILPATH;
79 char *clientname = NULL;
80 char *servers = "localhost";
84 * Global MailDelivery file
86 char *maildelivery = nmhetcdir(/maildelivery);
90 * Aliasing Facility (doesn't belong here)
93 static char *everyone = "-1";
97 * Customize the MTS settings for nmh by adjusting
98 * the file mts.conf in the nmh etc directory.
106 static struct bind binds[] = {
107 { "localname", &localname },
108 { "localdomain", &localdomain },
109 { "systemname", &systemname },
110 { "mmdfldir", &mmdfldir },
111 { "mmdflfil", &mmdflfil },
112 { "uucpldir", &uucpldir },
113 { "uucplfil", &uucplfil },
114 { "mmdelim1", &mmdlm1 },
115 { "mmdelim2", &mmdlm2 },
116 { "masquerade", &masquerade },
117 { "mts", &sm_method },
118 { "hostable", &hostable },
119 { "sendmail", &sendmail },
120 { "clientname", &clientname },
121 { "servers", &servers },
122 { "pophost", &pophost },
124 { "maildelivery", &maildelivery },
125 { "everyone", &everyone },
126 { "noshell", &NoShell },
132 * Read the configuration file for the nmh interface
133 * to the mail transport system (MTS).
137 mts_init (char *name)
143 static int inited = 0;
145 if (inited++ || (fp = fopen (get_mtsconf_pathname(), "r")) == NULL)
147 mts_read_conf_file(fp);
150 cp = get_mtsuserconf_pathname();
152 ((fp = fopen (get_mtsuserconf_pathname(), "r")) != NULL)) {
153 mts_read_conf_file(fp);
157 Everyone = atoi (everyone);
159 if (strstr(masquerade, "draft_from") != NULL)
160 draft_from_masquerading = TRUE;
162 if (strstr(masquerade, "mmailid") != NULL)
163 mmailid_masquerading = TRUE;
165 if (strstr(masquerade, "username_extension") != NULL)
166 username_extension_masquerading = TRUE;
168 if (strcmp(sm_method, "smtp") == 0)
170 else if (strcmp(sm_method, "sendmail") == 0)
171 sm_mts = MTS_SENDMAIL;
173 advise(NULL, "unsupported \"mts\" value in mts.conf: %s", sm_method);
182 * Convert escaped values, malloc some new space,
183 * and copy string to malloc'ed memory.
187 tailor_value (unsigned char *s)
194 for (bp = buffer; *s; bp++, s++) {
199 case 'b': *bp = '\b'; break;
200 case 'f': *bp = '\f'; break;
201 case 'n': *bp = '\n'; break;
202 case 't': *bp = '\t'; break;
214 r = *s != '0' ? 10 : 8;
215 for (i = 0; isdigit (*s); s++)
216 i = i * r + *s - '0';
225 len = strlen (buffer) + 1;
226 bp = mh_xmalloc (len);
227 memcpy (bp, buffer, len);
233 * Get the fully qualified name of the local host.
235 * If flag is 0, then use anything out of mts.conf (like localname).
236 * If flag is 1, then only use the "proper" local hostname.
242 static char buffer0[BUFSIZ] = "";
243 static char buffer1[BUFSIZ] = "";
244 static char *buffer[] = { buffer0, buffer1 };
246 struct addrinfo hints, *res;
248 if (flag < 0 || flag > 1)
253 /* check if we have cached the local name */
259 /* check if the mts.conf file specifies a "localname" */
260 if (*localname && flag == 0) {
261 strncpy (buf, localname, sizeof(buffer0));
263 memset(buf, 0, sizeof(buffer0));
264 /* first get our local name */
265 gethostname (buf, sizeof(buffer0) - 1);
266 /* now fully qualify our name */
268 memset(&hints, 0, sizeof(hints));
269 hints.ai_flags = AI_CANONNAME;
270 hints.ai_family = PF_UNSPEC;
271 if (getaddrinfo(buf, NULL, &hints, &res) == 0) {
272 strncpy(buf, res->ai_canonname, sizeof(buffer0) - 1);
278 * If the mts.conf file specifies a "localdomain",
279 * we append that now. This should rarely be needed.
283 strcat (buf, localdomain);
291 * This is only for UUCP mail. It gets the hostname
292 * as part of the UUCP "domain".
298 static char buffer[BUFSIZ] = "";
300 /* check if we have cached the system name */
306 /* check if mts.conf file specifies a "systemname" */
308 strncpy (buffer, systemname, sizeof(buffer));
312 gethostname (buffer, sizeof(buffer));
319 * Get the username of current user
325 if (username[0] == '\0')
333 * Get full name of current user (typically from GECOS
334 * field of password file).
340 if (username[0] == '\0')
348 * Get the full local mailbox name. This is in the form:
350 * User Name <user@name.com>
356 if (username[0] == '\0')
359 if (localmbox[0] == '\0') {
362 if ((cp = context_find("Local-Mailbox")) != NULL) {
363 strncpy(localmbox, cp, sizeof(localmbox));
365 snprintf(localmbox, sizeof(localmbox), "%s <%s@%s>", fullname,
366 username, LocalName(0));
369 localmbox[sizeof(localmbox) - 1] = '\0';
376 * Find the user's username and full name, and cache them.
377 * Also, handle "mmailid" username masquerading controlled from the GECOS field
378 * of the passwd file.
384 register unsigned char *cp;
386 register struct passwd *pw;
388 if ((pw = getpwuid (getuid ())) == NULL
389 || pw->pw_name == NULL
390 || *pw->pw_name == '\0') {
391 strncpy (username, "unknown", sizeof(username));
392 snprintf (fullname, sizeof(fullname), "The Unknown User-ID (%d)",
399 /* Get the user's real name from the GECOS field. Stop once we hit a ',',
400 which some OSes use to separate other 'finger' information in the GECOS
401 field, like phone number. Also, if mmailid masquerading is turned on due
402 to "mmailid" appearing on the "masquerade:" line of mts.conf, stop if we
403 hit a '<' (which should precede any ','s). */
404 if (mmailid_masquerading)
405 /* Stop at ',' or '<'. */
406 for (cp = fullname; *np != '\0' && *np != ',' && *np != '<';
410 /* Allow '<' as a legal character of the user's name. This code is
411 basically a duplicate of the code above the "else" -- we don't
412 collapse it down to one copy and put the mmailid_masquerading check
413 inside the loop with "(x ? y : z)" because that's inefficient and the
414 value'll never change while it's in there. */
415 for (cp = fullname; *np != '\0' && *np != ',';
420 if (mmailid_masquerading) {
421 /* Do mmailid processing. The GECOS field should have the form
422 "Full Name <fakeusername>". For instance,
423 "Dan Harkless <Dan.Harkless>". Naturally, you'll want your MTA to
424 have an alias (e.g. in /etc/aliases) from "fakeusername" to your
428 for (cp = username; *np && *np != '>'; *cp++ = *np++)
432 if (!mmailid_masquerading || *np == '\0')
433 strncpy (username, pw->pw_name, sizeof(username));
435 /* The $SIGNATURE environment variable overrides the GECOS field's idea of
436 your real name. If SIGNATURE isn't set, use the Signature profile
437 setting if it exists. */
438 if ((cp = getenv ("SIGNATURE")) && *cp)
439 strncpy (fullname, cp, sizeof(fullname));
440 else if ((cp = context_find("Signature")))
441 strncpy (fullname, cp, sizeof(fullname));
443 if (strchr(fullname, '.')) { /* quote any .'s */
446 /* should quote "'s too */
447 snprintf (tmp, sizeof(tmp), "\"%s\"", fullname);
448 strncpy (fullname, tmp, sizeof(fullname));
451 fullname[sizeof(fullname) - 1] = '\0';
459 get_mtsconf_pathname (void)
461 const char *cp = getenv ( "MHMTSCONF" );
462 if (cp != NULL && *cp != '\0') {
469 get_mtsuserconf_pathname (void)
471 const char *cp = getenv ( "MHMTSUSERCONF" );
472 if (cp != NULL && *cp != '\0') {
479 mts_read_conf_file (FILE *fp)
482 char *cp, buffer[BUFSIZ];
485 while (fgets (buffer, sizeof(buffer), fp)) {
486 if (!(cp = strchr(buffer, '\n')))
489 if (*buffer == '#' || *buffer == '\0')
491 if (!(bp = strchr(buffer, ':')))
494 while (isspace (*bp))
497 for (b = binds; b->keyword; b++)
498 if (!strcmp (buffer, b->keyword))
500 if (b->keyword && (cp = tailor_value (bp)))