]>
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.
8 #include <h/mh.h> /* for snprintf() */
11 #define nmhetcdir(file) NMHETCDIR#file
15 #include <sys/socket.h>
21 static char *tailor_value (char *);
22 static void getuserinfo (void);
23 static const char *get_mtsconf_pathname(void);
24 static const char *get_mtsuserconf_pathname(void);
25 static void mts_read_conf_file (FILE *fp
);
28 * *mmdfldir and *uucpldir are the maildrop directories. If maildrops
29 * are kept in the user's home directory, then these should be empty
30 * strings. In this case, the appropriate ...lfil array should contain
31 * the name of the file in the user's home directory. Usually, this is
32 * something like ".mail".
36 * nmh mail transport interface customization file
38 static char *mtsconf
= nmhetcdir(/mts
.conf
);
40 static char *localname
= "";
41 static char *localdomain
= "";
42 static char *systemname
= "";
44 char *mmdfldir
= MAILSPOOL
;
46 char *uucpldir
= "/usr/spool/mail";
49 char *mmdlm1
= "\001\001\001\001\n";
50 char *mmdlm2
= "\001\001\001\001\n";
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 { "mmdelim1", &mmdlm1
},
99 { "mmdelim2", &mmdlm2
},
100 { "mts", &mts_method
},
101 { "sendmail", &sendmail
},
102 { "clientname", &clientname
},
103 { "servers", &servers
},
104 { "pophost", &pophost
},
106 { "maildelivery", &maildelivery
},
111 /* Convert name of mts method to integer value and store it. */
113 save_mts_method (const char *value
) {
114 if (! strcasecmp (value
, "smtp")) {
117 } else if (! strcasecmp (value
, "sendmail/smtp") ||
118 ! strcasecmp (value
, "sendmail")) {
119 mts_method
= "sendmail/smtp";
120 sm_mts
= MTS_SENDMAIL_SMTP
;
121 } else if (! strcasecmp (value
, "sendmail/pipe")) {
122 mts_method
= "sendmail/pipe";
123 sm_mts
= MTS_SENDMAIL_PIPE
;
125 adios (NULL
, "unsupported mts selection \"%s\"", value
);
131 * Read the configuration file for the nmh interface
132 * to the mail transport system (MTS).
140 static int inited
= 0;
142 if (inited
++ || (fp
= fopen (get_mtsconf_pathname(), "r")) == NULL
)
144 mts_read_conf_file(fp
);
147 cp
= get_mtsuserconf_pathname();
149 ((fp
= fopen (get_mtsuserconf_pathname(), "r")) != NULL
)) {
150 mts_read_conf_file(fp
);
154 save_mts_method (mts_method
);
161 * Convert escaped values, malloc some new space,
162 * and copy string to malloc'ed memory.
166 tailor_value (char *s
)
172 for (bp
= buffer
; *s
; bp
++, s
++) {
177 case 'b': *bp
= '\b'; break;
178 case 'f': *bp
= '\f'; break;
179 case 'n': *bp
= '\n'; break;
180 case 't': *bp
= '\t'; break;
189 if (!isdigit ((unsigned char) *s
)) {
193 r
= ((unsigned char) *s
) != '0' ? 10 : 8;
194 for (i
= 0; isdigit ((unsigned char) *s
); s
++)
195 i
*= r
+ ((unsigned char) *s
) - '0';
204 return mh_xstrdup(buffer
);
208 * Get the fully qualified name of the local host.
210 * If flag is 0, then use anything out of mts.conf (like localname).
211 * If flag is 1, then only use the "proper" local hostname.
217 static char buffer0
[BUFSIZ
] = "";
218 static char buffer1
[BUFSIZ
] = "";
219 static char *buffer
[] = { buffer0
, buffer1
};
221 struct addrinfo hints
, *res
;
223 if (flag
< 0 || flag
> 1)
228 /* check if we have cached the local name */
234 /* check if the mts.conf file specifies a "localname" */
235 if (*localname
&& flag
== 0) {
236 strncpy (buf
, localname
, sizeof(buffer0
));
238 memset(buf
, 0, sizeof(buffer0
));
239 /* first get our local name */
240 gethostname (buf
, sizeof(buffer0
) - 1);
241 /* now fully qualify our name */
243 memset(&hints
, 0, sizeof(hints
));
244 hints
.ai_flags
= AI_CANONNAME
;
245 hints
.ai_family
= PF_UNSPEC
;
246 if (getaddrinfo(buf
, NULL
, &hints
, &res
) == 0) {
247 strncpy(buf
, res
->ai_canonname
, sizeof(buffer0
) - 1);
253 * If the mts.conf file specifies a "localdomain",
254 * we append that now. This should rarely be needed.
258 strcat (buf
, localdomain
);
266 * This is only for UUCP mail. It gets the hostname
267 * as part of the UUCP "domain".
273 static char buffer
[BUFSIZ
] = "";
275 /* check if we have cached the system name */
281 /* check if mts.conf file specifies a "systemname" */
283 strncpy (buffer
, systemname
, sizeof(buffer
));
287 gethostname (buffer
, sizeof(buffer
));
294 * Get the username of current user
300 if (username
[0] == '\0')
308 * Get full name of current user (typically from GECOS
309 * field of password file).
315 if (username
[0] == '\0')
323 * Get the full local mailbox name. This is in the form:
325 * User Name <user@name.com>
331 if (username
[0] == '\0')
338 * Find the user's username and full name, and cache them.
347 if ((pw
= getpwuid (getuid ())) == NULL
348 || pw
->pw_name
== NULL
349 || *pw
->pw_name
== '\0') {
350 strncpy (username
, "unknown", sizeof(username
));
351 snprintf (fullname
, sizeof(fullname
), "The Unknown User-ID (%d)",
358 /* If there's a Local-Mailbox profile component, try to extract
359 the username from it. But don't try very hard, this assumes
360 the very simple User Name <user@name.com> form.
361 Note that post(8) and whom(1) use context_foil (), so they
362 won't see the profile component. */
363 if ((np
= context_find("Local-Mailbox")) != NULL
) {
364 char *left_angle_bracket
= strchr (np
, '<');
365 char *at_sign
= strchr (np
, '@');
366 char *right_angle_bracket
= strchr (np
, '>');
368 strncpy(localmbox
, np
, sizeof(localmbox
));
370 if (left_angle_bracket
&& at_sign
&& right_angle_bracket
) {
371 if (at_sign
> left_angle_bracket
&&
372 at_sign
- left_angle_bracket
< BUFSIZ
) {
373 strncpy(username
, left_angle_bracket
+ 1,
374 at_sign
- left_angle_bracket
- 1);
379 if (username
[0] == '\0') {
380 strncpy (username
, pw
->pw_name
, sizeof(username
));
383 username
[sizeof(username
) - 1] = '\0';
385 escape_local_part(username
, sizeof(username
));
391 /* Get the user's real name from the GECOS field. Stop once we hit a ',',
392 which some OSes use to separate other 'finger' information in the GECOS
393 field, like phone number. */
394 for (cp
= fullname
; *np
!= '\0' && *np
!= ','; *cp
++ = *np
++)
398 /* The $SIGNATURE environment variable overrides the GECOS field's idea of
399 your real name. If SIGNATURE isn't set, use the Signature profile
400 setting if it exists.
401 Note that post(8) and whom(1) use context_foil (), so they
402 won't see the profile component. */
403 if ((cp
= getenv ("SIGNATURE")) && *cp
)
404 strncpy (fullname
, cp
, sizeof(fullname
));
405 else if ((cp
= context_find("Signature")))
406 strncpy (fullname
, cp
, sizeof(fullname
));
408 fullname
[sizeof(fullname
) - 1] = '\0';
410 escape_display_name(fullname
, sizeof(fullname
));
413 /* localmbox, if not using Local-Mailbox */
414 if (localmbox
[0] == '\0') {
415 snprintf(localmbox
, sizeof(localmbox
), "%s <%s@%s>", fullname
,
416 username
, LocalName(0));
419 localmbox
[sizeof(localmbox
) - 1] = '\0';
423 get_mtsconf_pathname (void)
425 const char *cp
= getenv ( "MHMTSCONF" );
426 if (cp
!= NULL
&& *cp
!= '\0') {
433 get_mtsuserconf_pathname (void)
435 const char *cp
= getenv ( "MHMTSUSERCONF" );
436 if (cp
!= NULL
&& *cp
!= '\0') {
443 mts_read_conf_file (FILE *fp
)
445 char *bp
, *cp
, buffer
[BUFSIZ
];
448 while (fgets (buffer
, sizeof(buffer
), fp
)) {
449 if (!(cp
= strchr(buffer
, '\n')))
452 if (*buffer
== '#' || *buffer
== '\0')
454 if (!(bp
= strchr(buffer
, ':')))
457 while (isspace ((unsigned char) *bp
))
460 for (b
= binds
; b
->keyword
; b
++)
461 if (!strcmp (buffer
, b
->keyword
))
463 if (b
->keyword
&& (cp
= tailor_value (bp
)))