1/*++
2/* NAME
3/*	inet_trigger 3
4/* SUMMARY
5/*	wakeup INET-domain server
6/* SYNOPSIS
7/*	#include <trigger.h>
8/*
9/*	int	inet_trigger(service, buf, len, timeout)
10/*	char	*service;
11/*	const char *buf;
12/*	ssize_t	len;
13/*	int	timeout;
14/* DESCRIPTION
15/*	inet_trigger() wakes up the named INET-domain server by making
16/*	a brief connection to it and by writing the contents of the
17/*	named buffer.
18/*
19/*	The connection is closed by a background thread. Some kernels
20/*	cannot handle client-side disconnect before the server has
21/*	received the message.
22/*
23/*	Arguments:
24/* .IP service
25/*	Name of the communication endpoint.
26/* .IP buf
27/*	Address of data to be written.
28/* .IP len
29/*	Amount of data to be written.
30/* .IP timeout
31/*	Deadline in seconds. Specify a value <= 0 to disable
32/*	the time limit.
33/* DIAGNOSTICS
34/*	The result is zero in case of success, -1 in case of problems.
35/* BUGS
36/* SEE ALSO
37/*	inet_connect(3), INET-domain client
38/* LICENSE
39/* .ad
40/* .fi
41/*	The Secure Mailer license must be distributed with this software.
42/* AUTHOR(S)
43/*	Wietse Venema
44/*	IBM T.J. Watson Research
45/*	P.O. Box 704
46/*	Yorktown Heights, NY 10598, USA
47/*--*/
48
49/* System library. */
50
51#include <sys_defs.h>
52#include <sys/socket.h>
53#include <unistd.h>
54#include <string.h>
55
56/* Utility library. */
57
58#include <msg.h>
59#include <connect.h>
60#include <iostuff.h>
61#include <mymalloc.h>
62#include <events.h>
63#include <trigger.h>
64
65struct inet_trigger {
66    int     fd;
67    char   *service;
68};
69
70/* inet_trigger_event - disconnect from peer */
71
72static void inet_trigger_event(int event, char *context)
73{
74    struct inet_trigger *ip = (struct inet_trigger *) context;
75    static const char *myname = "inet_trigger_event";
76
77    /*
78     * Disconnect.
79     */
80    if (event == EVENT_TIME)
81	msg_warn("%s: read timeout for service %s", myname, ip->service);
82    event_disable_readwrite(ip->fd);
83    event_cancel_timer(inet_trigger_event, context);
84    if (close(ip->fd) < 0)
85	msg_warn("%s: close %s: %m", myname, ip->service);
86    myfree(ip->service);
87    myfree((char *) ip);
88}
89
90
91/* inet_trigger - wakeup INET-domain server */
92
93int     inet_trigger(const char *service, const char *buf, ssize_t len, int timeout)
94{
95    const char *myname = "inet_trigger";
96    struct inet_trigger *ip;
97    int     fd;
98
99    if (msg_verbose > 1)
100	msg_info("%s: service %s", myname, service);
101
102    /*
103     * Connect...
104     */
105    if ((fd = inet_connect(service, BLOCKING, timeout)) < 0) {
106	if (msg_verbose)
107	    msg_warn("%s: connect to %s: %m", myname, service);
108	return (-1);
109    }
110    close_on_exec(fd, CLOSE_ON_EXEC);
111    ip = (struct inet_trigger *) mymalloc(sizeof(*ip));
112    ip->fd = fd;
113    ip->service = mystrdup(service);
114
115    /*
116     * Write the request...
117     */
118    if (write_buf(fd, buf, len, timeout) < 0
119	|| write_buf(fd, "", 1, timeout) < 0)
120	if (msg_verbose)
121	    msg_warn("%s: write to %s: %m", myname, service);
122
123    /*
124     * Wakeup when the peer disconnects, or when we lose patience.
125     */
126    if (timeout > 0)
127	event_request_timer(inet_trigger_event, (char *) ip, timeout + 100);
128    event_enable_read(fd, inet_trigger_event, (char *) ip);
129    return (0);
130}
131