1/* $NetBSD: unix_pass_trigger.c,v 1.1.1.1 2011/03/02 19:32:46 tron Exp $ */ 2 3/*++ 4/* NAME 5/* unix_pass_trigger 3 6/* SUMMARY 7/* wakeup UNIX-domain file descriptor listener 8/* SYNOPSIS 9/* #include <trigger.h> 10/* 11/* int unix_pass_trigger(service, buf, len, timeout) 12/* const char *service; 13/* const char *buf; 14/* ssize_t len; 15/* int timeout; 16/* DESCRIPTION 17/* unix_pass_trigger() wakes up the named UNIX-domain server by sending 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_pass_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 65struct unix_pass_trigger { 66 int fd; 67 char *service; 68 int pair[2]; 69}; 70 71/* unix_pass_trigger_event - disconnect from peer */ 72 73static void unix_pass_trigger_event(int event, char *context) 74{ 75 struct unix_pass_trigger *up = (struct unix_pass_trigger *) context; 76 static const char *myname = "unix_pass_trigger_event"; 77 78 /* 79 * Disconnect. 80 */ 81 if (event == EVENT_TIME) 82 msg_warn("%s: read timeout for service %s", myname, up->service); 83 event_disable_readwrite(up->fd); 84 event_cancel_timer(unix_pass_trigger_event, context); 85 /* Don't combine multiple close() calls into one boolean expression. */ 86 if (close(up->fd) < 0) 87 msg_warn("%s: close %s: %m", myname, up->service); 88 if (close(up->pair[0]) < 0) 89 msg_warn("%s: close pipe: %m", myname); 90 if (close(up->pair[1]) < 0) 91 msg_warn("%s: close pipe: %m", myname); 92 myfree(up->service); 93 myfree((char *) up); 94} 95 96/* unix_pass_trigger - wakeup UNIX-domain server */ 97 98int unix_pass_trigger(const char *service, const char *buf, ssize_t len, int timeout) 99{ 100 const char *myname = "unix_pass_trigger"; 101 int pair[2]; 102 struct unix_pass_trigger *up; 103 int fd; 104 105 if (msg_verbose > 1) 106 msg_info("%s: service %s", myname, service); 107 108 /* 109 * Connect... 110 */ 111 if ((fd = unix_pass_connect(service, BLOCKING, timeout)) < 0) { 112 if (msg_verbose) 113 msg_warn("%s: connect to %s: %m", myname, service); 114 return (-1); 115 } 116 close_on_exec(fd, CLOSE_ON_EXEC); 117 118 /* 119 * Create a pipe, and send one pipe end to the server. 120 */ 121 if (pipe(pair) < 0) 122 msg_fatal("%s: pipe: %m", myname); 123 close_on_exec(pair[0], CLOSE_ON_EXEC); 124 close_on_exec(pair[1], CLOSE_ON_EXEC); 125 if (unix_send_fd(fd, pair[0]) < 0) 126 msg_fatal("%s: send file descriptor: %m", myname); 127 128 /* 129 * Stash away context. 130 */ 131 up = (struct unix_pass_trigger *) mymalloc(sizeof(*up)); 132 up->fd = fd; 133 up->service = mystrdup(service); 134 up->pair[0] = pair[0]; 135 up->pair[1] = pair[1]; 136 137 /* 138 * Write the request... 139 */ 140 if (write_buf(pair[1], buf, len, timeout) < 0 141 || write_buf(pair[1], "", 1, timeout) < 0) 142 if (msg_verbose) 143 msg_warn("%s: write to %s: %m", myname, service); 144 145 /* 146 * Wakeup when the peer disconnects, or when we lose patience. 147 */ 148 if (timeout > 0) 149 event_request_timer(unix_pass_trigger_event, (char *) up, timeout + 100); 150 event_enable_read(fd, unix_pass_trigger_event, (char *) up); 151 return (0); 152} 153