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