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 30void 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 39int 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 50int 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 73int 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 92void os_daemonize_terminate(const char *pid_file) 93{ 94 if (pid_file) 95 unlink(pid_file); 96} 97 98 99int 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 117unsigned long os_random(void) 118{ 119 return random(); 120} 121 122 123char * 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 162int os_program_init(void) 163{ 164 return 0; 165} 166 167 168void os_program_deinit(void) 169{ 170} 171 172 173int os_setenv(const char *name, const char *value, int overwrite) 174{ 175 return setenv(name, value, overwrite); 176} 177 178 179int 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 190char * 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 if (fread(buf, 1, *len, f) != *len) { 210 fclose(f); 211 os_free(buf); 212 return NULL; 213 } 214 215 fclose(f); 216 217 return buf; 218} 219 220 221void * os_zalloc(size_t size) 222{ 223 void *n = os_malloc(size); 224 if (n) 225 os_memset(n, 0, size); 226 return n; 227} 228 229 230void * os_malloc(size_t size) 231{ 232 return malloc(size); 233} 234 235 236void * os_realloc(void *ptr, size_t size) 237{ 238 return realloc(ptr, size); 239} 240 241 242void os_free(void *ptr) 243{ 244 free(ptr); 245} 246 247 248void * os_memcpy(void *dest, const void *src, size_t n) 249{ 250 char *d = dest; 251 const char *s = src; 252 while (n--) 253 *d++ = *s++; 254 return dest; 255} 256 257 258void * os_memmove(void *dest, const void *src, size_t n) 259{ 260 if (dest < src) 261 os_memcpy(dest, src, n); 262 else { 263 /* overlapping areas */ 264 char *d = (char *) dest + n; 265 const char *s = (const char *) src + n; 266 while (n--) 267 *--d = *--s; 268 } 269 return dest; 270} 271 272 273void * os_memset(void *s, int c, size_t n) 274{ 275 char *p = s; 276 while (n--) 277 *p++ = c; 278 return s; 279} 280 281 282int os_memcmp(const void *s1, const void *s2, size_t n) 283{ 284 const unsigned char *p1 = s1, *p2 = s2; 285 286 if (n == 0) 287 return 0; 288 289 while (*p1 == *p2) { 290 p1++; 291 p2++; 292 n--; 293 if (n == 0) 294 return 0; 295 } 296 297 return *p1 - *p2; 298} 299 300 301char * os_strdup(const char *s) 302{ 303 char *res; 304 size_t len; 305 if (s == NULL) 306 return NULL; 307 len = os_strlen(s); 308 res = os_malloc(len + 1); 309 if (res) 310 os_memcpy(res, s, len + 1); 311 return res; 312} 313 314 315size_t os_strlen(const char *s) 316{ 317 const char *p = s; 318 while (*p) 319 p++; 320 return p - s; 321} 322 323 324int os_strcasecmp(const char *s1, const char *s2) 325{ 326 /* 327 * Ignoring case is not required for main functionality, so just use 328 * the case sensitive version of the function. 329 */ 330 return os_strcmp(s1, s2); 331} 332 333 334int os_strncasecmp(const char *s1, const char *s2, size_t n) 335{ 336 /* 337 * Ignoring case is not required for main functionality, so just use 338 * the case sensitive version of the function. 339 */ 340 return os_strncmp(s1, s2, n); 341} 342 343 344char * os_strchr(const char *s, int c) 345{ 346 while (*s) { 347 if (*s == c) 348 return (char *) s; 349 s++; 350 } 351 return NULL; 352} 353 354 355char * os_strrchr(const char *s, int c) 356{ 357 const char *p = s; 358 while (*p) 359 p++; 360 p--; 361 while (p >= s) { 362 if (*p == c) 363 return (char *) p; 364 p--; 365 } 366 return NULL; 367} 368 369 370int os_strcmp(const char *s1, const char *s2) 371{ 372 while (*s1 == *s2) { 373 if (*s1 == '\0') 374 break; 375 s1++; 376 s2++; 377 } 378 379 return *s1 - *s2; 380} 381 382 383int os_strncmp(const char *s1, const char *s2, size_t n) 384{ 385 if (n == 0) 386 return 0; 387 388 while (*s1 == *s2) { 389 if (*s1 == '\0') 390 break; 391 s1++; 392 s2++; 393 n--; 394 if (n == 0) 395 return 0; 396 } 397 398 return *s1 - *s2; 399} 400 401 402char * os_strncpy(char *dest, const char *src, size_t n) 403{ 404 char *d = dest; 405 406 while (n--) { 407 *d = *src; 408 if (*src == '\0') 409 break; 410 d++; 411 src++; 412 } 413 414 return dest; 415} 416 417 418size_t os_strlcpy(char *dest, const char *src, size_t siz) 419{ 420 const char *s = src; 421 size_t left = siz; 422 423 if (left) { 424 /* Copy string up to the maximum size of the dest buffer */ 425 while (--left != 0) { 426 if ((*dest++ = *s++) == '\0') 427 break; 428 } 429 } 430 431 if (left == 0) { 432 /* Not enough room for the string; force NUL-termination */ 433 if (siz != 0) 434 *dest = '\0'; 435 while (*s++) 436 ; /* determine total src string length */ 437 } 438 439 return s - src - 1; 440} 441 442 443char * os_strstr(const char *haystack, const char *needle) 444{ 445 size_t len = os_strlen(needle); 446 while (*haystack) { 447 if (os_strncmp(haystack, needle, len) == 0) 448 return (char *) haystack; 449 haystack++; 450 } 451 452 return NULL; 453} 454 455 456int os_snprintf(char *str, size_t size, const char *format, ...) 457{ 458 va_list ap; 459 int ret; 460 461 /* See http://www.ijs.si/software/snprintf/ for portable 462 * implementation of snprintf. 463 */ 464 465 va_start(ap, format); 466 ret = vsnprintf(str, size, format, ap); 467 va_end(ap); 468 if (size > 0) 469 str[size - 1] = '\0'; 470 return ret; 471} 472