1189251Ssam/* 2189251Ssam * wpa_supplicant/hostapd / Internal implementation of OS specific functions 3189251Ssam * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> 4189251Ssam * 5189251Ssam * This program is free software; you can redistribute it and/or modify 6189251Ssam * it under the terms of the GNU General Public License version 2 as 7189251Ssam * published by the Free Software Foundation. 8189251Ssam * 9189251Ssam * Alternatively, this software may be distributed under the terms of BSD 10189251Ssam * license. 11189251Ssam * 12189251Ssam * See README and COPYING for more details. 13189251Ssam * 14189251Ssam * This file is an example of operating system specific wrapper functions. 15189251Ssam * This version implements many of the functions internally, so it can be used 16189251Ssam * to fill in missing functions from the target system C libraries. 17189251Ssam * 18189251Ssam * Some of the functions are using standard C library calls in order to keep 19189251Ssam * this file in working condition to allow the functions to be tested on a 20189251Ssam * Linux target. Please note that OS_NO_C_LIB_DEFINES needs to be defined for 21189251Ssam * this file to work correctly. Note that these implementations are only 22189251Ssam * examples and are not optimized for speed. 23189251Ssam */ 24189251Ssam 25189251Ssam#include "includes.h" 26189251Ssam 27189251Ssam#undef OS_REJECT_C_LIB_FUNCTIONS 28189251Ssam#include "os.h" 29189251Ssam 30189251Ssamvoid os_sleep(os_time_t sec, os_time_t usec) 31189251Ssam{ 32189251Ssam if (sec) 33189251Ssam sleep(sec); 34189251Ssam if (usec) 35189251Ssam usleep(usec); 36189251Ssam} 37189251Ssam 38189251Ssam 39189251Ssamint os_get_time(struct os_time *t) 40189251Ssam{ 41189251Ssam int res; 42189251Ssam struct timeval tv; 43189251Ssam res = gettimeofday(&tv, NULL); 44189251Ssam t->sec = tv.tv_sec; 45189251Ssam t->usec = tv.tv_usec; 46189251Ssam return res; 47189251Ssam} 48189251Ssam 49189251Ssam 50189251Ssamint os_mktime(int year, int month, int day, int hour, int min, int sec, 51189251Ssam os_time_t *t) 52189251Ssam{ 53189251Ssam struct tm tm; 54189251Ssam 55189251Ssam if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 || 56189251Ssam hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || 57189251Ssam sec > 60) 58189251Ssam return -1; 59189251Ssam 60189251Ssam os_memset(&tm, 0, sizeof(tm)); 61189251Ssam tm.tm_year = year - 1900; 62189251Ssam tm.tm_mon = month - 1; 63189251Ssam tm.tm_mday = day; 64189251Ssam tm.tm_hour = hour; 65189251Ssam tm.tm_min = min; 66189251Ssam tm.tm_sec = sec; 67189251Ssam 68189251Ssam *t = (os_time_t) mktime(&tm); 69189251Ssam return 0; 70189251Ssam} 71189251Ssam 72189251Ssam 73189251Ssamint os_daemonize(const char *pid_file) 74189251Ssam{ 75189251Ssam if (daemon(0, 0)) { 76189251Ssam perror("daemon"); 77189251Ssam return -1; 78189251Ssam } 79189251Ssam 80189251Ssam if (pid_file) { 81189251Ssam FILE *f = fopen(pid_file, "w"); 82189251Ssam if (f) { 83189251Ssam fprintf(f, "%u\n", getpid()); 84189251Ssam fclose(f); 85189251Ssam } 86189251Ssam } 87189251Ssam 88189251Ssam return -0; 89189251Ssam} 90189251Ssam 91189251Ssam 92189251Ssamvoid os_daemonize_terminate(const char *pid_file) 93189251Ssam{ 94189251Ssam if (pid_file) 95189251Ssam unlink(pid_file); 96189251Ssam} 97189251Ssam 98189251Ssam 99189251Ssamint os_get_random(unsigned char *buf, size_t len) 100189251Ssam{ 101189251Ssam FILE *f; 102189251Ssam size_t rc; 103189251Ssam 104189251Ssam f = fopen("/dev/urandom", "rb"); 105189251Ssam if (f == NULL) { 106189251Ssam printf("Could not open /dev/urandom.\n"); 107189251Ssam return -1; 108189251Ssam } 109189251Ssam 110189251Ssam rc = fread(buf, 1, len, f); 111189251Ssam fclose(f); 112189251Ssam 113189251Ssam return rc != len ? -1 : 0; 114189251Ssam} 115189251Ssam 116189251Ssam 117189251Ssamunsigned long os_random(void) 118189251Ssam{ 119189251Ssam return random(); 120189251Ssam} 121189251Ssam 122189251Ssam 123189251Ssamchar * os_rel2abs_path(const char *rel_path) 124189251Ssam{ 125189251Ssam char *buf = NULL, *cwd, *ret; 126189251Ssam size_t len = 128, cwd_len, rel_len, ret_len; 127189251Ssam 128189251Ssam if (rel_path[0] == '/') 129189251Ssam return os_strdup(rel_path); 130189251Ssam 131189251Ssam for (;;) { 132189251Ssam buf = os_malloc(len); 133189251Ssam if (buf == NULL) 134189251Ssam return NULL; 135189251Ssam cwd = getcwd(buf, len); 136189251Ssam if (cwd == NULL) { 137189251Ssam os_free(buf); 138189251Ssam if (errno != ERANGE) { 139189251Ssam return NULL; 140189251Ssam } 141189251Ssam len *= 2; 142189251Ssam } else { 143189251Ssam break; 144189251Ssam } 145189251Ssam } 146189251Ssam 147189251Ssam cwd_len = strlen(cwd); 148189251Ssam rel_len = strlen(rel_path); 149189251Ssam ret_len = cwd_len + 1 + rel_len + 1; 150189251Ssam ret = os_malloc(ret_len); 151189251Ssam if (ret) { 152189251Ssam os_memcpy(ret, cwd, cwd_len); 153189251Ssam ret[cwd_len] = '/'; 154189251Ssam os_memcpy(ret + cwd_len + 1, rel_path, rel_len); 155189251Ssam ret[ret_len - 1] = '\0'; 156189251Ssam } 157189251Ssam os_free(buf); 158189251Ssam return ret; 159189251Ssam} 160189251Ssam 161189251Ssam 162189251Ssamint os_program_init(void) 163189251Ssam{ 164189251Ssam return 0; 165189251Ssam} 166189251Ssam 167189251Ssam 168189251Ssamvoid os_program_deinit(void) 169189251Ssam{ 170189251Ssam} 171189251Ssam 172189251Ssam 173189251Ssamint os_setenv(const char *name, const char *value, int overwrite) 174189251Ssam{ 175189251Ssam return setenv(name, value, overwrite); 176189251Ssam} 177189251Ssam 178189251Ssam 179189251Ssamint os_unsetenv(const char *name) 180189251Ssam{ 181189251Ssam#if defined(__FreeBSD__) || defined(__NetBSD__) 182189251Ssam unsetenv(name); 183189251Ssam return 0; 184189251Ssam#else 185189251Ssam return unsetenv(name); 186189251Ssam#endif 187189251Ssam} 188189251Ssam 189189251Ssam 190189251Ssamchar * os_readfile(const char *name, size_t *len) 191189251Ssam{ 192189251Ssam FILE *f; 193189251Ssam char *buf; 194189251Ssam 195189251Ssam f = fopen(name, "rb"); 196189251Ssam if (f == NULL) 197189251Ssam return NULL; 198189251Ssam 199189251Ssam fseek(f, 0, SEEK_END); 200189251Ssam *len = ftell(f); 201189251Ssam fseek(f, 0, SEEK_SET); 202189251Ssam 203189251Ssam buf = os_malloc(*len); 204189251Ssam if (buf == NULL) { 205189251Ssam fclose(f); 206189251Ssam return NULL; 207189251Ssam } 208189251Ssam 209214734Srpaulo if (fread(buf, 1, *len, f) != *len) { 210214734Srpaulo fclose(f); 211214734Srpaulo os_free(buf); 212214734Srpaulo return NULL; 213214734Srpaulo } 214214734Srpaulo 215189251Ssam fclose(f); 216189251Ssam 217189251Ssam return buf; 218189251Ssam} 219189251Ssam 220189251Ssam 221189251Ssamvoid * os_zalloc(size_t size) 222189251Ssam{ 223189251Ssam void *n = os_malloc(size); 224189251Ssam if (n) 225189251Ssam os_memset(n, 0, size); 226189251Ssam return n; 227189251Ssam} 228189251Ssam 229189251Ssam 230189251Ssamvoid * os_malloc(size_t size) 231189251Ssam{ 232189251Ssam return malloc(size); 233189251Ssam} 234189251Ssam 235189251Ssam 236189251Ssamvoid * os_realloc(void *ptr, size_t size) 237189251Ssam{ 238189251Ssam return realloc(ptr, size); 239189251Ssam} 240189251Ssam 241189251Ssam 242189251Ssamvoid os_free(void *ptr) 243189251Ssam{ 244189251Ssam free(ptr); 245189251Ssam} 246189251Ssam 247189251Ssam 248189251Ssamvoid * os_memcpy(void *dest, const void *src, size_t n) 249189251Ssam{ 250189251Ssam char *d = dest; 251189251Ssam const char *s = src; 252189251Ssam while (n--) 253189251Ssam *d++ = *s++; 254189251Ssam return dest; 255189251Ssam} 256189251Ssam 257189251Ssam 258189251Ssamvoid * os_memmove(void *dest, const void *src, size_t n) 259189251Ssam{ 260189251Ssam if (dest < src) 261189251Ssam os_memcpy(dest, src, n); 262189251Ssam else { 263189251Ssam /* overlapping areas */ 264189251Ssam char *d = (char *) dest + n; 265189251Ssam const char *s = (const char *) src + n; 266189251Ssam while (n--) 267189251Ssam *--d = *--s; 268189251Ssam } 269189251Ssam return dest; 270189251Ssam} 271189251Ssam 272189251Ssam 273189251Ssamvoid * os_memset(void *s, int c, size_t n) 274189251Ssam{ 275189251Ssam char *p = s; 276189251Ssam while (n--) 277189251Ssam *p++ = c; 278189251Ssam return s; 279189251Ssam} 280189251Ssam 281189251Ssam 282189251Ssamint os_memcmp(const void *s1, const void *s2, size_t n) 283189251Ssam{ 284189251Ssam const unsigned char *p1 = s1, *p2 = s2; 285189251Ssam 286189251Ssam if (n == 0) 287189251Ssam return 0; 288189251Ssam 289189251Ssam while (*p1 == *p2) { 290189251Ssam p1++; 291189251Ssam p2++; 292189251Ssam n--; 293189251Ssam if (n == 0) 294189251Ssam return 0; 295189251Ssam } 296189251Ssam 297189251Ssam return *p1 - *p2; 298189251Ssam} 299189251Ssam 300189251Ssam 301189251Ssamchar * os_strdup(const char *s) 302189251Ssam{ 303189251Ssam char *res; 304189251Ssam size_t len; 305189251Ssam if (s == NULL) 306189251Ssam return NULL; 307189251Ssam len = os_strlen(s); 308189251Ssam res = os_malloc(len + 1); 309189251Ssam if (res) 310189251Ssam os_memcpy(res, s, len + 1); 311189251Ssam return res; 312189251Ssam} 313189251Ssam 314189251Ssam 315189251Ssamsize_t os_strlen(const char *s) 316189251Ssam{ 317189251Ssam const char *p = s; 318189251Ssam while (*p) 319189251Ssam p++; 320189251Ssam return p - s; 321189251Ssam} 322189251Ssam 323189251Ssam 324189251Ssamint os_strcasecmp(const char *s1, const char *s2) 325189251Ssam{ 326189251Ssam /* 327189251Ssam * Ignoring case is not required for main functionality, so just use 328189251Ssam * the case sensitive version of the function. 329189251Ssam */ 330189251Ssam return os_strcmp(s1, s2); 331189251Ssam} 332189251Ssam 333189251Ssam 334189251Ssamint os_strncasecmp(const char *s1, const char *s2, size_t n) 335189251Ssam{ 336189251Ssam /* 337189251Ssam * Ignoring case is not required for main functionality, so just use 338189251Ssam * the case sensitive version of the function. 339189251Ssam */ 340189251Ssam return os_strncmp(s1, s2, n); 341189251Ssam} 342189251Ssam 343189251Ssam 344189251Ssamchar * os_strchr(const char *s, int c) 345189251Ssam{ 346189251Ssam while (*s) { 347189251Ssam if (*s == c) 348189251Ssam return (char *) s; 349189251Ssam s++; 350189251Ssam } 351189251Ssam return NULL; 352189251Ssam} 353189251Ssam 354189251Ssam 355189251Ssamchar * os_strrchr(const char *s, int c) 356189251Ssam{ 357189251Ssam const char *p = s; 358189251Ssam while (*p) 359189251Ssam p++; 360189251Ssam p--; 361189251Ssam while (p >= s) { 362189251Ssam if (*p == c) 363189251Ssam return (char *) p; 364189251Ssam p--; 365189251Ssam } 366189251Ssam return NULL; 367189251Ssam} 368189251Ssam 369189251Ssam 370189251Ssamint os_strcmp(const char *s1, const char *s2) 371189251Ssam{ 372189251Ssam while (*s1 == *s2) { 373189251Ssam if (*s1 == '\0') 374189251Ssam break; 375189251Ssam s1++; 376189251Ssam s2++; 377189251Ssam } 378189251Ssam 379189251Ssam return *s1 - *s2; 380189251Ssam} 381189251Ssam 382189251Ssam 383189251Ssamint os_strncmp(const char *s1, const char *s2, size_t n) 384189251Ssam{ 385189251Ssam if (n == 0) 386189251Ssam return 0; 387189251Ssam 388189251Ssam while (*s1 == *s2) { 389189251Ssam if (*s1 == '\0') 390189251Ssam break; 391189251Ssam s1++; 392189251Ssam s2++; 393189251Ssam n--; 394189251Ssam if (n == 0) 395189251Ssam return 0; 396189251Ssam } 397189251Ssam 398189251Ssam return *s1 - *s2; 399189251Ssam} 400189251Ssam 401189251Ssam 402189251Ssamchar * os_strncpy(char *dest, const char *src, size_t n) 403189251Ssam{ 404189251Ssam char *d = dest; 405189251Ssam 406189251Ssam while (n--) { 407189251Ssam *d = *src; 408189251Ssam if (*src == '\0') 409189251Ssam break; 410189251Ssam d++; 411189251Ssam src++; 412189251Ssam } 413189251Ssam 414189251Ssam return dest; 415189251Ssam} 416189251Ssam 417189251Ssam 418189251Ssamsize_t os_strlcpy(char *dest, const char *src, size_t siz) 419189251Ssam{ 420189251Ssam const char *s = src; 421189251Ssam size_t left = siz; 422189251Ssam 423189251Ssam if (left) { 424189251Ssam /* Copy string up to the maximum size of the dest buffer */ 425189251Ssam while (--left != 0) { 426189251Ssam if ((*dest++ = *s++) == '\0') 427189251Ssam break; 428189251Ssam } 429189251Ssam } 430189251Ssam 431189251Ssam if (left == 0) { 432189251Ssam /* Not enough room for the string; force NUL-termination */ 433189251Ssam if (siz != 0) 434189251Ssam *dest = '\0'; 435189251Ssam while (*s++) 436189251Ssam ; /* determine total src string length */ 437189251Ssam } 438189251Ssam 439189251Ssam return s - src - 1; 440189251Ssam} 441189251Ssam 442189251Ssam 443189251Ssamchar * os_strstr(const char *haystack, const char *needle) 444189251Ssam{ 445189251Ssam size_t len = os_strlen(needle); 446189251Ssam while (*haystack) { 447189251Ssam if (os_strncmp(haystack, needle, len) == 0) 448189251Ssam return (char *) haystack; 449189251Ssam haystack++; 450189251Ssam } 451189251Ssam 452189251Ssam return NULL; 453189251Ssam} 454189251Ssam 455189251Ssam 456189251Ssamint os_snprintf(char *str, size_t size, const char *format, ...) 457189251Ssam{ 458189251Ssam va_list ap; 459189251Ssam int ret; 460189251Ssam 461189251Ssam /* See http://www.ijs.si/software/snprintf/ for portable 462189251Ssam * implementation of snprintf. 463189251Ssam */ 464189251Ssam 465189251Ssam va_start(ap, format); 466189251Ssam ret = vsnprintf(str, size, format, ap); 467189251Ssam va_end(ap); 468189251Ssam if (size > 0) 469189251Ssam str[size - 1] = '\0'; 470189251Ssam return ret; 471189251Ssam} 472