]>
jfr.im git - solanum.git/blob - librb/src/helper.c
2 * ircd-ratbox: A slightly useful ircd
3 * helper.c: Starts and deals with ircd helpers
5 * Copyright (C) 2006 Aaron Sethman <androsyn@ratbox.org>
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.
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.
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
24 #include <librb_config.h>
26 #include <commio-int.h>
37 rb_helper_cb
*read_cb
;
38 rb_helper_cb
*error_cb
;
42 /* setup all the stuff a new child needs */
44 rb_helper_child(rb_helper_cb
* read_cb
, rb_helper_cb
* error_cb
, log_cb
* ilog
,
45 restart_cb
* irestart
, die_cb
* idie
, size_t lb_heap_size
,
46 size_t dh_size
, size_t fd_heap_size
)
51 char *tifd
, *tofd
, *tmaxfd
;
55 tmaxfd
= getenv("MAXFD");
57 if(tifd
== NULL
|| tofd
== NULL
|| tmaxfd
== NULL
)
60 helper
= rb_malloc(sizeof(rb_helper
));
61 ifd
= (int)strtol(tifd
, NULL
, 10);
62 ofd
= (int)strtol(tofd
, NULL
, 10);
63 maxfd
= (int)strtol(tmaxfd
, NULL
, 10);
65 for(x
= 0; x
< maxfd
; x
++)
67 if(x
!= ifd
&& x
!= ofd
)
70 x
= open("/dev/null", O_RDWR
);
71 if(ifd
!= 0 && ofd
!= 0)
73 if(ifd
!= 1 && ofd
!= 1)
75 if(ifd
!= 2 && ofd
!= 2)
77 if(x
> 2) /* don't undo what we just did */
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
);
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
);
90 helper
->read_cb
= read_cb
;
91 helper
->error_cb
= error_cb
;
97 * starts a new ircd helper
98 * note that this function doesn't start doing reading..thats the job of the caller
102 rb_helper_start(const char *name
, const char *fullpath
, rb_helper_cb
* read_cb
,
103 rb_helper_cb
* error_cb
)
108 char fx
[16], fy
[16], maxfd
[16];
113 if(access(fullpath
, X_OK
) == -1)
116 helper
= rb_malloc(sizeof(rb_helper
));
118 snprintf(buf
, sizeof(buf
), "%s helper - read", name
);
119 if(rb_pipe(&in_f
[0], &in_f
[1], buf
) < 0)
124 snprintf(buf
, sizeof(buf
), "%s helper - write", name
);
125 if(rb_pipe(&out_f
[0], &out_f
[1], buf
) < 0)
131 snprintf(fx
, sizeof(fx
), "%d", rb_get_fd(in_f
[1]));
132 snprintf(fy
, sizeof(fy
), "%d", rb_get_fd(out_f
[0]));
133 snprintf(maxfd
, sizeof(maxfd
), "%d", rb_getmaxconnect());
140 rb_setenv("IFD", fy
, 1);
141 rb_setenv("OFD", fx
, 1);
142 rb_setenv("MAXFD", maxfd
, 1);
144 snprintf(buf
, sizeof(buf
), "-ircd %s daemon", name
);
148 rb_clear_cloexec(in_f
[1]);
149 rb_clear_cloexec(out_f
[0]);
151 pid
= rb_spawn_process(fullpath
, (const char **)parv
);
166 rb_linebuf_newbuf(&helper
->sendq
);
167 rb_linebuf_newbuf(&helper
->recvq
);
169 helper
->ifd
= in_f
[0];
170 helper
->ofd
= out_f
[1];
171 helper
->read_cb
= read_cb
;
172 helper
->error_cb
= error_cb
;
173 helper
->fork_count
= 0;
181 rb_helper_restart(rb_helper
*helper
)
183 helper
->error_cb(helper
);
188 rb_helper_write_sendq(rb_fde_t
*F
, void *helper_ptr
)
190 rb_helper
*helper
= helper_ptr
;
193 if(rb_linebuf_len(&helper
->sendq
) > 0)
195 while((retlen
= rb_linebuf_flush(F
, &helper
->sendq
)) > 0)
197 if(retlen
== 0 || (retlen
< 0 && !rb_ignore_errno(errno
)))
199 rb_helper_restart(helper
);
204 if(rb_linebuf_len(&helper
->sendq
) > 0)
205 rb_setselect(helper
->ofd
, RB_SELECT_WRITE
, rb_helper_write_sendq
, helper
);
209 rb_helper_write_queue(rb_helper
*helper
, const char *format
, ...)
212 rb_strf_t strings
= { .format
= format
, .format_args
= &ap
, .next
= NULL
};
214 va_start(ap
, format
);
215 rb_linebuf_put(&helper
->sendq
, &strings
);
220 rb_helper_write_flush(rb_helper
*helper
)
222 rb_helper_write_sendq(helper
->ofd
, helper
);
227 rb_helper_write(rb_helper
*helper
, const char *format
, ...)
230 rb_strf_t strings
= { .format
= format
, .format_args
= &ap
, .next
= NULL
};
232 va_start(ap
, format
);
233 rb_linebuf_put(&helper
->sendq
, &strings
);
236 rb_helper_write_flush(helper
);
240 rb_helper_read_cb(rb_fde_t
*F
__attribute__((unused
)), void *data
)
242 rb_helper
*helper
= (rb_helper
*)data
;
243 static char buf
[32768];
248 while((length
= rb_read(helper
->ifd
, buf
, sizeof(buf
))) > 0)
250 rb_linebuf_parse(&helper
->recvq
, buf
, length
, 0);
251 helper
->read_cb(helper
);
254 if(length
== 0 || (length
< 0 && !rb_ignore_errno(errno
)))
256 rb_helper_restart(helper
);
260 rb_setselect(helper
->ifd
, RB_SELECT_READ
, rb_helper_read_cb
, helper
);
264 rb_helper_run(rb_helper
*helper
)
268 rb_helper_read_cb(helper
->ifd
, helper
);
273 rb_helper_close(rb_helper
*helper
)
277 rb_kill(helper
->pid
, SIGKILL
);
278 rb_close(helper
->ifd
);
279 rb_close(helper
->ofd
);
284 rb_helper_read(rb_helper
*helper
, void *buf
, size_t bufsize
)
286 return rb_linebuf_get(&helper
->recvq
, buf
, bufsize
, LINEBUF_COMPLETE
, LINEBUF_PARSED
);
290 rb_helper_loop(rb_helper
*helper
, long delay
)
292 rb_helper_run(helper
);