]> jfr.im git - solanum.git/blame - librb/src/helper.c
check bans and quiets for cmode -n/nonmember PRIVMSG
[solanum.git] / librb / src / helper.c
CommitLineData
db137867
AC
1/*
2 * ircd-ratbox: A slightly useful ircd
3 * helper.c: Starts and deals with ircd helpers
55abcbb2 4 *
db137867
AC
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 *
db137867 22 */
c056dba2 23
fe037171
EM
24#include <librb_config.h>
25#include <rb_lib.h>
db137867
AC
26#include <commio-int.h>
27
28struct _rb_helper
29{
30 char *path;
31 buf_head_t sendq;
32 buf_head_t recvq;
33 rb_fde_t *ifd;
34 rb_fde_t *ofd;
35 pid_t pid;
36 int fork_count;
37 rb_helper_cb *read_cb;
38 rb_helper_cb *error_cb;
39};
40
41
42/* setup all the stuff a new child needs */
43rb_helper *
3202e249 44rb_helper_child(rb_helper_cb * read_cb, rb_helper_cb * error_cb, log_cb * ilog,
29c92cf9 45 restart_cb * irestart, die_cb * idie, size_t lb_heap_size,
3202e249 46 size_t dh_size, size_t fd_heap_size)
db137867
AC
47{
48 rb_helper *helper;
49 int maxfd, x = 0;
50 int ifd, ofd;
51 char *tifd, *tofd, *tmaxfd;
3202e249 52
db137867
AC
53 tifd = getenv("IFD");
54 tofd = getenv("OFD");
55 tmaxfd = getenv("MAXFD");
3202e249 56
db137867
AC
57 if(tifd == NULL || tofd == NULL || tmaxfd == NULL)
58 return NULL;
59
60 helper = rb_malloc(sizeof(rb_helper));
3202e249 61 ifd = (int)strtol(tifd, NULL, 10);
db137867
AC
62 ofd = (int)strtol(tofd, NULL, 10);
63 maxfd = (int)strtol(tmaxfd, NULL, 10);
64
3202e249
VY
65 for(x = 0; x < maxfd; x++)
66 {
67 if(x != ifd && x != ofd)
68 close(x);
db137867
AC
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);
3202e249 77 if(x > 2) /* don't undo what we just did */
db137867 78 close(x);
db137867
AC
79
80 rb_lib_init(ilog, irestart, idie, 0, maxfd, dh_size, fd_heap_size);
81 rb_linebuf_init(lb_heap_size);
82 rb_linebuf_newbuf(&helper->sendq);
83 rb_linebuf_newbuf(&helper->recvq);
84
85 helper->ifd = rb_open(ifd, RB_FD_PIPE, "incoming connection");
86 helper->ofd = rb_open(ofd, RB_FD_PIPE, "outgoing connection");
87 rb_set_nb(helper->ifd);
88 rb_set_nb(helper->ofd);
3202e249 89
db137867
AC
90 helper->read_cb = read_cb;
91 helper->error_cb = error_cb;
92 return helper;
93}
94
95/*
96 * start_fork_helper
97 * starts a new ircd helper
98 * note that this function doesn't start doing reading..thats the job of the caller
99 */
100
101rb_helper *
3202e249
VY
102rb_helper_start(const char *name, const char *fullpath, rb_helper_cb * read_cb,
103 rb_helper_cb * error_cb)
db137867
AC
104{
105 rb_helper *helper;
106 const char *parv[2];
107 char buf[128];
33822550 108 char fx[16], fy[16], maxfd[16];
db137867
AC
109 rb_fde_t *in_f[2];
110 rb_fde_t *out_f[2];
111 pid_t pid;
3202e249 112
db137867
AC
113 if(access(fullpath, X_OK) == -1)
114 return NULL;
3202e249 115
db137867
AC
116 helper = rb_malloc(sizeof(rb_helper));
117
5203cba5 118 snprintf(buf, sizeof(buf), "%s helper - read", name);
3202e249 119 if(rb_pipe(&in_f[0], &in_f[1], buf) < 0)
db137867
AC
120 {
121 rb_free(helper);
122 return NULL;
123 }
5203cba5 124 snprintf(buf, sizeof(buf), "%s helper - write", name);
db137867
AC
125 if(rb_pipe(&out_f[0], &out_f[1], buf) < 0)
126 {
127 rb_free(helper);
128 return NULL;
129 }
3202e249 130
5203cba5
VI
131 snprintf(fx, sizeof(fx), "%d", rb_get_fd(in_f[1]));
132 snprintf(fy, sizeof(fy), "%d", rb_get_fd(out_f[0]));
33822550 133 snprintf(maxfd, sizeof(maxfd), "%d", rb_getmaxconnect());
3202e249 134
db137867
AC
135 rb_set_nb(in_f[0]);
136 rb_set_nb(in_f[1]);
137 rb_set_nb(out_f[0]);
138 rb_set_nb(out_f[1]);
3202e249
VY
139
140 rb_setenv("IFD", fy, 1);
141 rb_setenv("OFD", fx, 1);
33822550 142 rb_setenv("MAXFD", maxfd, 1);
3202e249 143
5203cba5 144 snprintf(buf, sizeof(buf), "-ircd %s daemon", name);
db137867
AC
145 parv[0] = buf;
146 parv[1] = NULL;
147
71325a98
DF
148 rb_clear_cloexec(in_f[1]);
149 rb_clear_cloexec(out_f[0]);
3202e249 150
db137867 151 pid = rb_spawn_process(fullpath, (const char **)parv);
3202e249 152
db137867
AC
153 if(pid == -1)
154 {
155 rb_close(in_f[0]);
156 rb_close(in_f[1]);
157 rb_close(out_f[0]);
158 rb_close(out_f[1]);
159 rb_free(helper);
160 return NULL;
161 }
162
163 rb_close(in_f[1]);
164 rb_close(out_f[0]);
3202e249 165
db137867
AC
166 rb_linebuf_newbuf(&helper->sendq);
167 rb_linebuf_newbuf(&helper->recvq);
3202e249 168
db137867
AC
169 helper->ifd = in_f[0];
170 helper->ofd = out_f[1];
171 helper->read_cb = read_cb;
3202e249 172 helper->error_cb = error_cb;
db137867
AC
173 helper->fork_count = 0;
174 helper->pid = pid;
175
176 return helper;
177}
178
179
180void
181rb_helper_restart(rb_helper *helper)
182{
183 helper->error_cb(helper);
184}
185
186
187static void
188rb_helper_write_sendq(rb_fde_t *F, void *helper_ptr)
189{
190 rb_helper *helper = helper_ptr;
191 int retlen;
3202e249 192
db137867
AC
193 if(rb_linebuf_len(&helper->sendq) > 0)
194 {
195 while((retlen = rb_linebuf_flush(F, &helper->sendq)) > 0)
5ef68b13 196 ;
3202e249
VY
197 if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno)))
198 {
db137867
AC
199 rb_helper_restart(helper);
200 return;
201 }
202 }
203
204 if(rb_linebuf_len(&helper->sendq) > 0)
205 rb_setselect(helper->ofd, RB_SELECT_WRITE, rb_helper_write_sendq, helper);
206}
207
3202e249 208void
db137867
AC
209rb_helper_write_queue(rb_helper *helper, const char *format, ...)
210{
211 va_list ap;
4b1cce65
SA
212 rb_strf_t strings = { .format = format, .format_args = &ap, .next = NULL };
213
db137867 214 va_start(ap, format);
4b1cce65 215 rb_linebuf_put(&helper->sendq, &strings);
db137867
AC
216 va_end(ap);
217}
218
219void
220rb_helper_write_flush(rb_helper *helper)
221{
3202e249 222 rb_helper_write_sendq(helper->ofd, helper);
db137867
AC
223}
224
225
226void
227rb_helper_write(rb_helper *helper, const char *format, ...)
228{
229 va_list ap;
4b1cce65
SA
230 rb_strf_t strings = { .format = format, .format_args = &ap, .next = NULL };
231
db137867 232 va_start(ap, format);
4b1cce65 233 rb_linebuf_put(&helper->sendq, &strings);
db137867 234 va_end(ap);
4b1cce65 235
db137867
AC
236 rb_helper_write_flush(helper);
237}
238
239static void
8679c0fe 240rb_helper_read_cb(rb_fde_t *F __attribute__((unused)), void *data)
db137867
AC
241{
242 rb_helper *helper = (rb_helper *)data;
243 static char buf[32768];
244 int length;
245 if(helper == NULL)
246 return;
3202e249 247
db137867
AC
248 while((length = rb_read(helper->ifd, buf, sizeof(buf))) > 0)
249 {
250 rb_linebuf_parse(&helper->recvq, buf, length, 0);
251 helper->read_cb(helper);
252 }
253
254 if(length == 0 || (length < 0 && !rb_ignore_errno(errno)))
255 {
256 rb_helper_restart(helper);
257 return;
258 }
3202e249 259
db137867
AC
260 rb_setselect(helper->ifd, RB_SELECT_READ, rb_helper_read_cb, helper);
261}
262
263void
264rb_helper_run(rb_helper *helper)
265{
266 if(helper == NULL)
267 return;
268 rb_helper_read_cb(helper->ifd, helper);
269}
270
271
272void
273rb_helper_close(rb_helper *helper)
274{
275 if(helper == NULL)
276 return;
3202e249 277 rb_kill(helper->pid, SIGKILL);
db137867
AC
278 rb_close(helper->ifd);
279 rb_close(helper->ofd);
3202e249 280 rb_free(helper);
db137867
AC
281}
282
283int
284rb_helper_read(rb_helper *helper, void *buf, size_t bufsize)
285{
286 return rb_linebuf_get(&helper->recvq, buf, bufsize, LINEBUF_COMPLETE, LINEBUF_PARSED);
287}
288
289void
290rb_helper_loop(rb_helper *helper, long delay)
291{
292 rb_helper_run(helper);
293 while(1)
294 {
295 rb_lib_loop(delay);
296 }
297}