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