]> jfr.im git - irc/rqf/shadowircd.git/blame - libratbox/src/helper.c
strip_colour(): strip ASCII 29 (mIRC 7 italics).
[irc/rqf/shadowircd.git] / libratbox / src / helper.c
CommitLineData
b57f37fb
WP
1/*
2 * ircd-ratbox: A slightly useful ircd
3 * helper.c: Starts and deals with ircd helpers
4 *
5 * Copyright (C) 2006 Aaron Sethman <androsyn@ratbox.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
20 * USA
21 *
b57f37fb
WP
22 */
23#include <libratbox_config.h>
24#include <ratbox_lib.h>
25#include <commio-int.h>
26
27struct _rb_helper
28{
29 char *path;
30 buf_head_t sendq;
31 buf_head_t recvq;
32 rb_fde_t *ifd;
33 rb_fde_t *ofd;
34 pid_t pid;
35 int fork_count;
36 rb_helper_cb *read_cb;
37 rb_helper_cb *error_cb;
38};
39
40
41/* setup all the stuff a new child needs */
42rb_helper *
94b4fbf9
VY
43rb_helper_child(rb_helper_cb * read_cb, rb_helper_cb * error_cb, log_cb * ilog,
44 restart_cb * irestart, die_cb * idie, int maxcon, size_t lb_heap_size,
45 size_t dh_size, size_t fd_heap_size)
b57f37fb
WP
46{
47 rb_helper *helper;
48 int maxfd, x = 0;
49 int ifd, ofd;
50 char *tifd, *tofd, *tmaxfd;
94b4fbf9 51
b57f37fb
WP
52 tifd = getenv("IFD");
53 tofd = getenv("OFD");
54 tmaxfd = getenv("MAXFD");
94b4fbf9 55
b57f37fb
WP
56 if(tifd == NULL || tofd == NULL || tmaxfd == NULL)
57 return NULL;
58
59 helper = rb_malloc(sizeof(rb_helper));
94b4fbf9 60 ifd = (int)strtol(tifd, NULL, 10);
b57f37fb
WP
61 ofd = (int)strtol(tofd, NULL, 10);
62 maxfd = (int)strtol(tmaxfd, NULL, 10);
63
94b4fbf9
VY
64#ifndef _WIN32
65 for(x = 0; x < maxfd; x++)
66 {
67 if(x != ifd && x != ofd)
68 close(x);
b57f37fb
WP
69 }
70 x = open("/dev/null", O_RDWR);
71 if(ifd != 0 && ofd != 0)
72 dup2(x, 0);
73 if(ifd != 1 && ofd != 1)
74 dup2(x, 1);
75 if(ifd != 2 && ofd != 2)
76 dup2(x, 2);
94b4fbf9 77 if(x > 2) /* don't undo what we just did */
b57f37fb
WP
78 close(x);
79#else
94b4fbf9 80 x = 0; /* shut gcc up */
b57f37fb
WP
81#endif
82
83 rb_lib_init(ilog, irestart, idie, 0, maxfd, dh_size, fd_heap_size);
84 rb_linebuf_init(lb_heap_size);
85 rb_linebuf_newbuf(&helper->sendq);
86 rb_linebuf_newbuf(&helper->recvq);
87
88 helper->ifd = rb_open(ifd, RB_FD_PIPE, "incoming connection");
89 helper->ofd = rb_open(ofd, RB_FD_PIPE, "outgoing connection");
90 rb_set_nb(helper->ifd);
91 rb_set_nb(helper->ofd);
94b4fbf9 92
b57f37fb
WP
93 helper->read_cb = read_cb;
94 helper->error_cb = error_cb;
95 return helper;
96}
97
98/*
99 * start_fork_helper
100 * starts a new ircd helper
101 * note that this function doesn't start doing reading..thats the job of the caller
102 */
103
104rb_helper *
94b4fbf9
VY
105rb_helper_start(const char *name, const char *fullpath, rb_helper_cb * read_cb,
106 rb_helper_cb * error_cb)
b57f37fb
WP
107{
108 rb_helper *helper;
109 const char *parv[2];
110 char buf[128];
111 char fx[16], fy[16];
112 rb_fde_t *in_f[2];
113 rb_fde_t *out_f[2];
114 pid_t pid;
94b4fbf9 115
b57f37fb
WP
116 if(access(fullpath, X_OK) == -1)
117 return NULL;
94b4fbf9 118
b57f37fb
WP
119 helper = rb_malloc(sizeof(rb_helper));
120
121 rb_snprintf(buf, sizeof(buf), "%s helper - read", name);
94b4fbf9 122 if(rb_pipe(&in_f[0], &in_f[1], buf) < 0)
b57f37fb
WP
123 {
124 rb_free(helper);
125 return NULL;
126 }
127 rb_snprintf(buf, sizeof(buf), "%s helper - write", name);
128 if(rb_pipe(&out_f[0], &out_f[1], buf) < 0)
129 {
130 rb_free(helper);
131 return NULL;
132 }
94b4fbf9 133
b57f37fb
WP
134 rb_snprintf(fx, sizeof(fx), "%d", rb_get_fd(in_f[1]));
135 rb_snprintf(fy, sizeof(fy), "%d", rb_get_fd(out_f[0]));
94b4fbf9 136
b57f37fb
WP
137 rb_set_nb(in_f[0]);
138 rb_set_nb(in_f[1]);
139 rb_set_nb(out_f[0]);
140 rb_set_nb(out_f[1]);
94b4fbf9
VY
141
142 rb_setenv("IFD", fy, 1);
143 rb_setenv("OFD", fx, 1);
144 rb_setenv("MAXFD", "256", 1);
145
b57f37fb
WP
146 rb_snprintf(buf, sizeof(buf), "-ircd %s daemon", name);
147 parv[0] = buf;
148 parv[1] = NULL;
149
94b4fbf9
VY
150#ifdef _WIN32
151 SetHandleInformation((HANDLE) rb_get_fd(in_f[1]), HANDLE_FLAG_INHERIT, 1);
152 SetHandleInformation((HANDLE) rb_get_fd(out_f[0]), HANDLE_FLAG_INHERIT, 1);
b57f37fb 153#endif
94b4fbf9 154
b57f37fb 155 pid = rb_spawn_process(fullpath, (const char **)parv);
94b4fbf9 156
b57f37fb
WP
157 if(pid == -1)
158 {
159 rb_close(in_f[0]);
160 rb_close(in_f[1]);
161 rb_close(out_f[0]);
162 rb_close(out_f[1]);
163 rb_free(helper);
164 return NULL;
165 }
166
167 rb_close(in_f[1]);
168 rb_close(out_f[0]);
94b4fbf9 169
b57f37fb
WP
170 rb_linebuf_newbuf(&helper->sendq);
171 rb_linebuf_newbuf(&helper->recvq);
94b4fbf9 172
b57f37fb
WP
173 helper->ifd = in_f[0];
174 helper->ofd = out_f[1];
175 helper->read_cb = read_cb;
94b4fbf9 176 helper->error_cb = error_cb;
b57f37fb
WP
177 helper->fork_count = 0;
178 helper->pid = pid;
179
180 return helper;
181}
182
183
184void
185rb_helper_restart(rb_helper *helper)
186{
187 helper->error_cb(helper);
188}
189
190
191static void
192rb_helper_write_sendq(rb_fde_t *F, void *helper_ptr)
193{
194 rb_helper *helper = helper_ptr;
195 int retlen;
94b4fbf9 196
b57f37fb
WP
197 if(rb_linebuf_len(&helper->sendq) > 0)
198 {
199 while((retlen = rb_linebuf_flush(F, &helper->sendq)) > 0)
200 ;;
94b4fbf9
VY
201 if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno)))
202 {
b57f37fb
WP
203 rb_helper_restart(helper);
204 return;
205 }
206 }
207
208 if(rb_linebuf_len(&helper->sendq) > 0)
209 rb_setselect(helper->ofd, RB_SELECT_WRITE, rb_helper_write_sendq, helper);
210}
211
94b4fbf9 212void
b57f37fb
WP
213rb_helper_write_queue(rb_helper *helper, const char *format, ...)
214{
215 va_list ap;
216 va_start(ap, format);
217 rb_linebuf_putmsg(&helper->sendq, format, &ap, NULL);
218 va_end(ap);
219}
220
221void
222rb_helper_write_flush(rb_helper *helper)
223{
94b4fbf9 224 rb_helper_write_sendq(helper->ofd, helper);
b57f37fb
WP
225}
226
227
228void
229rb_helper_write(rb_helper *helper, const char *format, ...)
230{
231 va_list ap;
232 va_start(ap, format);
233 rb_linebuf_putmsg(&helper->sendq, format, &ap, NULL);
234 va_end(ap);
235 rb_helper_write_flush(helper);
236}
237
238static void
239rb_helper_read_cb(rb_fde_t *F, void *data)
240{
241 rb_helper *helper = (rb_helper *)data;
242 static char buf[32768];
243 int length;
244 if(helper == NULL)
245 return;
94b4fbf9 246
b57f37fb
WP
247 while((length = rb_read(helper->ifd, buf, sizeof(buf))) > 0)
248 {
249 rb_linebuf_parse(&helper->recvq, buf, length, 0);
250 helper->read_cb(helper);
251 }
252
253 if(length == 0 || (length < 0 && !rb_ignore_errno(errno)))
254 {
255 rb_helper_restart(helper);
256 return;
257 }
94b4fbf9 258
b57f37fb
WP
259 rb_setselect(helper->ifd, RB_SELECT_READ, rb_helper_read_cb, helper);
260}
261
262void
263rb_helper_run(rb_helper *helper)
264{
265 if(helper == NULL)
266 return;
267 rb_helper_read_cb(helper->ifd, helper);
268}
269
270
271void
272rb_helper_close(rb_helper *helper)
273{
274 if(helper == NULL)
275 return;
94b4fbf9 276 rb_kill(helper->pid, SIGKILL);
b57f37fb
WP
277 rb_close(helper->ifd);
278 rb_close(helper->ofd);
94b4fbf9 279 rb_free(helper);
b57f37fb
WP
280}
281
282int
283rb_helper_read(rb_helper *helper, void *buf, size_t bufsize)
284{
285 return rb_linebuf_get(&helper->recvq, buf, bufsize, LINEBUF_COMPLETE, LINEBUF_PARSED);
286}
287
288void
289rb_helper_loop(rb_helper *helper, long delay)
290{
291 rb_helper_run(helper);
292 while(1)
293 {
294 rb_lib_loop(delay);
295 }
296}