]> jfr.im git - solanum.git/blame - libratbox/src/ratbox_lib.c
Add .travis.yml
[solanum.git] / libratbox / src / ratbox_lib.c
CommitLineData
db137867
AC
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 *
030272f3 23 * $Id: ratbox_lib.c 26282 2008-12-10 20:33:21Z androsyn $
db137867
AC
24 */
25
26#include <libratbox_config.h>
27#include <ratbox_lib.h>
28#include <commio-int.h>
030272f3 29#include <commio-ssl.h>
db137867
AC
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[] = {
3202e249
VY
41 "January", "February", "March", "April",
42 "May", "June", "July", "August",
43 "September", "October", "November", "December"
db137867
AC
44};
45
46static const char *weekdays[] = {
3202e249
VY
47 "Sunday", "Monday", "Tuesday", "Wednesday",
48 "Thursday", "Friday", "Saturday"
db137867
AC
49};
50
51static const char *s_month[] = {
52 "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
53 "Aug", "Sep", "Oct", "Nov", "Dec"
3202e249 54};
db137867
AC
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
db137867
AC
73 if(buf == NULL)
74 {
75 p = timex;
76 tlen = sizeof(timex);
3202e249
VY
77 }
78 else
79 {
db137867
AC
80 p = buf;
81 tlen = len;
82 }
83
56c1612f
AC
84 if(rb_unlikely(tp == NULL))
85 {
86 rb_strlcpy(p, "", tlen);
87 return (p);
88 }
89
db137867 90 rb_snprintf(p, tlen, "%s %s %d %02u:%02u:%02u %d",
3202e249
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);
db137867
AC
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
c2ac22cc 109 if(rb_unlikely(gm == NULL))
db137867 110 {
3202e249
VY
111 rb_strlcpy(buf, "", len);
112 return (buf);
db137867 113 }
3202e249
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);
db137867
AC
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);
3202e249 140 rb_vsnprintf(errbuf, sizeof(errbuf), format, args);
db137867
AC
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);
3202e249 152 rb_vsnprintf(errbuf, sizeof(errbuf), format, args);
db137867
AC
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);
3202e249 164 rb_vsnprintf(errbuf, sizeof(errbuf), format, args);
db137867
AC
165 va_end(args);
166 rb_restart(errbuf);
6993ae27 167 abort();
db137867
AC
168}
169
170void
171rb_set_time(void)
172{
173 struct timeval newtime;
174
c2ac22cc 175 if(rb_unlikely(rb_gettimeofday(&newtime, NULL) == -1))
db137867
AC
176 {
177 rb_lib_log("Clock Failure (%s)", strerror(errno));
178 rb_lib_restart("Clock Failure");
179 }
180
181 if(newtime.tv_sec < rb_time.tv_sec)
182 rb_set_back_events(rb_time.tv_sec - newtime.tv_sec);
183
184 memcpy(&rb_time, &newtime, sizeof(struct timeval));
185}
186
3202e249
VY
187extern const char *libratbox_serno;
188
db137867
AC
189const char *
190rb_lib_version(void)
191{
030272f3
VY
192 static char version_info[512];
193 char ssl_info[512];
194 rb_get_ssl_info(ssl_info, sizeof(ssl_info));
195 rb_snprintf(version_info, sizeof(version_info), "libratbox version: %s - %s", libratbox_serno, ssl_info);
196 return version_info;
db137867
AC
197}
198
199void
3202e249
VY
200rb_lib_init(log_cb * ilog, restart_cb * irestart, die_cb * idie, int closeall, int maxcon,
201 size_t dh_size, size_t fd_heap_size)
db137867
AC
202{
203 rb_set_time();
204 rb_log = ilog;
205 rb_restart = irestart;
206 rb_die = idie;
207 rb_event_init();
208 rb_init_bh();
209 rb_fdlist_init(closeall, maxcon, fd_heap_size);
210 rb_init_netio();
211 rb_init_rb_dlink_nodes(dh_size);
212 if(rb_io_supports_event())
213 {
214 rb_io_init_event();
215 }
216}
217
218void
219rb_lib_loop(long delay)
220{
221 time_t next;
222 rb_set_time();
223
224 if(rb_io_supports_event())
225 {
226 if(delay == 0)
227 delay = -1;
228 while(1)
229 rb_select(-1);
230 }
3202e249 231
db137867
AC
232
233 while(1)
234 {
235 if(delay == 0)
236 {
3202e249 237 if((next = rb_event_next()) > 0)
db137867
AC
238 {
239 next -= rb_current_time();
240 if(next <= 0)
241 next = 1000;
3202e249 242 else
db137867
AC
243 next *= 1000;
244 }
245 else
246 next = -1;
247 rb_select(next);
3202e249
VY
248 }
249 else
db137867
AC
250 rb_select(delay);
251 rb_event_run();
252 }
253}
254
255#ifndef HAVE_STRTOK_R
256char *
3202e249 257rb_strtok_r(char *s, const char *delim, char **save)
db137867
AC
258{
259 char *token;
260
3202e249 261 if(s == NULL)
db137867
AC
262 s = *save;
263
264 /* Scan leading delimiters. */
265 s += strspn(s, delim);
266
3202e249 267 if(*s == '\0')
db137867
AC
268 {
269 *save = s;
270 return NULL;
271 }
272
273 token = s;
274 s = strpbrk(token, delim);
3202e249
VY
275
276 if(s == NULL)
db137867
AC
277 *save = (token + strlen(token));
278 else
279 {
3202e249 280 *s = '\0';
db137867
AC
281 *save = s + 1;
282 }
283 return token;
284}
285#else
3202e249
VY
286char *
287rb_strtok_r(char *s, const char *delim, char **save)
db137867
AC
288{
289 return strtok_r(s, delim, save);
290}
291#endif
292
293
294static const char base64_table[] =
295 { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
3202e249
VY
296 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
297 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
298 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
299 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '\0'
300};
db137867
AC
301
302static const char base64_pad = '=';
303
304static const short base64_reverse_table[256] = {
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, -1, -1, -1, -1, -1,
307 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
308 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
3202e249 309 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
db137867
AC
310 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
311 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
312 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -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 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
321};
322
323unsigned char *
324rb_base64_encode(const unsigned char *str, int length)
325{
326 const unsigned char *current = str;
327 unsigned char *p;
328 unsigned char *result;
329
3202e249
VY
330 if((length + 2) < 0 || ((length + 2) / 3) >= (1 << (sizeof(int) * 8 - 2)))
331 {
db137867
AC
332 return NULL;
333 }
334
335 result = rb_malloc(((length + 2) / 3) * 5);
336 p = result;
337
3202e249
VY
338 while(length > 2)
339 {
db137867
AC
340 *p++ = base64_table[current[0] >> 2];
341 *p++ = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
342 *p++ = base64_table[((current[1] & 0x0f) << 2) + (current[2] >> 6)];
343 *p++ = base64_table[current[2] & 0x3f];
344
345 current += 3;
3202e249 346 length -= 3;
db137867
AC
347 }
348
3202e249
VY
349 if(length != 0)
350 {
db137867 351 *p++ = base64_table[current[0] >> 2];
3202e249
VY
352 if(length > 1)
353 {
db137867
AC
354 *p++ = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
355 *p++ = base64_table[(current[1] & 0x0f) << 2];
356 *p++ = base64_pad;
3202e249
VY
357 }
358 else
359 {
db137867
AC
360 *p++ = base64_table[(current[0] & 0x03) << 4];
361 *p++ = base64_pad;
362 *p++ = base64_pad;
363 }
364 }
365 *p = '\0';
366 return result;
367}
368
369unsigned char *
370rb_base64_decode(const unsigned char *str, int length, int *ret)
371{
372 const unsigned char *current = str;
373 int ch, i = 0, j = 0, k;
374 unsigned char *result;
3202e249 375
db137867
AC
376 result = rb_malloc(length + 1);
377
3202e249
VY
378 while((ch = *current++) != '\0' && length-- > 0)
379 {
380 if(ch == base64_pad)
381 break;
db137867
AC
382
383 ch = base64_reverse_table[ch];
3202e249
VY
384 if(ch < 0)
385 continue;
db137867 386
3202e249
VY
387 switch (i % 4)
388 {
db137867
AC
389 case 0:
390 result[j] = ch << 2;
391 break;
392 case 1:
393 result[j++] |= ch >> 4;
394 result[j] = (ch & 0x0f) << 4;
395 break;
396 case 2:
3202e249 397 result[j++] |= ch >> 2;
db137867
AC
398 result[j] = (ch & 0x03) << 6;
399 break;
400 case 3:
401 result[j++] |= ch;
402 break;
403 }
404 i++;
405 }
406
407 k = j;
408
3202e249
VY
409 if(ch == base64_pad)
410 {
411 switch (i % 4)
412 {
db137867
AC
413 case 1:
414 free(result);
415 return NULL;
416 case 2:
417 k++;
8c04f896 418 /* FALLTHROUGH */
db137867
AC
419 case 3:
420 result[k++] = 0;
421 }
422 }
423 result[j] = '\0';
424 *ret = j;
425 return result;
426}