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

snapshot-19990321

This commit is contained in:
Wietse Venema
1999-03-21 00:00:00 -05:00
parent bc5e358ef8
commit f0ecb1fb5d
47 changed files with 895 additions and 148 deletions

View File

@@ -2346,6 +2346,31 @@ Apologies for any names omitted.
recipients to a master.cf entry called "cyrus", allowing
you to have both UNIX and non-UNIX mailboxes side by side.
19990319
Workaround: on 4.4 BSD derivatives, fstat() can return
EBADF on an open file descriptor. Now, that was a surprise.
This caused std{out,err} from cron commands to not be
delivered.
Bugfix: "local -v" stopped working.
Workaround: more watchdog timers for postfix-unfriendly
systems. By now every Postfix daemon has one. Call it life
insurance.
Robustness: increased the maximal time to receive or deliver
mail from $ipc_timeout (default: 3600 seconds) to the more
generous $daemon_timeout (default: 18000 seconds). We don't
want false alarms.
Portability: IRIX 5.2 does not have usleep().
19990320
Bugfix: \username was broken. Frank Dziuba was the first
to notice.
Future:
Planned: must be able to list the same hash table in

View File

@@ -22,6 +22,8 @@ and add the path to the PCRE library to AUXLIBS, for example:
make -f Makefile.init makefiles 'CCARGS=-DHAS_PCRE -I../../pcre-2.04' \
'AUXLIBS=../../pcre-2.04/libpcre.a'
[note: earlier pcre versions have problems -- Wietse]
One possible use is to add a line to main.cf:
smtpd_recipient_restrictions = pcre:/opt/postfix/etc/smtprecipient

View File

@@ -577,6 +577,7 @@ mail_trigger.o: mail_params.h
mail_trigger.o: mail_proto.h
mail_trigger.o: ../include/vstream.h
mail_trigger.o: ../include/vbuf.h
mail_version.o: mail_version.c
maps.o: maps.c
maps.o: ../include/sys_defs.h
maps.o: ../include/argv.h

View File

