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
72 static char *sm_method = "smtp";
73 int sm_mts = MTS_SMTP;
74 char *hostable = nmhetcdir(/hosts);
75 char *sendmail = SENDMAILPATH;
81 char *clientname = NULL;
82 char *servers = "localhost";
86 * Global MailDelivery file
88 char *maildelivery = nmhetcdir(/maildelivery);
92 * Aliasing Facility (doesn't belong here)
95 static char *everyone = "-1";
99 * Customize the MTS settings for nmh by adjusting
100 * the file mts.conf in the nmh etc directory.
108 static struct bind binds[] = {
109 { "localname", &localname },
110 { "localdomain", &localdomain },
111 { "systemname", &systemname },
112 { "mmdfldir", &mmdfldir },
113 { "mmdflfil", &mmdflfil },
114 { "uucpldir", &uucpldir },
115 { "uucplfil", &uucplfil },
116 { "mmdelim1", &mmdlm1 },
117 { "mmdelim2", &mmdlm2 },
118 { "masquerade", &masquerade },
121 { "mts", &sm_method },
122 { "hostable", &hostable },
123 { "sendmail", &sendmail },
126 { "clientname", &clientname },
127 { "servers", &servers },
128 { "pophost", &pophost },
130 { "maildelivery", &maildelivery },
131 { "everyone", &everyone },
132 { "noshell", &NoShell },
138 * Read the configuration file for the nmh interface
139 * to the mail transport system (MTS).
143 mts_init (char *name)
149 static int inited = 0;
151 if (inited++ || (fp = fopen (get_mtsconf_pathname(), "r")) == NULL)
153 mts_read_conf_file(fp);
156 cp = get_mtsuserconf_pathname();
158 ((fp = fopen (get_mtsuserconf_pathname(), "r")) != NULL)) {
159 mts_read_conf_file(fp);
163 Everyone = atoi (everyone);
165 if (strstr(masquerade, "draft_from") != NULL)
166 draft_from_masquerading = TRUE;
168 if (strstr(masquerade, "mmailid") != NULL)
169 mmailid_masquerading = TRUE;
171 if (strstr(masquerade, "username_extension") != NULL)
172 username_extension_masquerading = TRUE;
175 if (strcmp(sm_method, "smtp") == 0)
177 else if (strcmp(sm_method, "sendmail") == 0)
178 sm_mts = MTS_SENDMAIL;
180 advise(NULL, "unsupported \"mts\" value in mts.conf: %s", sm_method);
190 * Convert escaped values, malloc some new space,
191 * and copy string to malloc'ed memory.
195 tailor_value (unsigned char *s)
202 for (bp = buffer; *s; bp++, s++) {
207 case 'b': *bp = '\b'; break;
208 case 'f': *bp = '\f'; break;
209 case 'n': *bp = '\n'; break;
210 case 't': *bp = '\t'; break;
222 r = *s != '0' ? 10 : 8;
223 for (i = 0; isdigit (*s); s++)
224 i = i * r + *s - '0';
233 len = strlen (buffer) + 1;
234 bp = mh_xmalloc (len);
235 memcpy (bp, buffer, len);
241 * Get the fully qualified name of the local host.
243 * If flag is 0, then use anything out of mts.conf (like localname).
244 * If flag is 1, then only use the "proper" local hostname.
250 static char buffer0[BUFSIZ] = "";
251 static char buffer1[BUFSIZ] = "";
252 static char *buffer[] = { buffer0, buffer1 };
254 struct addrinfo hints, *res;
256 if (flag < 0 || flag > 1)
261 /* check if we have cached the local name */
267 /* check if the mts.conf file specifies a "localname" */
268 if (*localname && flag == 0) {
269 strncpy (buf, localname, sizeof(buffer0));
271 memset(buf, 0, sizeof(buffer0));
272 /* first get our local name */
273 gethostname (buf, sizeof(buffer0) - 1);
274 /* now fully qualify our name */
276 memset(&hints, 0, sizeof(hints));
277 hints.ai_flags = AI_CANONNAME;
278 hints.ai_family = PF_UNSPEC;
279 if (getaddrinfo(buf, NULL, &hints, &res) == 0) {
280 strncpy(buf, res->ai_canonname, sizeof(buffer0) - 1);
286 * If the mts.conf file specifies a "localdomain",
287 * we append that now. This should rarely be needed.
291 strcat (buf, localdomain);
299 * This is only for UUCP mail. It gets the hostname
300 * as part of the UUCP "domain".
306 static char buffer[BUFSIZ] = "";
308 /* check if we have cached the system name */
314 /* check if mts.conf file specifies a "systemname" */
316 strncpy (buffer, systemname, sizeof(buffer));
320 gethostname (buffer, sizeof(buffer));
327 * Get the username of current user
333 if (username[0] == '\0')
341 * Get full name of current user (typically from GECOS
342 * field of password file).
348 if (username[0] == '\0')
356 * Get the full local mailbox name. This is in the form:
358 * User Name <user@name.com>
364 if (username[0] == '\0')
367 if (localmbox[0] == '\0') {
370 if ((cp = context_find("Local-Mailbox")) != NULL) {
371 strncpy(localmbox, cp, sizeof(localmbox));
373 snprintf(localmbox, sizeof(localmbox), "%s <%s@%s>", fullname,
374 username, LocalName(0));
377 localmbox[sizeof(localmbox) - 1] = '\0';
384 * Find the user's username and full name, and cache them.
385 * Also, handle "mmailid" username masquerading controlled from the GECOS field
386 * of the passwd file.
392 register unsigned char *cp;
394 register struct passwd *pw;
396 if ((pw = getpwuid (getuid ())) == NULL
397 || pw->pw_name == NULL
398 || *pw->pw_name == '\0') {
399 strncpy (username, "unknown", sizeof(username));
400 snprintf (fullname, sizeof(fullname), "The Unknown User-ID (%d)",
407 /* Get the user's real name from the GECOS field. Stop once we hit a ',',
408 which some OSes use to separate other 'finger' information in the GECOS
409 field, like phone number. Also, if mmailid masquerading is turned on due
410 to "mmailid" appearing on the "masquerade:" line of mts.conf, stop if we
411 hit a '<' (which should precede any ','s). */
412 if (mmailid_masquerading)
413 /* Stop at ',' or '<'. */
414 for (cp = fullname; *np != '\0' && *np != ',' && *np != '<';
418 /* Allow '<' as a legal character of the user's name. This code is
419 basically a duplicate of the code above the "else" -- we don't
420 collapse it down to one copy and put the mmailid_masquerading check
421 inside the loop with "(x ? y : z)" because that's inefficient and the
422 value'll never change while it's in there. */
423 for (cp = fullname; *np != '\0' && *np != ',';
428 if (mmailid_masquerading) {
429 /* Do mmailid processing. The GECOS field should have the form
430 "Full Name <fakeusername>". For instance,
431 "Dan Harkless <Dan.Harkless>". Naturally, you'll want your MTA to
432 have an alias (e.g. in /etc/aliases) from "fakeusername" to your
436 for (cp = username; *np && *np != '>'; *cp++ = *np++)
440 if (!mmailid_masquerading || *np == '\0')
441 strncpy (username, pw->pw_name, sizeof(username));
443 /* The $SIGNATURE environment variable overrides the GECOS field's idea of
444 your real name. If SIGNATURE isn't set, use the Signature profile
445 setting if it exists. */
446 if ((cp = getenv ("SIGNATURE")) && *cp)
447 strncpy (fullname, cp, sizeof(fullname));
448 else if ((cp = context_find("Signature")))
449 strncpy (fullname, cp, sizeof(fullname));
451 if (strchr(fullname, '.')) { /* quote any .'s */
454 /* should quote "'s too */
455 snprintf (tmp, sizeof(tmp), "\"%s\"", fullname);
456 strncpy (fullname, tmp, sizeof(fullname));
459 fullname[sizeof(fullname) - 1] = '\0';
467 get_mtsconf_pathname (void)
469 const char *cp = getenv ( "MHMTSCONF" );
470 if (cp != NULL && *cp != '\0') {
477 get_mtsuserconf_pathname (void)
479 const char *cp = getenv ( "MHMTSUSERCONF" );
480 if (cp != NULL && *cp != '\0') {
487 mts_read_conf_file (FILE *fp)
490 char *cp, buffer[BUFSIZ];
493 while (fgets (buffer, sizeof(buffer), fp)) {
494 if (!(cp = strchr(buffer, '\n')))
497 if (*buffer == '#' || *buffer == '\0')
499 if (!(bp = strchr(buffer, ':')))
502 while (isspace (*bp))
505 for (b = binds; b->keyword; b++)
506 if (!strcmp (buffer, b->keyword))
508 if (b->keyword && (cp = tailor_value (bp)))