]>
diplodocus.org Git - nmh/blob - sbr/mts.c
1 /* mts.c -- definitions for the mail transport system
3 * This code is Copyright (c) 2002, by the authors of nmh. See the
4 * COPYRIGHT file in the root directory of the nmh distribution for
5 * complete copyright information.
9 #include "escape_addresses.h"
10 #include "context_find.h"
14 #define nmhetcdir(file) NMHETCDIR#file
18 #include <sys/socket.h>
24 static char *tailor_value (char *);
25 static void getuserinfo (void);
26 static const char *get_mtsconf_pathname(void);
27 static const char *get_mtsuserconf_pathname(void);
28 static void mts_read_conf_file (FILE *fp
);
31 * *mmdfldir and *uucpldir are the maildrop directories. If maildrops
32 * are kept in the user's home directory, then these should be empty
33 * strings. In this case, the appropriate ...lfil array should contain
34 * the name of the file in the user's home directory. Usually, this is
35 * something like ".mail".
39 * nmh mail transport interface customization file
41 static char *mtsconf
= nmhetcdir(/mts
.conf
);
43 static char *localname
= "";
44 static char *localdomain
= "";
45 static char *systemname
= "";
47 char *mmdfldir
= MAILSPOOL
;
49 char *uucpldir
= "/usr/spool/mail";
52 char *spoollocking
= DEFAULT_LOCKING
;
54 /* Cache the username, fullname, and mailbox of the user */
55 static char username
[BUFSIZ
];
56 static char fullname
[BUFSIZ
];
57 static char localmbox
[BUFSIZ
];
60 * MTS specific variables
62 static char *mts_method
= "smtp";
63 int sm_mts
= MTS_SMTP
;
64 char *sendmail
= SENDMAILPATH
;
69 char *clientname
= NULL
;
70 char *servers
= "localhost";
74 * Global MailDelivery file
76 char *maildelivery
= nmhetcdir(/maildelivery
);
80 * Customize the MTS settings for nmh by adjusting
81 * the file mts.conf in the nmh etc directory.
89 static struct bind binds
[] = {
90 { "localname", &localname
},
91 { "localdomain", &localdomain
},
92 { "systemname", &systemname
},
93 { "mmdfldir", &mmdfldir
},
94 { "mmdflfil", &mmdflfil
},
95 { "spoollocking", &spoollocking
},
96 { "uucpldir", &uucpldir
},
97 { "uucplfil", &uucplfil
},
98 { "mts", &mts_method
},
99 { "sendmail", &sendmail
},
100 { "clientname", &clientname
},
101 { "servers", &servers
},
102 { "pophost", &pophost
},
104 { "maildelivery", &maildelivery
},
109 /* Convert name of mts method to integer value and store it. */
111 save_mts_method (const char *value
)
113 if (! strcasecmp (value
, "smtp")) {
116 } else if (! strcasecmp (value
, "sendmail/smtp") ||
117 ! strcasecmp (value
, "sendmail")) {
118 mts_method
= "sendmail/smtp";
119 sm_mts
= MTS_SENDMAIL_SMTP
;
120 } else if (! strcasecmp (value
, "sendmail/pipe")) {
121 mts_method
= "sendmail/pipe";
122 sm_mts
= MTS_SENDMAIL_PIPE
;
124 die("unsupported mts selection \"%s\"", value
);
130 * Read the configuration file for the nmh interface
131 * to the mail transport system (MTS).
139 static int inited
= 0;
141 if (inited
++ || (fp
= fopen (get_mtsconf_pathname(), "r")) == NULL
)
143 mts_read_conf_file(fp
);
146 cp
= get_mtsuserconf_pathname();
148 ((fp
= fopen (get_mtsuserconf_pathname(), "r")) != NULL
)) {
149 mts_read_conf_file(fp
);
153 save_mts_method (mts_method
);
160 * Convert escaped values, malloc some new space,
161 * and copy string to malloc'ed memory.
165 tailor_value (char *s
)
171 for (bp
= buffer
; *s
; bp
++, s
++) {
176 case 'b': *bp
= '\b'; break;
177 case 'f': *bp
= '\f'; break;
178 case 'n': *bp
= '\n'; break;
179 case 't': *bp
= '\t'; break;
188 if (!isdigit ((unsigned char) *s
)) {
192 r
= ((unsigned char) *s
) != '0' ? 10 : 8;
193 for (i
= 0; isdigit ((unsigned char) *s
); s
++)
194 i
*= r
+ ((unsigned char) *s
) - '0';
203 return mh_xstrdup(buffer
);
207 * Get the fully qualified name of the local host.
209 * If flag is 0, then use anything out of mts.conf (like localname).
210 * If flag is 1, then only use the "proper" local hostname.
216 static char buffer0
[BUFSIZ
] = "";
217 static char buffer1
[BUFSIZ
] = "";
218 static char *buffer
[] = { buffer0
, buffer1
};
220 struct addrinfo hints
, *res
;
222 if (flag
< 0 || flag
> 1)
227 /* check if we have cached the local name */
233 /* check if the mts.conf file specifies a "localname" */
234 if (*localname
&& flag
== 0) {
235 strncpy (buf
, localname
, sizeof(buffer0
));
237 memset(buf
, 0, sizeof(buffer0
));
238 /* first get our local name */
239 gethostname (buf
, sizeof(buffer0
) - 1);
240 /* now fully qualify our name */
243 hints
.ai_flags
= AI_CANONNAME
;
244 hints
.ai_family
= PF_UNSPEC
;
245 if (getaddrinfo(buf
, NULL
, &hints
, &res
) == 0) {
246 strncpy(buf
, res
->ai_canonname
, sizeof(buffer0
) - 1);
252 * If the mts.conf file specifies a "localdomain",
253 * we append that now. This should rarely be needed.
257 strcat (buf
, localdomain
);
265 * This is only for UUCP mail. It gets the hostname
266 * as part of the UUCP "domain".
272 static char buffer
[BUFSIZ
] = "";
274 /* check if we have cached the system name */
280 /* check if mts.conf file specifies a "systemname" */
282 strncpy (buffer
, systemname
, sizeof(buffer
));
286 gethostname (buffer
, sizeof(buffer
));
293 * Get the username of current user
299 if (username
[0] == '\0')
307 * Get full name of current user (typically from GECOS
308 * field of password file).
314 if (username
[0] == '\0')
322 * Get the full local mailbox name. This is in the form:
324 * User Name <user@name.com>
330 if (username
[0] == '\0')
337 * Find the user's username and full name, and cache them.
346 if ((pw
= getpwuid (getuid ())) == NULL
347 || pw
->pw_name
== NULL
348 || *pw
->pw_name
== '\0') {
349 strncpy (username
, "unknown", sizeof(username
));
350 snprintf (fullname
, sizeof(fullname
), "The Unknown User-ID (%d)",
357 /* If there's a Local-Mailbox profile component, try to extract
358 the username from it. But don't try very hard, this assumes
359 the very simple User Name <user@name.com> form.
360 Note that post(8) and whom(1) use context_foil (), so they
361 won't see the profile component. */
362 if ((np
= context_find("Local-Mailbox")) != NULL
) {
363 char *left_angle_bracket
= strchr (np
, '<');
364 char *at_sign
= strchr (np
, '@');
365 char *right_angle_bracket
= strchr (np
, '>');
367 strncpy(localmbox
, np
, sizeof(localmbox
));
369 if (left_angle_bracket
&& at_sign
&& right_angle_bracket
) {
370 if (at_sign
> left_angle_bracket
&&
371 at_sign
- left_angle_bracket
< BUFSIZ
) {
372 strncpy(username
, left_angle_bracket
+ 1,
373 at_sign
- left_angle_bracket
- 1);
378 if (username
[0] == '\0') {
379 strncpy (username
, pw
->pw_name
, sizeof(username
));
382 username
[sizeof(username
) - 1] = '\0';
384 escape_local_part(username
, sizeof(username
));
390 /* Get the user's real name from the GECOS field. Stop once we hit a ',',
391 which some OSes use to separate other 'finger' information in the GECOS
392 field, like phone number. */
393 for (cp
= fullname
; *np
!= '\0' && *np
!= ','; *cp
++ = *np
++)
397 /* The $SIGNATURE environment variable overrides the GECOS field's idea of
398 your real name. If SIGNATURE isn't set, use the Signature profile
399 setting if it exists.
400 Note that post(8) and whom(1) use context_foil (), so they
401 won't see the profile component. */
402 if ((cp
= getenv ("SIGNATURE")) && *cp
)
403 strncpy (fullname
, cp
, sizeof(fullname
));
404 else if ((cp
= context_find("Signature")))
405 strncpy (fullname
, cp
, sizeof(fullname
));
407 fullname
[sizeof(fullname
) - 1] = '\0';
409 escape_display_name(fullname
, sizeof(fullname
));
412 /* localmbox, if not using Local-Mailbox */
413 if (localmbox
[0] == '\0') {
414 snprintf(localmbox
, sizeof(localmbox
), "%s <%s@%s>", fullname
,
415 username
, LocalName(0));
418 localmbox
[sizeof(localmbox
) - 1] = '\0';
422 get_mtsconf_pathname (void)
424 const char *cp
= getenv ( "MHMTSCONF" );
425 if (cp
!= NULL
&& *cp
!= '\0') {
432 get_mtsuserconf_pathname (void)
434 const char *cp
= getenv ( "MHMTSUSERCONF" );
435 if (cp
!= NULL
&& *cp
!= '\0') {
442 mts_read_conf_file (FILE *fp
)
444 char *bp
, *cp
, buffer
[BUFSIZ
];
447 while (fgets (buffer
, sizeof(buffer
), fp
)) {
448 if (!(cp
= strchr(buffer
, '\n')))
451 if (*buffer
== '#' || *buffer
== '\0')
453 if (!(bp
= strchr(buffer
, ':')))
456 while (isspace ((unsigned char) *bp
))
459 for (b
= binds
; b
->keyword
; b
++)
460 if (!strcmp (buffer
, b
->keyword
))
462 if (b
->keyword
&& (cp
= tailor_value (bp
)))