1/*++ 2/* NAME 3/* inet_trigger 3 4/* SUMMARY 5/* wakeup INET-domain server 6/* SYNOPSIS 7/* #include <trigger.h> 8/* 9/* int inet_trigger(service, buf, len, timeout) 10/* char *service; 11/* const char *buf; 12/* ssize_t len; 13/* int timeout; 14/* DESCRIPTION 15/* inet_trigger() wakes up the named INET-domain server by making 16/* a brief connection to it and by writing the contents of the 17/* named buffer. 18/* 19/* The connection is closed by a background thread. Some kernels 20/* cannot handle client-side disconnect before the server has 21/* received the message. 22/* 23/* Arguments: 24/* .IP service 25/* Name of the communication endpoint. 26/* .IP buf 27/* Address of data to be written. 28/* .IP len 29/* Amount of data to be written. 30/* .IP timeout 31/* Deadline in seconds. Specify a value <= 0 to disable 32/* the time limit. 33/* DIAGNOSTICS 34/* The result is zero in case of success, -1 in case of problems. 35/* BUGS 36/* SEE ALSO 37/* inet_connect(3), INET-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 inet_trigger { 66 int fd; 67 char *service; 68}; 69 70/* inet_trigger_event - disconnect from peer */ 71 72static void inet_trigger_event(int event, char *context) 73{ 74 struct inet_trigger *ip = (struct inet_trigger *) context; 75 static const char *myname = "inet_trigger_event"; 76 77 /* 78 * Disconnect. 79 */ 80 if (event == EVENT_TIME) 81 msg_warn("%s: read timeout for service %s", myname, ip->service); 82 event_disable_readwrite(ip->fd); 83 event_cancel_timer(inet_trigger_event, context); 84 if (close(ip->fd) < 0) 85 msg_warn("%s: close %s: %m", myname, ip->service); 86 myfree(ip->service); 87 myfree((char *) ip); 88} 89 90 91/* inet_trigger - wakeup INET-domain server */ 92 93int inet_trigger(const char *service, const char *buf, ssize_t len, int timeout) 94{ 95 const char *myname = "inet_trigger"; 96 struct inet_trigger *ip; 97 int fd; 98 99 if (msg_verbose > 1) 100 msg_info("%s: service %s", myname, service); 101 102 /* 103 * Connect... 104 */ 105 if ((fd = inet_connect(service, BLOCKING, timeout)) < 0) { 106 if (msg_verbose) 107 msg_warn("%s: connect to %s: %m", myname, service); 108 return (-1); 109 } 110 close_on_exec(fd, CLOSE_ON_EXEC); 111 ip = (struct inet_trigger *) mymalloc(sizeof(*ip)); 112 ip->fd = fd; 113 ip->service = mystrdup(service); 114 115 /* 116 * Write the request... 117 */ 118 if (write_buf(fd, buf, len, timeout) < 0 119 || write_buf(fd, "", 1, timeout) < 0) 120 if (msg_verbose) 121 msg_warn("%s: write to %s: %m", myname, service); 122 123 /* 124 * Wakeup when the peer disconnects, or when we lose patience. 125 */ 126 if (timeout > 0) 127 event_request_timer(inet_trigger_event, (char *) ip, timeout + 100); 128 event_enable_read(fd, inet_trigger_event, (char *) ip); 129 return (0); 130} 131