LCOV - code coverage report
Current view: top level - src/utils - os_unix.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1422976643 Lines: 200 322 62.1 %
Date: 2015-02-03 Functions: 19 25 76.0 %

          Line data    Source code
       1             : /*
       2             :  * OS specific functions for UNIX/POSIX systems
       3             :  * Copyright (c) 2005-2009, Jouni Malinen <j@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 <sys/capability.h>
      16             : #include <sys/prctl.h>
      17             : #include <private/android_filesystem_config.h>
      18             : #endif /* ANDROID */
      19             : 
      20             : #include "os.h"
      21             : #include "common.h"
      22             : 
      23             : #ifdef WPA_TRACE
      24             : 
      25             : #include "wpa_debug.h"
      26             : #include "trace.h"
      27             : #include "list.h"
      28             : 
      29             : static struct dl_list alloc_list;
      30             : 
      31             : #define ALLOC_MAGIC 0xa84ef1b2
      32             : #define FREED_MAGIC 0x67fd487a
      33             : 
      34             : struct os_alloc_trace {
      35             :         unsigned int magic;
      36             :         struct dl_list list;
      37             :         size_t len;
      38             :         WPA_TRACE_INFO
      39             : };
      40             : 
      41             : #endif /* WPA_TRACE */
      42             : 
      43             : 
      44         530 : void os_sleep(os_time_t sec, os_time_t usec)
      45             : {
      46         530 :         if (sec)
      47           0 :                 sleep(sec);
      48         530 :         if (usec)
      49         530 :                 usleep(usec);
      50         530 : }
      51             : 
      52             : 
      53     3630934 : int os_get_time(struct os_time *t)
      54             : {
      55             :         int res;
      56             :         struct timeval tv;
      57     3630934 :         res = gettimeofday(&tv, NULL);
      58     3630934 :         t->sec = tv.tv_sec;
      59     3630934 :         t->usec = tv.tv_usec;
      60     3630934 :         return res;
      61             : }
      62             : 
      63             : 
      64      949047 : int os_get_reltime(struct os_reltime *t)
      65             : {
      66             : #if defined(CLOCK_BOOTTIME)
      67             :         static clockid_t clock_id = CLOCK_BOOTTIME;
      68             : #elif defined(CLOCK_MONOTONIC)
      69             :         static clockid_t clock_id = CLOCK_MONOTONIC;
      70             : #else
      71             :         static clockid_t clock_id = CLOCK_REALTIME;
      72             : #endif
      73             :         struct timespec ts;
      74             :         int res;
      75             : 
      76             :         while (1) {
      77      949047 :                 res = clock_gettime(clock_id, &ts);
      78      949047 :                 if (res == 0) {
      79      949047 :                         t->sec = ts.tv_sec;
      80      949047 :                         t->usec = ts.tv_nsec / 1000;
      81      949047 :                         return 0;
      82             :                 }
      83           0 :                 switch (clock_id) {
      84             : #ifdef CLOCK_BOOTTIME
      85             :                 case CLOCK_BOOTTIME:
      86           0 :                         clock_id = CLOCK_MONOTONIC;
      87           0 :                         break;
      88             : #endif
      89             : #ifdef CLOCK_MONOTONIC
      90             :                 case CLOCK_MONOTONIC:
      91           0 :                         clock_id = CLOCK_REALTIME;
      92           0 :                         break;
      93             : #endif
      94             :                 case CLOCK_REALTIME:
      95           0 :                         return -1;
      96             :                 }
      97           0 :         }
      98             : }
      99             : 
     100             : 
     101           0 : int os_mktime(int year, int month, int day, int hour, int min, int sec,
     102             :               os_time_t *t)
     103             : {
     104             :         struct tm tm, *tm1;
     105             :         time_t t_local, t1, t2;
     106             :         os_time_t tz_offset;
     107             : 
     108           0 :         if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
     109           0 :             hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 ||
     110             :             sec > 60)
     111           0 :                 return -1;
     112             : 
     113           0 :         memset(&tm, 0, sizeof(tm));
     114           0 :         tm.tm_year = year - 1900;
     115           0 :         tm.tm_mon = month - 1;
     116           0 :         tm.tm_mday = day;
     117           0 :         tm.tm_hour = hour;
     118           0 :         tm.tm_min = min;
     119           0 :         tm.tm_sec = sec;
     120             : 
     121           0 :         t_local = mktime(&tm);
     122             : 
     123             :         /* figure out offset to UTC */
     124           0 :         tm1 = localtime(&t_local);
     125           0 :         if (tm1) {
     126           0 :                 t1 = mktime(tm1);
     127           0 :                 tm1 = gmtime(&t_local);
     128           0 :                 if (tm1) {
     129           0 :                         t2 = mktime(tm1);
     130           0 :                         tz_offset = t2 - t1;
     131             :                 } else
     132           0 :                         tz_offset = 0;
     133             :         } else
     134           0 :                 tz_offset = 0;
     135             : 
     136           0 :         *t = (os_time_t) t_local - tz_offset;
     137           0 :         return 0;
     138             : }
     139             : 
     140             : 
     141           6 : int os_gmtime(os_time_t t, struct os_tm *tm)
     142             : {
     143             :         struct tm *tm2;
     144           6 :         time_t t2 = t;
     145             : 
     146           6 :         tm2 = gmtime(&t2);
     147           6 :         if (tm2 == NULL)
     148           0 :                 return -1;
     149           6 :         tm->sec = tm2->tm_sec;
     150           6 :         tm->min = tm2->tm_min;
     151           6 :         tm->hour = tm2->tm_hour;
     152           6 :         tm->day = tm2->tm_mday;
     153           6 :         tm->month = tm2->tm_mon + 1;
     154           6 :         tm->year = tm2->tm_year + 1900;
     155           6 :         return 0;
     156             : }
     157             : 
     158             : 
     159             : #ifdef __APPLE__
     160             : #include <fcntl.h>
     161             : static int os_daemon(int nochdir, int noclose)
     162             : {
     163             :         int devnull;
     164             : 
     165             :         if (chdir("/") < 0)
     166             :                 return -1;
     167             : 
     168             :         devnull = open("/dev/null", O_RDWR);
     169             :         if (devnull < 0)
     170             :                 return -1;
     171             : 
     172             :         if (dup2(devnull, STDIN_FILENO) < 0) {
     173             :                 close(devnull);
     174             :                 return -1;
     175             :         }
     176             : 
     177             :         if (dup2(devnull, STDOUT_FILENO) < 0) {
     178             :                 close(devnull);
     179             :                 return -1;
     180             :         }
     181             : 
     182             :         if (dup2(devnull, STDERR_FILENO) < 0) {
     183             :                 close(devnull);
     184             :                 return -1;
     185             :         }
     186             : 
     187             :         return 0;
     188             : }
     189             : #else /* __APPLE__ */
     190             : #define os_daemon daemon
     191             : #endif /* __APPLE__ */
     192             : 
     193             : 
     194           0 : int os_daemonize(const char *pid_file)
     195             : {
     196             : #if defined(__uClinux__) || defined(__sun__)
     197             :         return -1;
     198             : #else /* defined(__uClinux__) || defined(__sun__) */
     199           0 :         if (os_daemon(0, 0)) {
     200           0 :                 perror("daemon");
     201           0 :                 return -1;
     202             :         }
     203             : 
     204           0 :         if (pid_file) {
     205           0 :                 FILE *f = fopen(pid_file, "w");
     206           0 :                 if (f) {
     207           0 :                         fprintf(f, "%u\n", getpid());
     208           0 :                         fclose(f);
     209             :                 }
     210             :         }
     211             : 
     212           0 :         return -0;
     213             : #endif /* defined(__uClinux__) || defined(__sun__) */
     214             : }
     215             : 
     216             : 
     217          10 : void os_daemonize_terminate(const char *pid_file)
     218             : {
     219          10 :         if (pid_file)
     220           0 :                 unlink(pid_file);
     221          10 : }
     222             : 
     223             : 
     224       15312 : int os_get_random(unsigned char *buf, size_t len)
     225             : {
     226             :         FILE *f;
     227             :         size_t rc;
     228             : 
     229       15312 :         f = fopen("/dev/urandom", "rb");
     230       15312 :         if (f == NULL) {
     231           0 :                 printf("Could not open /dev/urandom.\n");
     232           0 :                 return -1;
     233             :         }
     234             : 
     235       15312 :         rc = fread(buf, 1, len, f);
     236       15312 :         fclose(f);
     237             : 
     238       15312 :         return rc != len ? -1 : 0;
     239             : }
     240             : 
     241             : 
     242        4572 : unsigned long os_random(void)
     243             : {
     244        4572 :         return random();
     245             : }
     246             : 
     247             : 
     248          52 : char * os_rel2abs_path(const char *rel_path)
     249             : {
     250          52 :         char *buf = NULL, *cwd, *ret;
     251          52 :         size_t len = 128, cwd_len, rel_len, ret_len;
     252             :         int last_errno;
     253             : 
     254          52 :         if (!rel_path)
     255          17 :                 return NULL;
     256             : 
     257          35 :         if (rel_path[0] == '/')
     258          18 :                 return os_strdup(rel_path);
     259             : 
     260             :         for (;;) {
     261          17 :                 buf = os_malloc(len);
     262          17 :                 if (buf == NULL)
     263           0 :                         return NULL;
     264          17 :                 cwd = getcwd(buf, len);
     265          17 :                 if (cwd == NULL) {
     266           0 :                         last_errno = errno;
     267           0 :                         os_free(buf);
     268           0 :                         if (last_errno != ERANGE)
     269           0 :                                 return NULL;
     270           0 :                         len *= 2;
     271           0 :                         if (len > 2000)
     272           0 :                                 return NULL;
     273             :                 } else {
     274          17 :                         buf[len - 1] = '\0';
     275          17 :                         break;
     276             :                 }
     277           0 :         }
     278             : 
     279          17 :         cwd_len = os_strlen(cwd);
     280          17 :         rel_len = os_strlen(rel_path);
     281          17 :         ret_len = cwd_len + 1 + rel_len + 1;
     282          17 :         ret = os_malloc(ret_len);
     283          17 :         if (ret) {
     284          17 :                 os_memcpy(ret, cwd, cwd_len);
     285          17 :                 ret[cwd_len] = '/';
     286          17 :                 os_memcpy(ret + cwd_len + 1, rel_path, rel_len);
     287          17 :                 ret[ret_len - 1] = '\0';
     288             :         }
     289          17 :         os_free(buf);
     290          17 :         return ret;
     291             : }
     292             : 
     293             : 
     294         150 : int os_program_init(void)
     295             : {
     296             : #ifdef ANDROID
     297             :         /*
     298             :          * We ignore errors here since errors are normal if we
     299             :          * are already running as non-root.
     300             :          */
     301             : #ifdef ANDROID_SETGROUPS_OVERRIDE
     302             :         gid_t groups[] = { ANDROID_SETGROUPS_OVERRIDE };
     303             : #else /* ANDROID_SETGROUPS_OVERRIDE */
     304             :         gid_t groups[] = { AID_INET, AID_WIFI, AID_KEYSTORE };
     305             : #endif /* ANDROID_SETGROUPS_OVERRIDE */
     306             :         struct __user_cap_header_struct header;
     307             :         struct __user_cap_data_struct cap;
     308             : 
     309             :         setgroups(ARRAY_SIZE(groups), groups);
     310             : 
     311             :         prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
     312             : 
     313             :         setgid(AID_WIFI);
     314             :         setuid(AID_WIFI);
     315             : 
     316             :         header.version = _LINUX_CAPABILITY_VERSION;
     317             :         header.pid = 0;
     318             :         cap.effective = cap.permitted =
     319             :                 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
     320             :         cap.inheritable = 0;
     321             :         capset(&header, &cap);
     322             : #endif /* ANDROID */
     323             : 
     324             : #ifdef WPA_TRACE
     325         150 :         dl_list_init(&alloc_list);
     326             : #endif /* WPA_TRACE */
     327         150 :         return 0;
     328             : }
     329             : 
     330             : 
     331          85 : void os_program_deinit(void)
     332             : {
     333             : #ifdef WPA_TRACE
     334             :         struct os_alloc_trace *a;
     335          85 :         unsigned long total = 0;
     336          85 :         dl_list_for_each(a, &alloc_list, struct os_alloc_trace, list) {
     337           0 :                 total += a->len;
     338           0 :                 if (a->magic != ALLOC_MAGIC) {
     339           0 :                         wpa_printf(MSG_INFO, "MEMLEAK[%p]: invalid magic 0x%x "
     340             :                                    "len %lu",
     341             :                                    a, a->magic, (unsigned long) a->len);
     342           0 :                         continue;
     343             :                 }
     344           0 :                 wpa_printf(MSG_INFO, "MEMLEAK[%p]: len %lu",
     345             :                            a, (unsigned long) a->len);
     346           0 :                 wpa_trace_dump("memleak", a);
     347             :         }
     348          85 :         if (total)
     349           0 :                 wpa_printf(MSG_INFO, "MEMLEAK: total %lu bytes",
     350             :                            (unsigned long) total);
     351             : #endif /* WPA_TRACE */
     352          85 : }
     353             : 
     354             : 
     355           0 : int os_setenv(const char *name, const char *value, int overwrite)
     356             : {
     357           0 :         return setenv(name, value, overwrite);
     358             : }
     359             : 
     360             : 
     361           0 : int os_unsetenv(const char *name)
     362             : {
     363             : #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || \
     364             :     defined(__OpenBSD__)
     365             :         unsetenv(name);
     366             :         return 0;
     367             : #else
     368           0 :         return unsetenv(name);
     369             : #endif
     370             : }
     371             : 
     372             : 
     373          21 : char * os_readfile(const char *name, size_t *len)
     374             : {
     375             :         FILE *f;
     376             :         char *buf;
     377             :         long pos;
     378             : 
     379          21 :         f = fopen(name, "rb");
     380          21 :         if (f == NULL)
     381           2 :                 return NULL;
     382             : 
     383          19 :         if (fseek(f, 0, SEEK_END) < 0 || (pos = ftell(f)) < 0) {
     384           0 :                 fclose(f);
     385           0 :                 return NULL;
     386             :         }
     387          19 :         *len = pos;
     388          19 :         if (fseek(f, 0, SEEK_SET) < 0) {
     389           0 :                 fclose(f);
     390           0 :                 return NULL;
     391             :         }
     392             : 
     393          19 :         buf = os_malloc(*len);
     394          19 :         if (buf == NULL) {
     395           0 :                 fclose(f);
     396           0 :                 return NULL;
     397             :         }
     398             : 
     399          19 :         if (fread(buf, 1, *len, f) != *len) {
     400           0 :                 fclose(f);
     401           0 :                 os_free(buf);
     402           0 :                 return NULL;
     403             :         }
     404             : 
     405          19 :         fclose(f);
     406             : 
     407          19 :         return buf;
     408             : }
     409             : 
     410             : 
     411           0 : int os_file_exists(const char *fname)
     412             : {
     413           0 :         FILE *f = fopen(fname, "rb");
     414           0 :         if (f == NULL)
     415           0 :                 return 0;
     416           0 :         fclose(f);
     417           0 :         return 1;
     418             : }
     419             : 
     420             : 
     421             : #ifndef WPA_TRACE
     422             : void * os_zalloc(size_t size)
     423             : {
     424             :         return calloc(1, size);
     425             : }
     426             : #endif /* WPA_TRACE */
     427             : 
     428             : 
     429       89957 : size_t os_strlcpy(char *dest, const char *src, size_t siz)
     430             : {
     431       89957 :         const char *s = src;
     432       89957 :         size_t left = siz;
     433             : 
     434       89957 :         if (left) {
     435             :                 /* Copy string up to the maximum size of the dest buffer */
     436      640503 :                 while (--left != 0) {
     437      550171 :                         if ((*dest++ = *s++) == '\0')
     438       89582 :                                 break;
     439             :                 }
     440             :         }
     441             : 
     442       89957 :         if (left == 0) {
     443             :                 /* Not enough room for the string; force NUL-termination */
     444         375 :                 if (siz != 0)
     445         375 :                         *dest = '\0';
     446         375 :                 while (*s++)
     447             :                         ; /* determine total src string length */
     448             :         }
     449             : 
     450       89957 :         return s - src - 1;
     451             : }
     452             : 
     453             : 
     454       23033 : int os_memcmp_const(const void *a, const void *b, size_t len)
     455             : {
     456       23033 :         const u8 *aa = a;
     457       23033 :         const u8 *bb = b;
     458             :         size_t i;
     459             :         u8 res;
     460             : 
     461      382891 :         for (res = 0, i = 0; i < len; i++)
     462      359858 :                 res |= aa[i] ^ bb[i];
     463             : 
     464       23033 :         return res;
     465             : }
     466             : 
     467             : 
     468             : #ifdef WPA_TRACE
     469             : 
     470             : #if defined(WPA_TRACE_BFD) && defined(CONFIG_TESTING_OPTIONS)
     471             : char wpa_trace_fail_func[256] = { 0 };
     472             : unsigned int wpa_trace_fail_after;
     473             : 
     474     2160230 : static int testing_fail_alloc(void)
     475             : {
     476             :         const char *func[WPA_TRACE_LEN];
     477             :         size_t i, res, len;
     478             :         char *pos, *next;
     479             :         int match;
     480             : 
     481     2160230 :         if (!wpa_trace_fail_after)
     482     2110968 :                 return 0;
     483             : 
     484       49262 :         res = wpa_trace_calling_func(func, WPA_TRACE_LEN);
     485       49262 :         i = 0;
     486       49262 :         if (i < res && os_strcmp(func[i], __func__) == 0)
     487       49262 :                 i++;
     488       49262 :         if (i < res && os_strcmp(func[i], "os_malloc") == 0)
     489       49262 :                 i++;
     490       49262 :         if (i < res && os_strcmp(func[i], "os_zalloc") == 0)
     491       15830 :                 i++;
     492       49262 :         if (i < res && os_strcmp(func[i], "os_calloc") == 0)
     493        1643 :                 i++;
     494       49262 :         if (i < res && os_strcmp(func[i], "os_realloc") == 0)
     495        4759 :                 i++;
     496       49262 :         if (i < res && os_strcmp(func[i], "os_realloc_array") == 0)
     497        4751 :                 i++;
     498       49262 :         if (i < res && os_strcmp(func[i], "os_strdup") == 0)
     499        3900 :                 i++;
     500             : 
     501       49262 :         pos = wpa_trace_fail_func;
     502             : 
     503       49262 :         match = 0;
     504      545692 :         while (i < res) {
     505      472152 :                 int allow_skip = 1;
     506      472152 :                 int maybe = 0;
     507             : 
     508      472152 :                 if (*pos == '=') {
     509         866 :                         allow_skip = 0;
     510         866 :                         pos++;
     511      471286 :                 } else if (*pos == '?') {
     512           6 :                         maybe = 1;
     513           6 :                         pos++;
     514             :                 }
     515      472152 :                 next = os_strchr(pos, ';');
     516      472152 :                 if (next)
     517        7567 :                         len = next - pos;
     518             :                 else
     519      464585 :                         len = os_strlen(pos);
     520      472152 :                 if (os_memcmp(pos, func[i], len) != 0) {
     521      447140 :                         if (maybe && next) {
     522           0 :                                 pos = next + 1;
     523           0 :                                 continue;
     524             :                         }
     525      447140 :                         if (allow_skip) {
     526      446351 :                                 i++;
     527      446351 :                                 continue;
     528             :                         }
     529         789 :                         return 0;
     530             :                 }
     531       25012 :                 if (!next) {
     532       24195 :                         match = 1;
     533       24195 :                         break;
     534             :                 }
     535         817 :                 pos = next + 1;
     536         817 :                 i++;
     537             :         }
     538       48473 :         if (!match)
     539       24278 :                 return 0;
     540             : 
     541       24195 :         wpa_trace_fail_after--;
     542       24195 :         if (wpa_trace_fail_after == 0) {
     543         546 :                 wpa_printf(MSG_INFO, "TESTING: fail allocation at %s",
     544             :                            wpa_trace_fail_func);
     545        7218 :                 for (i = 0; i < res; i++)
     546        6672 :                         wpa_printf(MSG_INFO, "backtrace[%d] = %s",
     547             :                                    (int) i, func[i]);
     548         546 :                 return 1;
     549             :         }
     550             : 
     551       23649 :         return 0;
     552             : }
     553             : 
     554             : #else
     555             : 
     556             : static inline int testing_fail_alloc(void)
     557             : {
     558             :         return 0;
     559             : }
     560             : #endif
     561             : 
     562     2160230 : void * os_malloc(size_t size)
     563             : {
     564             :         struct os_alloc_trace *a;
     565             : 
     566     2160230 :         if (testing_fail_alloc())
     567         546 :                 return NULL;
     568             : 
     569     2159684 :         a = malloc(sizeof(*a) + size);
     570     2159684 :         if (a == NULL)
     571           0 :                 return NULL;
     572     2159684 :         a->magic = ALLOC_MAGIC;
     573     2159684 :         dl_list_add(&alloc_list, &a->list);
     574     2159684 :         a->len = size;
     575     2159684 :         wpa_trace_record(a);
     576     2159684 :         return a + 1;
     577             : }
     578             : 
     579             : 
     580      411702 : void * os_realloc(void *ptr, size_t size)
     581             : {
     582             :         struct os_alloc_trace *a;
     583             :         size_t copy_len;
     584             :         void *n;
     585             : 
     586      411702 :         if (ptr == NULL)
     587       39914 :                 return os_malloc(size);
     588             : 
     589      371788 :         a = (struct os_alloc_trace *) ptr - 1;
     590      371788 :         if (a->magic != ALLOC_MAGIC) {
     591           0 :                 wpa_printf(MSG_INFO, "REALLOC[%p]: invalid magic 0x%x%s",
     592             :                            a, a->magic,
     593           0 :                            a->magic == FREED_MAGIC ? " (already freed)" : "");
     594           0 :                 wpa_trace_show("Invalid os_realloc() call");
     595           0 :                 abort();
     596             :         }
     597      371788 :         n = os_malloc(size);
     598      371788 :         if (n == NULL)
     599          12 :                 return NULL;
     600      371776 :         copy_len = a->len;
     601      371776 :         if (copy_len > size)
     602        2691 :                 copy_len = size;
     603      371776 :         os_memcpy(n, a + 1, copy_len);
     604      371776 :         os_free(ptr);
     605      371776 :         return n;
     606             : }
     607             : 
     608             : 
     609     2640922 : void os_free(void *ptr)
     610             : {
     611             :         struct os_alloc_trace *a;
     612             : 
     613     2640922 :         if (ptr == NULL)
     614     3122170 :                 return;
     615     2159674 :         a = (struct os_alloc_trace *) ptr - 1;
     616     2159674 :         if (a->magic != ALLOC_MAGIC) {
     617           0 :                 wpa_printf(MSG_INFO, "FREE[%p]: invalid magic 0x%x%s",
     618             :                            a, a->magic,
     619           0 :                            a->magic == FREED_MAGIC ? " (already freed)" : "");
     620           0 :                 wpa_trace_show("Invalid os_free() call");
     621           0 :                 abort();
     622             :         }
     623     2159674 :         dl_list_del(&a->list);
     624     2159674 :         a->magic = FREED_MAGIC;
     625             : 
     626     2159674 :         wpa_trace_check_ref(ptr);
     627     2159674 :         free(a);
     628             : }
     629             : 
     630             : 
     631      467676 : void * os_zalloc(size_t size)
     632             : {
     633      467676 :         void *ptr = os_malloc(size);
     634      467676 :         if (ptr)
     635      467452 :                 os_memset(ptr, 0, size);
     636      467676 :         return ptr;
     637             : }
     638             : 
     639             : 
     640      188666 : char * os_strdup(const char *s)
     641             : {
     642             :         size_t len;
     643             :         char *d;
     644      188666 :         len = os_strlen(s);
     645      188666 :         d = os_malloc(len + 1);
     646      188666 :         if (d == NULL)
     647          54 :                 return NULL;
     648      188612 :         os_memcpy(d, s, len);
     649      188612 :         d[len] = '\0';
     650      188612 :         return d;
     651             : }
     652             : 
     653             : #endif /* WPA_TRACE */
     654             : 
     655             : 
     656           0 : int os_exec(const char *program, const char *arg, int wait_completion)
     657             : {
     658             :         pid_t pid;
     659             :         int pid_status;
     660             : 
     661           0 :         pid = fork();
     662           0 :         if (pid < 0) {
     663           0 :                 perror("fork");
     664           0 :                 return -1;
     665             :         }
     666             : 
     667           0 :         if (pid == 0) {
     668             :                 /* run the external command in the child process */
     669           0 :                 const int MAX_ARG = 30;
     670             :                 char *_program, *_arg, *pos;
     671           0 :                 char *argv[MAX_ARG + 1];
     672             :                 int i;
     673             : 
     674           0 :                 _program = os_strdup(program);
     675           0 :                 _arg = os_strdup(arg);
     676             : 
     677           0 :                 argv[0] = _program;
     678             : 
     679           0 :                 i = 1;
     680           0 :                 pos = _arg;
     681           0 :                 while (i < MAX_ARG && pos && *pos) {
     682           0 :                         while (*pos == ' ')
     683           0 :                                 pos++;
     684           0 :                         if (*pos == '\0')
     685           0 :                                 break;
     686           0 :                         argv[i++] = pos;
     687           0 :                         pos = os_strchr(pos, ' ');
     688           0 :                         if (pos)
     689           0 :                                 *pos++ = '\0';
     690             :                 }
     691           0 :                 argv[i] = NULL;
     692             : 
     693           0 :                 execv(program, argv);
     694           0 :                 perror("execv");
     695           0 :                 os_free(_program);
     696           0 :                 os_free(_arg);
     697           0 :                 exit(0);
     698             :                 return -1;
     699             :         }
     700             : 
     701           0 :         if (wait_completion) {
     702             :                 /* wait for the child process to complete in the parent */
     703           0 :                 waitpid(pid, &pid_status, 0);
     704             :         }
     705             : 
     706           0 :         return 0;
     707             : }

Generated by: LCOV version 1.10