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_gmtime(os_time_t t, struct os_tm *tm) 74 { 75 struct tm *tm2; 76 time_t t2 = t; 77 78 tm2 = gmtime(&t2); 79 if (tm2 == NULL) 80 return -1; 81 tm->sec = tm2->tm_sec; 82 tm->min = tm2->tm_min; 83 tm->hour = tm2->tm_hour; 84 tm->day = tm2->tm_mday; 85 tm->month = tm2->tm_mon + 1; 86 tm->year = tm2->tm_year + 1900; 87 return 0; 88 } 89 90 91 int os_daemonize(const char *pid_file) 92 { 93 if (daemon(0, 0)) { 94 perror("daemon"); 95 return -1; 96 } 97 98 if (pid_file) { 99 FILE *f = fopen(pid_file, "w"); 100 if (f) { 101 fprintf(f, "%u\n", getpid()); 102 fclose(f); 103 } 104 } 105 106 return -0; 107 } 108 109 110 void os_daemonize_terminate(const char *pid_file) 111 { 112 if (pid_file) 113 unlink(pid_file); 114 } 115 116 117 int os_get_random(unsigned char *buf, size_t len) 118 { 119 FILE *f; 120 size_t rc; 121 122 f = fopen("/dev/urandom", "rb"); 123 if (f == NULL) { 124 printf("Could not open /dev/urandom.\n"); 125 return -1; 126 } 127 128 rc = fread(buf, 1, len, f); 129 fclose(f); 130 131 return rc != len ? -1 : 0; 132 } 133 134 135 unsigned long os_random(void) 136 { 137 return random(); 138 } 139 140 141 char * os_rel2abs_path(const char *rel_path) 142 { 143 char *buf = NULL, *cwd, *ret; 144 size_t len = 128, cwd_len, rel_len, ret_len; 145 146 if (rel_path[0] == '/') 147 return os_strdup(rel_path); 148 149 for (;;) { 150 buf = os_malloc(len); 151 if (buf == NULL) 152 return NULL; 153 cwd = getcwd(buf, len); 154 if (cwd == NULL) { 155 os_free(buf); 156 if (errno != ERANGE) { 157 return NULL; 158 } 159 len *= 2; 160 } else { 161 break; 162 } 163 } 164 165 cwd_len = strlen(cwd); 166 rel_len = strlen(rel_path); 167 ret_len = cwd_len + 1 + rel_len + 1; 168 ret = os_malloc(ret_len); 169 if (ret) { 170 os_memcpy(ret, cwd, cwd_len); 171 ret[cwd_len] = '/'; 172 os_memcpy(ret + cwd_len + 1, rel_path, rel_len); 173 ret[ret_len - 1] = '\0'; 174 } 175 os_free(buf); 176 return ret; 177 } 178 179 180 int os_program_init(void) 181 { 182 return 0; 183 } 184 185 186 void os_program_deinit(void) 187 { 188 } 189 190 191 int os_setenv(const char *name, const char *value, int overwrite) 192 { 193 return setenv(name, value, overwrite); 194 } 195 196 197 int os_unsetenv(const char *name) 198 { 199 #if defined(__FreeBSD__) || defined(__NetBSD__) 200 unsetenv(name); 201 return 0; 202 #else 203 return unsetenv(name); 204 #endif 205 } 206 207 208 char * os_readfile(const char *name, size_t *len) 209 { 210 FILE *f; 211 char *buf; 212 213 f = fopen(name, "rb"); 214 if (f == NULL) 215 return NULL; 216 217 fseek(f, 0, SEEK_END); 218 *len = ftell(f); 219 fseek(f, 0, SEEK_SET); 220 221 buf = os_malloc(*len); 222 if (buf == NULL) { 223 fclose(f); 224 return NULL; 225 } 226 227 if (fread(buf, 1, *len, f) != *len) { 228 fclose(f); 229 os_free(buf); 230 return NULL; 231 } 232 233 fclose(f); 234 235 return buf; 236 } 237 238 239 void * os_zalloc(size_t size) 240 { 241 void *n = os_malloc(size); 242 if (n) 243 os_memset(n, 0, size); 244 return n; 245 } 246 247 248 void * os_malloc(size_t size) 249 { 250 return malloc(size); 251 } 252 253 254 void * os_realloc(void *ptr, size_t size) 255 { 256 return realloc(ptr, size); 257 } 258 259 260 void os_free(void *ptr) 261 { 262 free(ptr); 263 } 264 265 266 void * os_memcpy(void *dest, const void *src, size_t n) 267 { 268 char *d = dest; 269 const char *s = src; 270 while (n--) 271 *d++ = *s++; 272 return dest; 273 } 274 275 276 void * os_memmove(void *dest, const void *src, size_t n) 277 { 278 if (dest < src) 279 os_memcpy(dest, src, n); 280 else { 281 /* overlapping areas */ 282 char *d = (char *) dest + n; 283 const char *s = (const char *) src + n; 284 while (n--) 285 *--d = *--s; 286 } 287 return dest; 288 } 289 290 291 void * os_memset(void *s, int c, size_t n) 292 { 293 char *p = s; 294 while (n--) 295 *p++ = c; 296 return s; 297 } 298 299 300 int os_memcmp(const void *s1, const void *s2, size_t n) 301 { 302 const unsigned char *p1 = s1, *p2 = s2; 303 304 if (n == 0) 305 return 0; 306 307 while (*p1 == *p2) { 308 p1++; 309 p2++; 310 n--; 311 if (n == 0) 312 return 0; 313 } 314 315 return *p1 - *p2; 316 } 317 318 319 char * os_strdup(const char *s) 320 { 321 char *res; 322 size_t len; 323 if (s == NULL) 324 return NULL; 325 len = os_strlen(s); 326 res = os_malloc(len + 1); 327 if (res) 328 os_memcpy(res, s, len + 1); 329 return res; 330 } 331 332 333 size_t os_strlen(const char *s) 334 { 335 const char *p = s; 336 while (*p) 337 p++; 338 return p - s; 339 } 340 341 342 int os_strcasecmp(const char *s1, const char *s2) 343 { 344 /* 345 * Ignoring case is not required for main functionality, so just use 346 * the case sensitive version of the function. 347 */ 348 return os_strcmp(s1, s2); 349 } 350 351 352 int os_strncasecmp(const char *s1, const char *s2, size_t n) 353 { 354 /* 355 * Ignoring case is not required for main functionality, so just use 356 * the case sensitive version of the function. 357 */ 358 return os_strncmp(s1, s2, n); 359 } 360 361 362 char * os_strchr(const char *s, int c) 363 { 364 while (*s) { 365 if (*s == c) 366 return (char *) s; 367 s++; 368 } 369 return NULL; 370 } 371 372 373 char * os_strrchr(const char *s, int c) 374 { 375 const char *p = s; 376 while (*p) 377 p++; 378 p--; 379 while (p >= s) { 380 if (*p == c) 381 return (char *) p; 382 p--; 383 } 384 return NULL; 385 } 386 387 388 int os_strcmp(const char *s1, const char *s2) 389 { 390 while (*s1 == *s2) { 391 if (*s1 == '\0') 392 break; 393 s1++; 394 s2++; 395 } 396 397 return *s1 - *s2; 398 } 399 400 401 int os_strncmp(const char *s1, const char *s2, size_t n) 402 { 403 if (n == 0) 404 return 0; 405 406 while (*s1 == *s2) { 407 if (*s1 == '\0') 408 break; 409 s1++; 410 s2++; 411 n--; 412 if (n == 0) 413 return 0; 414 } 415 416 return *s1 - *s2; 417 } 418 419 420 char * os_strncpy(char *dest, const char *src, size_t n) 421 { 422 char *d = dest; 423 424 while (n--) { 425 *d = *src; 426 if (*src == '\0') 427 break; 428 d++; 429 src++; 430 } 431 432 return dest; 433 } 434 435 436 size_t os_strlcpy(char *dest, const char *src, size_t siz) 437 { 438 const char *s = src; 439 size_t left = siz; 440 441 if (left) { 442 /* Copy string up to the maximum size of the dest buffer */ 443 while (--left != 0) { 444 if ((*dest++ = *s++) == '\0') 445 break; 446 } 447 } 448 449 if (left == 0) { 450 /* Not enough room for the string; force NUL-termination */ 451 if (siz != 0) 452 *dest = '\0'; 453 while (*s++) 454 ; /* determine total src string length */ 455 } 456 457 return s - src - 1; 458 } 459 460 461 char * os_strstr(const char *haystack, const char *needle) 462 { 463 size_t len = os_strlen(needle); 464 while (*haystack) { 465 if (os_strncmp(haystack, needle, len) == 0) 466 return (char *) haystack; 467 haystack++; 468 } 469 470 return NULL; 471 } 472 473 474 int os_snprintf(char *str, size_t size, const char *format, ...) 475 { 476 va_list ap; 477 int ret; 478 479 /* See http://www.ijs.si/software/snprintf/ for portable 480 * implementation of snprintf. 481 */ 482 483 va_start(ap, format); 484 ret = vsnprintf(str, size, format, ap); 485 va_end(ap); 486 if (size > 0) 487 str[size - 1] = '\0'; 488 return ret; 489 } 490