]> jfr.im git - irc/rqf/shadowircd.git/blame - libratbox/src/ratbox_lib.c
libratbox: Clean up uses of strcpy().
[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 *
b57f37fb
WP
23 */
24
25#include <libratbox_config.h>
26#include <ratbox_lib.h>
27#include <commio-int.h>
f030cae8 28#include <commio-ssl.h>
b57f37fb
WP
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
b57f37fb
WP
72 if(buf == NULL)
73 {
74 p = timex;
75 tlen = sizeof(timex);
94b4fbf9
VY
76 }
77 else
78 {
b57f37fb
WP
79 p = buf;
80 tlen = len;
81 }
82
ad06ad57
WP
83 if(rb_unlikely(tp == NULL))
84 {
85 rb_strlcpy(p, "", tlen);
86 return (p);
87 }
88
b57f37fb 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{
f030cae8
VY
190 static char version_info[512];
191 char ssl_info[512];
192 rb_get_ssl_info(ssl_info, sizeof(ssl_info));
193 rb_snprintf(version_info, sizeof(version_info), "libratbox version: %s - %s", libratbox_serno, ssl_info);
194 return version_info;
b57f37fb
WP
195}
196
197void
94b4fbf9
VY
198rb_lib_init(log_cb * ilog, restart_cb * irestart, die_cb * idie, int closeall, int maxcon,
199 size_t dh_size, size_t fd_heap_size)
b57f37fb
WP
200{
201 rb_set_time();
202 rb_log = ilog;
203 rb_restart = irestart;
204 rb_die = idie;
205 rb_event_init();
206 rb_init_bh();
207 rb_fdlist_init(closeall, maxcon, fd_heap_size);
208 rb_init_netio();
209 rb_init_rb_dlink_nodes(dh_size);
210 if(rb_io_supports_event())
211 {
212 rb_io_init_event();
213 }
214}
215
216void
217rb_lib_loop(long delay)
218{
219 time_t next;
220 rb_set_time();
221
222 if(rb_io_supports_event())
223 {
224 if(delay == 0)
225 delay = -1;
226 while(1)
227 rb_select(-1);
228 }
94b4fbf9 229
b57f37fb
WP
230
231 while(1)
232 {
233 if(delay == 0)
234 {
94b4fbf9 235 if((next = rb_event_next()) > 0)
b57f37fb
WP
236 {
237 next -= rb_current_time();
238 if(next <= 0)
239 next = 1000;
94b4fbf9 240 else
b57f37fb
WP
241 next *= 1000;
242 }
243 else
244 next = -1;
245 rb_select(next);
94b4fbf9
VY
246 }
247 else
b57f37fb
WP
248 rb_select(delay);
249 rb_event_run();
250 }
251}
252
253#ifndef HAVE_STRTOK_R
254char *
94b4fbf9 255rb_strtok_r(char *s, const char *delim, char **save)
b57f37fb
WP
256{
257 char *token;
258
94b4fbf9 259 if(s == NULL)
b57f37fb
WP
260 s = *save;
261
262 /* Scan leading delimiters. */
263 s += strspn(s, delim);
264
94b4fbf9 265 if(*s == '\0')
b57f37fb
WP
266 {
267 *save = s;
268 return NULL;
269 }
270
271 token = s;
272 s = strpbrk(token, delim);
94b4fbf9
VY
273
274 if(s == NULL)
b57f37fb
WP
275 *save = (token + strlen(token));
276 else
277 {
94b4fbf9 278 *s = '\0';
b57f37fb
WP
279 *save = s + 1;
280 }
281 return token;
282}
283#else
94b4fbf9
VY
284char *
285rb_strtok_r(char *s, const char *delim, char **save)
b57f37fb
WP
286{
287 return strtok_r(s, delim, save);
288}
289#endif
290
291
292static const char base64_table[] =
293 { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
94b4fbf9
VY
294 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
295 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
296 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
297 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '\0'
298};
b57f37fb
WP
299
300static const char base64_pad = '=';
301
302static const short base64_reverse_table[256] = {
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, 62, -1, -1, -1, 63,
306 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
94b4fbf9 307 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
b57f37fb
WP
308 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
309 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
310 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -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 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
319};
320
321unsigned char *
322rb_base64_encode(const unsigned char *str, int length)
323{
324 const unsigned char *current = str;
325 unsigned char *p;
326 unsigned char *result;
327
94b4fbf9
VY
328 if((length + 2) < 0 || ((length + 2) / 3) >= (1 << (sizeof(int) * 8 - 2)))
329 {
b57f37fb
WP
330 return NULL;
331 }
332
333 result = rb_malloc(((length + 2) / 3) * 5);
334 p = result;
335
94b4fbf9
VY
336 while(length > 2)
337 {
b57f37fb
WP
338 *p++ = base64_table[current[0] >> 2];
339 *p++ = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
340 *p++ = base64_table[((current[1] & 0x0f) << 2) + (current[2] >> 6)];
341 *p++ = base64_table[current[2] & 0x3f];
342
343 current += 3;
94b4fbf9 344 length -= 3;
b57f37fb
WP
345 }
346
94b4fbf9
VY
347 if(length != 0)
348 {
b57f37fb 349 *p++ = base64_table[current[0] >> 2];
94b4fbf9
VY
350 if(length > 1)
351 {
b57f37fb
WP
352 *p++ = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
353 *p++ = base64_table[(current[1] & 0x0f) << 2];
354 *p++ = base64_pad;
94b4fbf9
VY
355 }
356 else
357 {
b57f37fb
WP
358 *p++ = base64_table[(current[0] & 0x03) << 4];
359 *p++ = base64_pad;
360 *p++ = base64_pad;
361 }
362 }
363 *p = '\0';
364 return result;
365}
366
367unsigned char *
368rb_base64_decode(const unsigned char *str, int length, int *ret)
369{
370 const unsigned char *current = str;
371 int ch, i = 0, j = 0, k;
372 unsigned char *result;
94b4fbf9 373
b57f37fb
WP
374 result = rb_malloc(length + 1);
375
94b4fbf9
VY
376 while((ch = *current++) != '\0' && length-- > 0)
377 {
378 if(ch == base64_pad)
379 break;
b57f37fb
WP
380
381 ch = base64_reverse_table[ch];
94b4fbf9
VY
382 if(ch < 0)
383 continue;
b57f37fb 384
94b4fbf9
VY
385 switch (i % 4)
386 {
b57f37fb
WP
387 case 0:
388 result[j] = ch << 2;
389 break;
390 case 1:
391 result[j++] |= ch >> 4;
392 result[j] = (ch & 0x0f) << 4;
393 break;
394 case 2:
94b4fbf9 395 result[j++] |= ch >> 2;
b57f37fb
WP
396 result[j] = (ch & 0x03) << 6;
397 break;
398 case 3:
399 result[j++] |= ch;
400 break;
401 }
402 i++;
403 }
404
405 k = j;
406
94b4fbf9
VY
407 if(ch == base64_pad)
408 {
409 switch (i % 4)
410 {
b57f37fb
WP
411 case 1:
412 free(result);
413 return NULL;
414 case 2:
415 k++;
416 case 3:
417 result[k++] = 0;
418 }
419 }
420 result[j] = '\0';
421 *ret = j;
422 return result;
423}