added session manager and support for an external login system
[TransparentIRC.git] / src / tools.c
1 /* tools.c - TransparentIRC 0.1
2  * Copyright (C) 2011-2012  Philipp Kreil (pk910)
3  * 
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.
8  * 
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.
13  * 
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/>. 
16  */
17 #include "tools.h"
18
19 int stricmp(const char *s1, const char *s2) {
20     if (s1 == NULL) return s2 == NULL ? 0 : -(*s2);
21     if (s2 == NULL) return *s1;
22     char c1, c2;
23     while ((c1 = tolower (*s1)) == (c2 = tolower (*s2))) {
24         if (*s1 == '\0') break;
25         ++s1; ++s2;
26     }
27     return c1 - c2;
28 }
29
30 int stricmplen(const char *s1, const char *s2, int len) {
31     if (s1 == NULL) return s2 == NULL ? 0 : -(*s2);
32     if (s2 == NULL) return *s1;
33     char c1, c2;
34     int i = 0;
35     while ((c1 = tolower (*s1)) == (c2 = tolower (*s2))) {
36         i++;
37         if (*s1 == '\0') break;
38         ++s1; ++s2;
39         if(i == len) break;
40     }
41     return c1 - c2;
42 }
43
44 int parse_line(char *line, char **argv, int irc_raw) {
45     int argc = 0;
46     if(irc_raw) {
47         if(line[0] == ':')
48             line++;
49         else
50             argv[argc++] = NULL;
51     }
52     while(*line) {
53         //skip leading spaces
54         while (*line == ' ')
55             *line++ = 0;
56         if (*line == ':' && irc_raw) {
57            //the rest is a single parameter
58            argv[argc++] = line + 1;
59            break;
60         }
61         argv[argc++] = line;
62         if (argc >= MAXNUMPARAMS)
63             break;
64         while (*line != ' ' && *line)
65             line++;
66     }
67     return argc;
68 }
69
70 void build_var_string(char *buffer, char *format, struct variable_replace_map *map) {
71     int bufferpos = 0;
72     int i, escape = 0;
73     char *p = format;
74     char *tmp;
75     while(*p) {
76         if(escape) {
77             escape = 0;
78             goto build_var_string_addchar;
79         }
80         if(*p == '\\') {
81             escape = 1;
82             p++;
83             continue;
84         }
85         if(*p == '%') {
86             p++;
87             for(i = 0; ; i++) {
88                 if(!map[i].character) {
89                     tmp = NULL;
90                     break;
91                 }
92                 if(map[i].character == *p) {
93                     tmp = map[i].value;
94                     break;
95                 }
96             }
97             if(!tmp) {
98                 p--;
99                 goto build_var_string_addchar;
100             }
101             for(i = 0; tmp[i] && bufferpos < CMDLEN; i++) {
102                 buffer[bufferpos++] = tmp[i]; 
103             }
104         } else {
105             build_var_string_addchar:
106             buffer[bufferpos++] = *p;
107             if(bufferpos == CMDLEN)
108                 break;
109         }
110         p++;
111     }
112     buffer[bufferpos++] = '\0';
113 }
114
115 int run_external_process(char *command, char **parameters) { //win32 incompatible
116     int sockets[2], child;
117     if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) < 0)
118         return -1;
119     if ((child = fork()) == -1) {
120         close(sockets[0]);
121         close(sockets[1]);
122         return -1;
123     }
124     else if (child) { // This is the parent.
125         close(sockets[0]);
126         wait(NULL);
127         return sockets[1];
128     } else { // This is the child.
129         close(sockets[1]);
130         child = fork(); //double fork to prevent zombies
131         if(child < 0) exit(EXIT_FAILURE);
132         if(child != 0) exit(EXIT_SUCCESS);
133         if(dup2(sockets[0], 1) != -1) {
134             execvp(command, parameters);
135         }
136         close(sockets[0]);
137         exit(EXIT_FAILURE);
138     }
139 }
140