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 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 221 void * 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 230 void * os_malloc(size_t size) 231 { 232 return malloc(size); 233 } 234 235 236 void * os_realloc(void *ptr, size_t size) 237 { 238 return realloc(ptr, size); 239 } 240 241 242 void os_free(void *ptr) 243 { 244 free(ptr); 245 } 246 247 248 void * 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 258 void * 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 273 void * 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 282 int 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 301 char * 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 315 size_t os_strlen(const char *s) 316 { 317 const char *p = s; 318 while (*p) 319 p++; 320 return p - s; 321 } 322 323 324 int 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 334 int 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 344 char * 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 355 char * 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 370 int 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 383 int 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 402 char * 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 418 size_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 443 char * 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 456 int 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