1/* $NetBSD: stream_trigger.c,v 1.2 2017/02/14 01:16:49 christos 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 64struct stream_trigger { 65 int fd; 66 char *service; 67}; 68 69/* stream_trigger_event - disconnect from peer */ 70 71static void stream_trigger_event(int event, void *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((void *) sp); 87} 88 89/* stream_trigger - wakeup stream server */ 90 91int 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, (void *) sp, timeout + 100); 130 event_enable_read(fd, stream_trigger_event, (void *) sp); 131 return (0); 132} 133