1 /* $NetBSD: stream_trigger.c,v 1.2 2017/02/14 01:16:49 christos 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
stream_trigger_event(int event,void * context)71 static void stream_trigger_event(int event, void *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((void *) sp);
87 }
88
89 /* stream_trigger - wakeup stream server */
90
stream_trigger(const char * service,const char * buf,ssize_t len,int timeout)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, (void *) sp, timeout + 100);
130 event_enable_read(fd, stream_trigger_event, (void *) sp);
131 return (0);
132 }
133