@@ -81,7 +81,7 @@ VSTREAM *mail_connect(const char *class, const char *name, int block_mode)
int fd;
path = mail_pathname(class, name);
if ((fd = unix_connect(path, block_mode, 0)) < 0) {
if ((fd = LOCAL_CONNECT(path, block_mode, 0)) < 0) {
if (msg_verbose)
msg_info("connect to subsystem %s: %m", path);
stream = 0;

View File

@@ -55,10 +55,7 @@
/* int var_soft_bounce;
/* time_t var_starttime;
/* int var_ownreq_special;
/*
/* char *var_ldap_server_host;
/* char *var_ldap_search_base;
/* int var_ldap_timeout;
/* int var_daemon_timeout;
/*
/* void mail_params_init()
/* DESCRIPTION
@@ -160,14 +157,7 @@ int var_disable_dns;
int var_soft_bounce;
time_t var_starttime;
int var_ownreq_special;
#ifdef HAS_LDAP
char *var_ldap_server_host;
char *var_ldap_search_base;
int var_ldap_timeout;
#endif
int var_daemon_timeout;
/* check_myhostname - lookup hostname and validate */
@@ -259,10 +249,6 @@ void mail_params_init()
VAR_MAIL_VERSION, DEF_MAIL_VERSION, &var_mail_version, 1, 0,
VAR_DB_TYPE, DEF_DB_TYPE, &var_db_type, 1, 0,
VAR_HASH_QUEUE_NAMES, DEF_HASH_QUEUE_NAMES, &var_hash_queue_names, 1, 0,
#ifdef HAS_LDAP
VAR_LDAP_SERVER, DEF_LDAP_SERVER, &var_ldap_server_host, 0, 0,
VAR_LDAP_SEARCH, DEF_LDAP_SEARCH, &var_ldap_search_base, 0, 0,
#endif
VAR_RCPT_DELIM, DEF_RCPT_DELIM, &var_rcpt_delim, 0, 1,
0,
};
@@ -279,15 +265,13 @@ void mail_params_init()
VAR_MESSAGE_LIMIT, DEF_MESSAGE_LIMIT, &var_message_limit, 0, 0,
VAR_IPC_IDLE, DEF_IPC_IDLE, &var_ipc_idle_limit, 1, 0,
VAR_HASH_QUEUE_DEPTH, DEF_HASH_QUEUE_DEPTH, &var_hash_queue_depth, 1, 0,
#ifdef HAS_LDAP
VAR_LDAP_TIMEOUT, DEF_LDAP_TIMEOUT, &var_ldap_timeout, 1, 0,
#endif
VAR_TRIGGER_TIMEOUT, DEF_TRIGGER_TIMEOUT, &var_trigger_timeout, 1, 0,
VAR_FORK_TRIES, DEF_FORK_TRIES, &var_fork_tries, 1, 0,
VAR_FORK_DELAY, DEF_FORK_DELAY, &var_fork_delay, 1, 0,
VAR_FLOCK_TRIES, DEF_FLOCK_TRIES, &var_flock_tries, 1, 0,
VAR_FLOCK_DELAY, DEF_FLOCK_DELAY, &var_flock_delay, 1, 0,
VAR_FLOCK_STALE, DEF_FLOCK_STALE, &var_flock_stale, 1, 0,
VAR_DAEMON_TIMEOUT, DEF_DAEMON_TIMEOUT, &var_daemon_timeout, 1, 0,
0,
};
static CONFIG_BOOL_TABLE bool_defaults[] = {

View File

@@ -234,21 +234,6 @@ extern bool var_append_dot_mydomain;
#define DEF_PERCENT_HACK 1
extern bool var_percent_hack;
/*
* LDAP lookups. Preliminary code, interface subject to change.
*/
#define VAR_LDAP_SERVER "ldap_server_host"
#define DEF_LDAP_SERVER ""
extern char *var_ldap_server;
#define VAR_LDAP_SEARCH "ldap_search_base"
#define DEF_LDAP_SEARCH ""
extern char *var_ldap_search;
#define VAR_LDAP_TIMEOUT "ldap_lookup_timeout"
#define DEF_LDAP_TIMEOUT 10
extern int var_ldap_timeout;
/*
* Local delivery: alias databases.
*/
@@ -623,6 +608,14 @@ extern int var_flock_delay;
#define DEF_FLOCK_STALE 500
extern int var_flock_stale;
/*
* How long a daemon command may take to receive or deliver a message etc.
* before we assume it is wegded (should never happen).
*/
#define VAR_DAEMON_TIMEOUT "daemon_timeout"
#define DEF_DAEMON_TIMEOUT 18000
extern int var_daemon_timeout;
/*
* How long an intra-mail command may take before we assume the mail system
* is in deadlock (should never happen).

View File

@@ -83,9 +83,9 @@ int mail_trigger(const char *class, const char *service,
} else if (S_ISFIFO(st.st_mode)) {
status = fifo_trigger(path, req_buf, req_len, var_trigger_timeout);
if (status < 0 && S_ISSOCK(st.st_mode))
status = unix_trigger(path, req_buf, req_len, var_trigger_timeout);
status = LOCAL_TRIGGER(path, req_buf, req_len, var_trigger_timeout);
} else if (S_ISSOCK(st.st_mode)) {
status = unix_trigger(path, req_buf, req_len, var_trigger_timeout);
status = LOCAL_TRIGGER(path, req_buf, req_len, var_trigger_timeout);
} else {
msg_warn("%s is not a socket or a fifo", path);
status = -1;

View File

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

View File

@@ -81,6 +81,8 @@ alias.o: local.h
alias.o: ../include/been_here.h
alias.o: ../include/tok822.h
alias.o: ../include/resolve_clnt.h
alias.o: ../include/deliver_request.h
alias.o: ../include/recipient_list.h
biff_notify.o: biff_notify.c
biff_notify.o: ../include/sys_defs.h
biff_notify.o: ../include/msg.h
@@ -103,6 +105,8 @@ command.o: ../include/mail_copy.h
command.o: local.h
command.o: ../include/tok822.h
command.o: ../include/resolve_clnt.h
command.o: ../include/deliver_request.h
command.o: ../include/recipient_list.h
deliver_attr.o: deliver_attr.c
deliver_attr.o: ../include/sys_defs.h
deliver_attr.o: ../include/msg.h
@@ -114,6 +118,8 @@ deliver_attr.o: ../include/vstring.h
deliver_attr.o: ../include/been_here.h
deliver_attr.o: ../include/tok822.h
deliver_attr.o: ../include/resolve_clnt.h
deliver_attr.o: ../include/deliver_request.h
deliver_attr.o: ../include/recipient_list.h
delivered.o: delivered.c
delivered.o: ../include/sys_defs.h
delivered.o: ../include/msg.h
@@ -132,6 +138,8 @@ delivered.o: local.h
delivered.o: ../include/been_here.h
delivered.o: ../include/tok822.h
delivered.o: ../include/resolve_clnt.h
delivered.o: ../include/deliver_request.h
delivered.o: ../include/recipient_list.h
dotforward.o: dotforward.c
dotforward.o: ../include/sys_defs.h
dotforward.o: ../include/msg.h
@@ -151,6 +159,8 @@ dotforward.o: ../include/mail_params.h
dotforward.o: local.h
dotforward.o: ../include/tok822.h
dotforward.o: ../include/resolve_clnt.h
dotforward.o: ../include/deliver_request.h
dotforward.o: ../include/recipient_list.h
feature.o: feature.c
feature.o: ../include/sys_defs.h
feature.o: ../include/msg.h
@@ -165,6 +175,8 @@ feature.o: ../include/vstring.h
feature.o: ../include/been_here.h
feature.o: ../include/tok822.h
feature.o: ../include/resolve_clnt.h
feature.o: ../include/deliver_request.h
feature.o: ../include/recipient_list.h
file.o: file.c
file.o: ../include/sys_defs.h
file.o: ../include/msg.h
@@ -183,6 +195,8 @@ file.o: ../include/mail_params.h
file.o: local.h
file.o: ../include/tok822.h
file.o: ../include/resolve_clnt.h
file.o: ../include/deliver_request.h
file.o: ../include/recipient_list.h
forward.o: forward.c
forward.o: ../include/sys_defs.h
forward.o: ../include/msg.h
@@ -208,6 +222,8 @@ forward.o: local.h
forward.o: ../include/been_here.h
forward.o: ../include/tok822.h
forward.o: ../include/resolve_clnt.h
forward.o: ../include/deliver_request.h
forward.o: ../include/recipient_list.h
include.o: include.c
include.o: ../include/sys_defs.h
include.o: ../include/msg.h
@@ -227,6 +243,8 @@ include.o: local.h
include.o: ../include/vstring.h
include.o: ../include/tok822.h
include.o: ../include/resolve_clnt.h
include.o: ../include/deliver_request.h
include.o: ../include/recipient_list.h
indirect.o: indirect.c
indirect.o: ../include/sys_defs.h
indirect.o: ../include/msg.h
@@ -241,6 +259,8 @@ indirect.o: ../include/vbuf.h
indirect.o: ../include/vstring.h
indirect.o: ../include/tok822.h
indirect.o: ../include/resolve_clnt.h
indirect.o: ../include/deliver_request.h
indirect.o: ../include/recipient_list.h
local.o: local.c
local.o: ../include/sys_defs.h
local.o: ../include/msg.h
@@ -283,9 +303,13 @@ mailbox.o: ../include/sent.h
mailbox.o: ../include/mypwd.h
mailbox.o: ../include/been_here.h
mailbox.o: ../include/mail_params.h
mailbox.o: ../include/mail_proto.h
mailbox.o: ../include/iostuff.h
mailbox.o: local.h
mailbox.o: ../include/tok822.h
mailbox.o: ../include/resolve_clnt.h
mailbox.o: ../include/deliver_request.h
mailbox.o: ../include/recipient_list.h
mailbox.o: biff_notify.h
maildir.o: maildir.c
maildir.o: ../include/sys_defs.h
@@ -307,6 +331,8 @@ maildir.o: ../include/htable.h
maildir.o: ../include/been_here.h
maildir.o: ../include/tok822.h
maildir.o: ../include/resolve_clnt.h
maildir.o: ../include/deliver_request.h
maildir.o: ../include/recipient_list.h
recipient.o: recipient.c
recipient.o: ../include/sys_defs.h
recipient.o: ../include/msg.h
@@ -325,6 +351,8 @@ recipient.o: ../include/vstring.h
recipient.o: ../include/been_here.h
recipient.o: ../include/tok822.h
recipient.o: ../include/resolve_clnt.h
recipient.o: ../include/deliver_request.h
recipient.o: ../include/recipient_list.h
resolve.o: resolve.c
resolve.o: ../include/sys_defs.h
resolve.o: ../include/msg.h
@@ -340,6 +368,8 @@ resolve.o: ../include/tok822.h
resolve.o: ../include/mail_params.h
resolve.o: local.h
resolve.o: ../include/been_here.h
resolve.o: ../include/deliver_request.h
resolve.o: ../include/recipient_list.h
token.o: token.c
token.o: ../include/sys_defs.h
token.o: ../include/msg.h
@@ -355,6 +385,8 @@ token.o: ../include/resolve_clnt.h
token.o: ../include/mail_params.h
token.o: local.h
token.o: ../include/been_here.h
token.o: ../include/deliver_request.h
token.o: ../include/recipient_list.h
unknown.o: unknown.c
unknown.o: ../include/sys_defs.h
unknown.o: ../include/msg.h
@@ -362,11 +394,15 @@ unknown.o: ../include/stringops.h
unknown.o: ../include/mymalloc.h
unknown.o: ../include/been_here.h
unknown.o: ../include/mail_params.h
unknown.o: ../include/mail_proto.h
unknown.o: ../include/vstream.h
unknown.o: ../include/vbuf.h
unknown.o: ../include/iostuff.h
unknown.o: ../include/bounce.h
unknown.o: local.h
unknown.o: ../include/htable.h
unknown.o: ../include/vstream.h
unknown.o: ../include/vbuf.h
unknown.o: ../include/vstring.h
unknown.o: ../include/tok822.h
unknown.o: ../include/resolve_clnt.h
unknown.o: ../include/deliver_request.h
unknown.o: ../include/recipient_list.h

View File

@@ -126,7 +126,9 @@ typedef struct LOCAL_STATE {
#define MSG_LOG_STATE(m, s) \
msg_info("%s[%d]: local %s recip %s exten %s deliver %s", m, \
s.level, s.msg_attr.local, s.msg_attr.recipient, \
s.level, \
s.msg_attr.local ? s.msg_attr.local : "" , \
s.msg_attr.recipient ? s.msg_attr.recipient : "", \
s.msg_attr.extension ? s.msg_attr.extension : "", \
s.msg_attr.delivered ? s.msg_attr.delivered : "")

View File

@@ -105,7 +105,7 @@ static int deliver_switch(LOCAL_STATE state, USER_ATTR usr_attr)
* \user is special: it means don't do any alias or forward expansion.
*/
if (state.msg_attr.recipient[0] == '\\') {
state.msg_attr.recipient++;
state.msg_attr.recipient++, state.msg_attr.local++;
if (*var_rcpt_delim)
state.msg_attr.extension =
split_addr(state.msg_attr.local, *var_rcpt_delim);

View File

@@ -225,6 +225,7 @@ single_server.o: ../include/stringops.h
single_server.o: ../include/sane_accept.h
single_server.o: ../include/myflock.h
single_server.o: ../include/safe_open.h
single_server.o: ../include/listen.h
single_server.o: ../include/mail_params.h
single_server.o: ../include/mail_task.h
single_server.o: ../include/debug_process.h
@@ -249,6 +250,7 @@ trigger_server.o: ../include/stringops.h
trigger_server.o: ../include/sane_accept.h
trigger_server.o: ../include/myflock.h
trigger_server.o: ../include/safe_open.h
trigger_server.o: ../include/listen.h
trigger_server.o: ../include/mail_params.h
trigger_server.o: ../include/mail_task.h
trigger_server.o: ../include/debug_process.h

View File

@@ -152,6 +152,19 @@
#include "master.h"
/* master_watchdog - something got stuck */
static NORETURN master_watchdog(int unused_sig)
{
/*
* This runs as a signal handler. We should not do anything that could
* involve memory managent, but exiting without explanation would be
* worse.
*/
msg_fatal("watchdog timer");
}
int main(int argc, char **argv)
{
static VSTREAM *lock_fp;
@@ -316,7 +329,9 @@ int main(int argc, char **argv)
* multiple things at the same time, it really is all a single thread, so
* that there are no concurrency conflicts within the master process.
*/
signal(SIGALRM, master_watchdog);
for (;;) {
alarm(1000); /* same as trigger servers */
event_loop(-1);
if (master_gotsighup) {
msg_info("reload configuration");

View File

@@ -80,13 +80,13 @@ void master_listen_init(MASTER_SERV *serv)
switch (serv->type) {
/*
* UNIX-domain listener endpoints always come as singlets.
* UNIX-domain or stream listener endpoints always come as singlets.
*/
case MASTER_SERV_TYPE_UNIX:
set_eugid(var_owner_uid, var_owner_gid);
serv->listen_fd[0] =
unix_listen(serv->name, serv->max_proc > var_proc_limit ?
serv->max_proc : var_proc_limit, NON_BLOCKING);
LOCAL_LISTEN(serv->name, serv->max_proc > var_proc_limit ?
serv->max_proc : var_proc_limit, NON_BLOCKING);
close_on_exec(serv->listen_fd[0], CLOSE_ON_EXEC);
set_eugid(getuid(), getgid());
break;

View File

@@ -99,7 +99,7 @@ static void master_wakeup_timer_event(int unused_event, char *context)
status = inet_trigger(serv->name, &wakeup, sizeof(wakeup), BRIEFLY);
break;
case MASTER_SERV_TYPE_UNIX:
status = unix_trigger(serv->name, &wakeup, sizeof(wakeup), BRIEFLY);
status = LOCAL_TRIGGER(serv->name, &wakeup, sizeof(wakeup), BRIEFLY);
break;
case MASTER_SERV_TYPE_FIFO:
status = fifo_trigger(serv->name, &wakeup, sizeof(wakeup), BRIEFLY);

View File

@@ -137,6 +137,7 @@
#include <myflock.h>
#include <safe_open.h>
#endif
#include <listen.h>
/* Global library. */
@@ -164,6 +165,7 @@ static int use_count;
static void (*multi_server_service) (VSTREAM *, char *, char **);
static char *multi_server_name;
static char **multi_server_argv;
static void (*multi_server_accept) (int, char *);
static void (*multi_server_onexit) (void);
#ifndef NO_SELECT_COLLISION
@@ -180,6 +182,19 @@ static NORETURN multi_server_exit(void)
exit(0);
}
/* multi_server_watchdog - something got stuck */
static NORETURN multi_server_watchdog(int unused_sig)
{
/*
* This runs as a signal handler. We should not do anything that could
* involve memory managent, but exiting without explanation would be
* worse.
*/
msg_fatal("watchdog timer");
}
/* multi_server_abort - terminate after abnormal master exit */
static void multi_server_abort(int unused_event, char *unused_context)
@@ -234,20 +249,35 @@ static void multi_server_execute(int unused_event, char *context)
event_request_timer(multi_server_timeout, (char *) 0, var_idle_limit);
}
/* multi_server_accept - accept client connection request */
/* multi_server_wakeup - wake up application */
static void multi_server_accept(int unused_event, char *context)
static void multi_server_wakeup(int fd)
{
VSTREAM *stream;
if (msg_verbose)
msg_info("connection established fd %d", fd);
non_blocking(fd, BLOCKING);
close_on_exec(fd, CLOSE_ON_EXEC);
client_count++;
stream = vstream_fdopen(fd, O_RDWR);
timed_ipc_setup(stream);
event_enable_read(fd, multi_server_execute, (char *) stream);
}
/* multi_server_accept_local - accept client connection request */
static void multi_server_accept_local(int unused_event, char *context)
{
int listen_fd = (int) context;
int time_left = -1;
int fd;
VSTREAM *stream;
#ifndef NO_SELECT_COLLISION
if (multi_server_lock != 0
&& myflock(vstream_fileno(multi_server_lock), MYFLOCK_NONE) < 0)
msg_fatal("select unlock: %m");
#endif
/*
* Some buggy systems cause Postfix to lock up.
*/
signal(SIGALRM, multi_server_watchdog);
alarm(var_daemon_timeout);
/*
* Be prepared for accept() to fail because some other process already
@@ -258,21 +288,62 @@ static void multi_server_accept(int unused_event, char *context)
*/
if (client_count == 0 && var_idle_limit > 0)
time_left = event_cancel_timer(multi_server_timeout, (char *) 0);
if ((fd = sane_accept(listen_fd, (struct sockaddr *) 0, (SOCKADDR_SIZE *) 0)) < 0) {
fd = LOCAL_ACCEPT(listen_fd);
#ifndef NO_SELECT_COLLISION
if (multi_server_lock != 0
&& myflock(vstream_fileno(multi_server_lock), MYFLOCK_NONE) < 0)
msg_fatal("select unlock: %m");
#endif
if (fd < 0) {
if (errno != EAGAIN)
msg_fatal("accept connection: %m");
if (time_left >= 0)
event_request_timer(multi_server_timeout, (char *) 0, time_left);
return;
}
if (msg_verbose)
msg_info("connection established fd %d", fd);
non_blocking(fd, BLOCKING);
close_on_exec(fd, CLOSE_ON_EXEC);
client_count++;
stream = vstream_fdopen(fd, O_RDWR);
timed_ipc_setup(stream);
event_enable_read(fd, multi_server_execute, (char *) stream);
multi_server_wakeup(fd);
}
/* multi_server_accept_inet - accept client connection request */
static void multi_server_accept_inet(int unused_event, char *context)
{
int listen_fd = (int) context;
int time_left = -1;
int fd;
VSTREAM *stream;
/*
* Some buggy systems cause Postfix to lock up.
*/
signal(SIGALRM, multi_server_watchdog);
alarm(var_daemon_timeout);
/*
* Be prepared for accept() to fail because some other process already
* got the connection (the number of processes competing for clients is
* kept small, so this is not a "thundering herd" problem). If the
* accept() succeeds, be sure to disable non-blocking I/O, in order to
* minimize confusion.
*/
if (client_count == 0 && var_idle_limit > 0)
time_left = event_cancel_timer(multi_server_timeout, (char *) 0);
fd = inet_accept(listen_fd);
#ifndef NO_SELECT_COLLISION
if (multi_server_lock != 0
&& myflock(vstream_fileno(multi_server_lock), MYFLOCK_NONE) < 0)
msg_fatal("select unlock: %m");
#endif
if (fd < 0) {
if (errno != EAGAIN)
msg_fatal("accept connection: %m");
if (time_left >= 0)
event_request_timer(multi_server_timeout, (char *) 0, time_left);
return;
}
multi_server_wakeup(fd);
}
/* multi_server_main - the real main program */
@@ -428,8 +499,11 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...)
if (stream == 0) {
if (transport == 0)
msg_fatal("no transport type specified");
if (strcasecmp(transport, MASTER_XPORT_NAME_INET) != 0
&& strcasecmp(transport, MASTER_XPORT_NAME_UNIX) != 0)
if (strcasecmp(transport, MASTER_XPORT_NAME_INET) == 0)
multi_server_accept = multi_server_accept_inet;
else if (strcasecmp(transport, MASTER_XPORT_NAME_UNIX) == 0)
multi_server_accept = multi_server_accept_local;
else
msg_fatal("unsupported transport type: %s", transport);
}

View File

@@ -128,6 +128,7 @@
#include <myflock.h>
#include <safe_open.h>
#endif
#include <listen.h>
/* Global library. */
@@ -154,6 +155,7 @@ static int use_count;
static void (*single_server_service) (VSTREAM *, char *, char **);
static char *single_server_name;
static char **single_server_argv;
static void (*single_server_accept) (int, char *);
static void (*single_server_onexit) (void);
#ifndef NO_SELECT_COLLISION
@@ -170,6 +172,19 @@ static NORETURN single_server_exit(void)
exit(0);
}
/* single_server_watchdog - something got stuck */
static NORETURN single_server_watchdog(int unused_sig)
{
/*
* This runs as a signal handler. We should not do anything that could
* involve memory managent, but exiting without explanation would be
* worse.
*/
msg_fatal("watchdog timer");
}
/* single_server_abort - terminate after abnormal master exit */
static void single_server_abort(int unused_event, char *unused_context)
@@ -188,37 +203,11 @@ static void single_server_timeout(int unused_event, char *unused_context)
single_server_exit();
}
/* single_server_accept - accept client connection request */
/* single_server_wakeup - wake up application */
static void single_server_accept(int unused_event, char *context)
static void single_server_wakeup(int fd)
{
int listen_fd = (int) context;
VSTREAM *stream;
int time_left = -1;
int fd;
#ifndef NO_SELECT_COLLISION
if (single_server_lock != 0
&& myflock(vstream_fileno(single_server_lock), MYFLOCK_NONE) < 0)
msg_fatal("select unlock: %m");
#endif
/*
* Be prepared for accept() to fail because some other process already
* got the connection. We use select() + accept(), instead of simply
* blocking in accept(), because we must be able to detect that the
* master process has gone away unexpectedly.
*/
if (var_idle_limit > 0)
time_left = event_cancel_timer(single_server_timeout, (char *) 0);
if ((fd = sane_accept(listen_fd, (struct sockaddr *) 0, (SOCKADDR_SIZE *) 0)) < 0) {
if (errno != EAGAIN)
msg_fatal("accept connection: %m");
if (time_left >= 0)
event_request_timer(single_server_timeout, (char *) 0, time_left);
return;
}
/*
* If the accept() succeeds, be sure to disable non-blocking I/O, because
@@ -245,6 +234,84 @@ static void single_server_accept(int unused_event, char *context)
event_request_timer(single_server_timeout, (char *) 0, var_idle_limit);
}
/* single_server_accept_local - accept client connection request */
static void single_server_accept_local(int unused_event, char *context)
{
int listen_fd = (int) context;
int time_left = -1;
int fd;
/*
* Some buggy systems cause Postfix to lock up.
*/
signal(SIGALRM, single_server_watchdog);
alarm(var_daemon_timeout);
/*
* Be prepared for accept() to fail because some other process already
* got the connection. We use select() + accept(), instead of simply
* blocking in accept(), because we must be able to detect that the
* master process has gone away unexpectedly.
*/
if (var_idle_limit > 0)
time_left = event_cancel_timer(single_server_timeout, (char *) 0);
fd = LOCAL_ACCEPT(listen_fd);
#ifndef NO_SELECT_COLLISION
if (single_server_lock != 0
&& myflock(vstream_fileno(single_server_lock), MYFLOCK_NONE) < 0)
msg_fatal("select unlock: %m");
#endif
if (fd < 0) {
if (errno != EAGAIN)
msg_fatal("accept connection: %m");
if (time_left >= 0)
event_request_timer(single_server_timeout, (char *) 0, time_left);
return;
}
single_server_wakeup(fd);
}
/* single_server_accept_inet - accept client connection request */
static void single_server_accept_inet(int unused_event, char *context)
{
int listen_fd = (int) context;
int time_left = -1;
int fd;
/*
* Some buggy systems cause Postfix to lock up.
*/
signal(SIGALRM, single_server_watchdog);
alarm(var_daemon_timeout);
/*
* Be prepared for accept() to fail because some other process already
* got the connection. We use select() + accept(), instead of simply
* blocking in accept(), because we must be able to detect that the
* master process has gone away unexpectedly.
*/
if (var_idle_limit > 0)
time_left = event_cancel_timer(single_server_timeout, (char *) 0);
fd = inet_accept(listen_fd);
#ifndef NO_SELECT_COLLISION
if (single_server_lock != 0
&& myflock(vstream_fileno(single_server_lock), MYFLOCK_NONE) < 0)
msg_fatal("select unlock: %m");
#endif
if (fd < 0) {
if (errno != EAGAIN)
msg_fatal("accept connection: %m");
if (time_left >= 0)
event_request_timer(single_server_timeout, (char *) 0, time_left);
return;
}
single_server_wakeup(fd);
}
/* single_server_main - the real main program */
NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...)
@@ -398,8 +465,11 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...)
if (stream == 0) {
if (transport == 0)
msg_fatal("no transport type specified");
if (strcasecmp(transport, MASTER_XPORT_NAME_INET) != 0
&& strcasecmp(transport, MASTER_XPORT_NAME_UNIX) != 0)
if (strcasecmp(transport, MASTER_XPORT_NAME_INET) == 0)
single_server_accept = single_server_accept_inet;
else if (strcasecmp(transport, MASTER_XPORT_NAME_UNIX) == 0)
single_server_accept = single_server_accept_local;
else
msg_fatal("unsupported transport type: %s", transport);
}

View File

@@ -136,6 +136,7 @@
#include <myflock.h>
#include <safe_open.h>
#endif
#include <listen.h>
/* Global library. */
@@ -231,7 +232,7 @@ static void trigger_server_wakeup(int fd)
use_count++;
}
/* trigger_server_accept_fifo - accept socket client request */
/* trigger_server_accept_fifo - accept fifo client request */
static void trigger_server_accept_fifo(int unused_event, char *context)
{
@@ -260,20 +261,15 @@ static void trigger_server_accept_fifo(int unused_event, char *context)
trigger_server_wakeup(listen_fd);
}
/* trigger_server_accept_socket - accept socket client request */
/* trigger_server_accept_local - accept socket client request */
static void trigger_server_accept_socket(int unused_event, char *context)
static void trigger_server_accept_local(int unused_event, char *context)
{
char *myname = "trigger_server_accept_socket";
char *myname = "trigger_server_accept_local";
int listen_fd = (int) context;
int time_left = 0;
int fd;
#ifndef NO_SELECT_COLLISION
if (trigger_server_lock != 0
&& myflock(vstream_fileno(trigger_server_lock), MYFLOCK_NONE) < 0)
msg_fatal("select unlock: %m");
#endif
if (msg_verbose)
msg_info("%s: trigger arrived", myname);
@@ -281,6 +277,7 @@ static void trigger_server_accept_socket(int unused_event, char *context)
/*
* Some buggy systems cause Postfix to lock up.
*/
signal(SIGALRM, trigger_server_watchdog);
alarm(1000);
/*
@@ -292,7 +289,14 @@ static void trigger_server_accept_socket(int unused_event, char *context)
*/
if (var_idle_limit > 0)
time_left = event_cancel_timer(trigger_server_timeout, (char *) 0);
if ((fd = sane_accept(listen_fd, (struct sockaddr *) 0, (SOCKADDR_SIZE *) 0)) < 0) {
fd = LOCAL_ACCEPT(listen_fd);
#ifndef NO_SELECT_COLLISION
if (trigger_server_lock != 0
&& myflock(vstream_fileno(trigger_server_lock), MYFLOCK_NONE) < 0)
msg_fatal("select unlock: %m");
#endif
if (fd < 0) {
if (errno != EAGAIN)
msg_fatal("accept connection: %m");
if (time_left >= 0)
@@ -469,14 +473,15 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,..
* problems, witness the workarounds in the fifo_listen() routine.
* Therefore we support both FIFOs and UNIX-domain sockets, so that the
* user can choose whatever works best.
*
* Well, I give up. Solaris UNIX-domain sockets still don't work properly,
* so it will have to limp along with a streams-specific alternative.
*/
if (stream == 0) {
if (transport == 0)
msg_fatal("no transport type specified");
if (strcasecmp(transport, MASTER_XPORT_NAME_INET) == 0)
trigger_server_accept = trigger_server_accept_socket;
if (strcasecmp(transport, MASTER_XPORT_NAME_UNIX) == 0)
trigger_server_accept = trigger_server_accept_socket;
trigger_server_accept = trigger_server_accept_local;
else if (strcasecmp(transport, MASTER_XPORT_NAME_FIFO) == 0)
trigger_server_accept = trigger_server_accept_fifo;
else

View File

@@ -53,7 +53,6 @@ depend: $(MAKES)
@make -f Makefile.in Makefile
# do not edit below this line - it is generated by 'make depend'
cleanup_extra.o: cleanup_extra.c
pickup.o: pickup.c
pickup.o: ../include/sys_defs.h
pickup.o: ../include/msg.h

View File

@@ -282,10 +282,12 @@ int main(int argc, char **argv)
/*
* To minimize confusion, make sure that the standard file descriptors
* are open before opening anything else.
* are open before opening anything else. XXX Work around for 44BSD where
* fstat can return EBADF on an open file descriptor.
*/
for (fd = 0; fd < 3; fd++)
if (fstat(fd, &st) == -1 && open("/dev/null", 2) != fd)
if (fstat(fd, &st) == -1
&& (close(fd), open("/dev/null", O_RDWR, 0)) != fd)
msg_fatal("open /dev/null: %m");
/*

View File

@@ -146,10 +146,12 @@ int main(int argc, char **argv)
/*
* To minimize confusion, make sure that the standard file descriptors
* are open before opening anything else.
* are open before opening anything else. XXX Work around for 44BSD where
* fstat can return EBADF on an open file descriptor.
*/
for (fd = 0; fd < 3; fd++)
if (fstat(fd, &st) == -1 && open("/dev/null", 2) != fd)
if (fstat(fd, &st) == -1
&& (close(fd), open("/dev/null", O_RDWR, 0)) != fd)
msg_fatal("open /dev/null: %m");
/*

View File

@@ -450,10 +450,12 @@ int main(int argc, char **argv)
/*
* To minimize confusion, make sure that the standard file descriptors
* are open before opening anything else.
* are open before opening anything else. XXX Work around for 44BSD where
* fstat can return EBADF on an open file descriptor.
*/
for (fd = 0; fd < 3; fd++)
if (fstat(fd, &st) == -1 && open("/dev/null", 2) != fd)
if (fstat(fd, &st) == -1
&& (close(fd), open("/dev/null", O_RDWR, 0)) != fd)
msg_fatal("open /dev/null: %m");
/*

View File

@@ -161,10 +161,12 @@ int main(int argc, char **argv)
/*
* To minimize confusion, make sure that the standard file descriptors
* are open before opening anything else.
* are open before opening anything else. XXX Work around for 44BSD where
* fstat can return EBADF on an open file descriptor.
*/
for (fd = 0; fd < 3; fd++)
if (fstat(fd, &st) == -1 && open("/dev/null", 2) != fd)
if (fstat(fd, &st) == -1
&& (close(fd), open("/dev/null", O_RDWR, 0)) != fd)
msg_fatal("open /dev/null: %m");
/*

View File

@@ -147,10 +147,12 @@ int main(int argc, char **argv)
/*
* To minimize confusion, make sure that the standard file descriptors
* are open.
* are open before opening anything else. XXX Work around for 44BSD where
* fstat can return EBADF on an open file descriptor.
*/
for (fd = 0; fd < 3; fd++)
if (fstat(fd, &st) == -1 && open("/dev/null", 2) != fd)
if (fstat(fd, &st) == -1
&& (close(fd), open("/dev/null", O_RDWR, 0)) != fd)
msg_fatal("open /dev/null: %m");
/*

View File

@@ -104,10 +104,12 @@ int main(int argc, char **argv)
/*
* To minimize confusion, make sure that the standard file descriptors
* are open before opening anything else.
* are open before opening anything else. XXX Work around for 44BSD where
* fstat can return EBADF on an open file descriptor.
*/
for (fd = 0; fd < 3; fd++)
if (fstat(fd, &st) == -1 && open("/dev/null", 2) != fd)
if (fstat(fd, &st) == -1
&& (close(fd), open("/dev/null", O_RDWR, 0)) != fd)
msg_fatal("open /dev/null: %m");
/*

View File

@@ -5,7 +5,7 @@
/* lock mail folder and execute command
/* SYNOPSIS
/* .fi
/* \fBpostlock\fR [\fB-c \fIconfig_dir\fB] [\fB-v\fR]
/* \fBpostlock\fR [\fB-c \fIconfig_dir\fB] [\fB-v\fR]
/* \fIfile command...\fR
/* DESCRIPTION
/* The \fBpostlock\fR command locks \fIfile\fR for exclusive
@@ -14,17 +14,17 @@
/*
/* Options:
/* .IP "\fB-c \fIconfig_dir\fR"
/* Read configuration information from \fBmain.cf\fR in the named
/* Read configuration information from \fBmain.cf\fR in the named
/* configuration directory.
/* .IP \fB-v\fR
/* Enable verbose mode for debugging purposes. Multiple \fB-v\fR
/* Enable verbose mode for debugging purposes. Multiple \fB-v\fR
/* options make the software increasingly verbose.
/* .PP
/* Arguments:
/* .IP \fIfile\fR
/* A mailbox file. The user should have read/write permission.
/* .IP \fIcommand...\fR
/* The command to execute while \fIfile\fR is locked for exclusive
/* The command to execute while \fIfile\fR is locked for exclusive
/* access. The command is executed directly, i.e. without
/* interpretation by a shell command interpreter.
/* DIAGNOSTICS
@@ -50,7 +50,7 @@
/* and for default values.
/* .SH "Locking controls"
/* .ad
/* .fi
/* .fi
/* .IP \fBdeliver_lock_attempts\fR
/* Limit the number of attempts to acquire an exclusive lock.
/* .IP \fBdeliver_lock_delay\fR
@@ -137,10 +137,12 @@ int main(int argc, char **argv)
/*
* To minimize confusion, make sure that the standard file descriptors
* are open before opening anything else.
* are open before opening anything else. XXX Work around for 44BSD where
* fstat can return EBADF on an open file descriptor.
*/
for (fd = 0; fd < 3; fd++)
if (fstat(fd, &st) == -1 && open("/dev/null", 2) != fd)
if (fstat(fd, &st) == -1
&& (close(fd), open("/dev/null", O_RDWR, 0)) != fd)
msg_fatal("open /dev/null: %m");
/*

View File

@@ -29,7 +29,7 @@
/* Specifies the logging tag, that is, the identifying name that
/* appears at the beginning of each logging record.
/* .IP \fB-v\fR
/* Enable verbose logging for debugging purposes. Multiple \fB-v\fR
/* Enable verbose logging for debugging purposes. Multiple \fB-v\fR
/* options make the software increasingly verbose.
/* SEE ALSO
/* syslogd(8) syslog daemon.
@@ -151,10 +151,12 @@ int main(int argc, char **argv)
/*
* To minimize confusion, make sure that the standard file descriptors
* are open.
* are open before opening anything else. XXX Work around for 44BSD where
* fstat can return EBADF on an open file descriptor.
*/
for (fd = 0; fd < 3; fd++)
if (fstat(fd, &st) == -1 && open("/dev/null", 2) != fd)
if (fstat(fd, &st) == -1
&& (close(fd), open("/dev/null", O_RDWR, 0)) != fd)
msg_fatal("open /dev/null: %m");
/*

View File

@@ -247,10 +247,12 @@ int main(int argc, char **argv)
/*
* To minimize confusion, make sure that the standard file descriptors
* are open before opening anything else.
* are open before opening anything else. XXX Work around for 44BSD where
* fstat can return EBADF on an open file descriptor.
*/
for (fd = 0; fd < 3; fd++)
if (fstat(fd, &st) == -1 && open("/dev/null", 2) != fd)
if (fstat(fd, &st) == -1
&& (close(fd), open("/dev/null", O_RDWR, 0)) != fd)
msg_fatal("open /dev/null: %m");
/*

View File

@@ -297,10 +297,12 @@ main(int argc, char **argv)
/*
* To minimize confusion, make sure that the standard file descriptors
* are open before opening anything else.
* are open before opening anything else. XXX Work around for 44BSD where
* fstat can return EBADF on an open file descriptor.
*/
for (fd = 0; fd < 3; fd++)
if (fstat(fd, &st) == -1 && open("/dev/null", 2) != fd)
if (fstat(fd, &st) == -1
&& (close(fd), open("/dev/null", O_RDWR, 0)) != fd)
msg_fatal("open /dev/null: %m");
/*

View File

@@ -290,5 +290,5 @@ void qmgr_deliver(QMGR_TRANSPORT *transport, VSTREAM *stream)
/*
* Guard against broken systems.
*/
event_request_timer(qmgr_deliver_abort, (char *) entry, var_ipc_timeout);
event_request_timer(qmgr_deliver_abort, (char *) entry, var_daemon_timeout);
}

View File

@@ -299,7 +299,8 @@ void qmgr_transport_alloc(QMGR_TRANSPORT *transport, QMGR_TRANSPORT_ALLOC_NOT
/*
* Guard against broken systems.
*/
event_request_timer(qmgr_transport_abort, (char *) alloc, var_ipc_timeout);
event_request_timer(qmgr_transport_abort, (char *) alloc,
var_daemon_timeout);
}
/* qmgr_transport_create - create transport instance */

View File

@@ -564,10 +564,12 @@ int main(int argc, char **argv)
/*
* To minimize confusion, make sure that the standard file descriptors
* are open before opening anything else.
* are open before opening anything else. XXX Work around for 44BSD where
* fstat can return EBADF on an open file descriptor.
*/
for (fd = 0; fd < 3; fd++)
if (fstat(fd, &st) == -1 && open("/dev/null", 2) != fd)
if (fstat(fd, &st) == -1
&& (close(fd), open("/dev/null", O_RDWR, 0)) != fd)
msg_fatal("open /dev/null: %m");
/*

View File

@@ -78,9 +78,10 @@ smtp-sink.o: ../include/smtp_stream.h
smtp-source.o: smtp-source.c
smtp-source.o: ../include/sys_defs.h
smtp-source.o: ../include/msg.h
smtp-source.o: ../include/vstring.h
smtp-source.o: ../include/vbuf.h
smtp-source.o: ../include/msg_vstream.h
smtp-source.o: ../include/vstream.h
smtp-source.o: ../include/vbuf.h
smtp-source.o: ../include/vstring.h
smtp-source.o: ../include/vstring_vstream.h
smtp-source.o: ../include/get_hostname.h
smtp-source.o: ../include/split_at.h

View File

@@ -18,7 +18,8 @@ SRCS = argv.c argv_split.c attr.c basename.c binhash.c chroot_uid.c \
translit.c trimblanks.c unix_connect.c unix_listen.c unix_trigger.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
write_buf.c write_wait.c dict_unix.c dict_pcre.c stream_listen.c \
stream_connect.c stream_trigger.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 \
@@ -38,7 +39,8 @@ OBJS = argv.o argv_split.o attr.o basename.o binhash.o chroot_uid.o \
translit.o trimblanks.o unix_connect.o unix_listen.o unix_trigger.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
write_buf.o write_wait.o dict_unix.o dict_pcre.o stream_listen.o \
stream_connect.o stream_trigger.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 \
@@ -478,6 +480,7 @@ inet_listen.o: find_inet.h
inet_listen.o: inet_util.h
inet_listen.o: iostuff.h
inet_listen.o: listen.h
inet_listen.o: sane_accept.h
inet_trigger.o: inet_trigger.c
inet_trigger.o: sys_defs.h
inet_trigger.o: msg.h
@@ -661,6 +664,15 @@ select_bug.o: msg.h
select_bug.o: vstream.h
select_bug.o: vbuf.h
select_bug.o: msg_vstream.h
sendfd_test.o: sendfd_test.c
sendfd_test.o: sys_defs.h
sendfd_test.o: sendfd_test.c
sendfd_test.o: iostuff.h
sendfd_test.o: msg.h
sendfd_test.o: msg_vstream.h
sendfd_test.o: vstream.h
sendfd_test.o: vbuf.h
sendfd_test.o: listen.h
set_eugid.o: set_eugid.c
set_eugid.o: sys_defs.h
set_eugid.o: msg.h
@@ -685,6 +697,22 @@ stat_as.o: sys_defs.h
stat_as.o: msg.h
stat_as.o: set_eugid.h
stat_as.o: stat_as.h
stream_connect.o: stream_connect.c
stream_connect.o: sys_defs.h
stream_connect.o: msg.h
stream_connect.o: connect.h
stream_connect.o: iostuff.h
stream_listen.o: stream_listen.c
stream_listen.o: sys_defs.h
stream_listen.o: msg.h
stream_listen.o: listen.h
stream_listen.o: iostuff.h
stream_trigger.o: stream_trigger.c
stream_trigger.o: sys_defs.h
stream_trigger.o: msg.h
stream_trigger.o: connect.h
stream_trigger.o: iostuff.h
stream_trigger.o: trigger.h
sys_compat.o: sys_compat.c
sys_compat.o: sys_defs.h
timed_connect.o: timed_connect.c
@@ -714,6 +742,7 @@ unix_listen.o: sys_defs.h
unix_listen.o: msg.h
unix_listen.o: iostuff.h
unix_listen.o: listen.h
unix_listen.o: sane_accept.h
unix_trigger.o: unix_trigger.c
unix_trigger.o: sys_defs.h
unix_trigger.o: msg.h

View File

@@ -21,6 +21,7 @@
*/
extern int unix_connect(const char *, int, int);
extern int inet_connect(const char *, int, int);
extern int stream_connect(const char *, int, int);
/* LICENSE
/* .ad

View File

@@ -10,11 +10,16 @@
/* const char *addr;
/* int backlog;
/* int block_mode;
/*
/* int inet_accept(fd)
/* int fd;
/* DESCRIPTION
/* The \fBinet_listen\fR routine starts a listener in the INET domain
/* on the specified address, with the specified backlog, and returns
/* the resulting file descriptor.
/*
/* inet_accept() accepts a connection and sanitizes error results.
/*
/* Arguments:
/* .IP addr
/* The communication endpoint to listen on. The syntax is "host:port".
@@ -25,8 +30,11 @@
/* .IP block_mode
/* Either NON_BLOCKING for a non-blocking socket, or BLOCKING for
/* blocking mode.
/* .IP fd
/* File descriptor returned by inet_listen().
/* DIAGNOSTICS
/* Fatal errors: all errors are fatal.
/* Fatal errors: inet_listen() aborts upon any system call failure.
/* inet_accept() leaves all error handling up to the caller.
/* LICENSE
/* .ad
/* .fi
@@ -59,6 +67,7 @@
#include "inet_util.h"
#include "iostuff.h"
#include "listen.h"
#include "sane_accept.h"
/* Application-specific stuff. */
@@ -102,3 +111,10 @@ int inet_listen(const char *addr, int backlog, int block_mode)
msg_fatal("listen: %m");
return (sock);
}
/* inet_accept - accept connection */
int inet_accept(int fd)
{
return (sane_accept(fd, (struct sockaddr *) 0, (SOCKADDR_SIZE *) 0));
}

View File

@@ -22,6 +22,11 @@
extern int unix_listen(const char *, int, int);
extern int inet_listen(const char *, int, int);
extern int fifo_listen(const char *, int, int);
extern int stream_listen(const char *, int, int);
extern int inet_accept(int);
extern int unix_accept(int);
extern int stream_accept(int);
/* LICENSE
/* .ad

View File

@@ -9,7 +9,7 @@
/* int sane_accept(sock, buf, len)
/* int sock;
/* struct sockaddr *buf;
/* int len;
/* SOCKADDR_SIZE *len;
/* DESCRIPTION
/* sane_accept() implements the accept(2) socket call, and maps
/* known harmless error results to EAGAIN.

BIN
postfix/util/sendfd_test Executable file

Binary file not shown.

105
postfix/util/sendfd_test.c Normal file
View File

@@ -0,0 +1,105 @@
#include "sys_defs.h"
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <stropts.h>
#include "iostuff.h"
#include "msg.h"
#include "msg_vstream.h"
#include "listen.h"
#define FIFO "/tmp/test-fifo"
static const char *progname;
static print_fstat(int fd)
{
struct stat st;
if (fstat(fd, &st) < 0)
msg_fatal("fstat: %m");
vstream_printf("fd %d\n", fd);
vstream_printf("dev %d\n", st.st_dev);
vstream_printf("ino %d\n", st.st_ino);
vstream_fflush(VSTREAM_OUT);
}
static NORETURN usage(void)
{
msg_fatal("usage: %s [-p] [-n count] [-v]", progname);
}
main(int argc, char **argv)
{
struct strrecvfd fdinfo;
int server_fd;
int client_fd;
int print_fstats = 0;
int count = 1;
int ch;
int i;
progname = argv[0];
msg_vstream_init(argv[0], VSTREAM_ERR);
/*
* Parse JCL.
*/
while ((ch = GETOPT(argc, argv, "pn:v")) > 0) {
switch (ch) {
default:
usage();
case 'p':
print_fstats = 1;
break;
case 'n':
if ((count = atoi(optarg)) < 1)
usage();
break;
case 'v':
msg_verbose++;
break;
}
}
server_fd = fifo_listen(FIFO, 0600, NON_BLOCKING);
if (readable(server_fd))
msg_fatal("server fd is readable after create");
/*
* Connect in client.
*/
if ((client_fd = open(FIFO, O_RDWR, NON_BLOCKING)) < 0)
msg_fatal("open %s as client: %m", FIFO);
if (readable(server_fd))
msg_warn("server fd is readable after client open");
if (print_fstats)
print_fstat(0);
if (ioctl(client_fd, I_RECVFD, &fdinfo) < 0)
msg_fatal("receive fd: %m");
for (i = 0; i < count; i++) {
msg_info("send attempt %d", i);
while (!writable(client_fd))
msg_info("wait for client fd to become writable");
if (ioctl(client_fd, I_SENDFD, 0) < 0)
msg_fatal("send fd to server: %m");
}
if (close(client_fd) < 0)
msg_fatal("close client fd: %m");
/*
* Accept in server.
*/
for (i = 0; i < count; i++) {
msg_info("receive attempt %d", i);
while (!readable(server_fd))
msg_info("wait for server fd to become writable");
if (ioctl(server_fd, I_RECVFD, &fdinfo) < 0)
msg_fatal("receive fd: %m");
if (print_fstats)
print_fstat(fdinfo.fd);
if (close(fdinfo.fd) < 0)
msg_fatal("close received fd: %m");
}
}

View File

@@ -0,0 +1,102 @@
/*++
/* NAME
/* stream_connect 3
/* SUMMARY
/* connect to stream listener
/* SYNOPSIS
/* #include <connect.h>
/*
/* int stream_connect(path, block_mode, timeout)
/* const char *path;
/* int block_mode;
/* int timeout;
/* DESCRIPTION
/* stream_connect() connects to a stream listener for the specified
/* pathname, and returns the resulting file descriptor.
/*
/* Arguments:
/* .IP path
/* Null-terminated string with listener endpoint name.
/* .IP block_mode
/* Either NON_BLOCKING for a non-blocking stream, or BLOCKING for
/* blocking mode. However, a stream connection succeeds or fails
/* immediately.
/* .IP timeout
/* This argument is ignored; it is present for compatibility with
/* other interfaces. Stream connections succeed or fail immediately.
/* DIAGNOSTICS
/* The result is -1 in case the connection could not be made.
/* Fatal errors: other system call failures.
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
/* System library. */
#include <sys_defs.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
/* Utility library. */
#include <msg.h>
#include <connect.h>
/* stream_connect - connect to stream listener */
int stream_connect(const char *path, int block_mode, int unused_timeout)
{
#ifdef STREAM_CONNECTIONS
char *myname = "stream_connect";
struct stat st;
int fd;
int flags;
/*
* The requested file system object must exist, otherwise we can't reach
* the server.
*/
if (block_mode == NON_BLOCKING)
flags = O_RDWR | O_NONBLOCK;
else
flags = O_RDWR;
if ((fd = open(path, flags, 0)) < 0)
return (-1);
/*
* XXX Horror. If the open() result is a regular file, no server was
* listening. In this case we simulate what would have happened with
* UNIX-domain sockets.
*/
if (fstat(fd, &st) < 0)
msg_fatal("%s: fstat: %m", myname);
if (S_ISREG(st.st_mode)) {
close(fd);
errno = ECONNREFUSED;
return (-1);
}
/*
* This is for {unix,inet}_connect() compatibility.
*/
if (block_mode == NON_BLOCKING)
non_blocking(fd, NON_BLOCKING);
/*
* No trouble detected, so far.
*/
return (fd);
#else
msg_fatal("stream connections are not implemented");
#endif
}

View File

@@ -0,0 +1,136 @@
/*++
/* NAME
/* stream_listen 3
/* SUMMARY
/* start stream listener
/* SYNOPSIS
/* #include <listen.h>
/*
/* int stream_listen(path, backlog, block_mode)
/* const char *path;
/* int backlog;
/* int block_mode;
/*
/* int stream_accept(fd)
/* int fd;
/* DESCRIPTION
/* This module implements a substitute local IPC for systems that do
/* not have properly-working UNIX-domain sockets.
/*
/* stream_listen() creates a listener endpoint with the specified
/* permissions, and returns a file descriptor to be used for accepting
/* connections.
/*
/* stream_accept() accepts a connection.
/*
/* Arguments:
/* .IP path
/* Null-terminated string with connection destination.
/* .IP backlog
/* This argument exists for compatibility and is ignored.
/* .IP block_mode
/* This argument exists for compatibility and is ignored.
/* blocking mode.
/* .IP fd
/* File descriptor returned by stream_listen().
/* DIAGNOSTICS
/* Fatal errors: stream_listen() aborts upon any system call failure.
/* stream_accept() leaves all error handling up to the caller.
/* BUGS
/* This implementation leaks one file descriptor. This is fixed when
/* endpoints become objects rather than file descriptors.
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
/* System interfaces. */
#include <sys_defs.h>
#ifdef STREAM_CONNECTIONS
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <stropts.h>
#include <fcntl.h>
#endif
/* Utility library. */
#include "msg.h"
#include "listen.h"
/* stream_listen - create stream listener */
int stream_listen(const char *path, int unused_backlog,
int unused_block_mode)
{
#ifdef STREAM_CONNECTIONS
char *myname = "stream_listen";
static int pair[2];
int fd;
/*
* Initialize: create the specified endpoint with the right permissions.
*/
#define PERMS 0666
if (unlink(path) && errno != ENOENT)
msg_fatal("%s: remove %s: %m", myname, path);
if ((fd = open(path, PERMS, O_CREAT | O_TRUNC | O_WRONLY)) < 0)
msg_fatal("%s: create file %s: %m", myname, path);
if (fchmod(fd, PERMS) < 0)
msg_fatal("%s: chmod 0%o: %m", myname, PERMS);
if (close(fd) < 0)
msg_fatal("%s: close file %s: %m", myname, path);
/*
* Associate one pipe end with the file just created. See: Richard
* Stevens, Advanced Programming in the UNIX Environment Ch. 15.5.1
*
* On Solaris 2.4/SPARC, this gives us a "listen queue" of some 460
* connections.
*/
if (pipe(pair) < 0)
msg_fatal("%s: create pipe: %m", myname);
if (ioctl(pair[1], I_PUSH, "connld") < 0)
msg_fatal("%s: push connld module: %m", myname);
if (fattach(pair[1], path) < 0)
msg_fatal("%s: fattach %s: %m", myname, path);
/*
* Return one end, and leak the other. This will be fixed when all
* endpoints are objects instead of bare file descriptors.
*/
return (pair[0]);
#else
msg_fatal("stream connections are not implemented");
#endif
}
/* stream_accept - accept stream connection */
int stream_accept(int fd)
{
#ifdef STREAM_CONNECTIONS
struct strrecvfd fdinfo;
/*
* This will return EAGAIN on a non-blocking stream when someone else
* snatched the connection from us.
*/
if (ioctl(fd, I_RECVFD, &fdinfo) < 0)
return (-1);
return (fdinfo.fd);
#else
msg_fatal("stream connections are not implemented");
#endif
}

View File

@@ -0,0 +1,89 @@
/*++
/* NAME
/* stream_trigger 3
/* SUMMARY
/* wakeup stream server
/* SYNOPSIS
/* #include <trigger.h>
/*
/* int stream_trigger(service, buf, len, timeout)
/* const char *service;
/* const char *buf;
/* int len;
/* int timeout;
/* DESCRIPTION
/* stream_trigger() wakes up the named stream server by making
/* a brief connection to it and writing the named buffer.
/*
/* Arguments:
/* .IP service
/* Name of the communication endpoint.
/* .IP buf
/* Address of data to be written.
/* .IP len
/* Amount of data to be written.
/* .IP timeout
/* Deadline in seconds. Specify a value <= 0 to disable
/* the time limit.
/* DIAGNOSTICS
/* The result is zero in case of success, -1 in case of problems.
/* SEE ALSO
/* stream_connect(3), stream client
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
/* System library. */
#include <sys_defs.h>
#include <unistd.h>
#include <string.h>
/* Utility library. */
#include <msg.h>
#include <connect.h>
#include <iostuff.h>
#include <trigger.h>
/* stream_trigger - wakeup stream server */
int stream_trigger(const char *service, const char *buf, int len, int timeout)
{
char *myname = "stream_trigger";
int fd;
if (msg_verbose > 1)
msg_info("%s: service %s", myname, service);
/*
* Connect...
*/
if ((fd = stream_connect(service, BLOCKING, timeout)) < 0) {
if (msg_verbose)
msg_warn("%s: connect to %s: %m", myname, service);
return (-1);
}
/*
* Write the request...
*/
if (write_buf(fd, buf, len, timeout) < 0)
if (msg_verbose)
msg_warn("%s: write to %s: %m", myname, service);
/*
* Disconnect.
*/
if (close(fd) < 0)
if (msg_verbose)
msg_warn("%s: close %s: %m", myname, service);
return (0);
}

View File

@@ -151,7 +151,11 @@ extern int opterr;
#define DBM_NO_TRAILING_NULL
#define USE_STATVFS
#define STATVFS_IN_SYS_STATVFS_H
#define UNIX_DOMAIN_CONNECT_BLOCKS_FOR_ACCEPT /* Solaris 2.5.1, reportedly */
#define STREAM_CONNECTIONS /* connld module */
#define LOCAL_LISTEN stream_listen
#define LOCAL_ACCEPT stream_accept
#define LOCAL_CONNECT stream_connect
#define LOCAL_TRIGGER stream_trigger
#endif
#ifdef UW7 /* UnixWare 7 */
@@ -261,6 +265,10 @@ extern int initgroups(const char *, int);
#define STATVFS_IN_SYS_STATVFS_H
#endif
#if defined(IRIX5)
#define usleep doze
#endif
#ifdef LINUX2
#define SUPPORTED
#include <sys/types.h>
@@ -503,6 +511,13 @@ extern int opterr;
#define SOCKOPT_SIZE int
#endif
#ifndef LOCAL_LISTEN
#define LOCAL_LISTEN unix_listen
#define LOCAL_ACCEPT unix_accept
#define LOCAL_CONNECT unix_connect
#define LOCAL_TRIGGER unix_trigger
#endif
#if !defined (HAVE_SYS_NDIR_H) && !defined (HAVE_SYS_DIR_H) \
&& !defined (HAVE_NDIR_H)
#define HAVE_DIRENT_H

View File

@@ -17,6 +17,7 @@
extern int unix_trigger(const char *, const char *, int, int);
extern int inet_trigger(const char *, const char *, int, int);
extern int fifo_trigger(const char *, const char *, int, int);
extern int stream_trigger(const char *, const char *, int, int);
/* LICENSE
/* .ad

View File

@@ -10,11 +10,16 @@
/* const char *addr;
/* int backlog;
/* int block_mode;
/*
/* int unix_accept(fd)
/* int fd;
/* DESCRIPTION
/* The \fBunix_listen\fR() routine starts a listener in the UNIX domain
/* on the specified address, with the specified backlog, and returns
/* the resulting file descriptor.
/*
/* unix_accept() accepts a connection and sanitizes error results.
/*
/* Arguments:
/* .IP addr
/* Null-terminated string with connection destination.
@@ -23,8 +28,11 @@
/* .IP block_mode
/* Either NON_BLOCKING for a non-blocking socket, or BLOCKING for
/* blocking mode.
/* .IP fd
/* File descriptor returned by unix_listen().
/* DIAGNOSTICS
/* Fatal errors: all errors are fatal.
/* Fatal errors: unix_listen() aborts upon any system call failure.
/* unix_accept() leaves all error handling up to the caller.
/* LICENSE
/* .ad
/* .fi
@@ -50,6 +58,7 @@
#include "msg.h"
#include "iostuff.h"
#include "listen.h"
#include "sane_accept.h"
/* unix_listen - create UNIX-domain listener */
@@ -93,3 +102,10 @@ int unix_listen(const char *addr, int backlog, int block_mode)
msg_fatal("listen: %m");
return (sock);
}
/* unix_accept - accept connection */
int unix_accept(int fd)
{
return (sane_accept(fd, (struct sockaddr *) 0, (SOCKADDR_SIZE *) 0));
}

View File

@@ -77,7 +77,7 @@ int writable(int fd)
switch (select(fd + 1, (fd_set *) 0, &write_fds, &except_fds, &tv)) {
case -1:
if (errno != EINTR)
msg_fatal("select");
msg_fatal("select: %m");
continue;
default:
return (FD_ISSET(fd, &write_fds));