2 * Copyright (C) 2012-2013 Andy Spencer <andy753421@gmail.com>
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #define _XOPEN_SOURCE_EXTENDED
21 #define _POSIX_C_SOURCE 200100
31 #include <sys/epoll.h>
36 #pragma weak view_exit
37 #pragma weak view_debug
41 static FILE *debug_fd = NULL;
42 static int running = 0;
45 extern void view_debug(const char *fmt, va_list ap);
47 /* Helper functions */
48 static void message(FILE *output_fd, const char *prefix, const char *fmt, va_list ap)
53 clock_gettime(CLOCK_REALTIME, &ts);
54 unsigned int sec = ts.tv_sec;
55 unsigned int msec = ts.tv_nsec / 1000000;
57 /* Log to standard out */
60 fprintf(output_fd, "%u.%03u: ", sec, msec);
61 fprintf(output_fd, "%s: ", prefix);
62 vfprintf(output_fd, fmt, tmp);
63 fprintf(output_fd, "\n");
67 /* Log to debug file */
70 fprintf(debug_fd, "%u.%03u: ", sec, msec);
71 fprintf(debug_fd, "%s: ", prefix);
72 vfprintf(debug_fd, fmt, tmp);
73 fprintf(debug_fd, "\n");
77 /* Log to status bar */
87 epoll = epoll_create(1);
88 debug_fd = fopen("/tmp/lamechat.log", "w+");
92 /* String functions */
93 void strsub(char *str, char find, char repl)
95 for (char *cur = str; *cur; cur++)
100 char *strcopy(const char *str)
107 void strset(char **old, const char *str)
117 int match(const char *a, const char *b)
123 return !strcmp(a, b);
126 int prefix(const char *str, const char *prefix, const char **suffix)
128 while (*str && *prefix) {
136 if (*str && *str != ' ')
138 while (*str && *str == ' ')
141 *suffix = *str ? str : NULL;
145 char *despace(char *str)
150 while ((chr = *src++)) {
160 if (dst > str && spaces)
166 void escape(char *dst, const char *src, int len)
170 for (int si=0; src[si]; si++) {
172 case '&': n = 5; repl = "&"; break;
173 case '<': n = 4; repl = "<"; break;
174 case '>': n = 4; repl = ">"; break;
175 default: n = 1; repl = &src[si]; break;
179 for (int ri = 0; ri < n; ri++)
180 dst[di++] = repl[ri];
185 /* Memory functions */
186 void *alloc0(int size)
188 void *data = calloc(1, size);
190 error("memory allocation failed");
194 void append(buf_t *buf, const char *data, int len)
196 if (buf->len + len + 1 > buf->max) {
197 buf->max += (((buf->len+len)/4096)+1)*4096;
198 buf->data = realloc(buf->data, buf->max);
200 error("buffer reallocation allocation failed");
203 memcpy(buf->data + buf->len, data, len);
205 ((char*)buf->data)[buf->len] = '\0';
208 void release(buf_t *buf)
216 const char *reset(buf_t *buf)
225 int base64(const void *_in, int ilen, void *_out, int olen)
227 static const char table[] =
228 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
229 "abcdefghijklmnopqrstuvwxyz"
232 const unsigned char *in = _in;
233 unsigned char *out = _out;
236 int len = ((ilen-1)/3+1)*4;
241 for (int i=0; i<ilen/3; i++) {
242 val = *(in++) << 020;
243 val |= *(in++) << 010;
244 val |= *(in++) << 000;
245 *(out++) = table[(val>>6*3)&077];
246 *(out++) = table[(val>>6*2)&077];
247 *(out++) = table[(val>>6*1)&077];
248 *(out++) = table[(val>>6*0)&077];
255 *out++ = table[(val>>6*3)&077];
256 *out++ = table[(val>>6*2)&077];
257 *out++ = table[(val>>6*1)&077];
262 *out++ = table[(val>>6*3)&077];
263 *out++ = table[(val>>6*2)&077];
273 char *read_file(const char *path, int *len)
275 /* we could use stat, but we'll try to be portable */
276 FILE *fd = fopen(path, "rt+");
280 int block = 512; // read size
281 int size = 512; // buffer size
282 int slen = 0; // string length
283 char *buf = malloc(size);
288 if (slen + block + 1 > size) {
290 buf = realloc(buf, size);
294 slen += fread(&buf[slen], 1, block, fd);
305 /* Polling functions */
306 int poll_add(poll_t *poll, int fd, cb_t cb, void *data)
308 struct epoll_event ctl = {
309 .events = EPOLLET | EPOLLIN | EPOLLOUT | EPOLLERR,
315 return epoll_ctl(epoll, EPOLL_CTL_ADD, fd, &ctl);
318 int poll_ctl(poll_t *poll, int in, int out, int err)
320 struct epoll_event ctl = {
323 | (out ? EPOLLOUT : 0)
324 | (err ? EPOLLERR : 0),
327 return epoll_ctl(epoll, EPOLL_CTL_MOD, poll->fd, &ctl);
330 int poll_del(poll_t *poll)
332 return epoll_ctl(epoll, EPOLL_CTL_DEL, poll->fd, NULL);
335 int poll_run(int timeout)
339 struct epoll_event event;
343 count = epoll_wait(epoll, &event, 1, timeout);
350 if (!(poll = event.data.ptr))
354 //debug("poll fd=%d count=%d,%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
356 // event.events & EPOLLIN ? " in" : "",
357 // event.events & EPOLLPRI ? " pri" : "",
358 // event.events & EPOLLOUT ? " out" : "",
359 // event.events & EPOLLRDNORM ? " rdnorm" : "",
360 // event.events & EPOLLRDBAND ? " rdband" : "",
361 // event.events & EPOLLWRNORM ? " wrnorm" : "",
362 // event.events & EPOLLWRBAND ? " wrband" : "",
363 // event.events & EPOLLMSG ? " msg" : "",
364 // event.events & EPOLLERR ? " err" : "",
365 // event.events & EPOLLHUP ? " hup" : "",
366 // event.events & EPOLLRDHUP ? " rdhup" : "",
367 // event.events & EPOLLWAKEUP ? " wakeup" : "",
368 // event.events & EPOLLONESHOT ? " oneshot" : "",
369 // event.events & EPOLLET ? " et" : "");
370 poll->cb(poll->data);
381 /* Debugging functions */
382 void debug(char *fmt, ...)
386 message(NULL, "debug", fmt, ap);
390 void error(char *fmt, ...)
396 message(stderr, "error", fmt, ap);