1 /* $NetBSD: inet_trigger.c,v 1.1.1.1 2009/06/23 10:09:00 tron Exp $ */ 2 3 /*++ 4 /* NAME 5 /* inet_trigger 3 6 /* SUMMARY 7 /* wakeup INET-domain server 8 /* SYNOPSIS 9 /* #include <trigger.h> 10 /* 11 /* int inet_trigger(service, buf, len, timeout) 12 /* char *service; 13 /* const char *buf; 14 /* ssize_t len; 15 /* int timeout; 16 /* DESCRIPTION 17 /* inet_trigger() wakes up the named INET-domain server by making 18 /* a brief connection to it and by writing the contents of the 19 /* named buffer. 20 /* 21 /* The connection is closed by a background thread. Some kernels 22 /* cannot handle client-side disconnect before the server has 23 /* received the message. 24 /* 25 /* Arguments: 26 /* .IP service 27 /* Name of the communication endpoint. 28 /* .IP buf 29 /* Address of data to be written. 30 /* .IP len 31 /* Amount of data to be written. 32 /* .IP timeout 33 /* Deadline in seconds. Specify a value <= 0 to disable 34 /* the time limit. 35 /* DIAGNOSTICS 36 /* The result is zero in case of success, -1 in case of problems. 37 /* BUGS 38 /* SEE ALSO 39 /* inet_connect(3), INET-domain client 40 /* LICENSE 41 /* .ad 42 /* .fi 43 /* The Secure Mailer license must be distributed with this software. 44 /* AUTHOR(S) 45 /* Wietse Venema 46 /* IBM T.J. Watson Research 47 /* P.O. Box 704 48 /* Yorktown Heights, NY 10598, USA 49 /*--*/ 50 51 /* System library. */ 52 53 #include <sys_defs.h> 54 #include <sys/socket.h> 55 #include <unistd.h> 56 #include <string.h> 57 58 /* Utility library. */ 59 60 #include <msg.h> 61 #include <connect.h> 62 #include <iostuff.h> 63 #include <mymalloc.h> 64 #include <events.h> 65 #include <trigger.h> 66 67 struct inet_trigger { 68 int fd; 69 char *service; 70 }; 71 72 /* inet_trigger_event - disconnect from peer */ 73 74 static void inet_trigger_event(int event, char *context) 75 { 76 struct inet_trigger *ip = (struct inet_trigger *) context; 77 static const char *myname = "inet_trigger_event"; 78 79 /* 80 * Disconnect. 81 */ 82 if (event == EVENT_TIME) 83 msg_warn("%s: read timeout for service %s", myname, ip->service); 84 event_disable_readwrite(ip->fd); 85 event_cancel_timer(inet_trigger_event, context); 86 if (close(ip->fd) < 0) 87 msg_warn("%s: close %s: %m", myname, ip->service); 88 myfree(ip->service); 89 myfree((char *) ip); 90 } 91 92 93 /* inet_trigger - wakeup INET-domain server */ 94 95 int inet_trigger(const char *service, const char *buf, ssize_t len, int timeout) 96 { 97 const char *myname = "inet_trigger"; 98 struct inet_trigger *ip; 99 int fd; 100 101 if (msg_verbose > 1) 102 msg_info("%s: service %s", myname, service); 103 104 /* 105 * Connect... 106 */ 107 if ((fd = inet_connect(service, BLOCKING, timeout)) < 0) { 108 if (msg_verbose) 109 msg_warn("%s: connect to %s: %m", myname, service); 110 return (-1); 111 } 112 close_on_exec(fd, CLOSE_ON_EXEC); 113 ip = (struct inet_trigger *) mymalloc(sizeof(*ip)); 114 ip->fd = fd; 115 ip->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(inet_trigger_event, (char *) ip, timeout + 100); 130 event_enable_read(fd, inet_trigger_event, (char *) ip); 131 return (0); 132 } 133