callcgi: Added option to change CWD to the script's directory.
[ashd.git] / lib / utils.c
1 /*
2     ashd - A Sane HTTP Daemon
3     Copyright (C) 2008  Fredrik Tolf <fredrik@dolda2000.com>
4
5     This program is free software: you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation, either version 3 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <ctype.h>
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27 #include <utils.h>
28
29 void _sizebuf(struct buffer *buf, size_t wanted, size_t el)
30 {
31     size_t n;
32     
33     n = buf->s;
34     if(n == 0)
35         n = 1;
36     while(n < wanted)
37         n <<= 1;
38     if(n <= buf->s)
39         return;
40     if(buf->b != NULL)
41         buf->b = srealloc(buf->b, n * el);
42     else
43         buf->b = smalloc(n * el);
44     buf->s = n;
45 }
46
47 char *decstr(char **p, size_t *len)
48 {
49     char *p2, *ret;
50     
51     for(p2 = *p; (p2 - *p) < *len; p2++) {
52         if(*p2 == 0)
53             break;
54     }
55     if((p2 - *p) == *len)
56         return(NULL);
57     p2++;
58     ret = *p;
59     *len -= p2 - *p;
60     *p = p2;
61     return(ret);
62 }
63
64 char *vsprintf2(char *format, va_list al)
65 {
66     int ret;
67     char *buf;
68     va_list al2;
69     
70     va_copy(al2, al);
71     ret = vsnprintf(NULL, 0, format, al2);
72     va_end(al2);
73     buf = smalloc(ret + 1);
74     va_copy(al2, al);
75     vsnprintf(buf, ret + 1, format, al2);
76     va_end(al2);
77     return(buf);
78 }
79
80 char *sprintf2(char *format, ...)
81 {
82     va_list args;
83     char *buf;
84     
85     va_start(args, format);
86     buf = vsprintf2(format, args);
87     va_end(args);
88     return(buf);
89 }
90
91 char *sprintf3(char *format, ...)
92 {
93     static char *buf = NULL;
94     va_list args;
95     
96     if(buf != NULL)
97         free(buf);
98     va_start(args, format);
99     buf = vsprintf2(format, args);
100     va_end(args);
101     return(buf);
102 }
103
104 off_t atoo(char *n)
105 {
106     return((off_t)strtoll(n, NULL, 10));
107 }
108
109 char **tokenize(char *src)
110 {
111     char **ret;
112     char *p, *p2, *n;
113     int s, q, cl;
114     
115     p = src;
116     s = 0;
117     ret = NULL;
118     while(1) {
119         while(isspace(*p))
120             p++;
121         if(!*p)
122             break;
123         p2 = p;
124         q = 0;
125         while(1) {
126             if(q) {
127                 if(*p == '\"')
128                     q = 0;
129                 else if(*p == '\\')
130                     p++;
131             } else {
132                 if(*p == '\"')
133                     q = 1;
134                 else if(isspace(*p) || !*p)
135                     break;
136                 else if(*p == '\\')
137                     p++;
138             }
139             p++;
140         }
141         cl = p - p2;
142         n = memcpy(malloc(cl + 1), p2, cl);
143         n[cl] = 0;
144         for(p2 = n; *p2; cl--) {
145             if(*p2 == '\\') {
146                 memmove(p2, p2 + 1, cl--);
147                 p2++;
148             } else if(*p2 == '\"') {
149                 memmove(p2, p2 + 1, cl);
150             } else {
151                 p2++;
152             }
153         }
154         ret = realloc(ret, sizeof(char *) * (++s));
155         ret[s - 1] = n;
156     }
157     ret = realloc(ret, sizeof(char *) * (++s));
158     ret[s - 1] = NULL;
159     return(ret);
160 }
161
162 void freeca(char **ca)
163 {
164     char **c;
165     
166     if(ca == NULL)
167         return;
168     for(c = ca; *c; c++)
169         free(*c);
170     free(ca);
171 }
172
173 int calen(char **a)
174 {
175     int i;
176     
177     for(i = 0; *a; a++, i++);
178     return(i);
179 }
180
181 void bvprintf(struct charbuf *buf, char *format, va_list al)
182 {
183     va_list al2;
184     int ret;
185     
186     while(1) {
187         va_copy(al2, al);
188         ret = vsnprintf(buf->b + buf->d, buf->s - buf->d, format, al2);
189         va_end(al2);
190         if(ret < buf->s - buf->d) {
191             buf->d += ret;
192             return;
193         }
194         sizebuf(*buf, buf->d + ret + 1);
195     }
196 }
197
198 void bprintf(struct charbuf *buf, char *format, ...)
199 {
200     va_list args;
201     
202     va_start(args, format);
203     bvprintf(buf, format, args);
204     va_end(args);
205 }
206
207 void replstr(char **p, char *n)
208 {
209     char *tmp;
210     
211     tmp = *p;
212     if(n)
213         *p = sstrdup(n);
214     else
215         *p = NULL;
216     if(tmp)
217         free(tmp);
218 }