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 and fullname of the user */
58 static char username[BUFSIZ];
59 static char fullname[BUFSIZ];
61 /* Variables for username masquerading: */
62 boolean draft_from_masquerading = FALSE; /* also used from post.c */
63 static boolean mmailid_masquerading = FALSE;
64 boolean username_extension_masquerading = FALSE; /* " from addrsbr.c */
65 static char* masquerade = "";
68 * MTS specific variables
71 static char *sm_method = "smtp";
72 int sm_mts = MTS_SMTP;
73 char *hostable = nmhetcdir(/hosts);
74 char *sendmail = SENDMAILPATH;
80 char *clientname = NULL;
81 char *servers = "localhost \01localnet";
85 * Global MailDelivery file
87 char *maildelivery = nmhetcdir(/maildelivery);
91 * Aliasing Facility (doesn't belong here)
94 static char *everyone = "-1";
98 * Customize the MTS settings for nmh by adjusting
99 * the file mts.conf in the nmh etc directory.
107 static struct bind binds[] = {
108 { "localname", &localname },
109 { "localdomain", &localdomain },
110 { "systemname", &systemname },
111 { "mmdfldir", &mmdfldir },
112 { "mmdflfil", &mmdflfil },
113 { "uucpldir", &uucpldir },
114 { "uucplfil", &uucplfil },
115 { "mmdelim1", &mmdlm1 },
116 { "mmdelim2", &mmdlm2 },
117 { "masquerade", &masquerade },
120 { "mts", &sm_method },
121 { "hostable", &hostable },
122 { "sendmail", &sendmail },
125 { "clientname", &clientname },
126 { "servers", &servers },
127 { "pophost", &pophost },
129 { "maildelivery", &maildelivery },
130 { "everyone", &everyone },
131 { "noshell", &NoShell },
137 * Read the configuration file for the nmh interface
138 * to the mail transport system (MTS).
142 mts_init (char *name)
146 static int inited = 0;
148 if (inited++ || (fp = fopen (get_mtsconf_pathname(), "r")) == NULL)
150 mts_read_conf_file(fp);
153 cp = get_mtsuserconf_pathname();
155 ((fp = fopen (get_mtsuserconf_pathname(), "r")) != NULL)) {
156 mts_read_conf_file(fp);
160 Everyone = atoi (everyone);
162 if (strstr(masquerade, "draft_from") != NULL)
163 draft_from_masquerading = TRUE;
165 if (strstr(masquerade, "mmailid") != NULL)
166 mmailid_masquerading = TRUE;
168 if (strstr(masquerade, "username_extension") != NULL)
169 username_extension_masquerading = TRUE;
172 if (strcmp(sm_method, "smtp") == 0)
174 else if (strcmp(sm_method, "sendmail") == 0)
175 sm_mts = MTS_SENDMAIL;
177 advise(NULL, "unsupported \"mts\" value in mts.conf: %s", sm_method);
187 * Convert escaped values, malloc some new space,
188 * and copy string to malloc'ed memory.
192 tailor_value (unsigned char *s)
199 for (bp = buffer; *s; bp++, s++) {
204 case 'b': *bp = '\b'; break;
205 case 'f': *bp = '\f'; break;
206 case 'n': *bp = '\n'; break;
207 case 't': *bp = '\t'; break;
219 r = *s != '0' ? 10 : 8;
220 for (i = 0; isdigit (*s); s++)
221 i = i * r + *s - '0';
230 len = strlen (buffer) + 1;
231 bp = mh_xmalloc (len);
232 memcpy (bp, buffer, len);
238 * Get the fully qualified name of the local host.
244 static char buffer[BUFSIZ] = "";
245 struct addrinfo hints, *res;
247 /* check if we have cached the local name */
253 /* check if the mts.conf file specifies a "localname" */
255 strncpy (buffer, localname, sizeof(buffer));
257 memset(buffer, 0, sizeof(buffer));
258 /* first get our local name */
259 gethostname (buffer, sizeof(buffer) - 1);
260 /* now fully qualify our name */
262 memset(&hints, 0, sizeof(hints));
263 hints.ai_flags = AI_CANONNAME;
264 hints.ai_family = PF_UNSPEC;
265 if (getaddrinfo(buffer, NULL, &hints, &res) == 0) {
266 strncpy(buffer, res->ai_canonname, sizeof(buffer) - 1);
272 * If the mts.conf file specifies a "localdomain",
273 * we append that now. This should rarely be needed.
276 strcat (buffer, ".");
277 strcat (buffer, localdomain);
285 * This is only for UUCP mail. It gets the hostname
286 * as part of the UUCP "domain".
292 static char buffer[BUFSIZ] = "";
294 /* check if we have cached the system name */
300 /* check if mts.conf file specifies a "systemname" */
302 strncpy (buffer, systemname, sizeof(buffer));
306 gethostname (buffer, sizeof(buffer));
313 * Get the username of current user
319 if (username[0] == '\0')
327 * Get full name of current user (typically from GECOS
328 * field of password file).
334 if (username[0] == '\0')
342 * Find the user's username and full name, and cache them.
343 * Also, handle "mmailid" username masquerading controlled from the GECOS field
344 * of the passwd file.
350 register unsigned char *cp;
352 register struct passwd *pw;
354 if ((pw = getpwuid (getuid ())) == NULL
355 || pw->pw_name == NULL
356 || *pw->pw_name == '\0') {
357 strncpy (username, "unknown", sizeof(username));
358 snprintf (fullname, sizeof(fullname), "The Unknown User-ID (%d)",
365 /* Get the user's real name from the GECOS field. Stop once we hit a ',',
366 which some OSes use to separate other 'finger' information in the GECOS
367 field, like phone number. Also, if mmailid masquerading is turned on due
368 to "mmailid" appearing on the "masquerade:" line of mts.conf, stop if we
369 hit a '<' (which should precede any ','s). */
370 if (mmailid_masquerading)
371 /* Stop at ',' or '<'. */
372 for (cp = fullname; *np != '\0' && *np != ',' && *np != '<';
376 /* Allow '<' as a legal character of the user's name. This code is
377 basically a duplicate of the code above the "else" -- we don't
378 collapse it down to one copy and put the mmailid_masquerading check
379 inside the loop with "(x ? y : z)" because that's inefficient and the
380 value'll never change while it's in there. */
381 for (cp = fullname; *np != '\0' && *np != ',';
386 if (mmailid_masquerading) {
387 /* Do mmailid processing. The GECOS field should have the form
388 "Full Name <fakeusername>". For instance,
389 "Dan Harkless <Dan.Harkless>". Naturally, you'll want your MTA to
390 have an alias (e.g. in /etc/aliases) from "fakeusername" to your
394 for (cp = username; *np && *np != '>'; *cp++ = *np++)
398 if (!mmailid_masquerading || *np == '\0')
399 strncpy (username, pw->pw_name, sizeof(username));
401 /* The $SIGNATURE environment variable overrides the GECOS field's idea of
403 if ((cp = getenv ("SIGNATURE")) && *cp)
404 strncpy (fullname, cp, sizeof(fullname));
406 if (strchr(fullname, '.')) { /* quote any .'s */
409 /* should quote "'s too */
410 snprintf (tmp, sizeof(tmp), "\"%s\"", fullname);
411 strncpy (fullname, tmp, sizeof(fullname));
418 get_mtsconf_pathname (void)
420 const char *cp = getenv ( "MHMTSCONF ");
421 if (cp != NULL && *cp != '\0') {
428 get_mtsuserconf_pathname (void)
430 const char *cp = getenv ( "MHMTSUSERCONF" );
431 if (cp != NULL && *cp != '\0') {
438 mts_read_conf_file (FILE *fp)
441 char *cp, buffer[BUFSIZ];
444 while (fgets (buffer, sizeof(buffer), fp)) {
445 if (!(cp = strchr(buffer, '\n')))
448 if (*buffer == '#' || *buffer == '\0')
450 if (!(bp = strchr(buffer, ':')))
453 while (isspace (*bp))
456 for (b = binds; b->keyword; b++)
457 if (!strcmp (buffer, b->keyword))
459 if (b->keyword && (cp = tailor_value (bp)))