1/*++ 2/* NAME 3/* fifo_trigger 3 4/* SUMMARY 5/* wakeup fifo server 6/* SYNOPSIS 7/* #include <trigger.h> 8/* 9/* int fifo_trigger(service, buf, len, timeout) 10/* const char *service; 11/* const char *buf; 12/* ssize_t len; 13/* int timeout; 14/* DESCRIPTION 15/* fifo_trigger() wakes up the named fifo server by writing 16/* the contents of the specified buffer to the fifo. There is 17/* no guarantee that the written data will actually be received. 18/* 19/* Arguments: 20/* .IP service 21/* Name of the communication endpoint. 22/* .IP buf 23/* Address of data to be written. 24/* .IP len 25/* Amount of data to be written. 26/* .IP timeout 27/* Deadline in seconds. Specify a value <= 0 to disable 28/* the time limit. 29/* DIAGNOSTICS 30/* The result is zero when the fifo could be opened, -1 otherwise. 31/* BUGS 32/* LICENSE 33/* .ad 34/* .fi 35/* The Secure Mailer license must be distributed with this software. 36/* AUTHOR(S) 37/* Wietse Venema 38/* IBM T.J. Watson Research 39/* P.O. Box 704 40/* Yorktown Heights, NY 10598, USA 41/*--*/ 42 43/* System library. */ 44 45#include <sys_defs.h> 46#include <fcntl.h> 47#include <unistd.h> 48 49/* Utility library. */ 50 51#include <msg.h> 52#include <iostuff.h> 53#include <safe_open.h> 54#include <trigger.h> 55 56/* fifo_trigger - wakeup fifo server */ 57 58int fifo_trigger(const char *service, const char *buf, ssize_t len, int timeout) 59{ 60 static VSTRING *why; 61 const char *myname = "fifo_trigger"; 62 VSTREAM *fp; 63 int fd; 64 65 if (why == 0) 66 why = vstring_alloc(1); 67 68 /* 69 * Write the request to the service fifo. According to POSIX, the open 70 * shall always return immediately, and shall return an error when no 71 * process is reading from the FIFO. 72 * 73 * Use safe_open() so that we don't follow symlinks, and so that we don't 74 * open files with multiple hard links. We're not (yet) going to bother 75 * the caller with safe_open() specific quirks such as the why argument. 76 */ 77 if ((fp = safe_open(service, O_WRONLY | O_NONBLOCK, 0, 78 (struct stat *) 0, -1, -1, why)) == 0) { 79 if (msg_verbose) 80 msg_info("%s: open %s: %s", myname, service, vstring_str(why)); 81 return (-1); 82 } 83 fd = vstream_fileno(fp); 84 85 /* 86 * Write the request... 87 */ 88 non_blocking(fd, timeout > 0 ? NON_BLOCKING : BLOCKING); 89 if (write_buf(fd, buf, len, timeout) < 0) 90 if (msg_verbose) 91 msg_warn("%s: write %s: %m", myname, service); 92 93 /* 94 * Disconnect. 95 */ 96 if (vstream_fclose(fp)) 97 if (msg_verbose) 98 msg_warn("%s: close %s: %m", myname, service); 99 return (0); 100} 101 102#ifdef TEST 103 104 /* 105 * Set up a FIFO listener, and keep triggering until the listener becomes 106 * idle, which should never happen. 107 */ 108#include <signal.h> 109#include <stdlib.h> 110 111#include "events.h" 112#include "listen.h" 113 114#define TEST_FIFO "test-fifo" 115 116int trig_count; 117int wakeup_count; 118 119static void cleanup(void) 120{ 121 unlink(TEST_FIFO); 122 exit(1); 123} 124 125static void handler(int sig) 126{ 127 msg_fatal("got signal %d after %d triggers %d wakeups", 128 sig, trig_count, wakeup_count); 129} 130 131static void read_event(int unused_event, char *context) 132{ 133 int fd = CAST_CHAR_PTR_TO_INT(context); 134 char ch; 135 136 wakeup_count++; 137 138 if (read(fd, &ch, 1) != 1) 139 msg_fatal("read %s: %m", TEST_FIFO); 140} 141 142int main(int unused_argc, char **unused_argv) 143{ 144 int listen_fd; 145 146 listen_fd = fifo_listen(TEST_FIFO, 0600, NON_BLOCKING); 147 msg_cleanup(cleanup); 148 event_enable_read(listen_fd, read_event, CAST_INT_TO_CHAR_PTR(listen_fd)); 149 signal(SIGINT, handler); 150 signal(SIGALRM, handler); 151 for (;;) { 152 alarm(10); 153 if (fifo_trigger(TEST_FIFO, "", 1, 0) < 0) 154 msg_fatal("trigger %s: %m", TEST_FIFO); 155 trig_count++; 156 if (fifo_trigger(TEST_FIFO, "", 1, 0) < 0) 157 msg_fatal("trigger %s: %m", TEST_FIFO); 158 trig_count++; 159 if (fifo_trigger(TEST_FIFO, "", 1, 0) < 0) 160 msg_fatal("trigger %s: %m", TEST_FIFO); 161 trig_count++; 162 event_loop(-1); 163 event_loop(-1); 164 event_loop(-1); 165 } 166} 167 168#endif 169