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