import from branch_1_1:
[freeradius.git] / src / lib / missing.c
1 /*
2  * missing.c    Replacements for functions that are or can be
3  *              missing on some platforms.
4  *
5  * Version:     $Id$
6  *
7  *   This library is free software; you can redistribute it and/or
8  *   modify it under the terms of the GNU Lesser General Public
9  *   License as published by the Free Software Foundation; either
10  *   version 2.1 of the License, or (at your option) any later version.
11  *
12  *   This library is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  *   Lesser General Public License for more details.
16  *
17  *   You should have received a copy of the GNU Lesser General Public
18  *   License along with this library; if not, write to the Free Software
19  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  *
21  * Copyright 2000,2006  The FreeRADIUS server project
22  */
23
24 #include        <freeradius-devel/ident.h>
25 RCSID("$Id$")
26
27 #include        <freeradius-devel/libradius.h>
28
29 #include        <ctype.h>
30
31 #ifndef HAVE_CRYPT
32 char *crypt(char *key, char *salt)
33 {
34         /*log(L_ERR, "crypt() called but not implemented");*/
35         return "____fnord____";
36 }
37 #endif
38
39 #ifndef HAVE_STRNCASECMP
40 int strncasecmp(char *s1, char *s2, int n)
41 {
42         int             dif;
43         unsigned char   *p1, *p2;
44         int             c1, c2;
45
46         p1 = (unsigned char *)s1;
47         p2 = (unsigned char *)s2;
48         dif = 0;
49
50         while (n != 0) {
51                 if (*p1 == 0 && *p2 == 0)
52                         break;
53                 c1 = *p1;
54                 c2 = *p2;
55
56                 if (islower(c1)) c1 = toupper(c1);
57                 if (islower(c2)) c2 = toupper(c2);
58
59                 if ((dif = c1 - c2) != 0)
60                         break;
61                 p1++;
62                 p2++;
63                 n--;
64         }
65         return dif;
66 }
67 #endif
68
69 #ifndef HAVE_STRCASECMP
70 int strcasecmp(char *s1, char *s2)
71 {
72         int             l1, l2;
73
74         l1 = strlen(s1);
75         l2 = strlen(s2);
76         if (l2 > l1) l1 = l2;
77
78         return strncasecmp(s1, s2, l1);
79 }
80 #endif
81
82 #ifndef HAVE_INET_ATON
83 int inet_aton(char *cp, struct in_addr *inp)
84 {
85         int     a1, a2, a3, a4;
86
87         if (sscanf(cp, "%d.%d.%d.%d", &a1, &a2, &a3, &a4) != 4)
88                 return 0;
89
90         inp->s_addr = htonl((a1 << 24) + (a2 << 16) + (a3 << 8) + a4);
91         return 1;
92 }
93 #endif
94
95 #ifndef HAVE_STRSEP
96 /*
97  *      Get next token from string *stringp, where tokens are
98  *      possibly-empty strings separated by characters from delim.
99  *
100  *      Writes NULs into the string at *stringp to end tokens.
101  *      delim need not remain constant from call to call.  On
102  *      return, *stringp points past the last NUL written (if there
103  *      might be further tokens), or is NULL (if there are
104  *      definitely no more tokens).
105  *
106  *      If *stringp is NULL, strsep returns NULL.
107  */
108 char *
109 strsep(char **stringp, const char *delim)
110 {
111         char *s;
112         const char *spanp;
113         int c, sc;
114         char *tok;
115
116         if ((s = *stringp) == NULL)
117                 return (NULL);
118
119         for (tok = s;;) {
120                 c = *s++;
121                 spanp = delim;
122                 do {
123                         if ((sc = *spanp++) == c) {
124                                 if (c == 0)
125                                         s = NULL;
126                                 else
127                                         s[-1] = 0;
128                                 *stringp = s;
129                                 return (tok);
130                         }
131                 } while (sc != 0);
132         }
133
134         return NULL;            /* NOTREACHED, but the compiler complains */
135 }
136 #endif
137
138 #ifndef HAVE_LOCALTIME_R
139 /*
140  *      We use localtime_r() by default in the server.
141  *
142  *      For systems which do NOT have localtime_r(), we make the
143  *      assumption that localtime() is re-entrant, and returns a
144  *      per-thread data structure.
145  *
146  *      Even if localtime is NOT re-entrant, this function will
147  *      lower the possibility of race conditions.
148  */
149 struct tm *localtime_r(const time_t *l_clock, struct tm *result)
150 {
151   memcpy(result, localtime(l_clock), sizeof(*result));
152
153   return result;
154 }
155 #endif
156
157 #ifndef HAVE_CTIME_R
158 /*
159  *      We use ctime_r() by default in the server.
160  *
161  *      For systems which do NOT have ctime_r(), we make the
162  *      assumption that ctime() is re-entrant, and returns a
163  *      per-thread data structure.
164  *
165  *      Even if ctime is NOT re-entrant, this function will
166  *      lower the possibility of race conditions.
167  */
168 char *ctime_r(const time_t *l_clock, char *l_buf)
169 {
170   strcpy(l_buf, ctime(l_clock));
171
172   return l_buf;
173 }
174 #endif
175
176 #ifndef HAVE_GMTIME_R
177 /*
178  *      We use gmtime_r() by default in the server.
179  *
180  *      For systems which do NOT have gmtime_r(), we make the
181  *      assumption that gmtime() is re-entrant, and returns a
182  *      per-thread data structure.
183  *
184  *      Even if gmtime is NOT re-entrant, this function will
185  *      lower the possibility of race conditions.
186  */
187 struct tm *gmtime_r(const time_t *l_clock, struct tm *result)
188 {
189   memcpy(result, gmtime(l_clock), sizeof(*result));
190
191   return result;
192 }
193 #endif
194
195 #ifndef HAVE_GETTIMEOFDAY
196 #ifdef WIN32
197 /*
198  * Number of micro-seconds between the beginning of the Windows epoch
199  * (Jan. 1, 1601) and the Unix epoch (Jan. 1, 1970).
200  *
201  * This assumes all Win32 compilers have 64-bit support.
202  */
203 #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) || defined(__WATCOMC__)
204 #define DELTA_EPOCH_IN_USEC  11644473600000000Ui64
205 #else
206 #define DELTA_EPOCH_IN_USEC  11644473600000000ULL
207 #endif
208
209 static uint64_t filetime_to_unix_epoch (const FILETIME *ft)
210 {
211         uint64_t res = (uint64_t) ft->dwHighDateTime << 32;
212
213         res |= ft->dwLowDateTime;
214         res /= 10;                   /* from 100 nano-sec periods to usec */
215         res -= DELTA_EPOCH_IN_USEC;  /* from Win epoch to Unix epoch */
216         return (res);
217 }
218
219 int gettimeofday (struct timeval *tv, UNUSED void *tz)
220 {
221         FILETIME  ft;
222         uint64_t tim;
223
224         if (!tv) {
225                 errno = EINVAL;
226                 return (-1);
227         }
228         GetSystemTimeAsFileTime (&ft);
229         tim = filetime_to_unix_epoch (&ft);
230         tv->tv_sec  = (long) (tim / 1000000L);
231         tv->tv_usec = (long) (tim % 1000000L);
232         return (0);
233 }
234 #endif
235 #endif