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