1 /* 2 * wpa_supplicant/hostapd / Internal implementation of OS specific functions 3 * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> 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 version 2 as 7 * published by the Free Software Foundation. 8 * 9 * Alternatively, this software may be distributed under the terms of BSD 10 * license. 11 * 12 * See README and COPYING for more details. 13 * 14 * This file is an example of operating system specific wrapper functions. 15 * This version implements many of the functions internally, so it can be used 16 * to fill in missing functions from the target system C libraries. 17 * 18 * Some of the functions are using standard C library calls in order to keep 19 * this file in working condition to allow the functions to be tested on a 20 * Linux target. Please note that OS_NO_C_LIB_DEFINES needs to be defined for 21 * this file to work correctly. Note that these implementations are only 22 * examples and are not optimized for speed. 23 */ 24 25 #include "includes.h" 26 27 #undef OS_REJECT_C_LIB_FUNCTIONS 28 #include "os.h" 29 30 void os_sleep(os_time_t sec, os_time_t usec) 31 { 32 if (sec) 33 sleep(sec); 34 if (usec) 35 usleep(usec); 36 } 37 38 39 int os_get_time(struct os_time *t) 40 { 41 int res; 42 struct timeval tv; 43 res = gettimeofday(&tv, NULL); 44 t->sec = tv.tv_sec; 45 t->usec = tv.tv_usec; 46 return res; 47 } 48 49 50 int os_mktime(int year, int month, int day, int hour, int min, int sec, 51 os_time_t *t) 52 { 53 struct tm tm; 54 55 if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 || 56 hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || 57 sec > 60) 58 return -1; 59 60 os_memset(&tm, 0, sizeof(tm)); 61 tm.tm_year = year - 1900; 62 tm.tm_mon = month - 1; 63 tm.tm_mday = day; 64 tm.tm_hour = hour; 65 tm.tm_min = min; 66 tm.tm_sec = sec; 67 68 *t = (os_time_t) mktime(&tm); 69 return 0; 70 } 71 72 73 int os_daemonize(const char *pid_file) 74 { 75 if (daemon(0, 0)) { 76 perror("daemon"); 77 return -1; 78 } 79 80 if (pid_file) { 81 FILE *f = fopen(pid_file, "w"); 82 if (f) { 83 fprintf(f, "%u\n", getpid()); 84 fclose(f); 85 } 86 } 87 88 return -0; 89 } 90 91 92 void os_daemonize_terminate(const char *pid_file) 93 { 94 if (pid_file) 95 unlink(pid_file); 96 } 97 98 99 int os_get_random(unsigned char *buf, size_t len) 100 { 101 FILE *f; 102 size_t rc; 103 104 f = fopen("/dev/urandom", "rb"); 105 if (f == NULL) { 106 printf("Could not open /dev/urandom.\n"); 107 return -1; 108 } 109 110 rc = fread(buf, 1, len, f); 111 fclose(f); 112 113 return rc != len ? -1 : 0; 114 } 115 116 117 unsigned long os_random(void) 118 { 119 return random(); 120 } 121 122 123 char * os_rel2abs_path(const char *rel_path) 124 { 125 char *buf = NULL, *cwd, *ret; 126 size_t len = 128, cwd_len, rel_len, ret_len; 127 128 if (rel_path[0] == '/') 129 return os_strdup(rel_path); 130 131 for (;;) { 132 buf = os_malloc(len); 133 if (buf == NULL) 134 return NULL; 135 cwd = getcwd(buf, len); 136 if (cwd == NULL) { 137 os_free(buf); 138 if (errno != ERANGE) { 139 return NULL; 140 } 141 len *= 2; 142 } else { 143 break; 144 } 145 } 146 147 cwd_len = strlen(cwd); 148 rel_len = strlen(rel_path); 149 ret_len = cwd_len + 1 + rel_len + 1; 150 ret = os_malloc(ret_len); 151 if (ret) { 152 os_memcpy(ret, cwd, cwd_len); 153 ret[cwd_len] = '/'; 154 os_memcpy(ret + cwd_len + 1, rel_path, rel_len); 155 ret[ret_len - 1] = '\0'; 156 } 157 os_free(buf); 158 return ret; 159 } 160 161 162 int os_program_init(void) 163 { 164 return 0; 165 } 166 167 168 void os_program_deinit(void) 169 { 170 } 171 172 173 int os_setenv(const char *name, const char *value, int overwrite) 174 { 175 return setenv(name, value, overwrite); 176 } 177 178 179 int os_unsetenv(const char *name) 180 { 181 #if defined(__FreeBSD__) || defined(__NetBSD__) 182 unsetenv(name); 183 return 0; 184 #else 185 return unsetenv(name); 186 #endif 187 } 188 189 190 char * os_readfile(const char *name, size_t *len) 191 { 192 FILE *f; 193 char *buf; 194 195 f = fopen(name, "rb"); 196 if (f == NULL) 197 return NULL; 198 199 fseek(f, 0, SEEK_END); 200 *len = ftell(f); 201 fseek(f, 0, SEEK_SET); 202 203 buf = os_malloc(*len); 204 if (buf == NULL) { 205 fclose(f); 206 return NULL; 207 } 208 209 fread(buf, 1, *len, f); 210 fclose(f); 211 212 return buf; 213 } 214 215 216 void * os_zalloc(size_t size) 217 { 218 void *n = os_malloc(size); 219 if (n) 220 os_memset(n, 0, size); 221 return n; 222 } 223 224 225 void * os_malloc(size_t size) 226 { 227 return malloc(size); 228 } 229 230 231 void * os_realloc(void *ptr, size_t size) 232 { 233 return realloc(ptr, size); 234 } 235 236 237 void os_free(void *ptr) 238 { 239 free(ptr); 240 } 241 242 243 void * os_memcpy(void *dest, const void *src, size_t n) 244 { 245 char *d = dest; 246 const char *s = src; 247 while (n--) 248 *d++ = *s++; 249 return dest; 250 } 251 252 253 void * os_memmove(void *dest, const void *src, size_t n) 254 { 255 if (dest < src) 256 os_memcpy(dest, src, n); 257 else { 258 /* overlapping areas */ 259 char *d = (char *) dest + n; 260 const char *s = (const char *) src + n; 261 while (n--) 262 *--d = *--s; 263 } 264 return dest; 265 } 266 267 268 void * os_memset(void *s, int c, size_t n) 269 { 270 char *p = s; 271 while (n--) 272 *p++ = c; 273 return s; 274 } 275 276 277 int os_memcmp(const void *s1, const void *s2, size_t n) 278 { 279 const unsigned char *p1 = s1, *p2 = s2; 280 281 if (n == 0) 282 return 0; 283 284 while (*p1 == *p2) { 285 p1++; 286 p2++; 287 n--; 288 if (n == 0) 289 return 0; 290 } 291 292 return *p1 - *p2; 293 } 294 295 296 char * os_strdup(const char *s) 297 { 298 char *res; 299 size_t len; 300 if (s == NULL) 301 return NULL; 302 len = os_strlen(s); 303 res = os_malloc(len + 1); 304 if (res) 305 os_memcpy(res, s, len + 1); 306 return res; 307 } 308 309 310 size_t os_strlen(const char *s) 311 { 312 const char *p = s; 313 while (*p) 314 p++; 315 return p - s; 316 } 317 318 319 int os_strcasecmp(const char *s1, const char *s2) 320 { 321 /* 322 * Ignoring case is not required for main functionality, so just use 323 * the case sensitive version of the function. 324 */ 325 return os_strcmp(s1, s2); 326 } 327 328 329 int os_strncasecmp(const char *s1, const char *s2, size_t n) 330 { 331 /* 332 * Ignoring case is not required for main functionality, so just use 333 * the case sensitive version of the function. 334 */ 335 return os_strncmp(s1, s2, n); 336 } 337 338 339 char * os_strchr(const char *s, int c) 340 { 341 while (*s) { 342 if (*s == c) 343 return (char *) s; 344 s++; 345 } 346 return NULL; 347 } 348 349 350 char * os_strrchr(const char *s, int c) 351 { 352 const char *p = s; 353 while (*p) 354 p++; 355 p--; 356 while (p >= s) { 357 if (*p == c) 358 return (char *) p; 359 p--; 360 } 361 return NULL; 362 } 363 364 365 int os_strcmp(const char *s1, const char *s2) 366 { 367 while (*s1 == *s2) { 368 if (*s1 == '\0') 369 break; 370 s1++; 371 s2++; 372 } 373 374 return *s1 - *s2; 375 } 376 377 378 int os_strncmp(const char *s1, const char *s2, size_t n) 379 { 380 if (n == 0) 381 return 0; 382 383 while (*s1 == *s2) { 384 if (*s1 == '\0') 385 break; 386 s1++; 387 s2++; 388 n--; 389 if (n == 0) 390 return 0; 391 } 392 393 return *s1 - *s2; 394 } 395 396 397 char * os_strncpy(char *dest, const char *src, size_t n) 398 { 399 char *d = dest; 400 401 while (n--) { 402 *d = *src; 403 if (*src == '\0') 404 break; 405 d++; 406 src++; 407 } 408 409 return dest; 410 } 411 412 413 size_t os_strlcpy(char *dest, const char *src, size_t siz) 414 { 415 const char *s = src; 416 size_t left = siz; 417 418 if (left) { 419 /* Copy string up to the maximum size of the dest buffer */ 420 while (--left != 0) { 421 if ((*dest++ = *s++) == '\0') 422 break; 423 } 424 } 425 426 if (left == 0) { 427 /* Not enough room for the string; force NUL-termination */ 428 if (siz != 0) 429 *dest = '\0'; 430 while (*s++) 431 ; /* determine total src string length */ 432 } 433 434 return s - src - 1; 435 } 436 437 438 char * os_strstr(const char *haystack, const char *needle) 439 { 440 size_t len = os_strlen(needle); 441 while (*haystack) { 442 if (os_strncmp(haystack, needle, len) == 0) 443 return (char *) haystack; 444 haystack++; 445 } 446 447 return NULL; 448 } 449 450 451 int os_snprintf(char *str, size_t size, const char *format, ...) 452 { 453 va_list ap; 454 int ret; 455 456 /* See http://www.ijs.si/software/snprintf/ for portable 457 * implementation of snprintf. 458 */ 459 460 va_start(ap, format); 461 ret = vsnprintf(str, size, format, ap); 462 va_end(ap); 463 if (size > 0) 464 str[size - 1] = '\0'; 465 return ret; 466 } 467