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