1 /* $NetBSD: unix_trigger.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */
2
3 /*++
4 /* NAME
5 /* unix_trigger 3
6 /* SUMMARY
7 /* wakeup UNIX-domain server
8 /* SYNOPSIS
9 /* #include <trigger.h>
10 /*
11 /* int unix_trigger(service, buf, len, timeout)
12 /* const char *service;
13 /* const char *buf;
14 /* ssize_t len;
15 /* int timeout;
16 /* DESCRIPTION
17 /* unix_trigger() wakes up the named UNIX-domain 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 /* unix_connect(3), UNIX-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
65 struct unix_trigger {
66 int fd;
67 char *service;
68 };
69
70 /* unix_trigger_event - disconnect from peer */
71
unix_trigger_event(int event,void * context)72 static void unix_trigger_event(int event, void *context)
73 {
74 struct unix_trigger *up = (struct unix_trigger *) context;
75 static const char *myname = "unix_trigger_event";
76
77 /*
78 * Disconnect.
79 */
80 if (event == EVENT_TIME)
81 msg_warn("%s: read timeout for service %s", myname, up->service);
82 event_disable_readwrite(up->fd);
83 event_cancel_timer(unix_trigger_event, context);
84 if (close(up->fd) < 0)
85 msg_warn("%s: close %s: %m", myname, up->service);
86 myfree(up->service);
87 myfree((void *) up);
88 }
89
90 /* unix_trigger - wakeup UNIX-domain server */
91
unix_trigger(const char * service,const char * buf,ssize_t len,int timeout)92 int unix_trigger(const char *service, const char *buf, ssize_t len, int timeout)
93 {
94 const char *myname = "unix_trigger";
95 struct unix_trigger *up;
96 int fd;
97
98 if (msg_verbose > 1)
99 msg_info("%s: service %s", myname, service);
100
101 /*
102 * Connect...
103 */
104 if ((fd = unix_connect(service, BLOCKING, timeout)) < 0) {
105 if (msg_verbose)
106 msg_warn("%s: connect to %s: %m", myname, service);
107 return (-1);
108 }
109 close_on_exec(fd, CLOSE_ON_EXEC);
110
111 /*
112 * Stash away context.
113 */
114 up = (struct unix_trigger *) mymalloc(sizeof(*up));
115 up->fd = fd;
116 up->service = mystrdup(service);
117
118 /*
119 * Write the request...
120 */
121 if (write_buf(fd, buf, len, timeout) < 0
122 || write_buf(fd, "", 1, timeout) < 0)
123 if (msg_verbose)
124 msg_warn("%s: write to %s: %m", myname, service);
125
126 /*
127 * Wakeup when the peer disconnects, or when we lose patience.
128 */
129 if (timeout > 0)
130 event_request_timer(unix_trigger_event, (void *) up, timeout + 100);
131 event_enable_read(fd, unix_trigger_event, (void *) up);
132 return (0);
133 }
134