2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-30 05:38:06 +00:00

snapshot-19990423

This commit is contained in:
Wietse Venema 1999-04-23 00:00:00 -05:00
parent 5f740cf9e5
commit 54996be828
45 changed files with 476 additions and 251 deletions

1
postfix/.indent.pro vendored
View File

@ -97,6 +97,7 @@
-TUSER_ATTR
-TVBUF
-TVSTREAM
-TVSTREAM_POPEN_ARGS
-TVSTRING
-TWAIT_STATUS_T
-TWATCH_FD

View File

@ -2651,3 +2651,16 @@ Apologies for any names omitted.
report as part of the first message segment, because users
had trouble extracting the delivery error report from the
attachment.
19990423
Cleanup: the default junk mail reject code is now 554
(service unavailable) rather than 550 (user unknown).
Folded in the updated dict_ldap.c module by John Hensley,
Merit Network, USA.
Folded in the vstream_popen.c updates by Philip A.
Prindeville, Mirapoint, Inc., USA. This copies a lot of
code from pipe_command(); the next step is to trim that
module.

View File

@ -70,7 +70,7 @@ Defaults are given in parentheses:
result_attribute (maildrop)
The attribute Postfix will read from any directory entries
returned by the lookup, to be resolved to an email address.
ldapsource_result = mailbox
ldapsource_result_attribute = mailbox
bind (yes)
Whether or not to bind to the LDAP server. Newer LDAP
@ -185,6 +185,12 @@ NOTES AND THINGS TO THINK ABOUT
Any performance reports will be much appreciated on the postfix-users
list.
UPDATE: At Merit, I've seen over 150000 deliveries per day with no
noticeable delay from our OpenLDAP server. I'd now recommend not
resorting to the above unless you anticipate much more traffic than
that. It makes management of your directory less intuitive, which is
probably not worth the reduction in lookups.
CREDITS
=======

View File

@ -1,4 +1,4 @@
Incompatible changes with snapshot-19990422:
Incompatible changes with snapshot-19990423:
===========================================
- If an address extension (+foo) matches a user's .forward+foo file
@ -6,7 +6,7 @@ name, the +foo extension is no longer appended to recipient addresses
listed in the .forward+foo file. This is more consistent with the
way Postfix expands aliases.
Major changes with snapshot-19990422:
Major changes with snapshot-19990423:
=====================================
In addition to several little bugfixes, none related to security,

View File

@ -97,6 +97,7 @@
-TUSER_ATTR
-TVBUF
-TVSTREAM
-TVSTREAM_POPEN_ARGS
-TVSTRING
-TWAIT_STATUS_T
-TWATCH_FD

View File

@ -97,6 +97,7 @@
-TUSER_ATTR
-TVBUF
-TVSTREAM
-TVSTREAM_POPEN_ARGS
-TVSTRING
-TWAIT_STATUS_T
-TWATCH_FD

View File

@ -1,5 +1,5 @@
2bounce_notice_recipient = postmaster
access_map_reject_code = 550
access_map_reject_code = 554
alias_database = hash:/etc/aliases
alias_maps = hash:/etc/aliases
allow_mail_to_commands = alias,forward
@ -61,11 +61,11 @@ luser_relay =
mail_name = Postfix
mail_owner = postfix
mail_spool_directory = /var/mail
mail_version = Snapshot-19990422
mail_version = Snapshot-19990423
mailbox_command =
mailbox_transport =
maps_rbl_domains = rbl.maps.vix.com
maps_rbl_reject_code = 550
maps_rbl_reject_code = 554
masquerade_domains =
masquerade_exceptions =
max_idle = 100
@ -89,9 +89,9 @@ queue_run_delay = 1000
recipient_canonical_maps =
recipient_delimiter =
recipient_feature_delimiter =
reject_code = 550
reject_code = 554
relay_domains = $mydestination, $virtual_maps
relay_domains_reject_code = 550
relay_domains_reject_code = 554
relayhost =
relocated_maps =
sender_canonical_maps =

View File

@ -97,6 +97,7 @@
-TUSER_ATTR
-TVBUF
-TVSTREAM
-TVSTREAM_POPEN_ARGS
-TVSTRING
-TWAIT_STATUS_T
-TWATCH_FD

View File

@ -97,6 +97,7 @@
-TUSER_ATTR
-TVBUF
-TVSTREAM
-TVSTREAM_POPEN_ARGS
-TVSTRING
-TWAIT_STATUS_T
-TWATCH_FD

View File

@ -97,6 +97,7 @@
-TUSER_ATTR
-TVBUF
-TVSTREAM
-TVSTREAM_POPEN_ARGS
-TVSTRING
-TWAIT_STATUS_T
-TWATCH_FD

View File

@ -1,5 +1,5 @@
SHELL = /bin/sh
SRCS = been_here.c bounce.c canon_addr.c clean_env.c cleanup_strerror.c \
SRCS = been_here.c bounce.c canon_addr.c cleanup_strerror.c \
config.c config_bool.c config_int.c config_str.c debug_peer.c \
debug_process.c defer.c deliver_completed.c deliver_flock.c \
deliver_request.c domain_list.c dot_lockfile.c file_id.c \
@ -17,7 +17,7 @@ SRCS = been_here.c bounce.c canon_addr.c clean_env.c cleanup_strerror.c \
split_addr.c string_list.c sys_exits.c timed_ipc.c tok822_find.c \
tok822_node.c tok822_parse.c tok822_resolve.c tok822_rewrite.c \
tok822_tree.c clnt_stream.c deliver_pass.c config_raw.c
OBJS = been_here.o bounce.o canon_addr.o clean_env.o cleanup_strerror.o \
OBJS = been_here.o bounce.o canon_addr.o cleanup_strerror.o \
config.o config_bool.o config_int.o config_str.o debug_peer.o \
debug_process.o defer.o deliver_completed.o deliver_flock.o \
deliver_request.o domain_list.o dot_lockfile.o file_id.o \
@ -35,7 +35,7 @@ OBJS = been_here.o bounce.o canon_addr.o clean_env.o cleanup_strerror.o \
split_addr.o string_list.o sys_exits.o timed_ipc.o tok822_find.o \
tok822_node.o tok822_parse.o tok822_resolve.o tok822_rewrite.o \
tok822_tree.o clnt_stream.o deliver_pass.o config_raw.o
HDRS = been_here.h bounce.h canon_addr.h clean_env.h cleanup_user.h \
HDRS = been_here.h bounce.h canon_addr.h cleanup_user.h \
config.h debug_peer.h debug_process.h defer.h deliver_completed.h \
deliver_flock.h deliver_request.h domain_list.h dot_lockfile.h \
file_id.h header_opts.h is_header.h mail_addr.h mail_addr_crunch.h \
@ -238,10 +238,6 @@ canon_addr.o: ../include/vbuf.h
canon_addr.o: ../include/mymalloc.h
canon_addr.o: rewrite_clnt.h
canon_addr.o: canon_addr.h
clean_env.o: clean_env.c
clean_env.o: ../include/sys_defs.h
clean_env.o: ../include/msg.h
clean_env.o: clean_env.h
cleanup_strerror.o: cleanup_strerror.c
cleanup_strerror.o: ../include/sys_defs.h
cleanup_strerror.o: ../include/vstring.h
@ -499,6 +495,7 @@ mail_params.o: ../include/sys_defs.h
mail_params.o: ../include/msg.h
mail_params.o: ../include/get_hostname.h
mail_params.o: ../include/valid_hostname.h
mail_params.o: ../include/stringops.h
mail_params.o: mynetworks.h
mail_params.o: config.h
mail_params.o: mail_version.h
@ -694,7 +691,7 @@ pipe_command.o: ../include/set_ugid.h
pipe_command.o: ../include/argv.h
pipe_command.o: mail_params.h
pipe_command.o: mail_copy.h
pipe_command.o: clean_env.h
pipe_command.o: ../include/clean_env.h
pipe_command.o: pipe_command.h
pipe_command.o: ../include/exec_command.h
pipe_command.o: sys_exits.h

