]> diplodocus.org Git - nmh/blob - sbr/mts.c
Make POP support always be turned on.
[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 /*
24 * static prototypes
25 */
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);
31
32 /*
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".
38 */
39
40 /*
41 * nmh mail transport interface customization file
42 */
43 static char *mtsconf = nmhetcdir(/mts.conf);
44
45 static char *localname = "";
46 static char *localdomain = "";
47 static char *systemname = "";
48
49 char *mmdfldir = MAILSPOOL;
50 char *mmdflfil = "";
51 char *uucpldir = "/usr/spool/mail";
52 char *uucplfil = "";
53
54 char *mmdlm1 = "\001\001\001\001\n";
55 char *mmdlm2 = "\001\001\001\001\n";
56
57 /* Cache the username and fullname of the user */
58 static char username[BUFSIZ];
59 static char fullname[BUFSIZ];
60
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 = "";
66
67 /*
68 * MTS specific variables
69 */
70 #if defined(SMTPMTS)
71 static char *sm_method = "smtp";
72 int sm_mts = MTS_SMTP;
73 char *hostable = nmhetcdir(/hosts);
74 char *sendmail = SENDMAILPATH;
75 #endif
76
77 /*
78 * SMTP/POP stuff
79 */
80 char *clientname = NULL;
81 char *servers = "localhost \01localnet";
82 char *pophost = "";
83
84 /*
85 * Global MailDelivery file
86 */
87 char *maildelivery = nmhetcdir(/maildelivery);
88
89
90 /*
91 * Aliasing Facility (doesn't belong here)
92 */
93 int Everyone = NOTOK;
94 static char *everyone = "-1";
95 char *NoShell = "";
96
97 /*
98 * Customize the MTS settings for nmh by adjusting
99 * the file mts.conf in the nmh etc directory.
100 */
101
102 struct bind {
103 char *keyword;
104 char **value;
105 };
106
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 },
118
119 #if defined(SMTPMTS)
120 { "mts", &sm_method },
121 { "hostable", &hostable },
122 { "sendmail", &sendmail },
123 #endif
124
125 { "clientname", &clientname },
126 { "servers", &servers },
127 { "pophost", &pophost },
128
129 { "maildelivery", &maildelivery },
130 { "everyone", &everyone },
131 { "noshell", &NoShell },
132 { NULL, NULL }
133 };
134
135
136 /*
137 * Read the configuration file for the nmh interface
138 * to the mail transport system (MTS).
139 */
140
141 void
142 mts_init (char *name)
143 {
144 NMH_UNUSED (name);
145
146 const char *cp;
147 FILE *fp;
148 static int inited = 0;
149
150 if (inited++ || (fp = fopen (get_mtsconf_pathname(), "r")) == NULL)
151 return;
152 mts_read_conf_file(fp);
153 fclose (fp);
154
155 cp = get_mtsuserconf_pathname();
156 if (cp != NULL &&
157 ((fp = fopen (get_mtsuserconf_pathname(), "r")) != NULL)) {
158 mts_read_conf_file(fp);
159 fclose (fp);
160 }
161
162 Everyone = atoi (everyone);
163
164 if (strstr(masquerade, "draft_from") != NULL)
165 draft_from_masquerading = TRUE;
166
167 if (strstr(masquerade, "mmailid") != NULL)
168 mmailid_masquerading = TRUE;
169
170 if (strstr(masquerade, "username_extension") != NULL)
171 username_extension_masquerading = TRUE;
172
173 #ifdef SMTPMTS
174 if (strcmp(sm_method, "smtp") == 0)
175 sm_mts = MTS_SMTP;
176 else if (strcmp(sm_method, "sendmail") == 0)
177 sm_mts = MTS_SENDMAIL;
178 else {
179 advise(NULL, "unsupported \"mts\" value in mts.conf: %s", sm_method);
180 sm_mts = MTS_SMTP;
181 }
182 #endif
183 }
184
185
186 #define QUOTE '\\'
187
188 /*
189 * Convert escaped values, malloc some new space,
190 * and copy string to malloc'ed memory.
191 */
192
193 static char *
194 tailor_value (unsigned char *s)
195 {
196 int i, r;
197 char *bp;
198 char buffer[BUFSIZ];
199 size_t len;
200
201 for (bp = buffer; *s; bp++, s++) {
202 if (*s != QUOTE) {
203 *bp = *s;
204 } else {
205 switch (*++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;
210
211 case 0: s--;
212 case QUOTE:
213 *bp = QUOTE;
214 break;
215
216 default:
217 if (!isdigit (*s)) {
218 *bp++ = QUOTE;
219 *bp = *s;
220 }
221 r = *s != '0' ? 10 : 8;
222 for (i = 0; isdigit (*s); s++)
223 i = i * r + *s - '0';
224 s--;
225 *bp = toascii (i);
226 break;
227 }
228 }
229 }
230 *bp = 0;
231
232 len = strlen (buffer) + 1;
233 bp = mh_xmalloc (len);
234 memcpy (bp, buffer, len);
235
236 return bp;
237 }
238
239 /*
240 * Get the fully qualified name of the local host.
241 */
242
243 char *
244 LocalName (void)
245 {
246 static char buffer[BUFSIZ] = "";
247 struct addrinfo hints, *res;
248
249 /* check if we have cached the local name */
250 if (buffer[0])
251 return buffer;
252
253 mts_init ("mts");
254
255 /* check if the mts.conf file specifies a "localname" */
256 if (*localname) {
257 strncpy (buffer, localname, sizeof(buffer));
258 } else {
259 memset(buffer, 0, sizeof(buffer));
260 /* first get our local name */
261 gethostname (buffer, sizeof(buffer) - 1);
262 /* now fully qualify our name */
263
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);
269 freeaddrinfo(res);
270 }
271 }
272
273 /*
274 * If the mts.conf file specifies a "localdomain",
275 * we append that now. This should rarely be needed.
276 */
277 if (*localdomain) {
278 strcat (buffer, ".");
279 strcat (buffer, localdomain);
280 }
281
282 return buffer;
283 }
284
285
286 /*
287 * This is only for UUCP mail. It gets the hostname
288 * as part of the UUCP "domain".
289 */
290
291 char *
292 SystemName (void)
293 {
294 static char buffer[BUFSIZ] = "";
295
296 /* check if we have cached the system name */
297 if (buffer[0])
298 return buffer;
299
300 mts_init ("mts");
301
302 /* check if mts.conf file specifies a "systemname" */
303 if (*systemname) {
304 strncpy (buffer, systemname, sizeof(buffer));
305 return buffer;
306 }
307
308 gethostname (buffer, sizeof(buffer));
309
310 return buffer;
311 }
312
313
314 /*
315 * Get the username of current user
316 */
317
318 char *
319 getusername (void)
320 {
321 if (username[0] == '\0')
322 getuserinfo();
323
324 return username;
325 }
326
327
328 /*
329 * Get full name of current user (typically from GECOS
330 * field of password file).
331 */
332
333 char *
334 getfullname (void)
335 {
336 if (username[0] == '\0')
337 getuserinfo();
338
339 return fullname;
340 }
341
342
343 /*
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.
347 */
348
349 static void
350 getuserinfo (void)
351 {
352 register unsigned char *cp;
353 register char *np;
354 register struct passwd *pw;
355
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)",
361 (int) getuid ());
362 return;
363 }
364
365 np = pw->pw_gecos;
366
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 != '<';
375 *cp++ = *np++)
376 continue;
377 else
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 != ',';
384 *cp++ = *np++)
385 continue;
386 *cp = '\0';
387
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
393 account name. */
394 if (*np)
395 np++;
396 for (cp = username; *np && *np != '>'; *cp++ = *np++)
397 continue;
398 *cp = '\0';
399 }
400 if (!mmailid_masquerading || *np == '\0')
401 strncpy (username, pw->pw_name, sizeof(username));
402
403 /* The $SIGNATURE environment variable overrides the GECOS field's idea of
404 your real name. */
405 if ((cp = getenv ("SIGNATURE")) && *cp)
406 strncpy (fullname, cp, sizeof(fullname));
407
408 if (strchr(fullname, '.')) { /* quote any .'s */
409 char tmp[BUFSIZ];
410
411 /* should quote "'s too */
412 snprintf (tmp, sizeof(tmp), "\"%s\"", fullname);
413 strncpy (fullname, tmp, sizeof(fullname));
414 }
415
416 return;
417 }
418
419 static const char*
420 get_mtsconf_pathname (void)
421 {
422 const char *cp = getenv ( "MHMTSCONF ");
423 if (cp != NULL && *cp != '\0') {
424 return cp;
425 }
426 return mtsconf;
427 }
428
429 static const char*
430 get_mtsuserconf_pathname (void)
431 {
432 const char *cp = getenv ( "MHMTSUSERCONF" );
433 if (cp != NULL && *cp != '\0') {
434 return cp;
435 }
436 return NULL;
437 }
438
439 static void
440 mts_read_conf_file (FILE *fp)
441 {
442 unsigned char *bp;
443 char *cp, buffer[BUFSIZ];
444 struct bind *b;
445
446 while (fgets (buffer, sizeof(buffer), fp)) {
447 if (!(cp = strchr(buffer, '\n')))
448 break;
449 *cp = 0;
450 if (*buffer == '#' || *buffer == '\0')
451 continue;
452 if (!(bp = strchr(buffer, ':')))
453 break;
454 *bp++ = 0;
455 while (isspace (*bp))
456 *bp++ = 0;
457
458 for (b = binds; b->keyword; b++)
459 if (!strcmp (buffer, b->keyword))
460 break;
461 if (b->keyword && (cp = tailor_value (bp)))
462 *b->value = cp;
463 }
464 }