core: fix another bunch of 'no real prototype' warnings, add doxygen docs
[sip-router] / ut.c
1 /*
2  *$Id$
3  *
4  * various general purpose functions
5  *
6  * Copyright (C) 2001-2003 FhG Fokus
7  *
8  * Permission to use, copy, modify, and distribute this software for any
9  * purpose with or without fee is hereby granted, provided that the above
10  * copyright notice and this permission notice appear in all copies.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19  *
20  */
21
22
23 /** various general purpose/utility functions.
24  * @file ut.c
25  * @ingroup core
26  * Module: core
27  */
28
29 #include <sys/types.h>
30 #include <pwd.h>
31 #include <grp.h>
32 #include <stdlib.h>
33 #include <time.h>
34 #include <sys/utsname.h> /* uname() */
35 #include <libgen.h>
36
37
38 #include "ut.h"
39 #include "mem/mem.h"
40 #include "globals.h"
41
42 /* global buffer for ut.h int2str() */
43 char ut_buf_int2str[INT2STR_MAX_LEN];
44
45
46 /* converts a username into uid:gid,
47  * returns -1 on error & 0 on success */
48 int user2uid(int* uid, int* gid, char* user)
49 {
50         char* tmp;
51         struct passwd *pw_entry;
52         
53         if (user){
54                 *uid=strtol(user, &tmp, 10);
55                 if ((tmp==0) ||(*tmp)){
56                         /* maybe it's a string */
57                         pw_entry=getpwnam(user);
58                         if (pw_entry==0){
59                                 goto error;
60                         }
61                         *uid=pw_entry->pw_uid;
62                         if (gid) *gid=pw_entry->pw_gid;
63                 }
64                 return 0;
65         }
66 error:
67         return -1;
68 }
69
70
71
72 /* converts a group name into a gid
73  * returns -1 on error, 0 on success */
74 int group2gid(int* gid, char* group)
75 {
76         char* tmp;
77         struct group  *gr_entry;
78         
79         if (group){
80                 *gid=strtol(group, &tmp, 10);
81                 if ((tmp==0) ||(*tmp)){
82                         /* maybe it's a string */
83                         gr_entry=getgrnam(group);
84                         if (gr_entry==0){
85                                 goto error;
86                         }
87                         *gid=gr_entry->gr_gid;
88                 }
89                 return 0;
90         }
91  error:
92         return -1;
93 }
94
95
96 /*
97  * Replacement of timegm (does not exists on all platforms
98  * Taken from 
99  * http://lists.samba.org/archive/samba-technical/2002-November/025737.html
100  */
101 time_t _timegm(struct tm* t)
102 {
103         time_t tl, tb;
104         struct tm* tg;
105
106         t->tm_isdst = 0;
107         tl = mktime(t);
108         if (tl == -1) {
109                 t->tm_hour--;
110                 tl = mktime (t);
111                 if (tl == -1) {
112                         return -1; /* can't deal with output from strptime */
113                 }
114                 tl += 3600;
115         }
116         
117         tg = gmtime(&tl);
118         tg->tm_isdst = 0;
119         tb = mktime(tg);
120         if (tb == -1) {
121                 tg->tm_hour--;
122                 tb = mktime (tg);
123                 if (tb == -1) {
124                         return -1; /* can't deal with output from gmtime */
125                 }
126                 tb += 3600;
127         }
128         return (tl - (tb - tl));
129 }
130
131
132 /* Convert time_t value that is relative to local timezone to UTC */
133 time_t local2utc(time_t in)
134 {
135         struct tm* tt;
136         tt = gmtime(&in);
137         tt->tm_isdst = -1;
138         return mktime(tt);
139 }
140
141
142 /* Convert time_t value in UTC to to value relative to local time zone */
143 time_t utc2local(time_t in)
144 {
145         struct tm* tt;
146         tt = localtime(&in);
147 #ifdef HAVE_TIMEGM
148         return timegm(tt);
149 #else
150         return _timegm(tt);
151 #endif
152 }
153
154
155 /*
156  * Return str as zero terminated string allocated
157  * using pkg_malloc
158  */
159 char* as_asciiz(str* s)
160 {
161     char* r;
162
163     r = (char*)pkg_malloc(s->len + 1);
164     if (!r) {
165                 ERR("Out of memory\n");
166                 return 0;
167     }
168     memcpy(r, s->s, s->len);
169     r[s->len] = '\0';
170     return r;
171 }
172
173
174
175 /* return system version (major.minor.minor2) as
176  *  (major<<16)|(minor)<<8|(minor2)
177  * (if some of them are missing, they are set to 0)
178  * if the parameters are not null they are set to the coresp. part 
179  */
180 unsigned int get_sys_version(int* major, int* minor, int* minor2)
181 {
182         struct utsname un;
183         int m1;
184         int m2;
185         int m3;
186         char* p;
187         
188         memset (&un, 0, sizeof(un));
189         m1=m2=m3=0;
190         /* get sys version */
191         uname(&un);
192         m1=strtol(un.release, &p, 10);
193         if (*p=='.'){
194                 p++;
195                 m2=strtol(p, &p, 10);
196                 if (*p=='.'){
197                         p++;
198                         m3=strtol(p, &p, 10);
199                 }
200         }
201         if (major) *major=m1;
202         if (minor) *minor=m2;
203         if (minor2) *minor2=m3;
204         return ((m1<<16)|(m2<<8)|(m3));
205 }
206
207
208
209 /** transform a relative pathname into an absolute one.
210  * @param base  - base file, used to extract the absolute path prefix.
211  *                Might be NULL, in which case the path of the ser.cfg is
212  *                used.
213  * @param file  - file path to be transformed. If it's already absolute
214  *                (starts with '/') is left alone. If not the result will
215  *                be `dirname base`/file.
216  * @return  pkg allocated asciiz string or 0 on error.
217  */
218 char* get_abs_pathname(str* base, str* file)
219 {
220         str ser_cfg;
221         char* buf, *dir, *res;
222         int len;
223         
224         if (base == NULL) {
225                 ser_cfg.s = cfg_file;
226                 ser_cfg.len = strlen(cfg_file);
227                 base = &ser_cfg;
228         }
229         
230         if (!base->s || base->len <= 0 || base->s[0] != '/') {
231                 BUG("get_abs_pathname: Base file must be absolute pathname: "
232                         "'%.*s'\n", STR_FMT(base));
233                 return NULL;
234         }
235         
236         if (!file || !file->s || file->len <= 0) {
237                 BUG("get_abs_pathname: Invalid 'file' parameter\n");
238                 return NULL;
239         }
240         
241         if (file->s[0] == '/') {
242                 /* This is an absolute pathname, make a zero terminated
243                  * copy and use it as it is */
244                 if ((res = pkg_malloc(file->len+1)) == NULL) {
245                         ERR("get_abs_pathname: No memory left (pkg_malloc failed)\n");
246                         return NULL;
247                 }
248                 memcpy(res, file->s, file->len);
249                 res[file->len]=0;
250         } else {
251                 /* This is not an absolute pathname, make it relative
252                  * to the location of the base file
253                  */
254                 /* Make a copy, function dirname may modify the string */
255                 if ((buf = pkg_malloc(base->len+1)) == NULL) {
256                         ERR("get_abs_pathname: No memory left (pkg_malloc failed)\n");
257                         return NULL;
258                 }
259                 memcpy(buf, base->s, base->len);
260                 buf[base->len]=0;
261                 dir = dirname(buf);
262                 
263                 len = strlen(dir);
264                 if ((res = pkg_malloc(len + 1 + file->len + 1)) == NULL) {
265                         ERR("get_abs_pathname: No memory left (pkg_malloc failed)\n");
266                         pkg_free(buf);
267                         return NULL;
268                 }
269                 memcpy(res, dir, len);
270                 res[len] = '/';
271                 memcpy(res + len + 1, file->s, file->len);
272                 res[len + 1 + file->len] = '\0';
273                 pkg_free(buf);
274         }
275         return res;
276 }
277
278
279 /**
280  * @brief search for occurence of needle in text
281  * @return pointer to start of needle in text or NULL if the needle
282  *      is not found
283  */
284 char *str_search(str *text, str *needle)
285 {
286     char *p;
287
288     if(text==NULL || text->s==NULL || needle==NULL || needle->s==NULL
289                         || text->len<needle->len)
290         return NULL;
291
292     for (p = text->s; p <= text->s + text->len - needle->len; p++) {
293         if (*p == *needle->s && memcmp(p, needle->s, needle->len)==0) {
294             return p;
295         }
296     }
297
298     return NULL;
299 }