Postfix3.3.1
pass_trigger.c
[詳解]
1 /*++
2 /* NAME
3 /* pass_trigger 3
4 /* SUMMARY
5 /* trigger file descriptor listener
6 /* SYNOPSIS
7 /* #include <trigger.h>
8 /*
9 /* int pass_trigger(service, buf, len, timeout)
10 /* const char *service;
11 /* const char *buf;
12 /* ssize_t len;
13 /* int timeout;
14 /* DESCRIPTION
15 /* pass_trigger() connects to the named local server by sending
16 /* a file descriptor to it and writing the named buffer.
17 /*
18 /* The connection is closed by a background thread. Some kernels
19 /* cannot handle client-side disconnect before the server has
20 /* received the message.
21 /*
22 /* Arguments:
23 /* .IP service
24 /* Name of the communication endpoint.
25 /* .IP buf
26 /* Address of data to be written.
27 /* .IP len
28 /* Amount of data to be written.
29 /* .IP timeout
30 /* Deadline in seconds. Specify a value <= 0 to disable
31 /* the time limit.
32 /* DIAGNOSTICS
33 /* The result is zero in case of success, -1 in case of problems.
34 /* SEE ALSO
35 /* unix_connect(3), local client
36 /* stream_connect(3), streams-based client
37 /* LICENSE
38 /* .ad
39 /* .fi
40 /* The Secure Mailer license must be distributed with this software.
41 /* AUTHOR(S)
42 /* Wietse Venema
43 /* IBM T.J. Watson Research
44 /* P.O. Box 704
45 /* Yorktown Heights, NY 10598, USA
46 /*--*/
47 
48 /* System library. */
49 
50 #include <sys_defs.h>
51 #include <sys/socket.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 pass_trigger {
66  char *service;
67  int pass_fd[2];
68 };
69 
70 /* pass_trigger_event - disconnect from peer */
71 
72 static void pass_trigger_event(int event, void *context)
73 {
74  struct pass_trigger *pp = (struct pass_trigger *) context;
75  static const char *myname = "pass_trigger_event";
76 
77  /*
78  * Disconnect.
79  */
80  if (event == EVENT_TIME)
81  msg_warn("%s: read timeout for service %s", myname, pp->service);
83  event_cancel_timer(pass_trigger_event, context);
84  /* Don't combine multiple close() calls into one boolean expression. */
85  if (close(pp->connect_fd) < 0)
86  msg_warn("%s: close %s: %m", myname, pp->service);
87  if (close(pp->pass_fd[0]) < 0)
88  msg_warn("%s: close pipe: %m", myname);
89  if (close(pp->pass_fd[1]) < 0)
90  msg_warn("%s: close pipe: %m", myname);
91  myfree(pp->service);
92  myfree((void *) pp);
93 }
94 
95 /* pass_trigger - wakeup local server */
96 
97 int pass_trigger(const char *service, const char *buf, ssize_t len, int timeout)
98 {
99  const char *myname = "pass_trigger";
100  int pass_fd[2];
101  struct pass_trigger *pp;
102  int connect_fd;
103 
104  if (msg_verbose > 1)
105  msg_info("%s: service %s", myname, service);
106 
107  /*
108  * Connect...
109  */
110  if ((connect_fd = LOCAL_CONNECT(service, BLOCKING, timeout)) < 0) {
111  if (msg_verbose)
112  msg_warn("%s: connect to %s: %m", myname, service);
113  return (-1);
114  }
115  close_on_exec(connect_fd, CLOSE_ON_EXEC);
116 
117  /*
118  * Create a pipe, and send one pipe end to the server.
119  */
120  if (pipe(pass_fd) < 0)
121  msg_fatal("%s: pipe: %m", myname);
122  close_on_exec(pass_fd[0], CLOSE_ON_EXEC);
123  close_on_exec(pass_fd[1], CLOSE_ON_EXEC);
124  if (LOCAL_SEND_FD(connect_fd, pass_fd[0]) < 0)
125  msg_fatal("%s: send file descriptor: %m", myname);
126 
127  /*
128  * Stash away context.
129  */
130  pp = (struct pass_trigger *) mymalloc(sizeof(*pp));
131  pp->connect_fd = connect_fd;
132  pp->service = mystrdup(service);
133  pp->pass_fd[0] = pass_fd[0];
134  pp->pass_fd[1] = pass_fd[1];
135 
136  /*
137  * Write the request...
138  */
139  if (write_buf(pass_fd[1], buf, len, timeout) < 0
140  || write_buf(pass_fd[1], "", 1, timeout) < 0)
141  if (msg_verbose)
142  msg_warn("%s: write to %s: %m", myname, service);
143 
144  /*
145  * Wakeup when the peer disconnects, or when we lose patience.
146  */
147  if (timeout > 0)
148  event_request_timer(pass_trigger_event, (void *) pp, timeout + 100);
149  event_enable_read(connect_fd, pass_trigger_event, (void *) pp);
150  return (0);
151 }
int msg_verbose
Definition: msg.c:177
void event_enable_read(int fd, EVENT_NOTIFY_RDWR_FN callback, void *context)
Definition: events.c:729
void myfree(void *ptr)
Definition: mymalloc.c:207
char * mystrdup(const char *str)
Definition: mymalloc.c:225
char * service
Definition: pass_trigger.c:66
#define LOCAL_SEND_FD
Definition: sys_defs.h:1426
#define LOCAL_CONNECT
Definition: sys_defs.h:1424
void msg_warn(const char *fmt,...)
Definition: msg.c:215
int pass_fd[2]
Definition: pass_trigger.c:67
NORETURN msg_fatal(const char *fmt,...)
Definition: msg.c:249
#define EVENT_TIME
Definition: events.h:43
time_t event_request_timer(EVENT_NOTIFY_TIME_FN callback, void *context, int delay)
Definition: events.c:894
#define CLOSE_ON_EXEC
Definition: iostuff.h:51
void event_disable_readwrite(int fd)
Definition: events.c:839
int pass_trigger(const char *service, const char *buf, ssize_t len, int timeout)
Definition: pass_trigger.c:97
#define BLOCKING
Definition: iostuff.h:48
int event_cancel_timer(EVENT_NOTIFY_TIME_FN callback, void *context)
Definition: events.c:965
int close_on_exec(int fd, int on)
Definition: close_on_exec.c:49
ssize_t write_buf(int, const char *, ssize_t, int)
Definition: write_buf.c:58
void * mymalloc(ssize_t len)
Definition: mymalloc.c:150
void msg_info(const char *fmt,...)
Definition: msg.c:199