]> diplodocus.org Git - nmh/blob - sbr/mts.c
Ignore a.out.DSYM (this file sometims shows up when using the debugger)
[nmh] / sbr / mts.c
1
2 /*
3 * mts.c -- definitions for the mail transport system
4 *
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.
8 */
9
10 #include <h/mh.h> /* for snprintf() */
11 #include <h/nmh.h>
12 #include <h/utils.h>
13
14 #define nmhetcdir(file) NMHETCDIR#file
15
16 #include <ctype.h>
17 #include <stdio.h>
18 #include <h/mts.h>
19 #include <pwd.h>
20 #include <sys/socket.h>
21 #include <netdb.h>
22
23 #define NOTOK (-1)
24 #define OK 0
25
26 /*
27 * static prototypes
28 */
29 static char *tailor_value (unsigned char *);
30 static void getuserinfo (void);
31 static const char *get_mtsconf_pathname(void);
32 static const char *get_mtsuserconf_pathname(void);
33 static void mts_read_conf_file (FILE *fp);
34
35 /*
36 * *mmdfldir and *uucpldir are the maildrop directories. If maildrops
37 * are kept in the user's home directory, then these should be empty
38 * strings. In this case, the appropriate ...lfil array should contain
39 * the name of the file in the user's home directory. Usually, this is
40 * something like ".mail".
41 */
42
43 /*
44 * nmh mail transport interface customization file
45 */
46 static char *mtsconf = nmhetcdir(/mts.conf);
47
48 static char *localname = "";
49 static char *localdomain = "";
50 static char *systemname = "";
51
52 char *mmdfldir = MAILSPOOL;
53 char *mmdflfil = "";
54 char *uucpldir = "/usr/spool/mail";
55 char *uucplfil = "";
56
57 char *mmdlm1 = "\001\001\001\001\n";
58 char *mmdlm2 = "\001\001\001\001\n";
59
60 /* Cache the username and fullname of the user */
61 static char username[BUFSIZ];
62 static char fullname[BUFSIZ];
63
64 /* Variables for username masquerading: */
65 boolean draft_from_masquerading = FALSE; /* also used from post.c */
66 static boolean mmailid_masquerading = FALSE;
67 boolean username_extension_masquerading = FALSE; /* " from addrsbr.c */
68 static char* masquerade = "";
69
70 /*
71 * MTS specific variables
72 */
73 #if defined(SMTPMTS)
74 static char *sm_method = "smtp";
75 int sm_mts = MTS_SMTP;
76 char *hostable = nmhetcdir(/hosts);
77 char *sendmail = SENDMAILPATH;
78 #endif
79
80 /*
81 * SMTP/POP stuff
82 */
83 char *clientname = NULL;
84 char *servers = "localhost \01localnet";
85 char *pophost = "";
86
87 /*
88 * Global MailDelivery file
89 */
90 char *maildelivery = nmhetcdir(/maildelivery);
91
92
93 /*
94 * Aliasing Facility (doesn't belong here)
95 */
96 int Everyone = NOTOK;
97 static char *everyone = "-1";
98 char *NoShell = "";
99
100 /*
101 * Customize the MTS settings for nmh by adjusting
102 * the file mts.conf in the nmh etc directory.
103 */
104
105 struct bind {
106 char *keyword;
107 char **value;
108 };
109
110 static struct bind binds[] = {
111 { "localname", &localname },
112 { "localdomain", &localdomain },
113 { "systemname", &systemname },
114 { "mmdfldir", &mmdfldir },
115 { "mmdflfil", &mmdflfil },
116 { "uucpldir", &uucpldir },
117 { "uucplfil", &uucplfil },
118 { "mmdelim1", &mmdlm1 },
119 { "mmdelim2", &mmdlm2 },
120 { "masquerade", &masquerade },
121
122 #if defined(SMTPMTS)
123 { "mts", &sm_method },
124 { "hostable", &hostable },
125 { "sendmail", &sendmail },
126 #endif
127
128 { "clientname", &clientname },
129 { "servers", &servers },
130 { "pophost", &pophost },
131
132 { "maildelivery", &maildelivery },
133 { "everyone", &everyone },
134 { "noshell", &NoShell },
135 { NULL, NULL }
136 };
137
138
139 /*
140 * Read the configuration file for the nmh interface
141 * to the mail transport system (MTS).
142 */
143
144 void
145 mts_init (char *name)
146 {
147 const char *cp;
148 FILE *fp;
149 static int inited = 0;
150
151 if (inited++ || (fp = fopen (get_mtsconf_pathname(), "r")) == NULL)
152 return;
153 mts_read_conf_file(fp);
154 fclose (fp);
155
156 cp = get_mtsuserconf_pathname();
157 if (cp != NULL &&
158 ((fp = fopen (get_mtsuserconf_pathname(), "r")) != NULL)) {
159 mts_read_conf_file(fp);
160 fclose (fp);
161 }
162
163 Everyone = atoi (everyone);
164
165 if (strstr(masquerade, "draft_from") != NULL)
166 draft_from_masquerading = TRUE;
167
168 if (strstr(masquerade, "mmailid") != NULL)
169 mmailid_masquerading = TRUE;
170
171 if (strstr(masquerade, "username_extension") != NULL)
172 username_extension_masquerading = TRUE;
173
174 #ifdef SMTPMTS
175 if (strcmp(sm_method, "smtp") == 0)
176 sm_mts = MTS_SMTP;
177 else if (strcmp(sm_method, "sendmail") == 0)
178 sm_mts = MTS_SENDMAIL;
179 else {
180 advise(NULL, "unsupported \"mts\" value in mts.conf: %s", sm_method);
181 sm_mts = MTS_SMTP;
182 }
183 #endif
184 }
185
186
187 #define QUOTE '\\'
188
189 /*
190 * Convert escaped values, malloc some new space,
191 * and copy string to malloc'ed memory.
192 */
193
194 static char *
195 tailor_value (unsigned char *s)
196 {
197 int i, r;
198 char *bp;
199 char buffer[BUFSIZ];
200 size_t len;
201
202 for (bp = buffer; *s; bp++, s++) {
203 if (*s != QUOTE) {
204 *bp = *s;
205 } else {
206 switch (*++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;
211
212 case 0: s--;
213 case QUOTE:
214 *bp = QUOTE;
215 break;
216
217 default:
218 if (!isdigit (*s)) {
219 *bp++ = QUOTE;
220 *bp = *s;
221 }
222 r = *s != '0' ? 10 : 8;
223 for (i = 0; isdigit (*s); s++)
224 i = i * r + *s - '0';
225 s--;
226 *bp = toascii (i);
227 break;
228 }
229 }
230 }
231 *bp = 0;
232
233 len = strlen (buffer) + 1;
234 bp = mh_xmalloc (len);
235 memcpy (bp, buffer, len);
236
237 return bp;
238 }
239
240 /*
241 * Get the fully qualified name of the local host.
242 */
243
244 char *
245 LocalName (void)
246 {
247 static char buffer[BUFSIZ] = "";
248 struct addrinfo hints, *res;
249
250 /* check if we have cached the local name */
251 if (buffer[0])
252 return buffer;
253
254 mts_init ("mts");
255
256 /* check if the mts.conf file specifies a "localname" */
257 if (*localname) {
258 strncpy (buffer, localname, sizeof(buffer));
259 } else {
260 memset(buffer, 0, sizeof(buffer));
261 /* first get our local name */
262 gethostname (buffer, sizeof(buffer) - 1);
263 /* now fully qualify our name */
264
265 memset(&hints, 0, sizeof(hints));
266 hints.ai_flags = AI_CANONNAME;
267 hints.ai_family = PF_UNSPEC;
268 if (getaddrinfo(buffer, NULL, &hints, &res) == 0) {
269 strncpy(buffer, res->ai_canonname, sizeof(buffer) - 1);
270 freeaddrinfo(res);
271 }
272 }
273
274 /*
275 * If the mts.conf file specifies a "localdomain",
276 * we append that now. This should rarely be needed.
277 */
278 if (*localdomain) {
279 strcat (buffer, ".");
280 strcat (buffer, localdomain);
281 }
282
283 return buffer;
284 }
285
286
287 /*
288 * This is only for UUCP mail. It gets the hostname
289 * as part of the UUCP "domain".
290 */
291
292 char *
293 SystemName (void)
294 {
295 static char buffer[BUFSIZ] = "";
296
297 /* check if we have cached the system name */
298 if (buffer[0])
299 return buffer;
300
301 mts_init ("mts");
302
303 /* check if mts.conf file specifies a "systemname" */
304 if (*systemname) {
305 strncpy (buffer, systemname, sizeof(buffer));
306 return buffer;
307 }
308
309 gethostname (buffer, sizeof(buffer));
310
311 return buffer;
312 }
313
314
315 /*
316 * Get the username of current user
317 */
318
319 char *
320 getusername (void)
321 {
322 if (username[0] == '\0')
323 getuserinfo();
324
325 return username;
326 }
327
328
329 /*
330 * Get full name of current user (typically from GECOS
331 * field of password file).
332 */
333
334 char *
335 getfullname (void)
336 {
337 if (username[0] == '\0')
338 getuserinfo();
339
340 return fullname;
341 }
342
343
344 /*
345 * Find the user's username and full name, and cache them.
346 * Also, handle "mmailid" username masquerading controlled from the GECOS field
347 * of the passwd file.
348 */
349
350 static void
351 getuserinfo (void)
352 {
353 register unsigned char *cp;
354 register char *np;
355 register struct passwd *pw;
356
357 if ((pw = getpwuid (getuid ())) == NULL
358 || pw->pw_name == NULL
359 || *pw->pw_name == '\0') {
360 strncpy (username, "unknown", sizeof(username));
361 snprintf (fullname, sizeof(fullname), "The Unknown User-ID (%d)",
362 (int) getuid ());
363 return;
364 }
365
366 np = pw->pw_gecos;
367
368 /* Get the user's real name from the GECOS field. Stop once we hit a ',',
369 which some OSes use to separate other 'finger' information in the GECOS
370 field, like phone number. Also, if mmailid masquerading is turned on due
371 to "mmailid" appearing on the "masquerade:" line of mts.conf, stop if we
372 hit a '<' (which should precede any ','s). */
373 if (mmailid_masquerading)
374 /* Stop at ',' or '<'. */
375 for (cp = fullname; *np != '\0' && *np != ',' && *np != '<';
376 *cp++ = *np++)
377 continue;
378 else
379 /* Allow '<' as a legal character of the user's name. This code is
380 basically a duplicate of the code above the "else" -- we don't
381 collapse it down to one copy and put the mmailid_masquerading check
382 inside the loop with "(x ? y : z)" because that's inefficient and the
383 value'll never change while it's in there. */
384 for (cp = fullname; *np != '\0' && *np != ',';
385 *cp++ = *np++)
386 continue;
387 *cp = '\0';
388
389 if (mmailid_masquerading) {
390 /* Do mmailid processing. The GECOS field should have the form
391 "Full Name <fakeusername>". For instance,
392 "Dan Harkless <Dan.Harkless>". Naturally, you'll want your MTA to
393 have an alias (e.g. in /etc/aliases) from "fakeusername" to your
394 account name. */
395 if (*np)
396 np++;
397 for (cp = username; *np && *np != '>'; *cp++ = *np++)
398 continue;
399 *cp = '\0';
400 }
401 if (!mmailid_masquerading || *np == '\0')
402 strncpy (username, pw->pw_name, sizeof(username));
403
404 /* The $SIGNATURE environment variable overrides the GECOS field's idea of
405 your real name. */
406 if ((cp = getenv ("SIGNATURE")) && *cp)
407 strncpy (fullname, cp, sizeof(fullname));
408
409 if (strchr(fullname, '.')) { /* quote any .'s */
410 char tmp[BUFSIZ];
411
412 /* should quote "'s too */
413 snprintf (tmp, sizeof(tmp), "\"%s\"", fullname);
414 strncpy (fullname, tmp, sizeof(fullname));
415 }
416
417 return;
418 }
419
420 static const char*
421 get_mtsconf_pathname (void)
422 {
423 const char *cp = getenv ( "MHMTSCONF ");
424 if (cp != NULL && *cp != '\0') {
425 return cp;
426 }
427 return mtsconf;
428 }
429
430 static const char*
431 get_mtsuserconf_pathname (void)
432 {
433 const char *cp = getenv ( "MHMTSUSERCONF" );
434 if (cp != NULL && *cp != '\0') {
435 return cp;
436 }
437 return NULL;
438 }
439
440 static void
441 mts_read_conf_file (FILE *fp)
442 {
443 unsigned char *bp;
444 char *cp, buffer[BUFSIZ];
445 struct bind *b;
446
447 while (fgets (buffer, sizeof(buffer), fp)) {
448 if (!(cp = strchr(buffer, '\n')))
449 break;
450 *cp = 0;
451 if (*buffer == '#' || *buffer == '\0')
452 continue;
453 if (!(bp = strchr(buffer, ':')))
454 break;
455 *bp++ = 0;
456 while (isspace (*bp))
457 *bp++ = 0;
458
459 for (b = binds; b->keyword; b++)
460 if (!strcmp (buffer, b->keyword))
461 break;
462 if (b->keyword && (cp = tailor_value (bp)))
463 *b->value = cp;
464 }
465 }