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
22 #ifdef HAVE_SYS_UTSNAME_H
23 # include <sys/utsname.h>
32 static char *tailor_value (unsigned char *);
33 static void getuserinfo (void);
34 static const char *get_mtsconf_pathname(void);
35 static const char *get_mtsuserconf_pathname(void);
36 static void mts_read_conf_file (FILE *fp);
39 * *mmdfldir and *uucpldir are the maildrop directories. If maildrops
40 * are kept in the user's home directory, then these should be empty
41 * strings. In this case, the appropriate ...lfil array should contain
42 * the name of the file in the user's home directory. Usually, this is
43 * something like ".mail".
47 * nmh mail transport interface customization file
49 static char *mtsconf = nmhetcdir(/mts.conf);
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;
65 static boolean mmailid_masquerading = FALSE;
66 boolean username_extension_masquerading = FALSE; /* " from addrsbr.c */
67 static char* masquerade = "";
70 * Global MailDelivery file
72 char *maildelivery = nmhetcdir(/maildelivery);
76 * Aliasing Facility (doesn't belong here)
79 static char *everyone = "-1";
83 * Customize the MTS settings for nmh by adjusting
84 * the file mts.conf in the nmh etc directory.
92 static struct bind binds[] = {
93 { "mmdfldir", &mmdfldir },
94 { "mmdflfil", &mmdflfil },
95 { "uucpldir", &uucpldir },
96 { "uucplfil", &uucplfil },
97 { "mmdelim1", &mmdlm1 },
98 { "mmdelim2", &mmdlm2 },
99 { "masquerade", &masquerade },
100 { "maildelivery", &maildelivery },
101 { "everyone", &everyone },
102 { "noshell", &NoShell },
108 * Read the configuration file for the nmh interface
109 * to the mail transport system (MTS).
113 mts_init (char *name)
117 static int inited = 0;
119 if (inited++ || (fp = fopen (get_mtsconf_pathname(), "r")) == NULL)
121 mts_read_conf_file(fp);
124 cp = get_mtsuserconf_pathname();
126 ((fp = fopen (get_mtsuserconf_pathname(), "r")) != NULL)) {
127 mts_read_conf_file(fp);
131 Everyone = atoi (everyone);
133 if (strstr(masquerade, "draft_from") != NULL)
134 draft_from_masquerading = TRUE;
136 if (strstr(masquerade, "mmailid") != NULL)
137 mmailid_masquerading = TRUE;
139 if (strstr(masquerade, "username_extension") != NULL)
140 username_extension_masquerading = TRUE;
147 * Convert escaped values, malloc some new space,
148 * and copy string to malloc'ed memory.
152 tailor_value (unsigned char *s)
159 for (bp = buffer; *s; bp++, s++) {
164 case 'b': *bp = '\b'; break;
165 case 'f': *bp = '\f'; break;
166 case 'n': *bp = '\n'; break;
167 case 't': *bp = '\t'; break;
179 r = *s != '0' ? 10 : 8;
180 for (i = 0; isdigit (*s); s++)
181 i = i * r + *s - '0';
190 len = strlen (buffer) + 1;
191 bp = mh_xmalloc (len);
192 memcpy (bp, buffer, len);
198 * Get the fully qualified name of the local host.
204 static char buffer[BUFSIZ] = "";
205 struct addrinfo hints, *res;
210 /* check if we have cached the local name */
216 memset(buffer, 0, sizeof(buffer));
218 /* first get our local name */
220 strncpy (buffer, name.nodename, sizeof(buffer) - 1);
222 /* first get our local name */
223 gethostname (buffer, sizeof(buffer) - 1);
225 /* now fully qualify our name */
227 memset(&hints, 0, sizeof(hints));
228 hints.ai_flags = AI_CANONNAME;
229 hints.ai_family = PF_UNSPEC;
230 if (getaddrinfo(buffer, NULL, &hints, &res) == 0) {
231 strncpy(buffer, res->ai_canonname, sizeof(buffer) - 1);
240 * This is only for UUCP mail. It gets the hostname
241 * as part of the UUCP "domain".
247 static char buffer[BUFSIZ] = "";
253 /* check if we have cached the system name */
261 strncpy (buffer, name.nodename, sizeof(buffer));
263 gethostname (buffer, sizeof(buffer));
271 * Get the username of current user
277 if (username[0] == '\0')
285 * Get full name of current user (typically from GECOS
286 * field of password file).
292 if (username[0] == '\0')
300 * Find the user's username and full name, and cache them.
301 * Also, handle "mmailid" username masquerading controlled from the GECOS field
302 * of the passwd file.
308 register unsigned char *cp;
310 register struct passwd *pw;
312 if ((pw = getpwuid (getuid ())) == NULL
313 || pw->pw_name == NULL
314 || *pw->pw_name == '\0') {
315 strncpy (username, "unknown", sizeof(username));
316 snprintf (fullname, sizeof(fullname), "The Unknown User-ID (%d)",
323 /* Get the user's real name from the GECOS field. Stop once we hit a ',',
324 which some OSes use to separate other 'finger' information in the GECOS
325 field, like phone number. Also, if mmailid masquerading is turned on due
326 to "mmailid" appearing on the "masquerade:" line of mts.conf, stop if we
327 hit a '<' (which should precede any ','s). */
329 if (mmailid_masquerading)
330 /* Stop at ',' or '<'. */
331 for (cp = fullname; *np != '\0' && *np != ',' && *np != '<';
335 /* Allow '<' as a legal character of the user's name. This code is
336 basically a duplicate of the code above the "else" -- we don't
337 collapse it down to one copy and put the mmailid_masquerading check
338 inside the loop with "(x ? y : z)" because that's inefficient and the
339 value'll never change while it's in there. */
340 for (cp = fullname; *np != '\0' && *np != ',';
344 /* On BSD(-derived) systems, the system utilities that deal with the GECOS
345 field (finger, mail, sendmail, etc.) translate any '&' character in it to
346 the login name, with the first letter capitalized. So, for instance,
347 fingering a user "bob" with the GECOS field "& Jones" would reveal him to
348 be "In real life: Bob Jones". Surprisingly, though, the OS doesn't do
349 the translation for you, so we have to do it manually here. */
350 if (mmailid_masquerading)
351 /* Stop at ',' or '<'. */
353 *np != '\0' && *np != ',' && *np != '<';) {
354 if (*np == '&') { /* blech! */
355 strcpy (cp, pw->pw_name);
365 /* Allow '<' as a legal character of the user's name. This code is
366 basically a duplicate of the code above the "else" -- we don't
367 collapse it down to one copy and put the mmailid_masquerading check
368 inside the loop with "(x ? y : z)" because that's inefficient and the
369 value'll never change while it's in there. */
371 *np != '\0' && *np != ',';) {
372 if (*np == '&') { /* blech! */
373 strcpy (cp, pw->pw_name);
385 if (mmailid_masquerading) {
386 /* Do mmailid processing. The GECOS field should have the form
387 "Full Name <fakeusername>". For instance,
388 "Dan Harkless <Dan.Harkless>". Naturally, you'll want your MTA to
389 have an alias (e.g. in /etc/aliases) from "fakeusername" to your
393 for (cp = username; *np && *np != '>'; *cp++ = *np++)
397 if (!mmailid_masquerading || *np == '\0')
398 strncpy (username, pw->pw_name, sizeof(username));
400 /* The $SIGNATURE environment variable overrides the GECOS field's idea of
402 if ((cp = getenv ("SIGNATURE")) && *cp)
403 strncpy (fullname, cp, sizeof(fullname));
405 if (strchr(fullname, '.')) { /* quote any .'s */
408 /* should quote "'s too */
409 snprintf (tmp, sizeof(tmp), "\"%s\"", fullname);
410 strncpy (fullname, tmp, sizeof(fullname));
417 get_mtsconf_pathname (void)
419 const char *cp = getenv ( "MHMTSCONF ");
420 if (cp != NULL && *cp != '\0') {
427 get_mtsuserconf_pathname (void)
429 const char *cp = getenv ( "MHMTSUSERCONF" );
430 if (cp != NULL && *cp != '\0') {
437 mts_read_conf_file (FILE *fp)
440 char *cp, buffer[BUFSIZ];
443 while (fgets (buffer, sizeof(buffer), fp)) {
444 if (!(cp = strchr(buffer, '\n')))
447 if (*buffer == '#' || *buffer == '\0')
449 if (!(bp = strchr(buffer, ':')))
452 while (isspace (*bp))
455 for (b = binds; b->keyword; b++)
456 if (!strcmp (buffer, b->keyword))
458 if (b->keyword && (cp = tailor_value (bp)))