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)
148 static int inited = 0;
150 if (inited++ || (fp = fopen (get_mtsconf_pathname(), "r")) == NULL)
152 mts_read_conf_file(fp);
155 cp = get_mtsuserconf_pathname();
157 ((fp = fopen (get_mtsuserconf_pathname(), "r")) != NULL)) {
158 mts_read_conf_file(fp);
162 Everyone = atoi (everyone);
164 if (strstr(masquerade, "draft_from") != NULL)
165 draft_from_masquerading = TRUE;
167 if (strstr(masquerade, "mmailid") != NULL)
168 mmailid_masquerading = TRUE;
170 if (strstr(masquerade, "username_extension") != NULL)
171 username_extension_masquerading = TRUE;
174 if (strcmp(sm_method, "smtp") == 0)
176 else if (strcmp(sm_method, "sendmail") == 0)
177 sm_mts = MTS_SENDMAIL;
179 advise(NULL, "unsupported \"mts\" value in mts.conf: %s", sm_method);
189 * Convert escaped values, malloc some new space,
190 * and copy string to malloc'ed memory.
194 tailor_value (unsigned char *s)
201 for (bp = buffer; *s; bp++, s++) {
206 case 'b': *bp = '\b'; break;
207 case 'f': *bp = '\f'; break;
208 case 'n': *bp = '\n'; break;
209 case 't': *bp = '\t'; break;
221 r = *s != '0' ? 10 : 8;
222 for (i = 0; isdigit (*s); s++)
223 i = i * r + *s - '0';
232 len = strlen (buffer) + 1;
233 bp = mh_xmalloc (len);
234 memcpy (bp, buffer, len);
240 * Get the fully qualified name of the local host.
246 static char buffer[BUFSIZ] = "";
247 struct addrinfo hints, *res;
249 /* check if we have cached the local name */
255 /* check if the mts.conf file specifies a "localname" */
257 strncpy (buffer, localname, sizeof(buffer));
259 memset(buffer, 0, sizeof(buffer));
260 /* first get our local name */
261 gethostname (buffer, sizeof(buffer) - 1);
262 /* now fully qualify our name */
264 memset(&hints, 0, sizeof(hints));
265 hints.ai_flags = AI_CANONNAME;
266 hints.ai_family = PF_UNSPEC;
267 if (getaddrinfo(buffer, NULL, &hints, &res) == 0) {
268 strncpy(buffer, res->ai_canonname, sizeof(buffer) - 1);
274 * If the mts.conf file specifies a "localdomain",
275 * we append that now. This should rarely be needed.
278 strcat (buffer, ".");
279 strcat (buffer, localdomain);
287 * This is only for UUCP mail. It gets the hostname
288 * as part of the UUCP "domain".
294 static char buffer[BUFSIZ] = "";
296 /* check if we have cached the system name */
302 /* check if mts.conf file specifies a "systemname" */
304 strncpy (buffer, systemname, sizeof(buffer));
308 gethostname (buffer, sizeof(buffer));
315 * Get the username of current user
321 if (username[0] == '\0')
329 * Get full name of current user (typically from GECOS
330 * field of password file).
336 if (username[0] == '\0')
344 * Find the user's username and full name, and cache them.
345 * Also, handle "mmailid" username masquerading controlled from the GECOS field
346 * of the passwd file.
352 register unsigned char *cp;
354 register struct passwd *pw;
356 if ((pw = getpwuid (getuid ())) == NULL
357 || pw->pw_name == NULL
358 || *pw->pw_name == '\0') {
359 strncpy (username, "unknown", sizeof(username));
360 snprintf (fullname, sizeof(fullname), "The Unknown User-ID (%d)",
367 /* Get the user's real name from the GECOS field. Stop once we hit a ',',
368 which some OSes use to separate other 'finger' information in the GECOS
369 field, like phone number. Also, if mmailid masquerading is turned on due
370 to "mmailid" appearing on the "masquerade:" line of mts.conf, stop if we
371 hit a '<' (which should precede any ','s). */
372 if (mmailid_masquerading)
373 /* Stop at ',' or '<'. */
374 for (cp = fullname; *np != '\0' && *np != ',' && *np != '<';
378 /* Allow '<' as a legal character of the user's name. This code is
379 basically a duplicate of the code above the "else" -- we don't
380 collapse it down to one copy and put the mmailid_masquerading check
381 inside the loop with "(x ? y : z)" because that's inefficient and the
382 value'll never change while it's in there. */
383 for (cp = fullname; *np != '\0' && *np != ',';
388 if (mmailid_masquerading) {
389 /* Do mmailid processing. The GECOS field should have the form
390 "Full Name <fakeusername>". For instance,
391 "Dan Harkless <Dan.Harkless>". Naturally, you'll want your MTA to
392 have an alias (e.g. in /etc/aliases) from "fakeusername" to your
396 for (cp = username; *np && *np != '>'; *cp++ = *np++)
400 if (!mmailid_masquerading || *np == '\0')
401 strncpy (username, pw->pw_name, sizeof(username));
403 /* The $SIGNATURE environment variable overrides the GECOS field's idea of
405 if ((cp = getenv ("SIGNATURE")) && *cp)
406 strncpy (fullname, cp, sizeof(fullname));
408 if (strchr(fullname, '.')) { /* quote any .'s */
411 /* should quote "'s too */
412 snprintf (tmp, sizeof(tmp), "\"%s\"", fullname);
413 strncpy (fullname, tmp, sizeof(fullname));
420 get_mtsconf_pathname (void)
422 const char *cp = getenv ( "MHMTSCONF ");
423 if (cp != NULL && *cp != '\0') {
430 get_mtsuserconf_pathname (void)
432 const char *cp = getenv ( "MHMTSUSERCONF" );
433 if (cp != NULL && *cp != '\0') {
440 mts_read_conf_file (FILE *fp)
443 char *cp, buffer[BUFSIZ];
446 while (fgets (buffer, sizeof(buffer), fp)) {
447 if (!(cp = strchr(buffer, '\n')))
450 if (*buffer == '#' || *buffer == '\0')
452 if (!(bp = strchr(buffer, ':')))
455 while (isspace (*bp))
458 for (b = binds; b->keyword; b++)
459 if (!strcmp (buffer, b->keyword))
461 if (b->keyword && (cp = tailor_value (bp)))