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 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 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