]> jfr.im git - solanum.git/blob - librb/src/rb_lib.c
ircd: send tags on every message
[solanum.git] / librb / src / rb_lib.c
1 /*
2 * ircd-ratbox: A slightly useful ircd.
3 * rb_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 *
23 */
24
25 #include <librb_config.h>
26 #include <rb_lib.h>
27 #include <commio-int.h>
28 #include <commio-ssl.h>
29
30 static log_cb *rb_log;
31 static restart_cb *rb_restart;
32 static die_cb *rb_die;
33
34 static struct timeval rb_time;
35 static char errbuf[512];
36
37 /* this doesn't do locales...oh well i guess */
38
39 static const char *months[] = {
40 "January", "February", "March", "April",
41 "May", "June", "July", "August",
42 "September", "October", "November", "December"
43 };
44
45 static const char *weekdays[] = {
46 "Sunday", "Monday", "Tuesday", "Wednesday",
47 "Thursday", "Friday", "Saturday"
48 };
49
50 static const char *s_month[] = {
51 "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
52 "Aug", "Sep", "Oct", "Nov", "Dec"
53 };
54
55 static const char *s_weekdays[] = {
56 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
57 };
58
59 char *
60 rb_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
72 if(buf == NULL)
73 {
74 p = timex;
75 tlen = sizeof(timex);
76 }
77 else
78 {
79 p = buf;
80 tlen = len;
81 }
82
83 if(rb_unlikely(tp == NULL))
84 {
85 rb_strlcpy(p, "", tlen);
86 return (p);
87 }
88
89 snprintf(p, tlen, "%s %s %d %02u:%02u:%02u %d",
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);
93 }
94
95
96 /* I hate this..but its sort of ircd standard now.. */
97 char *
98 rb_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
108 if(rb_unlikely(gm == NULL))
109 {
110 rb_strlcpy(buf, "", len);
111 return (buf);
112 }
113
114 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);
118 }
119
120 time_t
121 rb_current_time(void)
122 {
123 return rb_time.tv_sec;
124 }
125
126 const struct timeval *
127 rb_current_time_tv(void)
128 {
129 return &rb_time;
130 }
131
132 void
133 rb_lib_log(const char *format, ...)
134 {
135 va_list args;
136 if(rb_log == NULL)
137 return;
138 va_start(args, format);
139 vsnprintf(errbuf, sizeof(errbuf), format, args);
140 va_end(args);
141 rb_log(errbuf);
142 }
143
144 void
145 rb_lib_die(const char *format, ...)
146 {
147 va_list args;
148 if(rb_die == NULL)
149 abort();
150 va_start(args, format);
151 vsnprintf(errbuf, sizeof(errbuf), format, args);
152 va_end(args);
153 rb_die(errbuf);
154 }
155
156 void
157 rb_lib_restart(const char *format, ...)
158 {
159 va_list args;
160 if(rb_restart == NULL)
161 abort();
162 va_start(args, format);
163 vsnprintf(errbuf, sizeof(errbuf), format, args);
164 va_end(args);
165 rb_restart(errbuf);
166 abort();
167 }
168
169 void
170 rb_set_time(void)
171 {
172 struct timeval newtime;
173
174 if(rb_unlikely(rb_gettimeofday(&newtime, NULL) == -1))
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
186 extern const char *librb_serno;
187
188 const char *
189 rb_lib_version(void)
190 {
191 static char version_info[512];
192 char ssl_info[512];
193 rb_get_ssl_info(ssl_info, sizeof(ssl_info));
194 snprintf(version_info, sizeof(version_info), "librb version: %s - %s", librb_serno, ssl_info);
195 return version_info;
196 }
197
198 void
199 rb_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)
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
217 void
218 rb_lib_loop(long delay)
219 {
220 time_t next;
221 rb_set_time();
222
223 if(rb_io_supports_event())
224 {
225 while(1)
226 rb_select(-1);
227 }
228
229
230 while(1)
231 {
232 if(delay == 0)
233 {
234 if((next = rb_event_next()) > 0)
235 {
236 next -= rb_current_time();
237 if(next <= 0)
238 next = 1000;
239 else
240 next *= 1000;
241 }
242 else
243 next = -1;
244 rb_select(next);
245 }
246 else
247 rb_select(delay);
248 rb_event_run();
249 }
250 }
251
252 #ifndef HAVE_STRTOK_R
253 char *
254 rb_strtok_r(char *s, const char *delim, char **save)
255 {
256 char *token;
257
258 if(s == NULL)
259 s = *save;
260
261 /* Scan leading delimiters. */
262 s += strspn(s, delim);
263
264 if(*s == '\0')
265 {
266 *save = s;
267 return NULL;
268 }
269
270 token = s;
271 s = strpbrk(token, delim);
272
273 if(s == NULL)
274 *save = (token + strlen(token));
275 else
276 {
277 *s = '\0';
278 *save = s + 1;
279 }
280 return token;
281 }
282 #else
283 char *
284 rb_strtok_r(char *s, const char *delim, char **save)
285 {
286 return strtok_r(s, delim, save);
287 }
288 #endif
289
290
291 static const char base64_table[] =
292 { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
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 };
298
299 static const char base64_pad = '=';
300
301 static 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,
306 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
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
320 unsigned char *
321 rb_base64_encode(const unsigned char *str, int length)
322 {
323 const unsigned char *current = str;
324 unsigned char *p;
325 unsigned char *result;
326
327 if((length + 2) < 0 || ((length + 2) / 3) >= (1 << (sizeof(int) * 8 - 2)))
328 {
329 return NULL;
330 }
331
332 result = rb_malloc(((length + 2) / 3) * 5);
333 p = result;
334
335 while(length > 2)
336 {
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;
343 length -= 3;
344 }
345
346 if(length != 0)
347 {
348 *p++ = base64_table[current[0] >> 2];
349 if(length > 1)
350 {
351 *p++ = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
352 *p++ = base64_table[(current[1] & 0x0f) << 2];
353 *p++ = base64_pad;
354 }
355 else
356 {
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
366 unsigned char *
367 rb_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;
372
373 result = rb_malloc(length + 1);
374
375 while((ch = *current++) != '\0' && length-- > 0)
376 {
377 if(ch == base64_pad)
378 break;
379
380 ch = base64_reverse_table[ch];
381 if(ch < 0)
382 continue;
383
384 switch (i % 4)
385 {
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:
394 result[j++] |= ch >> 2;
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
406 if(ch == base64_pad)
407 {
408 switch (i % 4)
409 {
410 case 1:
411 free(result);
412 return NULL;
413 case 2:
414 k++;
415 /* FALLTHROUGH */
416 case 3:
417 result[k++] = 0;
418 }
419 }
420 result[j] = '\0';
421 *ret = j;
422 return result;
423 }