18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * OS specific functions for UNIX/POSIX systems
38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include <time.h>
12772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen#include <sys/wait.h>
131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef ANDROID
15a562b19dfc52d80b60d485c5661f36d9d6b40911Nick Kralevich#include <sys/capability.h>
160f4fce149db4f45a9eb6776186c1858f8083e6f4Elliott Hughes#include <sys/prctl.h>
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <private/android_filesystem_config.h>
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* ANDROID */
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "os.h"
2168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt#include "common.h"
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef WPA_TRACE
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_debug.h"
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "trace.h"
271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "list.h"
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
297f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidtstatic struct dl_list alloc_list = DL_LIST_HEAD_INIT(alloc_list);
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define ALLOC_MAGIC 0xa84ef1b2
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define FREED_MAGIC 0x67fd487a
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct os_alloc_trace {
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int magic;
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct dl_list list;
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_TRACE_INFO
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* WPA_TRACE */
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid os_sleep(os_time_t sec, os_time_t usec)
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sec)
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sleep(sec);
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (usec)
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		usleep(usec);
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint os_get_time(struct os_time *t)
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct timeval tv;
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = gettimeofday(&tv, NULL);
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	t->sec = tv.tv_sec;
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	t->usec = tv.tv_usec;
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
64fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidtint os_get_reltime(struct os_reltime *t)
65fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt{
66fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt#if defined(CLOCK_BOOTTIME)
67fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt	static clockid_t clock_id = CLOCK_BOOTTIME;
68fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt#elif defined(CLOCK_MONOTONIC)
69fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt	static clockid_t clock_id = CLOCK_MONOTONIC;
70fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt#else
71fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt	static clockid_t clock_id = CLOCK_REALTIME;
72fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt#endif
73fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt	struct timespec ts;
74fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt	int res;
75fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt
76fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt	while (1) {
77fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt		res = clock_gettime(clock_id, &ts);
78fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt		if (res == 0) {
79fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt			t->sec = ts.tv_sec;
80fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt			t->usec = ts.tv_nsec / 1000;
81fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt			return 0;
82fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt		}
83fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt		switch (clock_id) {
84fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt#ifdef CLOCK_BOOTTIME
85fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt		case CLOCK_BOOTTIME:
86fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt			clock_id = CLOCK_MONOTONIC;
87fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt			break;
88fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt#endif
89fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt#ifdef CLOCK_MONOTONIC
90fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt		case CLOCK_MONOTONIC:
91fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt			clock_id = CLOCK_REALTIME;
92fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt			break;
93fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt#endif
94fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt		case CLOCK_REALTIME:
95fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt			return -1;
96fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt		}
97fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt	}
98fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt}
99fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt
100fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint os_mktime(int year, int month, int day, int hour, int min, int sec,
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	      os_time_t *t)
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct tm tm, *tm1;
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	time_t t_local, t1, t2;
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_time_t tz_offset;
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 ||
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    sec > 60)
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	memset(&tm, 0, sizeof(tm));
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tm.tm_year = year - 1900;
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tm.tm_mon = month - 1;
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tm.tm_mday = day;
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tm.tm_hour = hour;
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tm.tm_min = min;
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tm.tm_sec = sec;
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	t_local = mktime(&tm);
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* figure out offset to UTC */
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tm1 = localtime(&t_local);
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tm1) {
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		t1 = mktime(tm1);
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tm1 = gmtime(&t_local);
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tm1) {
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			t2 = mktime(tm1);
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tz_offset = t2 - t1;
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tz_offset = 0;
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tz_offset = 0;
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*t = (os_time_t) t_local - tz_offset;
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint os_gmtime(os_time_t t, struct os_tm *tm)
1421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
1431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct tm *tm2;
1441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	time_t t2 = t;
1451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	tm2 = gmtime(&t2);
1471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (tm2 == NULL)
1481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return -1;
1491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	tm->sec = tm2->tm_sec;
1501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	tm->min = tm2->tm_min;
1511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	tm->hour = tm2->tm_hour;
1521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	tm->day = tm2->tm_mday;
1531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	tm->month = tm2->tm_mon + 1;
1541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	tm->year = tm2->tm_year + 1900;
1551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return 0;
1561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
1571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef __APPLE__
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <fcntl.h>
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int os_daemon(int nochdir, int noclose)
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int devnull;
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (chdir("/") < 0)
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	devnull = open("/dev/null", O_RDWR);
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (devnull < 0)
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dup2(devnull, STDIN_FILENO) < 0) {
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		close(devnull);
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dup2(devnull, STDOUT_FILENO) < 0) {
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		close(devnull);
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dup2(devnull, STDERR_FILENO) < 0) {
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		close(devnull);
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* __APPLE__ */
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define os_daemon daemon
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* __APPLE__ */
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint os_daemonize(const char *pid_file)
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if defined(__uClinux__) || defined(__sun__)
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* defined(__uClinux__) || defined(__sun__) */
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_daemon(0, 0)) {
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		perror("daemon");
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pid_file) {
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		FILE *f = fopen(pid_file, "w");
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (f) {
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			fprintf(f, "%u\n", getpid());
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			fclose(f);
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -0;
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* defined(__uClinux__) || defined(__sun__) */
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid os_daemonize_terminate(const char *pid_file)
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pid_file)
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		unlink(pid_file);
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint os_get_random(unsigned char *buf, size_t len)
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	FILE *f;
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t rc;
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	f = fopen("/dev/urandom", "rb");
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (f == NULL) {
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Could not open /dev/urandom.\n");
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rc = fread(buf, 1, len, f);
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fclose(f);
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return rc != len ? -1 : 0;
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtunsigned long os_random(void)
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return random();
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtchar * os_rel2abs_path(const char *rel_path)
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *buf = NULL, *cwd, *ret;
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len = 128, cwd_len, rel_len, ret_len;
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int last_errno;
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25464f47c5c24428834677459e048420f86e3514c20Dmitry Shmidt	if (!rel_path)
25564f47c5c24428834677459e048420f86e3514c20Dmitry Shmidt		return NULL;
25664f47c5c24428834677459e048420f86e3514c20Dmitry Shmidt
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (rel_path[0] == '/')
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return os_strdup(rel_path);
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (;;) {
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		buf = os_malloc(len);
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (buf == NULL)
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cwd = getcwd(buf, len);
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (cwd == NULL) {
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			last_errno = errno;
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(buf);
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (last_errno != ERANGE)
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return NULL;
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			len *= 2;
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (len > 2000)
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return NULL;
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			buf[len - 1] = '\0';
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cwd_len = os_strlen(cwd);
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rel_len = os_strlen(rel_path);
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret_len = cwd_len + 1 + rel_len + 1;
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = os_malloc(ret_len);
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret) {
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(ret, cwd, cwd_len);
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret[cwd_len] = '/';
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(ret + cwd_len + 1, rel_path, rel_len);
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret[ret_len - 1] = '\0';
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(buf);
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint os_program_init(void)
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef ANDROID
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * We ignore errors here since errors are normal if we
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * are already running as non-root.
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
301f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt#ifdef ANDROID_SETGROUPS_OVERRIDE
302f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	gid_t groups[] = { ANDROID_SETGROUPS_OVERRIDE };
303f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt#else /* ANDROID_SETGROUPS_OVERRIDE */
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gid_t groups[] = { AID_INET, AID_WIFI, AID_KEYSTORE };
305f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt#endif /* ANDROID_SETGROUPS_OVERRIDE */
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct __user_cap_header_struct header;
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct __user_cap_data_struct cap;
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	setgroups(ARRAY_SIZE(groups), groups);
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	setgid(AID_WIFI);
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	setuid(AID_WIFI);
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	header.version = _LINUX_CAPABILITY_VERSION;
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	header.pid = 0;
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cap.effective = cap.permitted =
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		(1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cap.inheritable = 0;
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	capset(&header, &cap);
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* ANDROID */
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid os_program_deinit(void)
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef WPA_TRACE
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct os_alloc_trace *a;
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned long total = 0;
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(a, &alloc_list, struct os_alloc_trace, list) {
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		total += a->len;
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (a->magic != ALLOC_MAGIC) {
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_INFO, "MEMLEAK[%p]: invalid magic 0x%x "
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "len %lu",
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   a, a->magic, (unsigned long) a->len);
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "MEMLEAK[%p]: len %lu",
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   a, (unsigned long) a->len);
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_trace_dump("memleak", a);
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (total)
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "MEMLEAK: total %lu bytes",
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) total);
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* WPA_TRACE */
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint os_setenv(const char *name, const char *value, int overwrite)
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return setenv(name, value, overwrite);
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint os_unsetenv(const char *name)
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || \
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    defined(__OpenBSD__)
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsetenv(name);
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return unsetenv(name);
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtchar * os_readfile(const char *name, size_t *len)
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	FILE *f;
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *buf;
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	long pos;
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	f = fopen(name, "rb");
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (f == NULL)
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (fseek(f, 0, SEEK_END) < 0 || (pos = ftell(f)) < 0) {
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		fclose(f);
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*len = pos;
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (fseek(f, 0, SEEK_SET) < 0) {
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		fclose(f);
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = os_malloc(*len);
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL) {
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		fclose(f);
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (fread(buf, 1, *len, f) != *len) {
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		fclose(f);
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(buf);
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fclose(f);
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
408d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtint os_file_exists(const char *fname)
409d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
410d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	FILE *f = fopen(fname, "rb");
411d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (f == NULL)
412d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return 0;
413d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	fclose(f);
414d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	return 1;
415d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
416d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
417d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
418447c7ff83da0d89ffa70c378be2a4a58f9b14d3bMitchell Willsint os_fsync(FILE *stream)
419447c7ff83da0d89ffa70c378be2a4a58f9b14d3bMitchell Wills{
420447c7ff83da0d89ffa70c378be2a4a58f9b14d3bMitchell Wills	if (!fflush(stream))
421447c7ff83da0d89ffa70c378be2a4a58f9b14d3bMitchell Wills		return fsync(fileno(stream));
422447c7ff83da0d89ffa70c378be2a4a58f9b14d3bMitchell Wills	return -1;
423447c7ff83da0d89ffa70c378be2a4a58f9b14d3bMitchell Wills}
424447c7ff83da0d89ffa70c378be2a4a58f9b14d3bMitchell Wills
425447c7ff83da0d89ffa70c378be2a4a58f9b14d3bMitchell Wills
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef WPA_TRACE
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid * os_zalloc(size_t size)
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return calloc(1, size);
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* WPA_TRACE */
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtsize_t os_strlcpy(char *dest, const char *src, size_t siz)
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *s = src;
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t left = siz;
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (left) {
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Copy string up to the maximum size of the dest buffer */
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (--left != 0) {
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if ((*dest++ = *s++) == '\0')
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (left == 0) {
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Not enough room for the string; force NUL-termination */
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (siz != 0)
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*dest = '\0';
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (*s++)
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			; /* determine total src string length */
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return s - src - 1;
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
459c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidtint os_memcmp_const(const void *a, const void *b, size_t len)
460c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt{
461c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt	const u8 *aa = a;
462c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt	const u8 *bb = b;
463c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt	size_t i;
464c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt	u8 res;
465c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt
466c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt	for (res = 0, i = 0; i < len; i++)
467c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt		res |= aa[i] ^ bb[i];
468c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt
469c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt	return res;
470c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt}
471c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt
472c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef WPA_TRACE
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
475ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#if defined(WPA_TRACE_BFD) && defined(CONFIG_TESTING_OPTIONS)
476ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidtchar wpa_trace_fail_func[256] = { 0 };
477ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidtunsigned int wpa_trace_fail_after;
478ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt
479ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidtstatic int testing_fail_alloc(void)
480ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt{
481ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt	const char *func[WPA_TRACE_LEN];
482ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt	size_t i, res, len;
483ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt	char *pos, *next;
484ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt	int match;
485ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt
486ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt	if (!wpa_trace_fail_after)
487ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt		return 0;
488ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt
489ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt	res = wpa_trace_calling_func(func, WPA_TRACE_LEN);
490ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt	i = 0;
491ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt	if (i < res && os_strcmp(func[i], __func__) == 0)
492ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt		i++;
493ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt	if (i < res && os_strcmp(func[i], "os_malloc") == 0)
494ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt		i++;
495ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt	if (i < res && os_strcmp(func[i], "os_zalloc") == 0)
496ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt		i++;
497ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt	if (i < res && os_strcmp(func[i], "os_calloc") == 0)
498ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt		i++;
499ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt	if (i < res && os_strcmp(func[i], "os_realloc") == 0)
500ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt		i++;
501ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt	if (i < res && os_strcmp(func[i], "os_realloc_array") == 0)
502ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt		i++;
503ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt	if (i < res && os_strcmp(func[i], "os_strdup") == 0)
504ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt		i++;
505ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt
506ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt	pos = wpa_trace_fail_func;
507ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt
508ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt	match = 0;
509ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt	while (i < res) {
510ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt		int allow_skip = 1;
511ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt		int maybe = 0;
512ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt
513ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt		if (*pos == '=') {
514ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt			allow_skip = 0;
515ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt			pos++;
516ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt		} else if (*pos == '?') {
517ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt			maybe = 1;
518ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt			pos++;
519ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt		}
520ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt		next = os_strchr(pos, ';');
521ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt		if (next)
522ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt			len = next - pos;
523ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt		else
524ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt			len = os_strlen(pos);
525ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt		if (os_memcmp(pos, func[i], len) != 0) {
526ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt			if (maybe && next) {
527ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt				pos = next + 1;
528ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt				continue;
529ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt			}
530ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt			if (allow_skip) {
531ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt				i++;
532ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt				continue;
533ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt			}
534ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt			return 0;
535ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt		}
536ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt		if (!next) {
537ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt			match = 1;
538ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt			break;
539ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt		}
540ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt		pos = next + 1;
541ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt		i++;
542ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt	}
543ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt	if (!match)
544ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt		return 0;
545ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt
546ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt	wpa_trace_fail_after--;
547ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt	if (wpa_trace_fail_after == 0) {
548ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt		wpa_printf(MSG_INFO, "TESTING: fail allocation at %s",
549ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt			   wpa_trace_fail_func);
550ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt		for (i = 0; i < res; i++)
551ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt			wpa_printf(MSG_INFO, "backtrace[%d] = %s",
552ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt				   (int) i, func[i]);
553ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt		return 1;
554ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt	}
555ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt
556ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt	return 0;
557ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt}
558ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt
559ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#else
560ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt
561ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidtstatic inline int testing_fail_alloc(void)
562ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt{
563ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt	return 0;
564ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt}
565ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#endif
566ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid * os_malloc(size_t size)
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct os_alloc_trace *a;
570ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt
571ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt	if (testing_fail_alloc())
572ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt		return NULL;
573ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	a = malloc(sizeof(*a) + size);
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (a == NULL)
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	a->magic = ALLOC_MAGIC;
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_add(&alloc_list, &a->list);
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	a->len = size;
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_trace_record(a);
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return a + 1;
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid * os_realloc(void *ptr, size_t size)
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct os_alloc_trace *a;
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t copy_len;
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	void *n;
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ptr == NULL)
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return os_malloc(size);
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	a = (struct os_alloc_trace *) ptr - 1;
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (a->magic != ALLOC_MAGIC) {
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "REALLOC[%p]: invalid magic 0x%x%s",
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   a, a->magic,
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   a->magic == FREED_MAGIC ? " (already freed)" : "");
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_trace_show("Invalid os_realloc() call");
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		abort();
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	n = os_malloc(size);
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (n == NULL)
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	copy_len = a->len;
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (copy_len > size)
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		copy_len = size;
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(n, a + 1, copy_len);
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(ptr);
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return n;
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid os_free(void *ptr)
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct os_alloc_trace *a;
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ptr == NULL)
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	a = (struct os_alloc_trace *) ptr - 1;
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (a->magic != ALLOC_MAGIC) {
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "FREE[%p]: invalid magic 0x%x%s",
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   a, a->magic,
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   a->magic == FREED_MAGIC ? " (already freed)" : "");
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_trace_show("Invalid os_free() call");
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		abort();
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_del(&a->list);
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	a->magic = FREED_MAGIC;
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_trace_check_ref(ptr);
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	free(a);
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid * os_zalloc(size_t size)
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	void *ptr = os_malloc(size);
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ptr)
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(ptr, 0, size);
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ptr;
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtchar * os_strdup(const char *s)
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *d;
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = os_strlen(s);
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	d = os_malloc(len + 1);
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (d == NULL)
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(d, s, len);
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	d[len] = '\0';
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return d;
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* WPA_TRACE */
659772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen
660772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen
661772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinenint os_exec(const char *program, const char *arg, int wait_completion)
662772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen{
663772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen	pid_t pid;
664772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen	int pid_status;
665772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen
666772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen	pid = fork();
667772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen	if (pid < 0) {
668772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen		perror("fork");
669772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen		return -1;
670772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen	}
671772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen
672772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen	if (pid == 0) {
673772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen		/* run the external command in the child process */
674772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen		const int MAX_ARG = 30;
675772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen		char *_program, *_arg, *pos;
676772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen		char *argv[MAX_ARG + 1];
677772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen		int i;
678772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen
679772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen		_program = os_strdup(program);
680772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen		_arg = os_strdup(arg);
681772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen
682772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen		argv[0] = _program;
683772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen
684772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen		i = 1;
685772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen		pos = _arg;
686772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen		while (i < MAX_ARG && pos && *pos) {
687772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen			while (*pos == ' ')
688772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen				pos++;
689772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen			if (*pos == '\0')
690772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen				break;
691772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen			argv[i++] = pos;
692772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen			pos = os_strchr(pos, ' ');
693772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen			if (pos)
694772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen				*pos++ = '\0';
695772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen		}
696772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen		argv[i] = NULL;
697772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen
698772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen		execv(program, argv);
699772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen		perror("execv");
700772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen		os_free(_program);
701772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen		os_free(_arg);
702772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen		exit(0);
703772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen		return -1;
704772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen	}
705772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen
706772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen	if (wait_completion) {
707772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen		/* wait for the child process to complete in the parent */
708772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen		waitpid(pid, &pid_status, 0);
709772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen	}
710772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen
711772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen	return 0;
712772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen}
713