Home | History | Annotate | Download | only in utils
      1 /*
      2  * wpa_supplicant/hostapd / Internal implementation of OS specific functions
      3  * Copyright (c) 2005-2006, Jouni Malinen <j (at) 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 int os_fdatasync(FILE *stream)
    247 {
    248 	return 0;
    249 }
    250 
    251 
    252 void * os_zalloc(size_t size)
    253 {
    254 	void *n = os_malloc(size);
    255 	if (n)
    256 		os_memset(n, 0, size);
    257 	return n;
    258 }
    259 
    260 
    261 void * os_malloc(size_t size)
    262 {
    263 	return malloc(size);
    264 }
    265 
    266 
    267 void * os_realloc(void *ptr, size_t size)
    268 {
    269 	return realloc(ptr, size);
    270 }
    271 
    272 
    273 void os_free(void *ptr)
    274 {
    275 	free(ptr);
    276 }
    277 
    278 
    279 void * os_memcpy(void *dest, const void *src, size_t n)
    280 {
    281 	char *d = dest;
    282 	const char *s = src;
    283 	while (n--)
    284 		*d++ = *s++;
    285 	return dest;
    286 }
    287 
    288 
    289 void * os_memmove(void *dest, const void *src, size_t n)
    290 {
    291 	if (dest < src)
    292 		os_memcpy(dest, src, n);
    293 	else {
    294 		/* overlapping areas */
    295 		char *d = (char *) dest + n;
    296 		const char *s = (const char *) src + n;
    297 		while (n--)
    298 			*--d = *--s;
    299 	}
    300 	return dest;
    301 }
    302 
    303 
    304 void * os_memset(void *s, int c, size_t n)
    305 {
    306 	char *p = s;
    307 	while (n--)
    308 		*p++ = c;
    309 	return s;
    310 }
    311 
    312 
    313 int os_memcmp(const void *s1, const void *s2, size_t n)
    314 {
    315 	const unsigned char *p1 = s1, *p2 = s2;
    316 
    317 	if (n == 0)
    318 		return 0;
    319 
    320 	while (*p1 == *p2) {
    321 		p1++;
    322 		p2++;
    323 		n--;
    324 		if (n == 0)
    325 			return 0;
    326 	}
    327 
    328 	return *p1 - *p2;
    329 }
    330 
    331 
    332 char * os_strdup(const char *s)
    333 {
    334 	char *res;
    335 	size_t len;
    336 	if (s == NULL)
    337 		return NULL;
    338 	len = os_strlen(s);
    339 	res = os_malloc(len + 1);
    340 	if (res)
    341 		os_memcpy(res, s, len + 1);
    342 	return res;
    343 }
    344 
    345 
    346 size_t os_strlen(const char *s)
    347 {
    348 	const char *p = s;
    349 	while (*p)
    350 		p++;
    351 	return p - s;
    352 }
    353 
    354 
    355 int os_strcasecmp(const char *s1, const char *s2)
    356 {
    357 	/*
    358 	 * Ignoring case is not required for main functionality, so just use
    359 	 * the case sensitive version of the function.
    360 	 */
    361 	return os_strcmp(s1, s2);
    362 }
    363 
    364 
    365 int os_strncasecmp(const char *s1, const char *s2, size_t n)
    366 {
    367 	/*
    368 	 * Ignoring case is not required for main functionality, so just use
    369 	 * the case sensitive version of the function.
    370 	 */
    371 	return os_strncmp(s1, s2, n);
    372 }
    373 
    374 
    375 char * os_strchr(const char *s, int c)
    376 {
    377 	while (*s) {
    378 		if (*s == c)
    379 			return (char *) s;
    380 		s++;
    381 	}
    382 	return NULL;
    383 }
    384 
    385 
    386 char * os_strrchr(const char *s, int c)
    387 {
    388 	const char *p = s;
    389 	while (*p)
    390 		p++;
    391 	p--;
    392 	while (p >= s) {
    393 		if (*p == c)
    394 			return (char *) p;
    395 		p--;
    396 	}
    397 	return NULL;
    398 }
    399 
    400 
    401 int os_strcmp(const char *s1, const char *s2)
    402 {
    403 	while (*s1 == *s2) {
    404 		if (*s1 == '\0')
    405 			break;
    406 		s1++;
    407 		s2++;
    408 	}
    409 
    410 	return *s1 - *s2;
    411 }
    412 
    413 
    414 int os_strncmp(const char *s1, const char *s2, size_t n)
    415 {
    416 	if (n == 0)
    417 		return 0;
    418 
    419 	while (*s1 == *s2) {
    420 		if (*s1 == '\0')
    421 			break;
    422 		s1++;
    423 		s2++;
    424 		n--;
    425 		if (n == 0)
    426 			return 0;
    427 	}
    428 
    429 	return *s1 - *s2;
    430 }
    431 
    432 
    433 char * os_strncpy(char *dest, const char *src, size_t n)
    434 {
    435 	char *d = dest;
    436 
    437 	while (n--) {
    438 		*d = *src;
    439 		if (*src == '\0')
    440 			break;
    441 		d++;
    442 		src++;
    443 	}
    444 
    445 	return dest;
    446 }
    447 
    448 
    449 size_t os_strlcpy(char *dest, const char *src, size_t siz)
    450 {
    451 	const char *s = src;
    452 	size_t left = siz;
    453 
    454 	if (left) {
    455 		/* Copy string up to the maximum size of the dest buffer */
    456 		while (--left != 0) {
    457 			if ((*dest++ = *s++) == '\0')
    458 				break;
    459 		}
    460 	}
    461 
    462 	if (left == 0) {
    463 		/* Not enough room for the string; force NUL-termination */
    464 		if (siz != 0)
    465 			*dest = '\0';
    466 		while (*s++)
    467 			; /* determine total src string length */
    468 	}
    469 
    470 	return s - src - 1;
    471 }
    472 
    473 
    474 int os_memcmp_const(const void *a, const void *b, size_t len)
    475 {
    476 	const u8 *aa = a;
    477 	const u8 *bb = b;
    478 	size_t i;
    479 	u8 res;
    480 
    481 	for (res = 0, i = 0; i < len; i++)
    482 		res |= aa[i] ^ bb[i];
    483 
    484 	return res;
    485 }
    486 
    487 
    488 char * os_strstr(const char *haystack, const char *needle)
    489 {
    490 	size_t len = os_strlen(needle);
    491 	while (*haystack) {
    492 		if (os_strncmp(haystack, needle, len) == 0)
    493 			return (char *) haystack;
    494 		haystack++;
    495 	}
    496 
    497 	return NULL;
    498 }
    499 
    500 
    501 int os_snprintf(char *str, size_t size, const char *format, ...)
    502 {
    503 	va_list ap;
    504 	int ret;
    505 
    506 	/* See http://www.ijs.si/software/snprintf/ for portable
    507 	 * implementation of snprintf.
    508 	 */
    509 
    510 	va_start(ap, format);
    511 	ret = vsnprintf(str, size, format, ap);
    512 	va_end(ap);
    513 	if (size > 0)
    514 		str[size - 1] = '\0';
    515 	return ret;
    516 }
    517 
    518 
    519 int os_exec(const char *program, const char *arg, int wait_completion)
    520 {
    521 	pid_t pid;
    522 	int pid_status;
    523 
    524 	pid = fork();
    525 	if (pid < 0) {
    526 		wpa_printf(MSG_ERROR, "fork: %s", strerror(errno));
    527 		return -1;
    528 	}
    529 
    530 	if (pid == 0) {
    531 		/* run the external command in the child process */
    532 		const int MAX_ARG = 30;
    533 		char *_program, *_arg, *pos;
    534 		char *argv[MAX_ARG + 1];
    535 		int i;
    536 
    537 		_program = os_strdup(program);
    538 		_arg = os_strdup(arg);
    539 
    540 		argv[0] = _program;
    541 
    542 		i = 1;
    543 		pos = _arg;
    544 		while (i < MAX_ARG && pos && *pos) {
    545 			while (*pos == ' ')
    546 				pos++;
    547 			if (*pos == '\0')
    548 				break;
    549 			argv[i++] = pos;
    550 			pos = os_strchr(pos, ' ');
    551 			if (pos)
    552 				*pos++ = '\0';
    553 		}
    554 		argv[i] = NULL;
    555 
    556 		execv(program, argv);
    557 		wpa_printf(MSG_ERROR, "execv: %s", strerror(errno));
    558 		os_free(_program);
    559 		os_free(_arg);
    560 		exit(0);
    561 		return -1;
    562 	}
    563 
    564 	if (wait_completion) {
    565 		/* wait for the child process to complete in the parent */
    566 		waitpid(pid, &pid_status, 0);
    567 	}
    568 
    569 	return 0;
    570 }
    571