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