1 /*	$NetBSD: stream_trigger.c,v 1.1.1.1 2009/06/23 10:09:01 tron Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	stream_trigger 3
6 /* SUMMARY
7 /*	wakeup stream server
8 /* SYNOPSIS
9 /*	#include <trigger.h>
10 /*
11 /*	int	stream_trigger(service, buf, len, timeout)
12 /*	const char *service;
13 /*	const char *buf;
14 /*	ssize_t	len;
15 /*	int	timeout;
16 /* DESCRIPTION
17 /*	stream_trigger() wakes up the named stream server by making
18 /*	a brief connection to it and writing the named buffer.
19 /*
20 /*	The connection is closed by a background thread. Some kernels
21 /*	cannot handle client-side disconnect before the server has
22 /*	received the message.
23 /*
24 /*	Arguments:
25 /* .IP service
26 /*	Name of the communication endpoint.
27 /* .IP buf
28 /*	Address of data to be written.
29 /* .IP len
30 /*	Amount of data to be written.
31 /* .IP timeout
32 /*	Deadline in seconds. Specify a value <= 0 to disable
33 /*	the time limit.
34 /* DIAGNOSTICS
35 /*	The result is zero in case of success, -1 in case of problems.
36 /* SEE ALSO
37 /*	stream_connect(3), stream 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 <unistd.h>
53 #include <string.h>
54 
55 /* Utility library. */
56 
57 #include <msg.h>
58 #include <connect.h>
59 #include <iostuff.h>
60 #include <mymalloc.h>
61 #include <events.h>
62 #include <trigger.h>
63 
64 struct stream_trigger {
65     int     fd;
66     char   *service;
67 };
68 
69 /* stream_trigger_event - disconnect from peer */
70 
71 static void stream_trigger_event(int event, char *context)
72 {
73     struct stream_trigger *sp = (struct stream_trigger *) context;
74     static const char *myname = "stream_trigger_event";
75 
76     /*
77      * Disconnect.
78      */
79     if (event == EVENT_TIME)
80 	msg_warn("%s: read timeout for service %s", myname, sp->service);
81     event_disable_readwrite(sp->fd);
82     event_cancel_timer(stream_trigger_event, context);
83     if (close(sp->fd) < 0)
84 	msg_warn("%s: close %s: %m", myname, sp->service);
85     myfree(sp->service);
86     myfree((char *) sp);
87 }
88 
89 /* stream_trigger - wakeup stream server */
90 
91 int     stream_trigger(const char *service, const char *buf, ssize_t len, int timeout)
92 {
93     const char *myname = "stream_trigger";
94     struct stream_trigger *sp;
95     int     fd;
96 
97     if (msg_verbose > 1)
98 	msg_info("%s: service %s", myname, service);
99 
100     /*
101      * Connect...
102      */
103     if ((fd = stream_connect(service, BLOCKING, timeout)) < 0) {
104 	if (msg_verbose)
105 	    msg_warn("%s: connect to %s: %m", myname, service);
106 	return (-1);
107     }
108     close_on_exec(fd, CLOSE_ON_EXEC);
109 
110     /*
111      * Stash away context.
112      */
113     sp = (struct stream_trigger *) mymalloc(sizeof(*sp));
114     sp->fd = fd;
115     sp->service = mystrdup(service);
116 
117     /*
118      * Write the request...
119      */
120     if (write_buf(fd, buf, len, timeout) < 0
121 	|| write_buf(fd, "", 1, timeout) < 0)
122 	if (msg_verbose)
123 	    msg_warn("%s: write to %s: %m", myname, service);
124 
125     /*
126      * Wakeup when the peer disconnects, or when we lose patience.
127      */
128     if (timeout > 0)
129 	event_request_timer(stream_trigger_event, (char *) sp, timeout + 100);
130     event_enable_read(fd, stream_trigger_event, (char *) sp);
131     return (0);
132 }
133