18dbcf02cSchristos /* 28dbcf02cSchristos * wpa_supplicant/hostapd / Internal implementation of OS specific functions 38dbcf02cSchristos * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> 48dbcf02cSchristos * 5e604d861Schristos * This software may be distributed under the terms of the BSD license. 6e604d861Schristos * See README for more details. 78dbcf02cSchristos * 88dbcf02cSchristos * This file is an example of operating system specific wrapper functions. 98dbcf02cSchristos * This version implements many of the functions internally, so it can be used 108dbcf02cSchristos * to fill in missing functions from the target system C libraries. 118dbcf02cSchristos * 128dbcf02cSchristos * Some of the functions are using standard C library calls in order to keep 138dbcf02cSchristos * this file in working condition to allow the functions to be tested on a 148dbcf02cSchristos * Linux target. Please note that OS_NO_C_LIB_DEFINES needs to be defined for 158dbcf02cSchristos * this file to work correctly. Note that these implementations are only 168dbcf02cSchristos * examples and are not optimized for speed. 178dbcf02cSchristos */ 188dbcf02cSchristos 198dbcf02cSchristos #include "includes.h" 20bb610346Schristos #include <time.h> 21bb610346Schristos #include <sys/wait.h> 228dbcf02cSchristos 238dbcf02cSchristos #undef OS_REJECT_C_LIB_FUNCTIONS 24bb610346Schristos #include "common.h" 258dbcf02cSchristos 268dbcf02cSchristos void os_sleep(os_time_t sec, os_time_t usec) 278dbcf02cSchristos { 28*bb618362Schristos #if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200809L) 29*bb618362Schristos const struct timespec req = { sec, usec * 1000 }; 30*bb618362Schristos 31*bb618362Schristos nanosleep(&req, NULL); 32*bb618362Schristos #else 338dbcf02cSchristos if (sec) 348dbcf02cSchristos sleep(sec); 358dbcf02cSchristos if (usec) 368dbcf02cSchristos usleep(usec); 37*bb618362Schristos #endif 388dbcf02cSchristos } 398dbcf02cSchristos 408dbcf02cSchristos 418dbcf02cSchristos int os_get_time(struct os_time *t) 428dbcf02cSchristos { 438dbcf02cSchristos int res; 448dbcf02cSchristos struct timeval tv; 458dbcf02cSchristos res = gettimeofday(&tv, NULL); 468dbcf02cSchristos t->sec = tv.tv_sec; 478dbcf02cSchristos t->usec = tv.tv_usec; 488dbcf02cSchristos return res; 498dbcf02cSchristos } 508dbcf02cSchristos 518dbcf02cSchristos 523c260e60Schristos int os_get_reltime(struct os_reltime *t) 533c260e60Schristos { 543c260e60Schristos int res; 553c260e60Schristos struct timeval tv; 563c260e60Schristos res = gettimeofday(&tv, NULL); 573c260e60Schristos t->sec = tv.tv_sec; 583c260e60Schristos t->usec = tv.tv_usec; 593c260e60Schristos return res; 603c260e60Schristos } 613c260e60Schristos 623c260e60Schristos 638dbcf02cSchristos int os_mktime(int year, int month, int day, int hour, int min, int sec, 648dbcf02cSchristos os_time_t *t) 658dbcf02cSchristos { 668dbcf02cSchristos struct tm tm; 678dbcf02cSchristos 688dbcf02cSchristos if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 || 698dbcf02cSchristos hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || 708dbcf02cSchristos sec > 60) 718dbcf02cSchristos return -1; 728dbcf02cSchristos 738dbcf02cSchristos os_memset(&tm, 0, sizeof(tm)); 748dbcf02cSchristos tm.tm_year = year - 1900; 758dbcf02cSchristos tm.tm_mon = month - 1; 768dbcf02cSchristos tm.tm_mday = day; 778dbcf02cSchristos tm.tm_hour = hour; 788dbcf02cSchristos tm.tm_min = min; 798dbcf02cSchristos tm.tm_sec = sec; 808dbcf02cSchristos 818dbcf02cSchristos *t = (os_time_t) mktime(&tm); 828dbcf02cSchristos return 0; 838dbcf02cSchristos } 848dbcf02cSchristos 858dbcf02cSchristos 86111b9fd8Schristos int os_gmtime(os_time_t t, struct os_tm *tm) 87111b9fd8Schristos { 88111b9fd8Schristos struct tm *tm2; 89111b9fd8Schristos time_t t2 = t; 90111b9fd8Schristos 91111b9fd8Schristos tm2 = gmtime(&t2); 92111b9fd8Schristos if (tm2 == NULL) 93111b9fd8Schristos return -1; 94111b9fd8Schristos tm->sec = tm2->tm_sec; 95111b9fd8Schristos tm->min = tm2->tm_min; 96111b9fd8Schristos tm->hour = tm2->tm_hour; 97111b9fd8Schristos tm->day = tm2->tm_mday; 98111b9fd8Schristos tm->month = tm2->tm_mon + 1; 99111b9fd8Schristos tm->year = tm2->tm_year + 1900; 100111b9fd8Schristos return 0; 101111b9fd8Schristos } 102111b9fd8Schristos 103111b9fd8Schristos 1048dbcf02cSchristos int os_daemonize(const char *pid_file) 1058dbcf02cSchristos { 1068dbcf02cSchristos if (daemon(0, 0)) { 107bb610346Schristos wpa_printf(MSG_ERROR, "daemon: %s", strerror(errno)); 1088dbcf02cSchristos return -1; 1098dbcf02cSchristos } 1108dbcf02cSchristos 1118dbcf02cSchristos if (pid_file) { 1128dbcf02cSchristos FILE *f = fopen(pid_file, "w"); 1138dbcf02cSchristos if (f) { 1148dbcf02cSchristos fprintf(f, "%u\n", getpid()); 1158dbcf02cSchristos fclose(f); 1168dbcf02cSchristos } 1178dbcf02cSchristos } 1188dbcf02cSchristos 1198dbcf02cSchristos return -0; 1208dbcf02cSchristos } 1218dbcf02cSchristos 1228dbcf02cSchristos 1238dbcf02cSchristos void os_daemonize_terminate(const char *pid_file) 1248dbcf02cSchristos { 1258dbcf02cSchristos if (pid_file) 1268dbcf02cSchristos unlink(pid_file); 1278dbcf02cSchristos } 1288dbcf02cSchristos 1298dbcf02cSchristos 1308dbcf02cSchristos int os_get_random(unsigned char *buf, size_t len) 1318dbcf02cSchristos { 1328dbcf02cSchristos FILE *f; 1338dbcf02cSchristos size_t rc; 1348dbcf02cSchristos 1358dbcf02cSchristos f = fopen("/dev/urandom", "rb"); 1368dbcf02cSchristos if (f == NULL) { 1378dbcf02cSchristos printf("Could not open /dev/urandom.\n"); 1388dbcf02cSchristos return -1; 1398dbcf02cSchristos } 1408dbcf02cSchristos 1418dbcf02cSchristos rc = fread(buf, 1, len, f); 1428dbcf02cSchristos fclose(f); 1438dbcf02cSchristos 1448dbcf02cSchristos return rc != len ? -1 : 0; 1458dbcf02cSchristos } 1468dbcf02cSchristos 1478dbcf02cSchristos 1488dbcf02cSchristos unsigned long os_random(void) 1498dbcf02cSchristos { 1508dbcf02cSchristos return random(); 1518dbcf02cSchristos } 1528dbcf02cSchristos 1538dbcf02cSchristos 1548dbcf02cSchristos char * os_rel2abs_path(const char *rel_path) 1558dbcf02cSchristos { 1568dbcf02cSchristos char *buf = NULL, *cwd, *ret; 1578dbcf02cSchristos size_t len = 128, cwd_len, rel_len, ret_len; 1588dbcf02cSchristos 1598dbcf02cSchristos if (rel_path[0] == '/') 1608dbcf02cSchristos return os_strdup(rel_path); 1618dbcf02cSchristos 1628dbcf02cSchristos for (;;) { 1638dbcf02cSchristos buf = os_malloc(len); 1648dbcf02cSchristos if (buf == NULL) 1658dbcf02cSchristos return NULL; 1668dbcf02cSchristos cwd = getcwd(buf, len); 1678dbcf02cSchristos if (cwd == NULL) { 1688dbcf02cSchristos os_free(buf); 1698dbcf02cSchristos if (errno != ERANGE) { 1708dbcf02cSchristos return NULL; 1718dbcf02cSchristos } 1728dbcf02cSchristos len *= 2; 1738dbcf02cSchristos } else { 1748dbcf02cSchristos break; 1758dbcf02cSchristos } 1768dbcf02cSchristos } 1778dbcf02cSchristos 178bb610346Schristos cwd_len = os_strlen(cwd); 179bb610346Schristos rel_len = os_strlen(rel_path); 1808dbcf02cSchristos ret_len = cwd_len + 1 + rel_len + 1; 1818dbcf02cSchristos ret = os_malloc(ret_len); 1828dbcf02cSchristos if (ret) { 1838dbcf02cSchristos os_memcpy(ret, cwd, cwd_len); 1848dbcf02cSchristos ret[cwd_len] = '/'; 1858dbcf02cSchristos os_memcpy(ret + cwd_len + 1, rel_path, rel_len); 1868dbcf02cSchristos ret[ret_len - 1] = '\0'; 1878dbcf02cSchristos } 1888dbcf02cSchristos os_free(buf); 1898dbcf02cSchristos return ret; 1908dbcf02cSchristos } 1918dbcf02cSchristos 1928dbcf02cSchristos 1938dbcf02cSchristos int os_program_init(void) 1948dbcf02cSchristos { 1958dbcf02cSchristos return 0; 1968dbcf02cSchristos } 1978dbcf02cSchristos 1988dbcf02cSchristos 1998dbcf02cSchristos void os_program_deinit(void) 2008dbcf02cSchristos { 2018dbcf02cSchristos } 2028dbcf02cSchristos 2038dbcf02cSchristos 2048dbcf02cSchristos int os_setenv(const char *name, const char *value, int overwrite) 2058dbcf02cSchristos { 2068dbcf02cSchristos return setenv(name, value, overwrite); 2078dbcf02cSchristos } 2088dbcf02cSchristos 2098dbcf02cSchristos 2108dbcf02cSchristos int os_unsetenv(const char *name) 2118dbcf02cSchristos { 2128dbcf02cSchristos #if defined(__FreeBSD__) || defined(__NetBSD__) 2138dbcf02cSchristos unsetenv(name); 2148dbcf02cSchristos return 0; 2158dbcf02cSchristos #else 2168dbcf02cSchristos return unsetenv(name); 2178dbcf02cSchristos #endif 2188dbcf02cSchristos } 2198dbcf02cSchristos 2208dbcf02cSchristos 2218dbcf02cSchristos char * os_readfile(const char *name, size_t *len) 2228dbcf02cSchristos { 2238dbcf02cSchristos FILE *f; 2248dbcf02cSchristos char *buf; 2258dbcf02cSchristos 2268dbcf02cSchristos f = fopen(name, "rb"); 2278dbcf02cSchristos if (f == NULL) 2288dbcf02cSchristos return NULL; 2298dbcf02cSchristos 2308dbcf02cSchristos fseek(f, 0, SEEK_END); 2318dbcf02cSchristos *len = ftell(f); 2328dbcf02cSchristos fseek(f, 0, SEEK_SET); 2338dbcf02cSchristos 2348dbcf02cSchristos buf = os_malloc(*len); 2358dbcf02cSchristos if (buf == NULL) { 2368dbcf02cSchristos fclose(f); 2378dbcf02cSchristos return NULL; 2388dbcf02cSchristos } 2398dbcf02cSchristos 2408dbcf02cSchristos if (fread(buf, 1, *len, f) != *len) { 2418dbcf02cSchristos fclose(f); 2428dbcf02cSchristos os_free(buf); 2438dbcf02cSchristos return NULL; 2448dbcf02cSchristos } 2458dbcf02cSchristos 2468dbcf02cSchristos fclose(f); 2478dbcf02cSchristos 2488dbcf02cSchristos return buf; 2498dbcf02cSchristos } 2508dbcf02cSchristos 2518dbcf02cSchristos 25236ebd06eSchristos int os_fdatasync(FILE *stream) 25336ebd06eSchristos { 25436ebd06eSchristos return 0; 25536ebd06eSchristos } 25636ebd06eSchristos 25736ebd06eSchristos 2588dbcf02cSchristos void * os_zalloc(size_t size) 2598dbcf02cSchristos { 2608dbcf02cSchristos void *n = os_malloc(size); 2618dbcf02cSchristos if (n) 2628dbcf02cSchristos os_memset(n, 0, size); 2638dbcf02cSchristos return n; 2648dbcf02cSchristos } 2658dbcf02cSchristos 2668dbcf02cSchristos 2678dbcf02cSchristos void * os_malloc(size_t size) 2688dbcf02cSchristos { 2698dbcf02cSchristos return malloc(size); 2708dbcf02cSchristos } 2718dbcf02cSchristos 2728dbcf02cSchristos 2738dbcf02cSchristos void * os_realloc(void *ptr, size_t size) 2748dbcf02cSchristos { 2758dbcf02cSchristos return realloc(ptr, size); 2768dbcf02cSchristos } 2778dbcf02cSchristos 2788dbcf02cSchristos 2798dbcf02cSchristos void os_free(void *ptr) 2808dbcf02cSchristos { 2818dbcf02cSchristos free(ptr); 2828dbcf02cSchristos } 2838dbcf02cSchristos 2848dbcf02cSchristos 2858dbcf02cSchristos void * os_memcpy(void *dest, const void *src, size_t n) 2868dbcf02cSchristos { 2878dbcf02cSchristos char *d = dest; 2888dbcf02cSchristos const char *s = src; 2898dbcf02cSchristos while (n--) 2908dbcf02cSchristos *d++ = *s++; 2918dbcf02cSchristos return dest; 2928dbcf02cSchristos } 2938dbcf02cSchristos 2948dbcf02cSchristos 2958dbcf02cSchristos void * os_memmove(void *dest, const void *src, size_t n) 2968dbcf02cSchristos { 2978dbcf02cSchristos if (dest < src) 2988dbcf02cSchristos os_memcpy(dest, src, n); 2998dbcf02cSchristos else { 3008dbcf02cSchristos /* overlapping areas */ 3018dbcf02cSchristos char *d = (char *) dest + n; 3028dbcf02cSchristos const char *s = (const char *) src + n; 3038dbcf02cSchristos while (n--) 3048dbcf02cSchristos *--d = *--s; 3058dbcf02cSchristos } 3068dbcf02cSchristos return dest; 3078dbcf02cSchristos } 3088dbcf02cSchristos 3098dbcf02cSchristos 3108dbcf02cSchristos void * os_memset(void *s, int c, size_t n) 3118dbcf02cSchristos { 3128dbcf02cSchristos char *p = s; 3138dbcf02cSchristos while (n--) 3148dbcf02cSchristos *p++ = c; 3158dbcf02cSchristos return s; 3168dbcf02cSchristos } 3178dbcf02cSchristos 3188dbcf02cSchristos 3198dbcf02cSchristos int os_memcmp(const void *s1, const void *s2, size_t n) 3208dbcf02cSchristos { 3218dbcf02cSchristos const unsigned char *p1 = s1, *p2 = s2; 3228dbcf02cSchristos 3238dbcf02cSchristos if (n == 0) 3248dbcf02cSchristos return 0; 3258dbcf02cSchristos 3268dbcf02cSchristos while (*p1 == *p2) { 3278dbcf02cSchristos p1++; 3288dbcf02cSchristos p2++; 3298dbcf02cSchristos n--; 3308dbcf02cSchristos if (n == 0) 3318dbcf02cSchristos return 0; 3328dbcf02cSchristos } 3338dbcf02cSchristos 3348dbcf02cSchristos return *p1 - *p2; 3358dbcf02cSchristos } 3368dbcf02cSchristos 3378dbcf02cSchristos 3388dbcf02cSchristos char * os_strdup(const char *s) 3398dbcf02cSchristos { 3408dbcf02cSchristos char *res; 3418dbcf02cSchristos size_t len; 3428dbcf02cSchristos if (s == NULL) 3438dbcf02cSchristos return NULL; 3448dbcf02cSchristos len = os_strlen(s); 3458dbcf02cSchristos res = os_malloc(len + 1); 3468dbcf02cSchristos if (res) 3478dbcf02cSchristos os_memcpy(res, s, len + 1); 3488dbcf02cSchristos return res; 3498dbcf02cSchristos } 3508dbcf02cSchristos 3518dbcf02cSchristos 3528dbcf02cSchristos size_t os_strlen(const char *s) 3538dbcf02cSchristos { 3548dbcf02cSchristos const char *p = s; 3558dbcf02cSchristos while (*p) 3568dbcf02cSchristos p++; 3578dbcf02cSchristos return p - s; 3588dbcf02cSchristos } 3598dbcf02cSchristos 3608dbcf02cSchristos 3618dbcf02cSchristos int os_strcasecmp(const char *s1, const char *s2) 3628dbcf02cSchristos { 3638dbcf02cSchristos /* 3648dbcf02cSchristos * Ignoring case is not required for main functionality, so just use 3658dbcf02cSchristos * the case sensitive version of the function. 3668dbcf02cSchristos */ 3678dbcf02cSchristos return os_strcmp(s1, s2); 3688dbcf02cSchristos } 3698dbcf02cSchristos 3708dbcf02cSchristos 3718dbcf02cSchristos int os_strncasecmp(const char *s1, const char *s2, size_t n) 3728dbcf02cSchristos { 3738dbcf02cSchristos /* 3748dbcf02cSchristos * Ignoring case is not required for main functionality, so just use 3758dbcf02cSchristos * the case sensitive version of the function. 3768dbcf02cSchristos */ 3778dbcf02cSchristos return os_strncmp(s1, s2, n); 3788dbcf02cSchristos } 3798dbcf02cSchristos 3808dbcf02cSchristos 3818dbcf02cSchristos char * os_strchr(const char *s, int c) 3828dbcf02cSchristos { 3838dbcf02cSchristos while (*s) { 3848dbcf02cSchristos if (*s == c) 3858dbcf02cSchristos return (char *) s; 3868dbcf02cSchristos s++; 3878dbcf02cSchristos } 3888dbcf02cSchristos return NULL; 3898dbcf02cSchristos } 3908dbcf02cSchristos 3918dbcf02cSchristos 3928dbcf02cSchristos char * os_strrchr(const char *s, int c) 3938dbcf02cSchristos { 3948dbcf02cSchristos const char *p = s; 3958dbcf02cSchristos while (*p) 3968dbcf02cSchristos p++; 3978dbcf02cSchristos p--; 3988dbcf02cSchristos while (p >= s) { 3998dbcf02cSchristos if (*p == c) 4008dbcf02cSchristos return (char *) p; 4018dbcf02cSchristos p--; 4028dbcf02cSchristos } 4038dbcf02cSchristos return NULL; 4048dbcf02cSchristos } 4058dbcf02cSchristos 4068dbcf02cSchristos 4078dbcf02cSchristos int os_strcmp(const char *s1, const char *s2) 4088dbcf02cSchristos { 4098dbcf02cSchristos while (*s1 == *s2) { 4108dbcf02cSchristos if (*s1 == '\0') 4118dbcf02cSchristos break; 4128dbcf02cSchristos s1++; 4138dbcf02cSchristos s2++; 4148dbcf02cSchristos } 4158dbcf02cSchristos 4168dbcf02cSchristos return *s1 - *s2; 4178dbcf02cSchristos } 4188dbcf02cSchristos 4198dbcf02cSchristos 4208dbcf02cSchristos int os_strncmp(const char *s1, const char *s2, size_t n) 4218dbcf02cSchristos { 4228dbcf02cSchristos if (n == 0) 4238dbcf02cSchristos return 0; 4248dbcf02cSchristos 4258dbcf02cSchristos while (*s1 == *s2) { 4268dbcf02cSchristos if (*s1 == '\0') 4278dbcf02cSchristos break; 4288dbcf02cSchristos s1++; 4298dbcf02cSchristos s2++; 4308dbcf02cSchristos n--; 4318dbcf02cSchristos if (n == 0) 4328dbcf02cSchristos return 0; 4338dbcf02cSchristos } 4348dbcf02cSchristos 4358dbcf02cSchristos return *s1 - *s2; 4368dbcf02cSchristos } 4378dbcf02cSchristos 4388dbcf02cSchristos 4398dbcf02cSchristos size_t os_strlcpy(char *dest, const char *src, size_t siz) 4408dbcf02cSchristos { 4418dbcf02cSchristos const char *s = src; 4428dbcf02cSchristos size_t left = siz; 4438dbcf02cSchristos 4448dbcf02cSchristos if (left) { 4458dbcf02cSchristos /* Copy string up to the maximum size of the dest buffer */ 4468dbcf02cSchristos while (--left != 0) { 4478dbcf02cSchristos if ((*dest++ = *s++) == '\0') 4488dbcf02cSchristos break; 4498dbcf02cSchristos } 4508dbcf02cSchristos } 4518dbcf02cSchristos 4528dbcf02cSchristos if (left == 0) { 4538dbcf02cSchristos /* Not enough room for the string; force NUL-termination */ 4548dbcf02cSchristos if (siz != 0) 4558dbcf02cSchristos *dest = '\0'; 4568dbcf02cSchristos while (*s++) 4578dbcf02cSchristos ; /* determine total src string length */ 4588dbcf02cSchristos } 4598dbcf02cSchristos 4608dbcf02cSchristos return s - src - 1; 4618dbcf02cSchristos } 4628dbcf02cSchristos 4638dbcf02cSchristos 4643c260e60Schristos int os_memcmp_const(const void *a, const void *b, size_t len) 4653c260e60Schristos { 4663c260e60Schristos const u8 *aa = a; 4673c260e60Schristos const u8 *bb = b; 4683c260e60Schristos size_t i; 4693c260e60Schristos u8 res; 4703c260e60Schristos 4713c260e60Schristos for (res = 0, i = 0; i < len; i++) 4723c260e60Schristos res |= aa[i] ^ bb[i]; 4733c260e60Schristos 4743c260e60Schristos return res; 4753c260e60Schristos } 4763c260e60Schristos 4773c260e60Schristos 4788dbcf02cSchristos char * os_strstr(const char *haystack, const char *needle) 4798dbcf02cSchristos { 4808dbcf02cSchristos size_t len = os_strlen(needle); 4818dbcf02cSchristos while (*haystack) { 4828dbcf02cSchristos if (os_strncmp(haystack, needle, len) == 0) 4838dbcf02cSchristos return (char *) haystack; 4848dbcf02cSchristos haystack++; 4858dbcf02cSchristos } 4868dbcf02cSchristos 4878dbcf02cSchristos return NULL; 4888dbcf02cSchristos } 4898dbcf02cSchristos 4908dbcf02cSchristos 4918dbcf02cSchristos int os_snprintf(char *str, size_t size, const char *format, ...) 4928dbcf02cSchristos { 4938dbcf02cSchristos va_list ap; 4948dbcf02cSchristos int ret; 4958dbcf02cSchristos 4968dbcf02cSchristos /* See http://www.ijs.si/software/snprintf/ for portable 4978dbcf02cSchristos * implementation of snprintf. 4988dbcf02cSchristos */ 4998dbcf02cSchristos 5008dbcf02cSchristos va_start(ap, format); 5018dbcf02cSchristos ret = vsnprintf(str, size, format, ap); 5028dbcf02cSchristos va_end(ap); 5038dbcf02cSchristos if (size > 0) 5048dbcf02cSchristos str[size - 1] = '\0'; 5058dbcf02cSchristos return ret; 5068dbcf02cSchristos } 507bb610346Schristos 508bb610346Schristos 509bb610346Schristos int os_exec(const char *program, const char *arg, int wait_completion) 510bb610346Schristos { 511bb610346Schristos pid_t pid; 512bb610346Schristos int pid_status; 513bb610346Schristos 514bb610346Schristos pid = fork(); 515bb610346Schristos if (pid < 0) { 516bb610346Schristos wpa_printf(MSG_ERROR, "fork: %s", strerror(errno)); 517bb610346Schristos return -1; 518bb610346Schristos } 519bb610346Schristos 520bb610346Schristos if (pid == 0) { 521bb610346Schristos /* run the external command in the child process */ 522bb610346Schristos const int MAX_ARG = 30; 523bb610346Schristos char *_program, *_arg, *pos; 524bb610346Schristos char *argv[MAX_ARG + 1]; 525bb610346Schristos int i; 526bb610346Schristos 527bb610346Schristos _program = os_strdup(program); 528bb610346Schristos _arg = os_strdup(arg); 529bb610346Schristos 530bb610346Schristos argv[0] = _program; 531bb610346Schristos 532bb610346Schristos i = 1; 533bb610346Schristos pos = _arg; 534bb610346Schristos while (i < MAX_ARG && pos && *pos) { 535bb610346Schristos while (*pos == ' ') 536bb610346Schristos pos++; 537bb610346Schristos if (*pos == '\0') 538bb610346Schristos break; 539bb610346Schristos argv[i++] = pos; 540bb610346Schristos pos = os_strchr(pos, ' '); 541bb610346Schristos if (pos) 542bb610346Schristos *pos++ = '\0'; 543bb610346Schristos } 544bb610346Schristos argv[i] = NULL; 545bb610346Schristos 546bb610346Schristos execv(program, argv); 547bb610346Schristos wpa_printf(MSG_ERROR, "execv: %s", strerror(errno)); 548bb610346Schristos os_free(_program); 549bb610346Schristos os_free(_arg); 550bb610346Schristos exit(0); 551bb610346Schristos return -1; 552bb610346Schristos } 553bb610346Schristos 554bb610346Schristos if (wait_completion) { 555bb610346Schristos /* wait for the child process to complete in the parent */ 556bb610346Schristos waitpid(pid, &pid_status, 0); 557bb610346Schristos } 558bb610346Schristos 559bb610346Schristos return 0; 560bb610346Schristos } 561