View File

@ -177,8 +177,7 @@ static const char *check_myhostname(void)
name = get_hostname();
if ((dot = strchr(name, '.')) == 0) {
if ((domain = config_lookup_eval(VAR_MYDOMAIN)) == 0)
msg_fatal("My hostname %s is not a fully qualified name - "
"set %s or %s in %s/main.cf",
msg_fatal("My hostname %s is not a fully qualified name - set %s or %s in %s/main.cf",
name, VAR_MYHOSTNAME, VAR_MYDOMAIN, var_config_dir);
name = concatenate(name, ".", domain, (char *) 0);
}

View File

@ -706,7 +706,7 @@ extern char *var_etrn_checks;
#define PERMIT_ALL "permit"
#define REJECT_ALL "reject"
#define VAR_REJECT_CODE "reject_code"
#define DEF_REJECT_CODE 550
#define DEF_REJECT_CODE 554
extern int var_reject_code;
#define REJECT_UNKNOWN_CLIENT "reject_unknown_client"
@ -744,13 +744,13 @@ extern int var_unk_addr_code;
#define CHECK_RELAY_DOMAINS "check_relay_domains"
#define VAR_RELAY_CODE "relay_domains_reject_code"
#define DEF_RELAY_CODE 550
#define DEF_RELAY_CODE 554
extern int var_relay_code;
#define PERMIT_MX_BACKUP "permit_mx_backup"
#define VAR_ACCESS_MAP_CODE "access_map_reject_code"
#define DEF_ACCESS_MAP_CODE 550
#define DEF_ACCESS_MAP_CODE 554
extern int var_access_map_code;
#define CHECK_CLIENT_ACL "check_client_access"
@ -761,7 +761,7 @@ extern int var_access_map_code;
#define REJECT_MAPS_RBL "reject_maps_rbl"
#define VAR_MAPS_RBL_CODE "maps_rbl_reject_code"
#define DEF_MAPS_RBL_CODE 550
#define DEF_MAPS_RBL_CODE 554
extern int var_maps_rbl_code;
#define VAR_MAPS_RBL_DOMAINS "maps_rbl_domains"

View File

@ -15,7 +15,7 @@
* Version of this program.
*/
#define VAR_MAIL_VERSION "mail_version"
#define DEF_MAIL_VERSION "Snapshot-19990422"
#define DEF_MAIL_VERSION "Snapshot-19990423"
extern char *var_mail_version;
/* LICENSE

View File

@ -188,7 +188,7 @@ significant octets. Reject the request if the result is <b>REJECT</b>
or "[<b>45</b>]<i>XX text</i>". Permit the request if the result
is anything else. The <b>access_map_reject_code</b> parameter
specifies the response code for <b>REJECT</b> results (default:
<b>550</b>).
<b>554</b>).
<p>
@ -198,7 +198,7 @@ specifies the response code for <b>REJECT</b> results (default:
network address is listed under any of the domains listed in <a
href="#maps_rbl_domains">$maps_rbl_domains</a>. The <b>
maps_rbl_reject_code</b> parameter specifies the response code for
rejected requests (default: <b>550</b>).
rejected requests (default: <b>554</b>).
<p>
@ -333,7 +333,7 @@ or parent domains in the specified table. Reject the request if
the result is <b>REJECT</b> or "[<b>45</b>]<i>XX text</i>". Permit
the request when the result is anything else. The
<b>access_map_reject_code </b> parameter specifies the response
code for <b>REJECT</b> results (default: <b>550</b>).
code for <b>REJECT</b> results (default: <b>554</b>).
<p>
@ -420,7 +420,7 @@ parent domain, or <i>localpart</i>@. Reject the request if the
result is <b>REJECT</b> or "[<b>45</b>]<i>XX text</i>". Permit the
request if the result is anything else. The <b>access_map_reject_code
</b> parameter specifies the result code for rejected requests
(default: <b>550</b>).
(default: <b>554</b>).
<p>
@ -519,7 +519,7 @@ client hostname matches <a href="#relay_domains">$relay_domains</a>,
or when the resolved destination address matches <a href="#relay_domains">
$relay_domains</a>, otherwise reject. The <b>relay_domains_reject_code</b>
parameter specifies the response code for rejected requests (default:
<b>550</b>).
<b>554</b>).
<p>
@ -542,7 +542,7 @@ address, parent domain, or <i>localpart</i>@. Reject the request
if the result is <b>REJECT</b> or "[<b>45</b>]<i>XX text</i>".
Permit the request if the result is anything else. The
<b>access_map_reject_code </b> parameter specifies the result code
for rejected requests (default: <b>550</b>).
for rejected requests (default: <b>554</b>).
<p>
@ -661,7 +661,7 @@ in the ETRN command, or its parent domains. Reject the request if
the result is <b>REJECT</b> or "[<b>45</b>]<i>XX text</i>". Permit
the request if the result is anything else. The <b>access_map_reject_code
</b> parameter specifies the result code for rejected requests
(default: <b>550</b>).
(default: <b>554</b>).
<p>
@ -727,7 +727,7 @@ policy explicit.
is useful at the end of a restriction list, to make the default
policy explicit. The <b>reject_code</b> configuration parameter
specifies the response code to rejected requests (default:
<b>550</b>).
<b>554</b>).
</dl>

View File

@ -97,6 +97,7 @@
-TUSER_ATTR
-TVBUF
-TVSTREAM
-TVSTREAM_POPEN_ARGS
-TVSTRING
-TWAIT_STATUS_T
-TWATCH_FD

View File

@ -97,6 +97,7 @@
-TUSER_ATTR
-TVBUF
-TVSTREAM
-TVSTREAM_POPEN_ARGS
-TVSTRING
-TWAIT_STATUS_T
-TWATCH_FD

View File

@ -97,6 +97,7 @@
-TUSER_ATTR
-TVBUF
-TVSTREAM
-TVSTREAM_POPEN_ARGS
-TVSTRING
-TWAIT_STATUS_T
-TWATCH_FD

View File

@ -97,6 +97,7 @@
-TUSER_ATTR
-TVBUF
-TVSTREAM
-TVSTREAM_POPEN_ARGS
-TVSTRING
-TWAIT_STATUS_T
-TWATCH_FD

View File

@ -97,6 +97,7 @@
-TUSER_ATTR
-TVBUF
-TVSTREAM
-TVSTREAM_POPEN_ARGS
-TVSTRING
-TWAIT_STATUS_T
-TWATCH_FD

View File

@ -97,6 +97,7 @@
-TUSER_ATTR
-TVBUF
-TVSTREAM
-TVSTREAM_POPEN_ARGS
-TVSTRING
-TWAIT_STATUS_T
-TWATCH_FD

View File

@ -97,6 +97,7 @@
-TUSER_ATTR
-TVBUF
-TVSTREAM
-TVSTREAM_POPEN_ARGS
-TVSTRING
-TWAIT_STATUS_T
-TWATCH_FD

View File

@ -168,8 +168,7 @@ static const char *check_myhostname(void)
name = get_hostname();
if ((mode & SHOW_DEFS) == 0 && (dot = strchr(name, '.')) == 0) {
if ((domain = config_lookup_eval(VAR_MYDOMAIN)) == 0)
msg_fatal("My hostname %s is not a fully qualified name - "
"set %s or %s in %s/main.cf",
msg_fatal("My hostname %s is not a fully qualified name - set %s or %s in %s/main.cf",
name, VAR_MYHOSTNAME, VAR_MYDOMAIN, var_config_dir);
name = concatenate(name, ".", domain, (char *) 0);
}

View File

@ -97,6 +97,7 @@
-TUSER_ATTR
-TVBUF
-TVSTREAM
-TVSTREAM_POPEN_ARGS
-TVSTRING
-TWAIT_STATUS_T
-TWATCH_FD

View File

@ -97,6 +97,7 @@
-TUSER_ATTR
-TVBUF
-TVSTREAM
-TVSTREAM_POPEN_ARGS
-TVSTRING
-TWAIT_STATUS_T
-TWATCH_FD

View File

@ -97,6 +97,7 @@
-TUSER_ATTR
-TVBUF
-TVSTREAM
-TVSTREAM_POPEN_ARGS
-TVSTRING
-TWAIT_STATUS_T
-TWATCH_FD

View File

@ -97,6 +97,7 @@
-TUSER_ATTR
-TVBUF
-TVSTREAM
-TVSTREAM_POPEN_ARGS
-TVSTRING
-TWAIT_STATUS_T
-TWATCH_FD

View File

@ -97,6 +97,7 @@
-TUSER_ATTR
-TVBUF
-TVSTREAM
-TVSTREAM_POPEN_ARGS
-TVSTRING
-TWAIT_STATUS_T
-TWATCH_FD

View File

@ -97,6 +97,7 @@
-TUSER_ATTR
-TVBUF
-TVSTREAM
-TVSTREAM_POPEN_ARGS
-TVSTRING
-TWAIT_STATUS_T
-TWATCH_FD

View File

@ -97,6 +97,7 @@
-TUSER_ATTR
-TVBUF
-TVSTREAM
-TVSTREAM_POPEN_ARGS
-TVSTRING
-TWAIT_STATUS_T
-TWATCH_FD

View File

@ -97,6 +97,7 @@
-TUSER_ATTR
-TVBUF
-TVSTREAM
-TVSTREAM_POPEN_ARGS
-TVSTRING
-TWAIT_STATUS_T
-TWATCH_FD

View File

@ -97,6 +97,7 @@
-TUSER_ATTR
-TVBUF
-TVSTREAM
-TVSTREAM_POPEN_ARGS
-TVSTRING
-TWAIT_STATUS_T
-TWATCH_FD

View File

@ -97,6 +97,7 @@
-TUSER_ATTR
-TVBUF
-TVSTREAM
-TVSTREAM_POPEN_ARGS
-TVSTRING
-TWAIT_STATUS_T
-TWATCH_FD

View File

@ -97,6 +97,7 @@
-TUSER_ATTR
-TVBUF
-TVSTREAM
-TVSTREAM_POPEN_ARGS
-TVSTRING
-TWAIT_STATUS_T
-TWATCH_FD

View File

@ -97,6 +97,7 @@
-TUSER_ATTR
-TVBUF
-TVSTREAM
-TVSTREAM_POPEN_ARGS
-TVSTRING
-TWAIT_STATUS_T
-TWATCH_FD

View File

@ -68,7 +68,7 @@
/* 4xx or 5xx status code. Other numerical status codes are not
/* permitted. Allow the request otherwise. The
/* \fIaccess_map_reject_code\fR configuration parameter specifies the
/* reject status code (default: 550).
/* reject status code (default: 554).
/* .IP "check_client_access maptype:mapname"
/* Look up the client host name or any of its parent domains, or
/* the client address or any network obtained by stripping octets
@ -86,7 +86,7 @@
/* DNS zones below the domains listed in the "maps_rbl_domains"
/* configuration parameter. The \fImaps_rbl_reject_code\fR
/* configuration parameter specifies the reject status code
/* (default: 550).
/* (default: 554).
/* .IP permit_naked_ip_address
/* Permit the use of a naked IP address (without enclosing [])
/* in HELO/EHLO commands.
@ -123,7 +123,7 @@
/* recipient domain matches the \fIrelay_domains\fR configuration
/* parameter. Reject the request otherwise.
/* The \fIrelay_domains_reject_code\fR configuration parameter specifies
/* the reject status code (default: 550).
/* the reject status code (default: 554).
/* .IP permit_mx_backup
/* Allow the request when the local mail system is mail exchanger
/* for the recipient domain (this includes the case where the local

View File

@ -97,6 +97,7 @@
-TUSER_ATTR
-TVBUF
-TVSTREAM
-TVSTREAM_POPEN_ARGS
-TVSTRING
-TWAIT_STATUS_T
-TWATCH_FD

View File

@ -97,6 +97,7 @@
-TUSER_ATTR
-TVBUF
-TVSTREAM
-TVSTREAM_POPEN_ARGS
-TVSTRING
-TWAIT_STATUS_T
-TWATCH_FD

View File

@ -97,6 +97,7 @@
-TUSER_ATTR
-TVBUF
-TVSTREAM
-TVSTREAM_POPEN_ARGS
-TVSTRING
-TWAIT_STATUS_T
-TWATCH_FD

View File

@ -19,7 +19,8 @@ SRCS = argv.c argv_split.c attr.c basename.c binhash.c chroot_uid.c \
unsafe.c username.c valid_hostname.c vbuf.c vbuf_print.c \
vstream.c vstream_popen.c vstring.c vstring_vstream.c writable.c \
write_buf.c write_wait.c dict_unix.c dict_pcre.c stream_listen.c \
stream_connect.c stream_trigger.c dict_regexp.c watch_fd.c
stream_connect.c stream_trigger.c dict_regexp.c watch_fd.c \
clean_env.c
OBJS = argv.o argv_split.o attr.o basename.o binhash.o chroot_uid.o \
close_on_exec.o concatenate.o dict.o dict_db.o dict_dbm.o \
dict_env.o dict_ht.o dict_ldap.o dict_ni.o dict_nis.o \
@ -40,7 +41,8 @@ OBJS = argv.o argv_split.o attr.o basename.o binhash.o chroot_uid.o \
unsafe.o username.o valid_hostname.o vbuf.o vbuf_print.o \
vstream.o vstream_popen.o vstring.o vstring_vstream.o writable.o \
write_buf.o write_wait.o dict_unix.o dict_pcre.o stream_listen.o \
stream_connect.o stream_trigger.o dict_regexp.o watch_fd.o
stream_connect.o stream_trigger.o dict_regexp.o watch_fd.o \
clean_env.o
HDRS = argv.h attr.h binhash.h chroot_uid.h connect.h dict.h dict_db.h \
dict_dbm.h dict_env.h dict_ht.h dict_ldap.h dict_ni.h dict_nis.h \
dict_nisplus.h dir_forest.h events.h exec_command.h find_inet.h \
@ -54,7 +56,7 @@ HDRS = argv.h attr.h binhash.h chroot_uid.h connect.h dict.h dict_db.h \
sigdelay.h split_at.h stat_as.h stringops.h sys_defs.h \
timed_connect.h timed_wait.h trigger.h username.h valid_hostname.h \
vbuf.h vbuf_print.h vstream.h vstring.h vstring_vstream.h \
dict_unix.h dict_pcre.h dict_regexp.h watch_fd.h
dict_unix.h dict_pcre.h dict_regexp.h watch_fd.h clean_env.h
TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
stream_test.c
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
@ -274,6 +276,10 @@ chroot_uid.o: chroot_uid.c
chroot_uid.o: sys_defs.h
chroot_uid.o: msg.h
chroot_uid.o: chroot_uid.h
clean_env.o: clean_env.c
clean_env.o: sys_defs.h
clean_env.o: msg.h
clean_env.o: clean_env.h
close_on_exec.o: close_on_exec.c
close_on_exec.o: sys_defs.h
close_on_exec.o: msg.h
@ -802,10 +808,12 @@ vstream.o: vstream.h
vstream_popen.o: vstream_popen.c
vstream_popen.o: sys_defs.h
vstream_popen.o: msg.h
vstream_popen.o: binhash.h
vstream_popen.o: exec_command.h
vstream_popen.o: vstream.h
vstream_popen.o: vbuf.h
vstream_popen.o: argv.h
vstream_popen.o: set_ugid.h
vstream_popen.o: clean_env.h
vstring.o: vstring.c
vstring.o: sys_defs.h
vstring.o: mymalloc.h

View File

@ -31,10 +31,7 @@
/* Utility library. */
#include <msg.h>
/* Global library. */
#include "clean_env.h"
#include <clean_env.h>
/* clean_env - clean up the environment */

View File

@ -17,7 +17,7 @@
/* Arguments:
/* .IP ldapsource
/* The prefix which will be used to obtain configuration parameters
/* for this search. If it's 'ldapone', the configuration variables below
/* for this search. If it's 'ldapone', the configuration variables below
/* would look like 'ldapone_server_host', 'ldapone_search_base', and so
/* on in main.cf.
/* .IP dummy
@ -61,7 +61,7 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10532, USA
/*
/*
/* John Hensley
/* Merit Network, Inc.
/* hensley@merit.edu
@ -97,23 +97,23 @@
* themselves, including their configuration file parameters.
*/
/*
/*
* structure containing all the configuration parameters for a given
* LDAP source, plus its connection handle
*/
typedef struct {
DICT dict; /* generic member */
char *ldapsource;
char *server_host;
DICT dict; /* generic member */
char *ldapsource;
char *server_host;
int server_port;
char *search_base;
char *query_filter;
char *result_attribute;
char *search_base;
char *query_filter;
char *result_attribute;
int bind;
char *bind_dn;
char *bind_pw;
char *bind_dn;
char *bind_pw;
int timeout;
LDAP *ld;
LDAP *ld;
} DICT_LDAP;
/*
@ -133,14 +133,13 @@ static const char *dict_ldap_lookup(DICT *dict, const char *name)
char *myname = "dict_ldap_lookup";
DICT_LDAP *dict_ldap = (DICT_LDAP *) dict;
static VSTRING *result;
int LDAP_UNBIND = 0;
LDAPMessage *res = 0;
LDAPMessage *entry = 0;
LDAPMessage *res = 0;
LDAPMessage *entry = 0;
struct timeval tv;
VSTRING *filter_buf = 0;
char **attr_values;
long i = 0, j = 0;
int rc = 0;
long i = 0;
int rc = 0;
void (*saved_alarm) (int);
dict_errno = 0;
@ -149,60 +148,61 @@ static const char *dict_ldap_lookup(DICT *dict, const char *name)
* Initialize.
*/
if (result == 0)
result = vstring_alloc(2);
result = vstring_alloc(2);
vstring_strcpy(result,"");
vstring_strcpy(result, "");
if (msg_verbose)
msg_info("%s: In dict_ldap_lookup", myname);
msg_info("%s: In dict_ldap_lookup", myname);
if (dict_ldap->ld == 0) {
msg_warn("%s: no existing connection for ldapsource %s, reopening",
myname, dict_ldap->ldapsource);
if (msg_verbose)
msg_info("%s: connecting to server %s", myname,
dict_ldap->server_host);
msg_warn("%s: no existing connection for ldapsource %s, reopening",
myname, dict_ldap->ldapsource);
if (msg_verbose)
msg_info("%s: connecting to server %s", myname,
dict_ldap->server_host);
if ((saved_alarm = signal(SIGALRM, dict_ldap_timeout)) == SIG_ERR)
msg_fatal("%s: signal: %m", myname);
if ((saved_alarm = signal(SIGALRM, dict_ldap_timeout)) == SIG_ERR)
msg_fatal("%s: signal: %m", myname);
alarm(dict_ldap->timeout);
if (setjmp(env) == 0)
dict_ldap->ld = ldap_open(dict_ldap->server_host,
(int) dict_ldap->server_port);
alarm(0);
alarm(dict_ldap->timeout);
if (setjmp(env) == 0)
dict_ldap->ld = ldap_open(dict_ldap->server_host,
(int) dict_ldap->server_port);
alarm(0);
if (signal(SIGALRM, saved_alarm) == SIG_ERR)
msg_fatal("%s: signal: %m", myname);
if (signal(SIGALRM, saved_alarm) == SIG_ERR)
msg_fatal("%s: signal: %m", myname);
if (msg_verbose)
msg_info("%s: after ldap_open", myname);
if (msg_verbose)
msg_info("%s: after ldap_open", myname);
if (dict_ldap->ld == 0) {
msg_fatal("%s: Unable to contact LDAP server %s",
myname, dict_ldap->server_host);
} else {
/*
* If this server requires us to bind, do so.
*/
if (dict_ldap->bind) {
if (msg_verbose)
msg_info("%s: about to bind: server %s, base %s", myname,
dict_ldap->server_host, dict_ldap->search_base);
if (dict_ldap->ld == 0) {
msg_fatal("%s: Unable to contact LDAP server %s",
myname, dict_ldap->server_host);
} else {
rc = ldap_bind_s(dict_ldap->ld, dict_ldap->search_base, NULL,
LDAP_AUTH_SIMPLE);
if (rc != LDAP_SUCCESS) {
msg_fatal("%s: Unable to bind with search base %s at server %s (%d -- %s): ", myname, dict_ldap->search_base, dict_ldap->server_host, rc, ldap_err2string(rc));
} else {
if (msg_verbose)
msg_info("%s: Successful bind to server %s with search base %s(%d -- %s): ", myname, dict_ldap->search_base, dict_ldap->server_host, rc, ldap_err2string(rc));
}
}
if (msg_verbose)
msg_info("%s: cached connection handle for LDAP source %s",
myname, dict_ldap->ldapsource);
}
/*
* If this server requires us to bind, do so.
*/
if (dict_ldap->bind) {
if (msg_verbose)
msg_info("%s: about to bind: server %s, base %s", myname,
dict_ldap->server_host, dict_ldap->search_base);
rc = ldap_bind_s(dict_ldap->ld, dict_ldap->search_base, NULL,
LDAP_AUTH_SIMPLE);
if (rc != LDAP_SUCCESS) {
msg_fatal("%s: Unable to bind with search base %s at server %s (%d -- %s): ", myname, dict_ldap->search_base, dict_ldap->server_host, rc, ldap_err2string(rc));
} else {
if (msg_verbose)
msg_info("%s: Successful bind to server %s with search base %s(%d -- %s): ", myname, dict_ldap->search_base, dict_ldap->server_host, rc, ldap_err2string(rc));
}
}
if (msg_verbose)
msg_info("%s: cached connection handle for LDAP source %s",
myname, dict_ldap->ldapsource);
}
}
/*
@ -214,47 +214,51 @@ static const char *dict_ldap_lookup(DICT *dict, const char *name)
vstring_sprintf(filter_buf, dict_ldap->query_filter, name);
if (msg_verbose)
msg_info("%s: searching with filter %s", myname,
vstring_str(filter_buf));
msg_info("%s: searching with filter %s", myname,
vstring_str(filter_buf));
if ((rc=ldap_search_st(dict_ldap->ld, dict_ldap->search_base,
LDAP_SCOPE_SUBTREE,
vstring_str(filter_buf),
0, 0, &tv, &res)) != LDAP_SUCCESS) {
if ((rc = ldap_search_st(dict_ldap->ld, dict_ldap->search_base,
LDAP_SCOPE_SUBTREE,
vstring_str(filter_buf),
0, 0, &tv, &res)) != LDAP_SUCCESS) {
msg_info("%s: right after search", myname);
msg_warn("%s: Unable to search base %s at server %s (%d -- %s): ",
myname, dict_ldap->search_base, dict_ldap->server_host, rc,
ldap_err2string(rc));
LDAP_UNBIND = 1;
ldap_unbind(dict_ldap->ld);
dict_ldap->ld = 0;
if (msg_verbose)
msg_info("%s: freed connection handle for LDAP source %s", myname, dict_ldap->ldapsource);
msg_fatal("%s: Unable to search base %s at server %s (%d -- %s): ",
myname, dict_ldap->search_base, dict_ldap->server_host, rc,
ldap_err2string(rc));
} else {
/*
* Extract the requested result_attribute.
*/
if (msg_verbose)
msg_info("%s: search completed", myname);
if ((entry = ldap_first_entry(dict_ldap->ld, res)) != 0) {
attr_values = ldap_get_values(dict_ldap->ld, entry,
dict_ldap->result_attribute);
/*
* Append each returned address to the result list.
*/
while (attr_values[i]) {
if (VSTRING_LEN(result) > 0)
vstring_strcat(result, ",");
vstring_strcat(result, attr_values[i]);
i++;
}
ldap_value_free(attr_values);
if (msg_verbose)
msg_info("%s: search returned: %s", myname, vstring_str(result));
} else {
if (msg_verbose)
msg_info("%s: search returned nothing", myname);
}
/*
* Extract the requested result_attribute.
*/
if (msg_verbose)
msg_info("%s: search found %d", myname,
ldap_count_entries(dict_ldap->ld, res));
for (entry = ldap_first_entry(dict_ldap->ld, res); entry != NULL; entry = ldap_next_entry(dict_ldap->ld, entry)) {
attr_values = ldap_get_values(dict_ldap->ld, entry,
dict_ldap->result_attribute);
if (attr_values == NULL) {
msg_warn("%s: entry doesn't have any values for %s", myname, dict_ldap->result_attribute);
continue;
}
/*
* Append each returned address to the result list.
*/
for (i = 0; attr_values[i] != NULL; i++) {
if (VSTRING_LEN(result) > 0)
vstring_strcat(result, ",");
vstring_strcat(result, attr_values[i]);
}
ldap_value_free(attr_values);
}
if (msg_verbose)
msg_info("%s: search returned: %s", myname, vstring_str(result));
}
/*
@ -262,28 +266,18 @@ static const char *dict_ldap_lookup(DICT *dict, const char *name)
* perform the query.
*/
if (res != 0)
ldap_msgfree(res);
ldap_msgfree(res);
else
dict_errno = 1;
if (LDAP_UNBIND == 1) {
/*
* there was an LDAP problem; free the handle
*/
ldap_unbind(dict_ldap->ld);
dict_ldap->ld = 0;
if (msg_verbose)
msg_info("%s: freed connection handle for LDAP source %s",
myname, dict_ldap->ldapsource);
}
dict_errno = 1;
if (filter_buf != 0)
vstring_free(filter_buf);
return (entry != 0 ? vstring_str(result) : 0);
vstring_free(filter_buf);
return (VSTRING_LEN(result) > 0 ? vstring_str(result) : 0);
}
/* dict_ldap_update - add or update database entry */
static void dict_ldap_update(DICT *dict, const char *unused_name,
const char *unused_value)
const char *unused_value)
{
msg_fatal("dict_ldap_update: operation not implemented");
}
@ -296,7 +290,7 @@ static void dict_ldap_close(DICT *dict)
DICT_LDAP *dict_ldap = (DICT_LDAP *) dict;
if (dict_ldap->ld)
ldap_unbind(dict_ldap->ld);
ldap_unbind(dict_ldap->ld);
myfree(dict_ldap->ldapsource);
myfree(dict_ldap->server_host);
@ -305,7 +299,7 @@ static void dict_ldap_close(DICT *dict)
myfree(dict_ldap->result_attribute);
myfree(dict_ldap->bind_dn);
myfree(dict_ldap->bind_pw);
myfree((char *)dict_ldap);
myfree((char *) dict_ldap);
}
/* dict_ldap_open - create association with data base */
@ -315,7 +309,7 @@ DICT *dict_ldap_open(const char *ldapsource, int dummy, int dict_flags)
char *myname = "dict_ldap_open";
DICT_LDAP *dict_ldap;
VSTRING *config_param;
int rc = 0;
int rc = 0;
void (*saved_alarm) (int);
dict_ldap = (DICT_LDAP *) mymalloc(sizeof(*dict_ldap));
@ -326,129 +320,132 @@ DICT *dict_ldap_open(const char *ldapsource, int dummy, int dict_flags)
dict_ldap->dict.flags = dict_flags | DICT_FLAG_FIXED;
if (msg_verbose)
msg_info("%s: using LDAP source %s", myname, ldapsource);
msg_info("%s: using LDAP source %s", myname, ldapsource);
dict_ldap->ldapsource = mystrdup(ldapsource);
config_param = vstring_alloc(15);
vstring_sprintf(config_param, "%s_server_host", ldapsource);
dict_ldap->server_host =
mystrdup((char *)get_config_str(vstring_str(config_param),
"localhost",0,0));
dict_ldap->server_host =
mystrdup((char *) get_config_str(vstring_str(config_param),
"localhost", 0, 0));
if (msg_verbose)
msg_info("%s: %s is %s", myname, vstring_str(config_param),
dict_ldap->server_host);
msg_info("%s: %s is %s", myname, vstring_str(config_param),
dict_ldap->server_host);
/* get configured value of "ldapsource_server_port"; default to
/* LDAP_PORT (389) */
/*
* get configured value of "ldapsource_server_port"; default to LDAP_PORT
* (389)
*/
vstring_sprintf(config_param, "%s_server_port", ldapsource);
dict_ldap->server_port =
get_config_int(vstring_str(config_param),LDAP_PORT,0,0);
dict_ldap->server_port =
get_config_int(vstring_str(config_param), LDAP_PORT, 0, 0);
if (msg_verbose)
msg_info("%s: %s is %d", myname, vstring_str(config_param),
dict_ldap->server_port);
msg_info("%s: %s is %d", myname, vstring_str(config_param),
dict_ldap->server_port);
vstring_sprintf(config_param, "%s_search_base", ldapsource);
dict_ldap->search_base =
mystrdup((char *)get_config_str(vstring_str(config_param),"",0,0));
dict_ldap->search_base =
mystrdup((char *) get_config_str(vstring_str(config_param), "", 0, 0));
if (msg_verbose)
msg_info("%s: %s is %s", myname, vstring_str(config_param),
dict_ldap->search_base);
msg_info("%s: %s is %s", myname, vstring_str(config_param),
dict_ldap->search_base);
/* get configured value of "ldapsource_timeout"; default to 10 */
vstring_sprintf(config_param, "%s_timeout", ldapsource);
dict_ldap->timeout = get_config_int(config_param,10,0,0);
dict_ldap->timeout = get_config_int(config_param, 10, 0, 0);
if (msg_verbose)
msg_info("%s: %s is %d", myname, vstring_str(config_param),
dict_ldap->timeout);
msg_info("%s: %s is %d", myname, vstring_str(config_param),
dict_ldap->timeout);
vstring_sprintf(config_param, "%s_query_filter", ldapsource);
dict_ldap->query_filter =
mystrdup((char *)get_config_str(vstring_str(config_param),
"(mailacceptinggeneralid=%s)",0,0));
dict_ldap->query_filter =
mystrdup((char *) get_config_str(vstring_str(config_param),
"(mailacceptinggeneralid=%s)", 0, 0));
if (msg_verbose)
msg_info("%s: %s is %s", myname, vstring_str(config_param),
dict_ldap->query_filter);
msg_info("%s: %s is %s", myname, vstring_str(config_param),
dict_ldap->query_filter);
vstring_sprintf(config_param, "%s_result_attribute", ldapsource);
dict_ldap->result_attribute =
mystrdup((char *)get_config_str(vstring_str(config_param),
"maildrop",0,0));
dict_ldap->result_attribute =
mystrdup((char *) get_config_str(vstring_str(config_param),
"maildrop", 0, 0));
if (msg_verbose)
msg_info("%s: %s is %s", myname, vstring_str(config_param),
dict_ldap->result_attribute);
msg_info("%s: %s is %s", myname, vstring_str(config_param),
dict_ldap->result_attribute);
/* get configured value of "ldapsource_bind"; default to true */
vstring_sprintf(config_param, "%s_bind", ldapsource);
dict_ldap->bind = get_config_bool(vstring_str(config_param), 1);
if (msg_verbose)
msg_info("%s: %s is %d", myname, vstring_str(config_param),
dict_ldap->bind);
msg_info("%s: %s is %d", myname, vstring_str(config_param),
dict_ldap->bind);
/* get configured value of "ldapsource_bind_dn"; default to "" */
vstring_sprintf(config_param, "%s_bind_dn", ldapsource);
dict_ldap->bind_dn =
mystrdup((char *)get_config_str(vstring_str(config_param),"",0,0));
dict_ldap->bind_dn =
mystrdup((char *) get_config_str(vstring_str(config_param), "", 0, 0));
if (msg_verbose)
msg_info("%s: %s is %s", myname, vstring_str(config_param),
dict_ldap->bind_dn);
msg_info("%s: %s is %s", myname, vstring_str(config_param),
dict_ldap->bind_dn);
/* get configured value of "ldapsource_bind_pw"; default to "" */
vstring_sprintf(config_param, "%s_bind_pw", ldapsource);
dict_ldap->bind_pw =
mystrdup((char *)get_config_str(vstring_str(config_param),"",0,0));
dict_ldap->bind_pw =
mystrdup((char *) get_config_str(vstring_str(config_param), "", 0, 0));
if (msg_verbose)
msg_info("%s: %s is %s", myname, vstring_str(config_param),
dict_ldap->bind_pw);
msg_info("%s: %s is %s", myname, vstring_str(config_param),
dict_ldap->bind_pw);
/*
/*
* establish the connection to the LDAP server
*/
if (msg_verbose)
msg_info("%s: connecting to server %s", myname,
dict_ldap->server_host);
msg_info("%s: connecting to server %s", myname,
dict_ldap->server_host);
if ((saved_alarm = signal(SIGALRM, dict_ldap_timeout)) == SIG_ERR)
msg_fatal("%s: signal: %m", myname);
msg_fatal("%s: signal: %m", myname);
alarm(dict_ldap->timeout);
if (setjmp(env) == 0)
dict_ldap->ld = ldap_open(dict_ldap->server_host,
(int) dict_ldap->server_port);
dict_ldap->ld = ldap_open(dict_ldap->server_host,
(int) dict_ldap->server_port);
alarm(0);
if (signal(SIGALRM, saved_alarm) == SIG_ERR)
msg_fatal("%s: signal: %m", myname);
msg_fatal("%s: signal: %m", myname);
if (msg_verbose)
msg_info("%s: after ldap_open", myname);
msg_info("%s: after ldap_open", myname);
if (dict_ldap->ld == 0) {
msg_fatal("%s: Unable to contact LDAP server %s",
myname, dict_ldap->server_host);
msg_fatal("%s: Unable to contact LDAP server %s",
myname, dict_ldap->server_host);
} else {
/*
* If this server requires us to bind, do so.
*/
if (dict_ldap->bind) {
if (msg_verbose)
msg_info("%s: about to bind: server %s, base %s", myname,
dict_ldap->server_host, dict_ldap->search_base);
rc = ldap_bind_s(dict_ldap->ld, dict_ldap->search_base, NULL,
LDAP_AUTH_SIMPLE);
if (rc != LDAP_SUCCESS) {
msg_fatal("%s: Unable to bind with search base %s at server %s (%d -- %s): ", myname, dict_ldap->search_base, dict_ldap->server_host, rc, ldap_err2string(rc));
} else {
if (msg_verbose)
msg_info("%s: Successful bind to server %s with search base %s(%d -- %s): ", myname, dict_ldap->search_base, dict_ldap->server_host, rc, ldap_err2string(rc));
}
}
if (msg_verbose)
msg_info("%s: cached connection handle for LDAP source %s",
myname, dict_ldap->ldapsource);
/*
* If this server requires us to bind, do so.
*/
if (dict_ldap->bind) {
if (msg_verbose)
msg_info("%s: about to bind: server %s, base %s", myname,
dict_ldap->server_host, dict_ldap->search_base);
rc = ldap_bind_s(dict_ldap->ld, dict_ldap->search_base, NULL,
LDAP_AUTH_SIMPLE);
if (rc != LDAP_SUCCESS) {
msg_fatal("%s: Unable to bind with search base %s at server %s (%d -- %s): ", myname, dict_ldap->search_base, dict_ldap->server_host, rc, ldap_err2string(rc));
} else {
if (msg_verbose)
msg_info("%s: Successful bind to server %s with search base %s(%d -- %s): ", myname, dict_ldap->search_base, dict_ldap->server_host, rc, ldap_err2string(rc));
}
}
if (msg_verbose)
msg_info("%s: cached connection handle for LDAP source %s",
myname, dict_ldap->ldapsource);
}
return (&dict_ldap->dict);

