]>
diplodocus.org Git - nmh/blob - sbr/mts.c
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() */
13 #define nmhetcdir(file) NMHETCDIR#file
17 #include <sys/socket.h>
23 static char *tailor_value (char *);
24 static void getuserinfo (void);
25 static const char *get_mtsconf_pathname(void);
26 static const char *get_mtsuserconf_pathname(void);
27 static void mts_read_conf_file (FILE *fp
);
30 * *mmdfldir and *uucpldir are the maildrop directories. If maildrops
31 * are kept in the user's home directory, then these should be empty
32 * strings. In this case, the appropriate ...lfil array should contain
33 * the name of the file in the user's home directory. Usually, this is
34 * something like ".mail".
38 * nmh mail transport interface customization file
40 static char *mtsconf
= nmhetcdir(/mts
.conf
);
42 static char *localname
= "";
43 static char *localdomain
= "";
44 static char *systemname
= "";
46 char *mmdfldir
= MAILSPOOL
;
48 char *uucpldir
= "/usr/spool/mail";
51 char *mmdlm1
= "\001\001\001\001\n";
52 char *mmdlm2
= "\001\001\001\001\n";
54 char *spoollocking
= DEFAULT_LOCKING
;
56 /* Cache the username, fullname, and mailbox of the user */
57 static char username
[BUFSIZ
];
58 static char fullname
[BUFSIZ
];
59 static char localmbox
[BUFSIZ
];
62 * MTS specific variables
64 static char *mts_method
= "smtp";
65 int sm_mts
= MTS_SMTP
;
66 char *sendmail
= SENDMAILPATH
;
71 char *clientname
= NULL
;
72 char *servers
= "localhost";
76 * Global MailDelivery file
78 char *maildelivery
= nmhetcdir(/maildelivery
);
82 * Customize the MTS settings for nmh by adjusting
83 * the file mts.conf in the nmh etc directory.
91 static struct bind binds
[] = {
92 { "localname", &localname
},
93 { "localdomain", &localdomain
},
94 { "systemname", &systemname
},
95 { "mmdfldir", &mmdfldir
},
96 { "mmdflfil", &mmdflfil
},
97 { "spoollocking", &spoollocking
},
98 { "uucpldir", &uucpldir
},
99 { "uucplfil", &uucplfil
},
100 { "mmdelim1", &mmdlm1
},
101 { "mmdelim2", &mmdlm2
},
102 { "mts", &mts_method
},
103 { "sendmail", &sendmail
},
104 { "clientname", &clientname
},
105 { "servers", &servers
},
106 { "pophost", &pophost
},
108 { "maildelivery", &maildelivery
},
113 /* Convert name of mts method to integer value and store it. */
115 save_mts_method (const char *value
) {
116 if (! strcasecmp (value
, "smtp")) {
119 } else if (! strcasecmp (value
, "sendmail/smtp") ||
120 ! strcasecmp (value
, "sendmail")) {
121 mts_method
= "sendmail/smtp";
122 sm_mts
= MTS_SENDMAIL_SMTP
;
123 } else if (! strcasecmp (value
, "sendmail/pipe")) {
124 mts_method
= "sendmail/pipe";
125 sm_mts
= MTS_SENDMAIL_PIPE
;
127 adios (NULL
, "unsupported mts selection \"%s\"", value
);
133 * Read the configuration file for the nmh interface
134 * to the mail transport system (MTS).
142 static int inited
= 0;
144 if (inited
++ || (fp
= fopen (get_mtsconf_pathname(), "r")) == NULL
)
146 mts_read_conf_file(fp
);
149 cp
= get_mtsuserconf_pathname();
151 ((fp
= fopen (get_mtsuserconf_pathname(), "r")) != NULL
)) {
152 mts_read_conf_file(fp
);
156 save_mts_method (mts_method
);
163 * Convert escaped values, malloc some new space,
164 * and copy string to malloc'ed memory.
168 tailor_value (char *s
)
175 for (bp
= buffer
; *s
; bp
++, s
++) {
180 case 'b': *bp
= '\b'; break;
181 case 'f': *bp
= '\f'; break;
182 case 'n': *bp
= '\n'; break;
183 case 't': *bp
= '\t'; break;
191 if (!isdigit ((unsigned char) *s
)) {
195 r
= ((unsigned char) *s
) != '0' ? 10 : 8;
196 for (i
= 0; isdigit ((unsigned char) *s
); s
++)
197 i
= i
* r
+ ((unsigned char) *s
) - '0';
206 len
= strlen (buffer
) + 1;
207 bp
= mh_xmalloc (len
);
208 memcpy (bp
, buffer
, len
);
214 * Get the fully qualified name of the local host.
216 * If flag is 0, then use anything out of mts.conf (like localname).
217 * If flag is 1, then only use the "proper" local hostname.
223 static char buffer0
[BUFSIZ
] = "";
224 static char buffer1
[BUFSIZ
] = "";
225 static char *buffer
[] = { buffer0
, buffer1
};
227 struct addrinfo hints
, *res
;
229 if (flag
< 0 || flag
> 1)
234 /* check if we have cached the local name */
240 /* check if the mts.conf file specifies a "localname" */
241 if (*localname
&& flag
== 0) {
242 strncpy (buf
, localname
, sizeof(buffer0
));
244 memset(buf
, 0, sizeof(buffer0
));
245 /* first get our local name */
246 gethostname (buf
, sizeof(buffer0
) - 1);
247 /* now fully qualify our name */
249 memset(&hints
, 0, sizeof(hints
));
250 hints
.ai_flags
= AI_CANONNAME
;
251 hints
.ai_family
= PF_UNSPEC
;
252 if (getaddrinfo(buf
, NULL
, &hints
, &res
) == 0) {
253 strncpy(buf
, res
->ai_canonname
, sizeof(buffer0
) - 1);
259 * If the mts.conf file specifies a "localdomain",
260 * we append that now. This should rarely be needed.
264 strcat (buf
, localdomain
);
272 * This is only for UUCP mail. It gets the hostname
273 * as part of the UUCP "domain".
279 static char buffer
[BUFSIZ
] = "";
281 /* check if we have cached the system name */
287 /* check if mts.conf file specifies a "systemname" */
289 strncpy (buffer
, systemname
, sizeof(buffer
));
293 gethostname (buffer
, sizeof(buffer
));
300 * Get the username of current user
306 if (username
[0] == '\0')
314 * Get full name of current user (typically from GECOS
315 * field of password file).
321 if (username
[0] == '\0')
329 * Get the full local mailbox name. This is in the form:
331 * User Name <user@name.com>
337 if (username
[0] == '\0')
344 * Find the user's username and full name, and cache them.
353 if ((pw
= getpwuid (getuid ())) == NULL
354 || pw
->pw_name
== NULL
355 || *pw
->pw_name
== '\0') {
356 strncpy (username
, "unknown", sizeof(username
));
357 snprintf (fullname
, sizeof(fullname
), "The Unknown User-ID (%d)",
364 /* If there's a Local-Mailbox profile component, try to extract
365 the username from it. But don't try very hard, this assumes
366 the very simple User Name <user@name.com> form.
367 Note that post(8) and whom(1) use context_foil (), so they
368 won't see the profile component. */
369 if ((np
= context_find("Local-Mailbox")) != NULL
) {
370 char *left_angle_bracket
= strchr (np
, '<');
371 char *at_sign
= strchr (np
, '@');
372 char *right_angle_bracket
= strchr (np
, '>');
374 strncpy(localmbox
, np
, sizeof(localmbox
));
376 if (left_angle_bracket
&& at_sign
&& right_angle_bracket
) {
377 if (at_sign
> left_angle_bracket
&&
378 at_sign
- left_angle_bracket
< BUFSIZ
) {
379 strncpy(username
, left_angle_bracket
+ 1,
380 at_sign
- left_angle_bracket
- 1);
385 if (username
[0] == '\0') {
386 strncpy (username
, pw
->pw_name
, sizeof(username
));
389 username
[sizeof(username
) - 1] = '\0';
391 escape_local_part(username
, sizeof(username
));
397 /* Get the user's real name from the GECOS field. Stop once we hit a ',',
398 which some OSes use to separate other 'finger' information in the GECOS
399 field, like phone number. */
400 for (cp
= fullname
; *np
!= '\0' && *np
!= ','; *cp
++ = *np
++)
404 /* The $SIGNATURE environment variable overrides the GECOS field's idea of
405 your real name. If SIGNATURE isn't set, use the Signature profile
406 setting if it exists.
407 Note that post(8) and whom(1) use context_foil (), so they
408 won't see the profile component. */
409 if ((cp
= getenv ("SIGNATURE")) && *cp
)
410 strncpy (fullname
, cp
, sizeof(fullname
));
411 else if ((cp
= context_find("Signature")))
412 strncpy (fullname
, cp
, sizeof(fullname
));
414 fullname
[sizeof(fullname
) - 1] = '\0';
416 escape_display_name(fullname
, sizeof(fullname
));
419 /* localmbox, if not using Local-Mailbox */
420 if (localmbox
[0] == '\0') {
421 snprintf(localmbox
, sizeof(localmbox
), "%s <%s@%s>", fullname
,
422 username
, LocalName(0));
425 localmbox
[sizeof(localmbox
) - 1] = '\0';
429 get_mtsconf_pathname (void)
431 const char *cp
= getenv ( "MHMTSCONF" );
432 if (cp
!= NULL
&& *cp
!= '\0') {
439 get_mtsuserconf_pathname (void)
441 const char *cp
= getenv ( "MHMTSUSERCONF" );
442 if (cp
!= NULL
&& *cp
!= '\0') {
449 mts_read_conf_file (FILE *fp
)
451 char *bp
, *cp
, buffer
[BUFSIZ
];
454 while (fgets (buffer
, sizeof(buffer
), fp
)) {
455 if (!(cp
= strchr(buffer
, '\n')))
458 if (*buffer
== '#' || *buffer
== '\0')
460 if (!(bp
= strchr(buffer
, ':')))
463 while (isspace ((unsigned char) *bp
))
466 for (b
= binds
; b
->keyword
; b
++)
467 if (!strcmp (buffer
, b
->keyword
))
469 if (b
->keyword
&& (cp
= tailor_value (bp
)))