]> jfr.im git - irc/rqf/shadowircd.git/blob - libratbox/src/ratbox_lib.c
e80f5d16531159e147002125de7b3d1eda62e23f
[irc/rqf/shadowircd.git] / libratbox / src / ratbox_lib.c
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 *
23 * $Id: ratbox_lib.c 25375 2008-05-16 15:19:51Z androsyn $
24 */
25
26 #include <libratbox_config.h>
27 #include <ratbox_lib.h>
28 #include <commio-int.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(rb_unlikely(tp == NULL))
73 {
74 strcpy(buf, "");
75 return(buf);
76 }
77
78 if(buf == NULL)
79 {
80 p = timex;
81 tlen = sizeof(timex);
82 } else {
83 p = buf;
84 tlen = len;
85 }
86
87 rb_snprintf(p, tlen, "%s %s %d %02u:%02u:%02u %d",
88 s_weekdays[tp->tm_wday], s_month[tp->tm_mon],
89 tp->tm_mday, tp->tm_hour, tp->tm_min, tp->tm_sec,
90 tp->tm_year + 1900);
91 return(p);
92 }
93
94
95 /* I hate this..but its sort of ircd standard now.. */
96 char *
97 rb_date(const time_t t, char *buf, size_t len)
98 {
99 struct tm *gm;
100 #if defined(HAVE_GMTIME_R)
101 struct tm gmbuf;
102 gm = gmtime_r(&t, &gmbuf);
103 #else
104 gm = gmtime(&t);
105 #endif
106
107 if(rb_unlikely(gm == NULL))
108 {
109 rb_strlcpy(buf, "", len);
110 return(buf);
111 }
112
113 rb_snprintf(buf, len, "%s %s %d %d -- %02u:%02u:%02u +00:00",
114 weekdays[gm->tm_wday], months[gm->tm_mon], gm->tm_mday,
115 gm->tm_year + 1900, gm->tm_hour, gm->tm_min, gm->tm_sec);
116 return(buf);
117 }
118
119 time_t
120 rb_current_time(void)
121 {
122 return rb_time.tv_sec;
123 }
124
125 const struct timeval *
126 rb_current_time_tv(void)
127 {
128 return &rb_time;
129 }
130
131 void
132 rb_lib_log(const char *format, ...)
133 {
134 va_list args;
135 if(rb_log == NULL)
136 return;
137 va_start(args, format);
138 rb_vsnprintf(errbuf, sizeof(errbuf), format, args);
139 va_end(args);
140 rb_log(errbuf);
141 }
142
143 void
144 rb_lib_die(const char *format, ...)
145 {
146 va_list args;
147 if(rb_die == NULL)
148 abort();
149 va_start(args, format);
150 rb_vsnprintf(errbuf, sizeof(errbuf), format, args);
151 va_end(args);
152 rb_die(errbuf);
153 }
154
155 void
156 rb_lib_restart(const char *format, ...)
157 {
158 va_list args;
159 if(rb_restart == NULL)
160 abort();
161 va_start(args, format);
162 rb_vsnprintf(errbuf, sizeof(errbuf), format, args);
163 va_end(args);
164 rb_restart(errbuf);
165 }
166
167 void
168 rb_set_time(void)
169 {
170 struct timeval newtime;
171
172 if(rb_unlikely(rb_gettimeofday(&newtime, NULL) == -1))
173 {
174 rb_lib_log("Clock Failure (%s)", strerror(errno));
175 rb_lib_restart("Clock Failure");
176 }
177
178 if(newtime.tv_sec < rb_time.tv_sec)
179 rb_set_back_events(rb_time.tv_sec - newtime.tv_sec);
180
181 memcpy(&rb_time, &newtime, sizeof(struct timeval));
182 }
183
184 const char *
185 rb_lib_version(void)
186 {
187 static const char *id = "$Rev: 25375 $";
188 return id;
189 }
190
191 void
192 rb_lib_init(log_cb *ilog, restart_cb *irestart, die_cb *idie, int closeall, int maxcon, size_t dh_size, size_t fd_heap_size)
193 {
194 rb_set_time();
195 rb_log = ilog;
196 rb_restart = irestart;
197 rb_die = idie;
198 rb_event_init();
199 rb_init_bh();
200 rb_fdlist_init(closeall, maxcon, fd_heap_size);
201 rb_init_netio();
202 rb_init_rb_dlink_nodes(dh_size);
203 if(rb_io_supports_event())
204 {
205 rb_io_init_event();
206 }
207 }
208
209 void
210 rb_lib_loop(long delay)
211 {
212 time_t next;
213 rb_set_time();
214
215 if(rb_io_supports_event())
216 {
217 if(delay == 0)
218 delay = -1;
219 while(1)
220 rb_select(-1);
221 }
222
223
224 while(1)
225 {
226 if(delay == 0)
227 {
228 if((next = rb_event_next()) > 0)
229 {
230 next -= rb_current_time();
231 if(next <= 0)
232 next = 1000;
233 else
234 next *= 1000;
235 }
236 else
237 next = -1;
238 rb_select(next);
239 } else
240 rb_select(delay);
241 rb_event_run();
242 }
243 }
244
245 #ifndef HAVE_STRTOK_R
246 char *
247 rb_strtok_r (char *s, const char *delim, char **save)
248 {
249 char *token;
250
251 if (s == NULL)
252 s = *save;
253
254 /* Scan leading delimiters. */
255 s += strspn(s, delim);
256
257 if (*s == '\0')
258 {
259 *save = s;
260 return NULL;
261 }
262
263 token = s;
264 s = strpbrk(token, delim);
265
266 if (s == NULL)
267 *save = (token + strlen(token));
268 else
269 {
270 *s = '\0';
271 *save = s + 1;
272 }
273 return token;
274 }
275 #else
276 char
277 *rb_strtok_r(char *s, const char *delim, char **save)
278 {
279 return strtok_r(s, delim, save);
280 }
281 #endif
282
283
284 static const char base64_table[] =
285 { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
286 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
287 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
288 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
289 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '\0'
290 };
291
292 static const char base64_pad = '=';
293
294 static const short base64_reverse_table[256] = {
295 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
296 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
297 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
298 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
299 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
300 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
301 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
302 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -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, -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, -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 };
312
313 unsigned char *
314 rb_base64_encode(const unsigned char *str, int length)
315 {
316 const unsigned char *current = str;
317 unsigned char *p;
318 unsigned char *result;
319
320 if ((length + 2) < 0 || ((length + 2) / 3) >= (1 << (sizeof(int) * 8 - 2))) {
321 return NULL;
322 }
323
324 result = rb_malloc(((length + 2) / 3) * 5);
325 p = result;
326
327 while (length > 2)
328 {
329 *p++ = base64_table[current[0] >> 2];
330 *p++ = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
331 *p++ = base64_table[((current[1] & 0x0f) << 2) + (current[2] >> 6)];
332 *p++ = base64_table[current[2] & 0x3f];
333
334 current += 3;
335 length -= 3;
336 }
337
338 if (length != 0) {
339 *p++ = base64_table[current[0] >> 2];
340 if (length > 1) {
341 *p++ = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
342 *p++ = base64_table[(current[1] & 0x0f) << 2];
343 *p++ = base64_pad;
344 } else {
345 *p++ = base64_table[(current[0] & 0x03) << 4];
346 *p++ = base64_pad;
347 *p++ = base64_pad;
348 }
349 }
350 *p = '\0';
351 return result;
352 }
353
354 unsigned char *
355 rb_base64_decode(const unsigned char *str, int length, int *ret)
356 {
357 const unsigned char *current = str;
358 int ch, i = 0, j = 0, k;
359 unsigned char *result;
360
361 result = rb_malloc(length + 1);
362
363 while ((ch = *current++) != '\0' && length-- > 0) {
364 if (ch == base64_pad) break;
365
366 ch = base64_reverse_table[ch];
367 if (ch < 0) continue;
368
369 switch(i % 4) {
370 case 0:
371 result[j] = ch << 2;
372 break;
373 case 1:
374 result[j++] |= ch >> 4;
375 result[j] = (ch & 0x0f) << 4;
376 break;
377 case 2:
378 result[j++] |= ch >>2;
379 result[j] = (ch & 0x03) << 6;
380 break;
381 case 3:
382 result[j++] |= ch;
383 break;
384 }
385 i++;
386 }
387
388 k = j;
389
390 if (ch == base64_pad) {
391 switch(i % 4) {
392 case 1:
393 free(result);
394 return NULL;
395 case 2:
396 k++;
397 case 3:
398 result[k++] = 0;
399 }
400 }
401 result[j] = '\0';
402 *ret = j;
403 return result;
404 }
405
406