1 /* $NetBSD: stream_trigger.c,v 1.1.1.1 2009/06/23 10:09:01 tron Exp $ */ 2 3 /*++ 4 /* NAME 5 /* stream_trigger 3 6 /* SUMMARY 7 /* wakeup stream server 8 /* SYNOPSIS 9 /* #include <trigger.h> 10 /* 11 /* int stream_trigger(service, buf, len, timeout) 12 /* const char *service; 13 /* const char *buf; 14 /* ssize_t len; 15 /* int timeout; 16 /* DESCRIPTION 17 /* stream_trigger() wakes up the named stream 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 /* stream_connect(3), stream 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 <unistd.h> 53 #include <string.h> 54 55 /* Utility library. */ 56 57 #include <msg.h> 58 #include <connect.h> 59 #include <iostuff.h> 60 #include <mymalloc.h> 61 #include <events.h> 62 #include <trigger.h> 63 64 struct stream_trigger { 65 int fd; 66 char *service; 67 }; 68 69 /* stream_trigger_event - disconnect from peer */ 70 71 static void stream_trigger_event(int event, char *context) 72 { 73 struct stream_trigger *sp = (struct stream_trigger *) context; 74 static const char *myname = "stream_trigger_event"; 75 76 /* 77 * Disconnect. 78 */ 79 if (event == EVENT_TIME) 80 msg_warn("%s: read timeout for service %s", myname, sp->service); 81 event_disable_readwrite(sp->fd); 82 event_cancel_timer(stream_trigger_event, context); 83 if (close(sp->fd) < 0) 84 msg_warn("%s: close %s: %m", myname, sp->service); 85 myfree(sp->service); 86 myfree((char *) sp); 87 } 88 89 /* stream_trigger - wakeup stream server */ 90 91 int stream_trigger(const char *service, const char *buf, ssize_t len, int timeout) 92 { 93 const char *myname = "stream_trigger"; 94 struct stream_trigger *sp; 95 int fd; 96 97 if (msg_verbose > 1) 98 msg_info("%s: service %s", myname, service); 99 100 /* 101 * Connect... 102 */ 103 if ((fd = stream_connect(service, BLOCKING, timeout)) < 0) { 104 if (msg_verbose) 105 msg_warn("%s: connect to %s: %m", myname, service); 106 return (-1); 107 } 108 close_on_exec(fd, CLOSE_ON_EXEC); 109 110 /* 111 * Stash away context. 112 */ 113 sp = (struct stream_trigger *) mymalloc(sizeof(*sp)); 114 sp->fd = fd; 115 sp->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(stream_trigger_event, (char *) sp, timeout + 100); 130 event_enable_read(fd, stream_trigger_event, (char *) sp); 131 return (0); 132 } 133