View File

@ -103,8 +103,20 @@ extern VSTREAM *vstream_printf(const char *,...);
extern VSTREAM *vstream_fprintf(VSTREAM *, const char *,...);
extern VSTREAM *vstream_popen(const char *, int);
extern VSTREAM *vstream_popen_vargs(int,...);
extern int vstream_pclose(VSTREAM *);
#define vstream_ispipe(vp) ((vp)->pid != 0)
#define VSTREAM_POPEN_END 0 /* terminator */
#define VSTREAM_POPEN_COMMAND 1 /* command is string */
#define VSTREAM_POPEN_ARGV 2 /* command is array */
#define VSTREAM_POPEN_UID 3 /* privileges */
#define VSTREAM_POPEN_GID 4 /* privileges */
#define VSTREAM_POPEN_ENV 5 /* extra environment */
#define VSTREAM_POPEN_SHELL 6 /* alternative shell */
#define VSTREAM_POPEN_WAITPID_FN 7 /* child catcher, waitpid() compat. */
extern VSTREAM *vstream_vfprintf(VSTREAM *, const char *, va_list);
extern int vstream_peek(VSTREAM *);

View File

@ -12,6 +12,9 @@
/*
/* int vstream_pclose(stream)
/* VSTREAM *stream;
/*
/* VSTREAM *vstream_popen_vargs(key, value, ...)
/* int key;
/* DESCRIPTION
/* vstream_popen() opens a one-way or two-way stream to the specified
/* \fIcommand\fR, which is executed by a child process. The \fIflags\fR
@ -19,6 +22,41 @@
/* standard output are redirected to the stream, which is based on a
/* socketpair.
/*
/* vstream_popen_vargs() offers the user more control over the
/* child process and over how it is managed. The key argument
/* specifies what value will follow. pipe_command() takes a list
/* of (key, value) arguments, terminated by VSTREAM_POPEN_END. The
/* following is a listing of key codes together with the expected
/* value type.
/* .RS
/* .IP "VSTREAM_POPEN_COMMAND (char *)"
/* Specifies the command to execute as a string. The string is
/* passed to the shell when it contains shell meta characters
/* or when it appears to be a shell built-in command, otherwise
/* the command is executed without invoking a shell.
/* One of VSTREAM_POPEN_COMMAND or VSTREAM_POPEN_ARGV must be specified.
/* .IP "VSTREAM_POPEN_ARGV (char **)"
/* The command is specified as an argument vector. This vector is
/* passed without further inspection to the \fIexecvp\fR() routine.
/* One of VSTREAM_POPEN_COMMAND or VSTREAM_POPEN_ARGV must be specified.
/* See also the VSTREAM_POPEN_SHELL attribute below.
/* .IP "VSTREAM_POPEN_ENV (char **)"
/* Additional environment information, in the form of a null-terminated
/* list of name, value, name, value, ... elements. By default only the
/* command search path is initialized to _PATH_DEFPATH.
/* .IP "VSTREAM_POPEN_UID (int)"
/* The user ID to execute the command as. The user ID must be non-zero.
/* .IP "VSTREAM_POPEN_GID (int)"
/* The group ID to execute the command as. The group ID must be non-zero.
/* .IP "VSTREAM_POPEN_SHELL (char *)"
/* The shell to use when executing the command specified with
/* VSTREAM_POPEN_COMMAND. This shell is invoked regardless of the
/* command content.
/* .IP "VSTREAM_POPEN_WAITPID_FN ((*)(pid_t, WAIT_STATUS_T *, int))"
/* waitpid()-like function to reap the child exit status when
/* vstream_pclose() is called.
/* .RE
/* .PP
/* vstream_pclose() closes the named stream and returns the child
/* exit status. It is an error to specify a stream that was not
/* returned by vstream_popen() or that is no longer open.
@ -55,27 +93,119 @@
#include <sys/socket.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#ifdef USE_PATHS_H
#include <paths.h>
#endif
#include <syslog.h>
/* Utility library. */
#include <msg.h>
#include <binhash.h>
#include <exec_command.h>
#include <vstream.h>
#include <argv.h>
#include <set_ugid.h>
#include <clean_env.h>
/* Application-specific. */
static BINHASH *vstream_popen_table = 0;
typedef struct VSTREAM_POPEN_ARGS {
char **argv;
char *command;
uid_t uid;
gid_t gid;
int privileged;
char **env;
char *shell;
VSTREAM_WAITPID_FN waitpid_fn;
} VSTREAM_POPEN_ARGS;
/* vstream_popen - open stream to child process */
/* vstream_parse_args - get arguments from variadic list */
VSTREAM *vstream_popen(const char *command, int flags)
static VSTREAM *vstream_parse_args(VSTREAM_POPEN_ARGS *args, va_list ap)
{
char *myname = "vstream_parse_args";
int key;
/*
* First, set the default values (on all non-zero entries)
*/
args->argv = 0;
args->command = 0;
args->uid = 0;
args->gid = 0;
args->privileged = 0;
args->env = 0;
args->shell = 0;
args->waitpid_fn = 0;
/*
* Then, override the defaults with user-supplied inputs.
*/
while ((key = va_arg(ap, int)) != VSTREAM_POPEN_END) {
switch (key) {
case VSTREAM_POPEN_ARGV:
if (args->command != 0)
msg_panic("%s: got VSTREAM_POPEN_ARGV and VSTREAM_POPEN_COMMAND", myname);
args->argv = va_arg(ap, char **);
break;
case VSTREAM_POPEN_COMMAND:
if (args->argv != 0)
msg_panic("%s: got VSTREAM_POPEN_ARGV and VSTREAM_POPEN_COMMAND", myname);
args->command = va_arg(ap, char *);
break;
case VSTREAM_POPEN_UID:
args->privileged = 1;
args->uid = va_arg(ap, int);
break;
case VSTREAM_POPEN_GID:
args->privileged = 1;
args->gid = va_arg(ap, int);
break;
case VSTREAM_POPEN_ENV:
args->env = va_arg(ap, char **);
break;
case VSTREAM_POPEN_SHELL:
args->shell = va_arg(ap, char *);
break;
case VSTREAM_POPEN_WAITPID_FN:
args->waitpid_fn = va_arg(ap, VSTREAM_WAITPID_FN);
break;
default:
msg_panic("%s: unknown key: %d", myname, key);
}
}
if (args->command == 0 && args->argv == 0)
msg_panic("%s: missing VSTREAM_POPEN_ARGV or VSTREAM_POPEN_COMMAND", myname);
if (args->privileged != 0 && args->uid == 0)
msg_panic("%s: privileged uid", myname);
if (args->privileged != 0 && args->gid == 0)
msg_panic("%s: privileged gid", myname);
}
/* vstream_popen_vargs - open stream to child process */
VSTREAM *vstream_popen_vargs(int flags,...)
{
char *myname = "vstream_popen_vargs";
VSTREAM_POPEN_ARGS args;
va_list ap;
VSTREAM *stream;
int sockfd[2];
pid_t pid;
int pid;
int fd;
ARGV *argv;
char **cpp;
va_start(ap, flags);
vstream_parse_args(&args, ap);
va_end(ap);
if (args.command == 0)
args.command = args.argv[0];
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd) < 0)
return (0);
@ -92,48 +222,87 @@ VSTREAM *vstream_popen(const char *command, int flags)
msg_fatal("dup2: %m");
if (sockfd[0] >= 2 && close(sockfd[0]))
msg_warn("close: %m");
exec_command(command);
/*
* Don't try to become someone else unless the user specified it.
*/
if (args.privileged)
set_ugid(args.uid, args.gid);
/*
* Environment plumbing. Always reset the command search path. XXX
* That should probably be done by clean_env().
*/
clean_env();
if (setenv("PATH", _PATH_DEFPATH, 1))
msg_fatal("%s: setenv: %m", myname);
if (args.env)
for (cpp = args.env; *cpp; cpp += 2)
if (setenv(cpp[0], cpp[1], 1))
msg_fatal("setenv: %m");
/*
* Process plumbing. If possible, avoid running a shell.
*/
closelog();
if (args.argv) {
execvp(args.argv[0], args.argv);
msg_fatal("%s: execvp %s: %m", myname, args.argv[0]);
} else if (args.shell && *args.shell) {
argv = argv_split(args.shell, " \t\r\n");
argv_add(argv, args.command, (char *) 0);
argv_terminate(argv);
execvp(argv->argv[0], argv->argv);
msg_fatal("%s: execvp %s: %m", myname, argv->argv[0]);
} else {
exec_command(args.command);
}
/* NOTREACHED */
default: /* parent */
if (close(sockfd[0]))
msg_warn("close: %m");
stream = vstream_fdopen(sockfd[1], flags);
if (vstream_popen_table == 0)
vstream_popen_table = binhash_create(10);
binhash_enter(vstream_popen_table, (char *) &stream,
sizeof(stream), (char *) pid);
stream->waitpid_fn = args.waitpid_fn;
stream->pid = pid;
return (stream);
}
}
/* vstream_popen - retro-compatible wrapper for new interface */
VSTREAM *vstream_popen(const char *command, int flags)
{
return (vstream_popen_vargs(flags,
VSTREAM_POPEN_COMMAND, command,
VSTREAM_POPEN_END));
}
/* vstream_pclose - close stream to child process */
int vstream_pclose(VSTREAM *stream)
{
char *myname = "vstream_pclose";
BINHASH_INFO *info;
int pid;
pid_t saved_pid = stream->pid;
VSTREAM_WAITPID_FN saved_waitpid_fn = stream->waitpid_fn;
pid_t pid;
WAIT_STATUS_T wait_status;
/*
* Sanity check.
* Close the pipe. Don't trigger an alarm in vstream_fclose().
*/
if (vstream_popen_table == 0
|| (info = binhash_locate(vstream_popen_table, (char *) &stream,
sizeof(stream))) == 0)
msg_panic("%s: spurious stream %p", myname, (char *) stream);
if (saved_pid == 0)
msg_panic("vstream_pclose: stream has no process");
stream->pid = 0;
vstream_fclose(stream);
/*
* Close the stream and reap the child exit status. Ignore errors while
* flushing the stream. The child might already have terminated.
* Reap the child exit status.
*/
(void) vstream_fclose(stream);
do {
pid = waitpid((pid_t) info->value, &wait_status, 0);
if (saved_waitpid_fn != 0)
pid = saved_waitpid_fn(saved_pid, &wait_status, 0);
else
pid = waitpid(saved_pid, &wait_status, 0);
} while (pid == -1 && errno == EINTR);
binhash_delete(vstream_popen_table, (char *) &stream, sizeof(stream),
(void (*) (char *)) 0);
return (pid == -1 ? -1 :
WIFSIGNALED(wait_status) ? WTERMSIG(wait_status) :
WEXITSTATUS(wait_status));