Home | History | Annotate | Download | only in utils
      1 /*
      2  * OS specific functions for UNIX/POSIX systems
      3  * Copyright (c) 2005-2009, 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 
      9 #include "includes.h"
     10 
     11 #include <time.h>
     12 #include <sys/wait.h>
     13 
     14 #ifdef ANDROID
     15 #include <grp.h>
     16 #include <pwd.h>
     17 #include <sys/capability.h>
     18 #include <sys/prctl.h>
     19 #include <sys/types.h>
     20 #endif /* ANDROID */
     21 
     22 #ifdef __MACH__
     23 #include <CoreServices/CoreServices.h>
     24 #include <mach/mach.h>
     25 #include <mach/mach_time.h>
     26 #endif /* __MACH__ */
     27 
     28 #include "os.h"
     29 #include "common.h"
     30 
     31 #ifdef WPA_TRACE
     32 
     33 #include "wpa_debug.h"
     34 #include "trace.h"
     35 #include "list.h"
     36 
     37 static struct dl_list alloc_list = DL_LIST_HEAD_INIT(alloc_list);
     38 
     39 #define ALLOC_MAGIC 0xa84ef1b2
     40 #define FREED_MAGIC 0x67fd487a
     41 
     42 struct os_alloc_trace {
     43 	unsigned int magic;
     44 	struct dl_list list;
     45 	size_t len;
     46 	WPA_TRACE_INFO
     47 } __attribute__((aligned(16)));
     48 
     49 #endif /* WPA_TRACE */
     50 
     51 
     52 void os_sleep(os_time_t sec, os_time_t usec)
     53 {
     54 	if (sec)
     55 		sleep(sec);
     56 	if (usec)
     57 		usleep(usec);
     58 }
     59 
     60 
     61 int os_get_time(struct os_time *t)
     62 {
     63 	int res;
     64 	struct timeval tv;
     65 	res = gettimeofday(&tv, NULL);
     66 	t->sec = tv.tv_sec;
     67 	t->usec = tv.tv_usec;
     68 	return res;
     69 }
     70 
     71 
     72 int os_get_reltime(struct os_reltime *t)
     73 {
     74 #ifndef __MACH__
     75 #if defined(CLOCK_BOOTTIME)
     76 	static clockid_t clock_id = CLOCK_BOOTTIME;
     77 #elif defined(CLOCK_MONOTONIC)
     78 	static clockid_t clock_id = CLOCK_MONOTONIC;
     79 #else
     80 	static clockid_t clock_id = CLOCK_REALTIME;
     81 #endif
     82 	struct timespec ts;
     83 	int res;
     84 
     85 	if (TEST_FAIL())
     86 		return -1;
     87 
     88 	while (1) {
     89 		res = clock_gettime(clock_id, &ts);
     90 		if (res == 0) {
     91 			t->sec = ts.tv_sec;
     92 			t->usec = ts.tv_nsec / 1000;
     93 			return 0;
     94 		}
     95 		switch (clock_id) {
     96 #ifdef CLOCK_BOOTTIME
     97 		case CLOCK_BOOTTIME:
     98 			clock_id = CLOCK_MONOTONIC;
     99 			break;
    100 #endif
    101 #ifdef CLOCK_MONOTONIC
    102 		case CLOCK_MONOTONIC:
    103 			clock_id = CLOCK_REALTIME;
    104 			break;
    105 #endif
    106 		case CLOCK_REALTIME:
    107 			return -1;
    108 		}
    109 	}
    110 #else /* __MACH__ */
    111 	uint64_t abstime, nano;
    112 	static mach_timebase_info_data_t info = { 0, 0 };
    113 
    114 	if (!info.denom) {
    115 		if (mach_timebase_info(&info) != KERN_SUCCESS)
    116 			return -1;
    117 	}
    118 
    119 	abstime = mach_absolute_time();
    120 	nano = (abstime * info.numer) / info.denom;
    121 
    122 	t->sec = nano / NSEC_PER_SEC;
    123 	t->usec = (nano - (((uint64_t) t->sec) * NSEC_PER_SEC)) / NSEC_PER_USEC;
    124 
    125 	return 0;
    126 #endif /* __MACH__ */
    127 }
    128 
    129 
    130 int os_mktime(int year, int month, int day, int hour, int min, int sec,
    131 	      os_time_t *t)
    132 {
    133 	struct tm tm, *tm1;
    134 	time_t t_local, t1, t2;
    135 	os_time_t tz_offset;
    136 
    137 	if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
    138 	    hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 ||
    139 	    sec > 60)
    140 		return -1;
    141 
    142 	memset(&tm, 0, sizeof(tm));
    143 	tm.tm_year = year - 1900;
    144 	tm.tm_mon = month - 1;
    145 	tm.tm_mday = day;
    146 	tm.tm_hour = hour;
    147 	tm.tm_min = min;
    148 	tm.tm_sec = sec;
    149 
    150 	t_local = mktime(&tm);
    151 
    152 	/* figure out offset to UTC */
    153 	tm1 = localtime(&t_local);
    154 	if (tm1) {
    155 		t1 = mktime(tm1);
    156 		tm1 = gmtime(&t_local);
    157 		if (tm1) {
    158 			t2 = mktime(tm1);
    159 			tz_offset = t2 - t1;
    160 		} else
    161 			tz_offset = 0;
    162 	} else
    163 		tz_offset = 0;
    164 
    165 	*t = (os_time_t) t_local - tz_offset;
    166 	return 0;
    167 }
    168 
    169 
    170 int os_gmtime(os_time_t t, struct os_tm *tm)
    171 {
    172 	struct tm *tm2;
    173 	time_t t2 = t;
    174 
    175 	tm2 = gmtime(&t2);
    176 	if (tm2 == NULL)
    177 		return -1;
    178 	tm->sec = tm2->tm_sec;
    179 	tm->min = tm2->tm_min;
    180 	tm->hour = tm2->tm_hour;
    181 	tm->day = tm2->tm_mday;
    182 	tm->month = tm2->tm_mon + 1;
    183 	tm->year = tm2->tm_year + 1900;
    184 	return 0;
    185 }
    186 
    187 
    188 #ifdef __APPLE__
    189 #include <fcntl.h>
    190 static int os_daemon(int nochdir, int noclose)
    191 {
    192 	int devnull;
    193 
    194 	if (chdir("/") < 0)
    195 		return -1;
    196 
    197 	devnull = open("/dev/null", O_RDWR);
    198 	if (devnull < 0)
    199 		return -1;
    200 
    201 	if (dup2(devnull, STDIN_FILENO) < 0) {
    202 		close(devnull);
    203 		return -1;
    204 	}
    205 
    206 	if (dup2(devnull, STDOUT_FILENO) < 0) {
    207 		close(devnull);
    208 		return -1;
    209 	}
    210 
    211 	if (dup2(devnull, STDERR_FILENO) < 0) {
    212 		close(devnull);
    213 		return -1;
    214 	}
    215 
    216 	return 0;
    217 }
    218 #else /* __APPLE__ */
    219 #define os_daemon daemon
    220 #endif /* __APPLE__ */
    221 
    222 
    223 int os_daemonize(const char *pid_file)
    224 {
    225 #if defined(__uClinux__) || defined(__sun__)
    226 	return -1;
    227 #else /* defined(__uClinux__) || defined(__sun__) */
    228 	if (os_daemon(0, 0)) {
    229 		perror("daemon");
    230 		return -1;
    231 	}
    232 
    233 	if (pid_file) {
    234 		FILE *f = fopen(pid_file, "w");
    235 		if (f) {
    236 			fprintf(f, "%u\n", getpid());
    237 			fclose(f);
    238 		}
    239 	}
    240 
    241 	return -0;
    242 #endif /* defined(__uClinux__) || defined(__sun__) */
    243 }
    244 
    245 
    246 void os_daemonize_terminate(const char *pid_file)
    247 {
    248 	if (pid_file)
    249 		unlink(pid_file);
    250 }
    251 
    252 
    253 int os_get_random(unsigned char *buf, size_t len)
    254 {
    255 	FILE *f;
    256 	size_t rc;
    257 
    258 	if (TEST_FAIL())
    259 		return -1;
    260 
    261 	f = fopen("/dev/urandom", "rb");
    262 	if (f == NULL) {
    263 		printf("Could not open /dev/urandom.\n");
    264 		return -1;
    265 	}
    266 
    267 	rc = fread(buf, 1, len, f);
    268 	fclose(f);
    269 
    270 	return rc != len ? -1 : 0;
    271 }
    272 
    273 
    274 unsigned long os_random(void)
    275 {
    276 	return random();
    277 }
    278 
    279 
    280 char * os_rel2abs_path(const char *rel_path)
    281 {
    282 	char *buf = NULL, *cwd, *ret;
    283 	size_t len = 128, cwd_len, rel_len, ret_len;
    284 	int last_errno;
    285 
    286 	if (!rel_path)
    287 		return NULL;
    288 
    289 	if (rel_path[0] == '/')
    290 		return os_strdup(rel_path);
    291 
    292 	for (;;) {
    293 		buf = os_malloc(len);
    294 		if (buf == NULL)
    295 			return NULL;
    296 		cwd = getcwd(buf, len);
    297 		if (cwd == NULL) {
    298 			last_errno = errno;
    299 			os_free(buf);
    300 			if (last_errno != ERANGE)
    301 				return NULL;
    302 			len *= 2;
    303 			if (len > 2000)
    304 				return NULL;
    305 		} else {
    306 			buf[len - 1] = '\0';
    307 			break;
    308 		}
    309 	}
    310 
    311 	cwd_len = os_strlen(cwd);
    312 	rel_len = os_strlen(rel_path);
    313 	ret_len = cwd_len + 1 + rel_len + 1;
    314 	ret = os_malloc(ret_len);
    315 	if (ret) {
    316 		os_memcpy(ret, cwd, cwd_len);
    317 		ret[cwd_len] = '/';
    318 		os_memcpy(ret + cwd_len + 1, rel_path, rel_len);
    319 		ret[ret_len - 1] = '\0';
    320 	}
    321 	os_free(buf);
    322 	return ret;
    323 }
    324 
    325 
    326 int os_program_init(void)
    327 {
    328 #ifdef ANDROID
    329 	struct __user_cap_header_struct header;
    330 	struct __user_cap_data_struct cap;
    331 	struct group *grp = getgrnam("wifi");
    332 	gid_t gid_wifi = grp ? grp->gr_gid : 0;
    333 	struct passwd *pwd = getpwnam("wifi");
    334 	uid_t uid_wifi = pwd ? pwd->pw_uid : 0;
    335 
    336 	/*
    337 	 * We ignore errors here since errors are normal if we
    338 	 * are already running as non-root.
    339 	 */
    340 #ifdef ANDROID_SETGROUPS_OVERRIDE
    341 	gid_t groups[] = { ANDROID_SETGROUPS_OVERRIDE };
    342 
    343 	if (!gid_wifi || !uid_wifi) return -1;
    344 	setgroups(ARRAY_SIZE(groups), groups);
    345 #else /* ANDROID_SETGROUPS_OVERRIDE */
    346 	gid_t groups[4];
    347 	int group_idx = 0;
    348 
    349 	if (!gid_wifi || !uid_wifi) return -1;
    350 	groups[group_idx] = gid_wifi;
    351 
    352 	grp = getgrnam("inet");
    353 	groups[++group_idx] = grp ? grp->gr_gid : 0;
    354 	if (!groups[group_idx]) return -1;
    355 
    356 	grp = getgrnam("keystore");
    357 	groups[++group_idx] = grp ? grp->gr_gid : 0;
    358 	if (!groups[group_idx]) return -1;
    359 
    360 	grp = getgrnam("log");
    361 	groups[++group_idx] = grp ? grp->gr_gid : 0;
    362 	if (!groups[group_idx]) group_idx--;
    363 
    364 	setgroups(group_idx + 1, groups);
    365 #endif /* ANDROID_SETGROUPS_OVERRIDE */
    366 
    367 	prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
    368 
    369 	setgid(gid_wifi);
    370 	setuid(uid_wifi);
    371 
    372 	header.version = _LINUX_CAPABILITY_VERSION;
    373 	header.pid = 0;
    374 	cap.effective = cap.permitted =
    375 		(1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
    376 	cap.inheritable = 0;
    377 	capset(&header, &cap);
    378 #endif /* ANDROID */
    379 
    380 	return 0;
    381 }
    382 
    383 
    384 void os_program_deinit(void)
    385 {
    386 #ifdef WPA_TRACE
    387 	struct os_alloc_trace *a;
    388 	unsigned long total = 0;
    389 	dl_list_for_each(a, &alloc_list, struct os_alloc_trace, list) {
    390 		total += a->len;
    391 		if (a->magic != ALLOC_MAGIC) {
    392 			wpa_printf(MSG_INFO, "MEMLEAK[%p]: invalid magic 0x%x "
    393 				   "len %lu",
    394 				   a, a->magic, (unsigned long) a->len);
    395 			continue;
    396 		}
    397 		wpa_printf(MSG_INFO, "MEMLEAK[%p]: len %lu",
    398 			   a, (unsigned long) a->len);
    399 		wpa_trace_dump("memleak", a);
    400 	}
    401 	if (total)
    402 		wpa_printf(MSG_INFO, "MEMLEAK: total %lu bytes",
    403 			   (unsigned long) total);
    404 	wpa_trace_deinit();
    405 #endif /* WPA_TRACE */
    406 }
    407 
    408 
    409 int os_setenv(const char *name, const char *value, int overwrite)
    410 {
    411 	return setenv(name, value, overwrite);
    412 }
    413 
    414 
    415 int os_unsetenv(const char *name)
    416 {
    417 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || \
    418     defined(__OpenBSD__)
    419 	unsetenv(name);
    420 	return 0;
    421 #else
    422 	return unsetenv(name);
    423 #endif
    424 }
    425 
    426 
    427 char * os_readfile(const char *name, size_t *len)
    428 {
    429 	FILE *f;
    430 	char *buf;
    431 	long pos;
    432 
    433 	f = fopen(name, "rb");
    434 	if (f == NULL)
    435 		return NULL;
    436 
    437 	if (fseek(f, 0, SEEK_END) < 0 || (pos = ftell(f)) < 0) {
    438 		fclose(f);
    439 		return NULL;
    440 	}
    441 	*len = pos;
    442 	if (fseek(f, 0, SEEK_SET) < 0) {
    443 		fclose(f);
    444 		return NULL;
    445 	}
    446 
    447 	buf = os_malloc(*len);
    448 	if (buf == NULL) {
    449 		fclose(f);
    450 		return NULL;
    451 	}
    452 
    453 	if (fread(buf, 1, *len, f) != *len) {
    454 		fclose(f);
    455 		os_free(buf);
    456 		return NULL;
    457 	}
    458 
    459 	fclose(f);
    460 
    461 	return buf;
    462 }
    463 
    464 
    465 int os_file_exists(const char *fname)
    466 {
    467 	return access(fname, F_OK) == 0;
    468 }
    469 
    470 
    471 int os_fdatasync(FILE *stream)
    472 {
    473 	if (!fflush(stream)) {
    474 #ifdef __linux__
    475 		return fdatasync(fileno(stream));
    476 #else /* !__linux__ */
    477 #ifdef F_FULLFSYNC
    478 		/* OS X does not implement fdatasync(). */
    479 		return fcntl(fileno(stream), F_FULLFSYNC);
    480 #else /* F_FULLFSYNC */
    481 		return fsync(fileno(stream));
    482 #endif /* F_FULLFSYNC */
    483 #endif /* __linux__ */
    484 	}
    485 
    486 	return -1;
    487 }
    488 
    489 
    490 #ifndef WPA_TRACE
    491 void * os_zalloc(size_t size)
    492 {
    493 	return calloc(1, size);
    494 }
    495 #endif /* WPA_TRACE */
    496 
    497 
    498 size_t os_strlcpy(char *dest, const char *src, size_t siz)
    499 {
    500 	const char *s = src;
    501 	size_t left = siz;
    502 
    503 	if (left) {
    504 		/* Copy string up to the maximum size of the dest buffer */
    505 		while (--left != 0) {
    506 			if ((*dest++ = *s++) == '\0')
    507 				break;
    508 		}
    509 	}
    510 
    511 	if (left == 0) {
    512 		/* Not enough room for the string; force NUL-termination */
    513 		if (siz != 0)
    514 			*dest = '\0';
    515 		while (*s++)
    516 			; /* determine total src string length */
    517 	}
    518 
    519 	return s - src - 1;
    520 }
    521 
    522 
    523 int os_memcmp_const(const void *a, const void *b, size_t len)
    524 {
    525 	const u8 *aa = a;
    526 	const u8 *bb = b;
    527 	size_t i;
    528 	u8 res;
    529 
    530 	for (res = 0, i = 0; i < len; i++)
    531 		res |= aa[i] ^ bb[i];
    532 
    533 	return res;
    534 }
    535 
    536 
    537 void * os_memdup(const void *src, size_t len)
    538 {
    539 	void *r = os_malloc(len);
    540 
    541 	if (r)
    542 		os_memcpy(r, src, len);
    543 	return r;
    544 }
    545 
    546 
    547 #ifdef WPA_TRACE
    548 
    549 #if defined(WPA_TRACE_BFD) && defined(CONFIG_TESTING_OPTIONS)
    550 char wpa_trace_fail_func[256] = { 0 };
    551 unsigned int wpa_trace_fail_after;
    552 
    553 static int testing_fail_alloc(void)
    554 {
    555 	const char *func[WPA_TRACE_LEN];
    556 	size_t i, res, len;
    557 	char *pos, *next;
    558 	int match;
    559 
    560 	if (!wpa_trace_fail_after)
    561 		return 0;
    562 
    563 	res = wpa_trace_calling_func(func, WPA_TRACE_LEN);
    564 	i = 0;
    565 	if (i < res && os_strcmp(func[i], __func__) == 0)
    566 		i++;
    567 	if (i < res && os_strcmp(func[i], "os_malloc") == 0)
    568 		i++;
    569 	if (i < res && os_strcmp(func[i], "os_zalloc") == 0)
    570 		i++;
    571 	if (i < res && os_strcmp(func[i], "os_calloc") == 0)
    572 		i++;
    573 	if (i < res && os_strcmp(func[i], "os_realloc") == 0)
    574 		i++;
    575 	if (i < res && os_strcmp(func[i], "os_realloc_array") == 0)
    576 		i++;
    577 	if (i < res && os_strcmp(func[i], "os_strdup") == 0)
    578 		i++;
    579 	if (i < res && os_strcmp(func[i], "os_memdup") == 0)
    580 		i++;
    581 
    582 	pos = wpa_trace_fail_func;
    583 
    584 	match = 0;
    585 	while (i < res) {
    586 		int allow_skip = 1;
    587 		int maybe = 0;
    588 
    589 		if (*pos == '=') {
    590 			allow_skip = 0;
    591 			pos++;
    592 		} else if (*pos == '?') {
    593 			maybe = 1;
    594 			pos++;
    595 		}
    596 		next = os_strchr(pos, ';');
    597 		if (next)
    598 			len = next - pos;
    599 		else
    600 			len = os_strlen(pos);
    601 		if (os_memcmp(pos, func[i], len) != 0) {
    602 			if (maybe && next) {
    603 				pos = next + 1;
    604 				continue;
    605 			}
    606 			if (allow_skip) {
    607 				i++;
    608 				continue;
    609 			}
    610 			return 0;
    611 		}
    612 		if (!next) {
    613 			match = 1;
    614 			break;
    615 		}
    616 		pos = next + 1;
    617 		i++;
    618 	}
    619 	if (!match)
    620 		return 0;
    621 
    622 	wpa_trace_fail_after--;
    623 	if (wpa_trace_fail_after == 0) {
    624 		wpa_printf(MSG_INFO, "TESTING: fail allocation at %s",
    625 			   wpa_trace_fail_func);
    626 		for (i = 0; i < res; i++)
    627 			wpa_printf(MSG_INFO, "backtrace[%d] = %s",
    628 				   (int) i, func[i]);
    629 		return 1;
    630 	}
    631 
    632 	return 0;
    633 }
    634 
    635 
    636 char wpa_trace_test_fail_func[256] = { 0 };
    637 unsigned int wpa_trace_test_fail_after;
    638 
    639 int testing_test_fail(void)
    640 {
    641 	const char *func[WPA_TRACE_LEN];
    642 	size_t i, res, len;
    643 	char *pos, *next;
    644 	int match;
    645 
    646 	if (!wpa_trace_test_fail_after)
    647 		return 0;
    648 
    649 	res = wpa_trace_calling_func(func, WPA_TRACE_LEN);
    650 	i = 0;
    651 	if (i < res && os_strcmp(func[i], __func__) == 0)
    652 		i++;
    653 
    654 	pos = wpa_trace_test_fail_func;
    655 
    656 	match = 0;
    657 	while (i < res) {
    658 		int allow_skip = 1;
    659 		int maybe = 0;
    660 
    661 		if (*pos == '=') {
    662 			allow_skip = 0;
    663 			pos++;
    664 		} else if (*pos == '?') {
    665 			maybe = 1;
    666 			pos++;
    667 		}
    668 		next = os_strchr(pos, ';');
    669 		if (next)
    670 			len = next - pos;
    671 		else
    672 			len = os_strlen(pos);
    673 		if (os_memcmp(pos, func[i], len) != 0) {
    674 			if (maybe && next) {
    675 				pos = next + 1;
    676 				continue;
    677 			}
    678 			if (allow_skip) {
    679 				i++;
    680 				continue;
    681 			}
    682 			return 0;
    683 		}
    684 		if (!next) {
    685 			match = 1;
    686 			break;
    687 		}
    688 		pos = next + 1;
    689 		i++;
    690 	}
    691 	if (!match)
    692 		return 0;
    693 
    694 	wpa_trace_test_fail_after--;
    695 	if (wpa_trace_test_fail_after == 0) {
    696 		wpa_printf(MSG_INFO, "TESTING: fail at %s",
    697 			   wpa_trace_test_fail_func);
    698 		for (i = 0; i < res; i++)
    699 			wpa_printf(MSG_INFO, "backtrace[%d] = %s",
    700 				   (int) i, func[i]);
    701 		return 1;
    702 	}
    703 
    704 	return 0;
    705 }
    706 
    707 #else
    708 
    709 static inline int testing_fail_alloc(void)
    710 {
    711 	return 0;
    712 }
    713 #endif
    714 
    715 void * os_malloc(size_t size)
    716 {
    717 	struct os_alloc_trace *a;
    718 
    719 	if (testing_fail_alloc())
    720 		return NULL;
    721 
    722 	a = malloc(sizeof(*a) + size);
    723 	if (a == NULL)
    724 		return NULL;
    725 	a->magic = ALLOC_MAGIC;
    726 	dl_list_add(&alloc_list, &a->list);
    727 	a->len = size;
    728 	wpa_trace_record(a);
    729 	return a + 1;
    730 }
    731 
    732 
    733 void * os_realloc(void *ptr, size_t size)
    734 {
    735 	struct os_alloc_trace *a;
    736 	size_t copy_len;
    737 	void *n;
    738 
    739 	if (ptr == NULL)
    740 		return os_malloc(size);
    741 
    742 	a = (struct os_alloc_trace *) ptr - 1;
    743 	if (a->magic != ALLOC_MAGIC) {
    744 		wpa_printf(MSG_INFO, "REALLOC[%p]: invalid magic 0x%x%s",
    745 			   a, a->magic,
    746 			   a->magic == FREED_MAGIC ? " (already freed)" : "");
    747 		wpa_trace_show("Invalid os_realloc() call");
    748 		abort();
    749 	}
    750 	n = os_malloc(size);
    751 	if (n == NULL)
    752 		return NULL;
    753 	copy_len = a->len;
    754 	if (copy_len > size)
    755 		copy_len = size;
    756 	os_memcpy(n, a + 1, copy_len);
    757 	os_free(ptr);
    758 	return n;
    759 }
    760 
    761 
    762 void os_free(void *ptr)
    763 {
    764 	struct os_alloc_trace *a;
    765 
    766 	if (ptr == NULL)
    767 		return;
    768 	a = (struct os_alloc_trace *) ptr - 1;
    769 	if (a->magic != ALLOC_MAGIC) {
    770 		wpa_printf(MSG_INFO, "FREE[%p]: invalid magic 0x%x%s",
    771 			   a, a->magic,
    772 			   a->magic == FREED_MAGIC ? " (already freed)" : "");
    773 		wpa_trace_show("Invalid os_free() call");
    774 		abort();
    775 	}
    776 	dl_list_del(&a->list);
    777 	a->magic = FREED_MAGIC;
    778 
    779 	wpa_trace_check_ref(ptr);
    780 	free(a);
    781 }
    782 
    783 
    784 void * os_zalloc(size_t size)
    785 {
    786 	void *ptr = os_malloc(size);
    787 	if (ptr)
    788 		os_memset(ptr, 0, size);
    789 	return ptr;
    790 }
    791 
    792 
    793 char * os_strdup(const char *s)
    794 {
    795 	size_t len;
    796 	char *d;
    797 	len = os_strlen(s);
    798 	d = os_malloc(len + 1);
    799 	if (d == NULL)
    800 		return NULL;
    801 	os_memcpy(d, s, len);
    802 	d[len] = '\0';
    803 	return d;
    804 }
    805 
    806 #endif /* WPA_TRACE */
    807 
    808 
    809 int os_exec(const char *program, const char *arg, int wait_completion)
    810 {
    811 	pid_t pid;
    812 	int pid_status;
    813 
    814 	pid = fork();
    815 	if (pid < 0) {
    816 		perror("fork");
    817 		return -1;
    818 	}
    819 
    820 	if (pid == 0) {
    821 		/* run the external command in the child process */
    822 		const int MAX_ARG = 30;
    823 		char *_program, *_arg, *pos;
    824 		char *argv[MAX_ARG + 1];
    825 		int i;
    826 
    827 		_program = os_strdup(program);
    828 		_arg = os_strdup(arg);
    829 
    830 		argv[0] = _program;
    831 
    832 		i = 1;
    833 		pos = _arg;
    834 		while (i < MAX_ARG && pos && *pos) {
    835 			while (*pos == ' ')
    836 				pos++;
    837 			if (*pos == '\0')
    838 				break;
    839 			argv[i++] = pos;
    840 			pos = os_strchr(pos, ' ');
    841 			if (pos)
    842 				*pos++ = '\0';
    843 		}
    844 		argv[i] = NULL;
    845 
    846 		execv(program, argv);
    847 		perror("execv");
    848 		os_free(_program);
    849 		os_free(_arg);
    850 		exit(0);
    851 		return -1;
    852 	}
    853 
    854 	if (wait_completion) {
    855 		/* wait for the child process to complete in the parent */
    856 		waitpid(pid, &pid_status, 0);
    857 	}
    858 
    859 	return 0;
    860 }
    861