]> jfr.im git - solanum.git/blame - librb/src/rb_lib.c
Merge pull request #278 from edk0/override
[solanum.git] / librb / src / rb_lib.c
CommitLineData
db137867
AC
1/*
2 * ircd-ratbox: A slightly useful ircd.
fe037171 3 * rb_lib.c: libircd initialization functions at the like
db137867
AC
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 *
db137867
AC
23 */
24
fe037171
EM
25#include <librb_config.h>
26#include <rb_lib.h>
db137867 27#include <commio-int.h>
030272f3 28#include <commio-ssl.h>
db137867
AC
29
30static log_cb *rb_log;
31static restart_cb *rb_restart;
32static die_cb *rb_die;
33
34static struct timeval rb_time;
35static char errbuf[512];
36
37/* this doesn't do locales...oh well i guess */
38
39static const char *months[] = {
3202e249
VY
40 "January", "February", "March", "April",
41 "May", "June", "July", "August",
42 "September", "October", "November", "December"
db137867
AC
43};
44
45static const char *weekdays[] = {
3202e249
VY
46 "Sunday", "Monday", "Tuesday", "Wednesday",
47 "Thursday", "Friday", "Saturday"
db137867
AC
48};
49
50static const char *s_month[] = {
51 "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
52 "Aug", "Sep", "Oct", "Nov", "Dec"
3202e249 53};
db137867
AC
54
55static const char *s_weekdays[] = {
56 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
57};
58
59char *
60rb_ctime(const time_t t, char *buf, size_t len)
61{
62 char *p;
63 struct tm *tp;
64 static char timex[128];
65 size_t tlen;
66#if defined(HAVE_GMTIME_R)
67 struct tm tmr;
68 tp = gmtime_r(&t, &tmr);
69#else
70 tp = gmtime(&t);
71#endif
db137867
AC
72 if(buf == NULL)
73 {
74 p = timex;
75 tlen = sizeof(timex);
3202e249
VY
76 }
77 else
78 {
db137867
AC
79 p = buf;
80 tlen = len;
81 }
82
56c1612f
AC
83 if(rb_unlikely(tp == NULL))
84 {
85 rb_strlcpy(p, "", tlen);
86 return (p);
87 }
88
5203cba5 89 snprintf(p, tlen, "%s %s %d %02u:%02u:%02u %d",
3202e249
VY
90 s_weekdays[tp->tm_wday], s_month[tp->tm_mon],
91 tp->tm_mday, tp->tm_hour, tp->tm_min, tp->tm_sec, tp->tm_year + 1900);
92 return (p);
db137867
AC
93}
94
95
96/* I hate this..but its sort of ircd standard now.. */
97char *
98rb_date(const time_t t, char *buf, size_t len)
99{
100 struct tm *gm;
101#if defined(HAVE_GMTIME_R)
102 struct tm gmbuf;
103 gm = gmtime_r(&t, &gmbuf);
104#else
105 gm = gmtime(&t);
106#endif
107
c2ac22cc 108 if(rb_unlikely(gm == NULL))
db137867 109 {
3202e249
VY
110 rb_strlcpy(buf, "", len);
111 return (buf);
db137867 112 }
3202e249 113
5203cba5 114 snprintf(buf, len, "%s %s %d %d -- %02u:%02u:%02u +00:00",
3202e249
VY
115 weekdays[gm->tm_wday], months[gm->tm_mon], gm->tm_mday,
116 gm->tm_year + 1900, gm->tm_hour, gm->tm_min, gm->tm_sec);
117 return (buf);
db137867
AC
118}
119
120time_t
121rb_current_time(void)
122{
123 return rb_time.tv_sec;
124}
125
126const struct timeval *
127rb_current_time_tv(void)
128{
129 return &rb_time;
130}
131
132void
133rb_lib_log(const char *format, ...)
134{
135 va_list args;
136 if(rb_log == NULL)
137 return;
138 va_start(args, format);
5203cba5 139 vsnprintf(errbuf, sizeof(errbuf), format, args);
db137867
AC
140 va_end(args);
141 rb_log(errbuf);
142}
143
144void
145rb_lib_die(const char *format, ...)
146{
147 va_list args;
148 if(rb_die == NULL)
149 abort();
150 va_start(args, format);
5203cba5 151 vsnprintf(errbuf, sizeof(errbuf), format, args);
db137867
AC
152 va_end(args);
153 rb_die(errbuf);
154}
155
156void
157rb_lib_restart(const char *format, ...)
158{
159 va_list args;
160 if(rb_restart == NULL)
161 abort();
162 va_start(args, format);
5203cba5 163 vsnprintf(errbuf, sizeof(errbuf), format, args);
db137867
AC
164 va_end(args);
165 rb_restart(errbuf);
6993ae27 166 abort();
db137867
AC
167}
168
169void
170rb_set_time(void)
171{
172 struct timeval newtime;
173
c2ac22cc 174 if(rb_unlikely(rb_gettimeofday(&newtime, NULL) == -1))
db137867
AC
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
fe037171 186extern const char *librb_serno;
3202e249 187
db137867
AC
188const char *
189rb_lib_version(void)
190{
030272f3
VY
191 static char version_info[512];
192 char ssl_info[512];
193 rb_get_ssl_info(ssl_info, sizeof(ssl_info));
fe037171 194 snprintf(version_info, sizeof(version_info), "librb version: %s - %s", librb_serno, ssl_info);
030272f3 195 return version_info;
db137867
AC
196}
197
198void
3202e249
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)
db137867
AC
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 {
db137867
AC
225 while(1)
226 rb_select(-1);
227 }
3202e249 228
db137867
AC
229
230 while(1)
231 {
232 if(delay == 0)
233 {
3202e249 234 if((next = rb_event_next()) > 0)
db137867
AC
235 {
236 next -= rb_current_time();
237 if(next <= 0)
238 next = 1000;
3202e249 239 else
db137867
AC
240 next *= 1000;
241 }
242 else
243 next = -1;
244 rb_select(next);
3202e249
VY
245 }
246 else
db137867
AC
247 rb_select(delay);
248 rb_event_run();
249 }
250}
251
252#ifndef HAVE_STRTOK_R
253char *
3202e249 254rb_strtok_r(char *s, const char *delim, char **save)
db137867
AC
255{
256 char *token;
257
3202e249 258 if(s == NULL)
db137867
AC
259 s = *save;
260
261 /* Scan leading delimiters. */
262 s += strspn(s, delim);
263
3202e249 264 if(*s == '\0')
db137867
AC
265 {
266 *save = s;
267 return NULL;
268 }
269
270 token = s;
271 s = strpbrk(token, delim);
3202e249
VY
272
273 if(s == NULL)
db137867
AC
274 *save = (token + strlen(token));
275 else
276 {
3202e249 277 *s = '\0';
db137867
AC
278 *save = s + 1;
279 }
280 return token;
281}
282#else
3202e249
VY
283char *
284rb_strtok_r(char *s, const char *delim, char **save)
db137867
AC
285{
286 return strtok_r(s, delim, save);
287}
288#endif
289
290
291static const char base64_table[] =
292 { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
3202e249
VY
293 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
294 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
295 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
296 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '\0'
297};
db137867
AC
298
299static const char base64_pad = '=';
300
301static const short base64_reverse_table[256] = {
302 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
303 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
304 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
305 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
3202e249 306 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
db137867
AC
307 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
308 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
309 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
310 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
311 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -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};
319
320unsigned char *
321rb_base64_encode(const unsigned char *str, int length)
322{
323 const unsigned char *current = str;
324 unsigned char *p;
325 unsigned char *result;
326
3202e249
VY
327 if((length + 2) < 0 || ((length + 2) / 3) >= (1 << (sizeof(int) * 8 - 2)))
328 {
db137867
AC
329 return NULL;
330 }
331
332 result = rb_malloc(((length + 2) / 3) * 5);
333 p = result;
334
3202e249
VY
335 while(length > 2)
336 {
db137867
AC
337 *p++ = base64_table[current[0] >> 2];
338 *p++ = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
339 *p++ = base64_table[((current[1] & 0x0f) << 2) + (current[2] >> 6)];
340 *p++ = base64_table[current[2] & 0x3f];
341
342 current += 3;
3202e249 343 length -= 3;
db137867
AC
344 }
345
3202e249
VY
346 if(length != 0)
347 {
db137867 348 *p++ = base64_table[current[0] >> 2];
3202e249
VY
349 if(length > 1)
350 {
db137867
AC
351 *p++ = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
352 *p++ = base64_table[(current[1] & 0x0f) << 2];
353 *p++ = base64_pad;
3202e249
VY
354 }
355 else
356 {
db137867
AC
357 *p++ = base64_table[(current[0] & 0x03) << 4];
358 *p++ = base64_pad;
359 *p++ = base64_pad;
360 }
361 }
362 *p = '\0';
363 return result;
364}
365
366unsigned char *
367rb_base64_decode(const unsigned char *str, int length, int *ret)
368{
369 const unsigned char *current = str;
370 int ch, i = 0, j = 0, k;
371 unsigned char *result;
3202e249 372
db137867
AC
373 result = rb_malloc(length + 1);
374
3202e249
VY
375 while((ch = *current++) != '\0' && length-- > 0)
376 {
377 if(ch == base64_pad)
378 break;
db137867
AC
379
380 ch = base64_reverse_table[ch];
3202e249
VY
381 if(ch < 0)
382 continue;
db137867 383
3202e249
VY
384 switch (i % 4)
385 {
db137867
AC
386 case 0:
387 result[j] = ch << 2;
388 break;
389 case 1:
390 result[j++] |= ch >> 4;
391 result[j] = (ch & 0x0f) << 4;
392 break;
393 case 2:
3202e249 394 result[j++] |= ch >> 2;
db137867
AC
395 result[j] = (ch & 0x03) << 6;
396 break;
397 case 3:
398 result[j++] |= ch;
399 break;
400 }
401 i++;
402 }
403
404 k = j;
405
3202e249
VY
406 if(ch == base64_pad)
407 {
408 switch (i % 4)
409 {
db137867
AC
410 case 1:
411 free(result);
412 return NULL;
413 case 2:
414 k++;
8c04f896 415 /* FALLTHROUGH */
db137867
AC
416 case 3:
417 result[k++] = 0;
418 }
419 }
420 result[j] = '\0';
421 *ret = j;
422 return result;
423}