]> jfr.im git - irc/rqf/shadowircd.git/blame - libratbox/src/ratbox_lib.c
autogen.sh is not necessary at this time, and did not work anyway.
[irc/rqf/shadowircd.git] / libratbox / src / ratbox_lib.c
CommitLineData
b57f37fb
WP
1/*
2 * ircd-ratbox: A slightly useful ircd.
3 * ratbox_lib.c: libircd initialization functions at the like
4 *
5 * Copyright (C) 2005,2006 ircd-ratbox development team
6 * Copyright (C) 2005,2006 Aaron Sethman <androsyn@ratbox.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
21 * USA
22 *
f030cae8 23 * $Id: ratbox_lib.c 26282 2008-12-10 20:33:21Z androsyn $
b57f37fb
WP
24 */
25
26#include <libratbox_config.h>
27#include <ratbox_lib.h>
28#include <commio-int.h>
f030cae8 29#include <commio-ssl.h>
b57f37fb
WP
30
31static log_cb *rb_log;
32static restart_cb *rb_restart;
33static die_cb *rb_die;
34
35static struct timeval rb_time;
36static char errbuf[512];
37
38/* this doesn't do locales...oh well i guess */
39
40static const char *months[] = {
94b4fbf9
VY
41 "January", "February", "March", "April",
42 "May", "June", "July", "August",
43 "September", "October", "November", "December"
b57f37fb
WP
44};
45
46static const char *weekdays[] = {
94b4fbf9
VY
47 "Sunday", "Monday", "Tuesday", "Wednesday",
48 "Thursday", "Friday", "Saturday"
b57f37fb
WP
49};
50
51static const char *s_month[] = {
52 "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
53 "Aug", "Sep", "Oct", "Nov", "Dec"
94b4fbf9 54};
b57f37fb
WP
55
56static const char *s_weekdays[] = {
57 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
58};
59
60char *
61rb_ctime(const time_t t, char *buf, size_t len)
62{
63 char *p;
64 struct tm *tp;
65 static char timex[128];
66 size_t tlen;
67#if defined(HAVE_GMTIME_R)
68 struct tm tmr;
69 tp = gmtime_r(&t, &tmr);
70#else
71 tp = gmtime(&t);
72#endif
033be687 73 if(rb_unlikely(tp == NULL))
b57f37fb
WP
74 {
75 strcpy(buf, "");
94b4fbf9 76 return (buf);
b57f37fb
WP
77 }
78
79 if(buf == NULL)
80 {
81 p = timex;
82 tlen = sizeof(timex);
94b4fbf9
VY
83 }
84 else
85 {
b57f37fb
WP
86 p = buf;
87 tlen = len;
88 }
89
90 rb_snprintf(p, tlen, "%s %s %d %02u:%02u:%02u %d",
94b4fbf9
VY
91 s_weekdays[tp->tm_wday], s_month[tp->tm_mon],
92 tp->tm_mday, tp->tm_hour, tp->tm_min, tp->tm_sec, tp->tm_year + 1900);
93 return (p);
b57f37fb
WP
94}
95
96
97/* I hate this..but its sort of ircd standard now.. */
98char *
99rb_date(const time_t t, char *buf, size_t len)
100{
101 struct tm *gm;
102#if defined(HAVE_GMTIME_R)
103 struct tm gmbuf;
104 gm = gmtime_r(&t, &gmbuf);
105#else
106 gm = gmtime(&t);
107#endif
108
033be687 109 if(rb_unlikely(gm == NULL))
b57f37fb 110 {
94b4fbf9
VY
111 rb_strlcpy(buf, "", len);
112 return (buf);
b57f37fb 113 }
94b4fbf9
VY
114
115 rb_snprintf(buf, len, "%s %s %d %d -- %02u:%02u:%02u +00:00",
116 weekdays[gm->tm_wday], months[gm->tm_mon], gm->tm_mday,
117 gm->tm_year + 1900, gm->tm_hour, gm->tm_min, gm->tm_sec);
118 return (buf);
b57f37fb
WP
119}
120
121time_t
122rb_current_time(void)
123{
124 return rb_time.tv_sec;
125}
126
127const struct timeval *
128rb_current_time_tv(void)
129{
130 return &rb_time;
131}
132
133void
134rb_lib_log(const char *format, ...)
135{
136 va_list args;
137 if(rb_log == NULL)
138 return;
139 va_start(args, format);
94b4fbf9 140 rb_vsnprintf(errbuf, sizeof(errbuf), format, args);
b57f37fb
WP
141 va_end(args);
142 rb_log(errbuf);
143}
144
145void
146rb_lib_die(const char *format, ...)
147{
148 va_list args;
149 if(rb_die == NULL)
150 abort();
151 va_start(args, format);
94b4fbf9 152 rb_vsnprintf(errbuf, sizeof(errbuf), format, args);
b57f37fb
WP
153 va_end(args);
154 rb_die(errbuf);
155}
156
157void
158rb_lib_restart(const char *format, ...)
159{
160 va_list args;
161 if(rb_restart == NULL)
162 abort();
163 va_start(args, format);
94b4fbf9 164 rb_vsnprintf(errbuf, sizeof(errbuf), format, args);
b57f37fb
WP
165 va_end(args);
166 rb_restart(errbuf);
167}
168
169void
170rb_set_time(void)
171{
172 struct timeval newtime;
173
033be687 174 if(rb_unlikely(rb_gettimeofday(&newtime, NULL) == -1))
b57f37fb
WP
175 {
176 rb_lib_log("Clock Failure (%s)", strerror(errno));
177 rb_lib_restart("Clock Failure");
178 }
179
180 if(newtime.tv_sec < rb_time.tv_sec)
181 rb_set_back_events(rb_time.tv_sec - newtime.tv_sec);
182
183 memcpy(&rb_time, &newtime, sizeof(struct timeval));
184}
185
94b4fbf9
VY
186extern const char *libratbox_serno;
187
b57f37fb
WP
188const char *
189rb_lib_version(void)
190{
f030cae8
VY
191 static char version_info[512];
192 char ssl_info[512];
193 rb_get_ssl_info(ssl_info, sizeof(ssl_info));
194 rb_snprintf(version_info, sizeof(version_info), "libratbox version: %s - %s", libratbox_serno, ssl_info);
195 return version_info;
b57f37fb
WP
196}
197
198void
94b4fbf9
VY
199rb_lib_init(log_cb * ilog, restart_cb * irestart, die_cb * idie, int closeall, int maxcon,
200 size_t dh_size, size_t fd_heap_size)
b57f37fb
WP
201{
202 rb_set_time();
203 rb_log = ilog;
204 rb_restart = irestart;
205 rb_die = idie;
206 rb_event_init();
207 rb_init_bh();
208 rb_fdlist_init(closeall, maxcon, fd_heap_size);
209 rb_init_netio();
210 rb_init_rb_dlink_nodes(dh_size);
211 if(rb_io_supports_event())
212 {
213 rb_io_init_event();
214 }
215}
216
217void
218rb_lib_loop(long delay)
219{
220 time_t next;
221 rb_set_time();
222
223 if(rb_io_supports_event())
224 {
225 if(delay == 0)
226 delay = -1;
227 while(1)
228 rb_select(-1);
229 }
94b4fbf9 230
b57f37fb
WP
231
232 while(1)
233 {
234 if(delay == 0)
235 {
94b4fbf9 236 if((next = rb_event_next()) > 0)
b57f37fb
WP
237 {
238 next -= rb_current_time();
239 if(next <= 0)
240 next = 1000;
94b4fbf9 241 else
b57f37fb
WP
242 next *= 1000;
243 }
244 else
245 next = -1;
246 rb_select(next);
94b4fbf9
VY
247 }
248 else
b57f37fb
WP
249 rb_select(delay);
250 rb_event_run();
251 }
252}
253
254#ifndef HAVE_STRTOK_R
255char *
94b4fbf9 256rb_strtok_r(char *s, const char *delim, char **save)
b57f37fb
WP
257{
258 char *token;
259
94b4fbf9 260 if(s == NULL)
b57f37fb
WP
261 s = *save;
262
263 /* Scan leading delimiters. */
264 s += strspn(s, delim);
265
94b4fbf9 266 if(*s == '\0')
b57f37fb
WP
267 {
268 *save = s;
269 return NULL;
270 }
271
272 token = s;
273 s = strpbrk(token, delim);
94b4fbf9
VY
274
275 if(s == NULL)
b57f37fb
WP
276 *save = (token + strlen(token));
277 else
278 {
94b4fbf9 279 *s = '\0';
b57f37fb
WP
280 *save = s + 1;
281 }
282 return token;
283}
284#else
94b4fbf9
VY
285char *
286rb_strtok_r(char *s, const char *delim, char **save)
b57f37fb
WP
287{
288 return strtok_r(s, delim, save);
289}
290#endif
291
292
293static const char base64_table[] =
294 { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
94b4fbf9
VY
295 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
296 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
297 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
298 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '\0'
299};
b57f37fb
WP
300
301static const char base64_pad = '=';
302
303static const short base64_reverse_table[256] = {
304 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
305 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
306 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
307 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
94b4fbf9 308 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
b57f37fb
WP
309 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
310 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
311 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
312 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
313 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
314 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
315 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
316 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
317 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
318 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
319 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
320};
321
322unsigned char *
323rb_base64_encode(const unsigned char *str, int length)
324{
325 const unsigned char *current = str;
326 unsigned char *p;
327 unsigned char *result;
328
94b4fbf9
VY
329 if((length + 2) < 0 || ((length + 2) / 3) >= (1 << (sizeof(int) * 8 - 2)))
330 {
b57f37fb
WP
331 return NULL;
332 }
333
334 result = rb_malloc(((length + 2) / 3) * 5);
335 p = result;
336
94b4fbf9
VY
337 while(length > 2)
338 {
b57f37fb
WP
339 *p++ = base64_table[current[0] >> 2];
340 *p++ = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
341 *p++ = base64_table[((current[1] & 0x0f) << 2) + (current[2] >> 6)];
342 *p++ = base64_table[current[2] & 0x3f];
343
344 current += 3;
94b4fbf9 345 length -= 3;
b57f37fb
WP
346 }
347
94b4fbf9
VY
348 if(length != 0)
349 {
b57f37fb 350 *p++ = base64_table[current[0] >> 2];
94b4fbf9
VY
351 if(length > 1)
352 {
b57f37fb
WP
353 *p++ = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
354 *p++ = base64_table[(current[1] & 0x0f) << 2];
355 *p++ = base64_pad;
94b4fbf9
VY
356 }
357 else
358 {
b57f37fb
WP
359 *p++ = base64_table[(current[0] & 0x03) << 4];
360 *p++ = base64_pad;
361 *p++ = base64_pad;
362 }
363 }
364 *p = '\0';
365 return result;
366}
367
368unsigned char *
369rb_base64_decode(const unsigned char *str, int length, int *ret)
370{
371 const unsigned char *current = str;
372 int ch, i = 0, j = 0, k;
373 unsigned char *result;
94b4fbf9 374
b57f37fb
WP
375 result = rb_malloc(length + 1);
376
94b4fbf9
VY
377 while((ch = *current++) != '\0' && length-- > 0)
378 {
379 if(ch == base64_pad)
380 break;
b57f37fb
WP
381
382 ch = base64_reverse_table[ch];
94b4fbf9
VY
383 if(ch < 0)
384 continue;
b57f37fb 385
94b4fbf9
VY
386 switch (i % 4)
387 {
b57f37fb
WP
388 case 0:
389 result[j] = ch << 2;
390 break;
391 case 1:
392 result[j++] |= ch >> 4;
393 result[j] = (ch & 0x0f) << 4;
394 break;
395 case 2:
94b4fbf9 396 result[j++] |= ch >> 2;
b57f37fb
WP
397 result[j] = (ch & 0x03) << 6;
398 break;
399 case 3:
400 result[j++] |= ch;
401 break;
402 }
403 i++;
404 }
405
406 k = j;
407
94b4fbf9
VY
408 if(ch == base64_pad)
409 {
410 switch (i % 4)
411 {
b57f37fb
WP
412 case 1:
413 free(result);
414 return NULL;
415 case 2:
416 k++;
417 case 3:
418 result[k++] = 0;
419 }
420 }
421 result[j] = '\0';
422 *ret = j;
423 return result;
424}