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 1426431149 Lines: 199 321 62.0 %
Date: 2015-03-15 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 = DL_LIST_HEAD_INIT(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         535 : void os_sleep(os_time_t sec, os_time_t usec)
      45             : {
      46         535 :         if (sec)
      47           0 :                 sleep(sec);
      48         535 :         if (usec)
      49         535 :                 usleep(usec);
      50         535 : }
      51             : 
      52             : 
      53     3852997 : int os_get_time(struct os_time *t)
      54             : {
      55             :         int res;
      56             :         struct timeval tv;
      57     3852997 :         res = gettimeofday(&tv, NULL);
      58     3852997 :         t->sec = tv.tv_sec;
      59     3852997 :         t->usec = tv.tv_usec;
      60     3852997 :         return res;
      61             : }
      62             : 
      63             : 
      64      982767 : 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      982767 :                 res = clock_gettime(clock_id, &ts);
      78      982767 :                 if (res == 0) {
      79      982767 :                         t->sec = ts.tv_sec;
      80      982767 :                         t->usec = ts.tv_nsec / 1000;
      81      982767 :                         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       16319 : int os_get_random(unsigned char *buf, size_t len)
     225             : {
     226             :         FILE *f;
     227             :         size_t rc;
     228             : 
     229       16319 :         f = fopen("/dev/urandom", "rb");
     230       16319 :         if (f == NULL) {
     231           0 :                 printf("Could not open /dev/urandom.\n");
     232           0 :                 return -1;
     233             :         }
     234             : 
     235       16319 :         rc = fread(buf, 1, len, f);
     236       16319 :         fclose(f);
     237             : 
     238       16319 :         return rc != len ? -1 : 0;
     239             : }
     240             : 
     241             : 
     242        4626 : unsigned long os_random(void)
     243             : {
     244        4626 :         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         150 :         return 0;
     325             : }
     326             : 
     327             : 
     328          85 : void os_program_deinit(void)
     329             : {
     330             : #ifdef WPA_TRACE
     331             :         struct os_alloc_trace *a;
     332          85 :         unsigned long total = 0;
     333          85 :         dl_list_for_each(a, &alloc_list, struct os_alloc_trace, list) {
     334           0 :                 total += a->len;
     335           0 :                 if (a->magic != ALLOC_MAGIC) {
     336           0 :                         wpa_printf(MSG_INFO, "MEMLEAK[%p]: invalid magic 0x%x "
     337             :                                    "len %lu",
     338             :                                    a, a->magic, (unsigned long) a->len);
     339           0 :                         continue;
     340             :                 }
     341           0 :                 wpa_printf(MSG_INFO, "MEMLEAK[%p]: len %lu",
     342             :                            a, (unsigned long) a->len);
     343           0 :                 wpa_trace_dump("memleak", a);
     344             :         }
     345          85 :         if (total)
     346           0 :                 wpa_printf(MSG_INFO, "MEMLEAK: total %lu bytes",
     347             :                            (unsigned long) total);
     348             : #endif /* WPA_TRACE */
     349          85 : }
     350             : 
     351             : 
     352           0 : int os_setenv(const char *name, const char *value, int overwrite)
     353             : {
     354           0 :         return setenv(name, value, overwrite);
     355             : }
     356             : 
     357             : 
     358           0 : int os_unsetenv(const char *name)
     359             : {
     360             : #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || \
     361             :     defined(__OpenBSD__)
     362             :         unsetenv(name);
     363             :         return 0;
     364             : #else
     365           0 :         return unsetenv(name);
     366             : #endif
     367             : }
     368             : 
     369             : 
     370          21 : char * os_readfile(const char *name, size_t *len)
     371             : {
     372             :         FILE *f;
     373             :         char *buf;
     374             :         long pos;
     375             : 
     376          21 :         f = fopen(name, "rb");
     377          21 :         if (f == NULL)
     378           2 :                 return NULL;
     379             : 
     380          19 :         if (fseek(f, 0, SEEK_END) < 0 || (pos = ftell(f)) < 0) {
     381           0 :                 fclose(f);
     382           0 :                 return NULL;
     383             :         }
     384          19 :         *len = pos;
     385          19 :         if (fseek(f, 0, SEEK_SET) < 0) {
     386           0 :                 fclose(f);
     387           0 :                 return NULL;
     388             :         }
     389             : 
     390          19 :         buf = os_malloc(*len);
     391          19 :         if (buf == NULL) {
     392           0 :                 fclose(f);
     393           0 :                 return NULL;
     394             :         }
     395             : 
     396          19 :         if (fread(buf, 1, *len, f) != *len) {
     397           0 :                 fclose(f);
     398           0 :                 os_free(buf);
     399           0 :                 return NULL;
     400             :         }
     401             : 
     402          19 :         fclose(f);
     403             : 
     404          19 :         return buf;
     405             : }
     406             : 
     407             : 
     408           0 : int os_file_exists(const char *fname)
     409             : {
     410           0 :         FILE *f = fopen(fname, "rb");
     411           0 :         if (f == NULL)
     412           0 :                 return 0;
     413           0 :         fclose(f);
     414           0 :         return 1;
     415             : }
     416             : 
     417             : 
     418             : #ifndef WPA_TRACE
     419             : void * os_zalloc(size_t size)
     420             : {
     421             :         return calloc(1, size);
     422             : }
     423             : #endif /* WPA_TRACE */
     424             : 
     425             : 
     426       98589 : size_t os_strlcpy(char *dest, const char *src, size_t siz)
     427             : {
     428       98589 :         const char *s = src;
     429       98589 :         size_t left = siz;
     430             : 
     431       98589 :         if (left) {
     432             :                 /* Copy string up to the maximum size of the dest buffer */
     433      698729 :                 while (--left != 0) {
     434      599726 :                         if ((*dest++ = *s++) == '\0')
     435       98175 :                                 break;
     436             :                 }
     437             :         }
     438             : 
     439       98589 :         if (left == 0) {
     440             :                 /* Not enough room for the string; force NUL-termination */
     441         414 :                 if (siz != 0)
     442         414 :                         *dest = '\0';
     443         414 :                 while (*s++)
     444             :                         ; /* determine total src string length */
     445             :         }
     446             : 
     447       98589 :         return s - src - 1;
     448             : }
     449             : 
     450             : 
     451       23875 : int os_memcmp_const(const void *a, const void *b, size_t len)
     452             : {
     453       23875 :         const u8 *aa = a;
     454       23875 :         const u8 *bb = b;
     455             :         size_t i;
     456             :         u8 res;
     457             : 
     458      399649 :         for (res = 0, i = 0; i < len; i++)
     459      375774 :                 res |= aa[i] ^ bb[i];
     460             : 
     461       23875 :         return res;
     462             : }
     463             : 
     464             : 
     465             : #ifdef WPA_TRACE
     466             : 
     467             : #if defined(WPA_TRACE_BFD) && defined(CONFIG_TESTING_OPTIONS)
     468             : char wpa_trace_fail_func[256] = { 0 };
     469             : unsigned int wpa_trace_fail_after;
     470             : 
     471     2251940 : static int testing_fail_alloc(void)
     472             : {
     473             :         const char *func[WPA_TRACE_LEN];
     474             :         size_t i, res, len;
     475             :         char *pos, *next;
     476             :         int match;
     477             : 
     478     2251940 :         if (!wpa_trace_fail_after)
     479     2202465 :                 return 0;
     480             : 
     481       49475 :         res = wpa_trace_calling_func(func, WPA_TRACE_LEN);
     482       49475 :         i = 0;
     483       49475 :         if (i < res && os_strcmp(func[i], __func__) == 0)
     484       49475 :                 i++;
     485       49475 :         if (i < res && os_strcmp(func[i], "os_malloc") == 0)
     486       49475 :                 i++;
     487       49475 :         if (i < res && os_strcmp(func[i], "os_zalloc") == 0)
     488       15801 :                 i++;
     489       49475 :         if (i < res && os_strcmp(func[i], "os_calloc") == 0)
     490        1653 :                 i++;
     491       49475 :         if (i < res && os_strcmp(func[i], "os_realloc") == 0)
     492        4960 :                 i++;
     493       49475 :         if (i < res && os_strcmp(func[i], "os_realloc_array") == 0)
     494        4957 :                 i++;
     495       49475 :         if (i < res && os_strcmp(func[i], "os_strdup") == 0)
     496        3869 :                 i++;
     497             : 
     498       49475 :         pos = wpa_trace_fail_func;
     499             : 
     500       49475 :         match = 0;
     501      548181 :         while (i < res) {
     502      474234 :                 int allow_skip = 1;
     503      474234 :                 int maybe = 0;
     504             : 
     505      474234 :                 if (*pos == '=') {
     506         879 :                         allow_skip = 0;
     507         879 :                         pos++;
     508      473355 :                 } else if (*pos == '?') {
     509           6 :                         maybe = 1;
     510           6 :                         pos++;
     511             :                 }
     512      474234 :                 next = os_strchr(pos, ';');
     513      474234 :                 if (next)
     514        7612 :                         len = next - pos;
     515             :                 else
     516      466622 :                         len = os_strlen(pos);
     517      474234 :                 if (os_memcmp(pos, func[i], len) != 0) {
     518      449216 :                         if (maybe && next) {
     519           0 :                                 pos = next + 1;
     520           0 :                                 continue;
     521             :                         }
     522      449216 :                         if (allow_skip) {
     523      448414 :                                 i++;
     524      448414 :                                 continue;
     525             :                         }
     526         802 :                         return 0;
     527             :                 }
     528       25018 :                 if (!next) {
     529       24201 :                         match = 1;
     530       24201 :                         break;
     531             :                 }
     532         817 :                 pos = next + 1;
     533         817 :                 i++;
     534             :         }
     535       48673 :         if (!match)
     536       24472 :                 return 0;
     537             : 
     538       24201 :         wpa_trace_fail_after--;
     539       24201 :         if (wpa_trace_fail_after == 0) {
     540         549 :                 wpa_printf(MSG_INFO, "TESTING: fail allocation at %s",
     541             :                            wpa_trace_fail_func);
     542        7210 :                 for (i = 0; i < res; i++)
     543        6661 :                         wpa_printf(MSG_INFO, "backtrace[%d] = %s",
     544             :                                    (int) i, func[i]);
     545         549 :                 return 1;
     546             :         }
     547             : 
     548       23652 :         return 0;
     549             : }
     550             : 
     551             : #else
     552             : 
     553             : static inline int testing_fail_alloc(void)
     554             : {
     555             :         return 0;
     556             : }
     557             : #endif
     558             : 
     559     2251940 : void * os_malloc(size_t size)
     560             : {
     561             :         struct os_alloc_trace *a;
     562             : 
     563     2251940 :         if (testing_fail_alloc())
     564         549 :                 return NULL;
     565             : 
     566     2251391 :         a = malloc(sizeof(*a) + size);
     567     2251391 :         if (a == NULL)
     568           0 :                 return NULL;
     569     2251391 :         a->magic = ALLOC_MAGIC;
     570     2251391 :         dl_list_add(&alloc_list, &a->list);
     571     2251391 :         a->len = size;
     572     2251391 :         wpa_trace_record(a);
     573     2251391 :         return a + 1;
     574             : }
     575             : 
     576             : 
     577      437216 : void * os_realloc(void *ptr, size_t size)
     578             : {
     579             :         struct os_alloc_trace *a;
     580             :         size_t copy_len;
     581             :         void *n;
     582             : 
     583      437216 :         if (ptr == NULL)
     584       42224 :                 return os_malloc(size);
     585             : 
     586      394992 :         a = (struct os_alloc_trace *) ptr - 1;
     587      394992 :         if (a->magic != ALLOC_MAGIC) {
     588           0 :                 wpa_printf(MSG_INFO, "REALLOC[%p]: invalid magic 0x%x%s",
     589             :                            a, a->magic,
     590           0 :                            a->magic == FREED_MAGIC ? " (already freed)" : "");
     591           0 :                 wpa_trace_show("Invalid os_realloc() call");
     592           0 :                 abort();
     593             :         }
     594      394992 :         n = os_malloc(size);
     595      394992 :         if (n == NULL)
     596          11 :                 return NULL;
     597      394981 :         copy_len = a->len;
     598      394981 :         if (copy_len > size)
     599        1842 :                 copy_len = size;
     600      394981 :         os_memcpy(n, a + 1, copy_len);
     601      394981 :         os_free(ptr);
     602      394981 :         return n;
     603             : }
     604             : 
     605             : 
     606     2765151 : void os_free(void *ptr)
     607             : {
     608             :         struct os_alloc_trace *a;
     609             : 
     610     2765151 :         if (ptr == NULL)
     611     3278921 :                 return;
     612     2251381 :         a = (struct os_alloc_trace *) ptr - 1;
     613     2251381 :         if (a->magic != ALLOC_MAGIC) {
     614           0 :                 wpa_printf(MSG_INFO, "FREE[%p]: invalid magic 0x%x%s",
     615             :                            a, a->magic,
     616           0 :                            a->magic == FREED_MAGIC ? " (already freed)" : "");
     617           0 :                 wpa_trace_show("Invalid os_free() call");
     618           0 :                 abort();
     619             :         }
     620     2251381 :         dl_list_del(&a->list);
     621     2251381 :         a->magic = FREED_MAGIC;
     622             : 
     623     2251381 :         wpa_trace_check_ref(ptr);
     624     2251381 :         free(a);
     625             : }
     626             : 
     627             : 
     628      486589 : void * os_zalloc(size_t size)
     629             : {
     630      486589 :         void *ptr = os_malloc(size);
     631      486589 :         if (ptr)
     632      486362 :                 os_memset(ptr, 0, size);
     633      486589 :         return ptr;
     634             : }
     635             : 
     636             : 
     637      197654 : char * os_strdup(const char *s)
     638             : {
     639             :         size_t len;
     640             :         char *d;
     641      197654 :         len = os_strlen(s);
     642      197654 :         d = os_malloc(len + 1);
     643      197654 :         if (d == NULL)
     644          50 :                 return NULL;
     645      197604 :         os_memcpy(d, s, len);
     646      197604 :         d[len] = '\0';
     647      197604 :         return d;
     648             : }
     649             : 
     650             : #endif /* WPA_TRACE */
     651             : 
     652             : 
     653           0 : int os_exec(const char *program, const char *arg, int wait_completion)
     654             : {
     655             :         pid_t pid;
     656             :         int pid_status;
     657             : 
     658           0 :         pid = fork();
     659           0 :         if (pid < 0) {
     660           0 :                 perror("fork");
     661           0 :                 return -1;
     662             :         }
     663             : 
     664           0 :         if (pid == 0) {
     665             :                 /* run the external command in the child process */
     666           0 :                 const int MAX_ARG = 30;
     667             :                 char *_program, *_arg, *pos;
     668           0 :                 char *argv[MAX_ARG + 1];
     669             :                 int i;
     670             : 
     671           0 :                 _program = os_strdup(program);
     672           0 :                 _arg = os_strdup(arg);
     673             : 
     674           0 :                 argv[0] = _program;
     675             : 
     676           0 :                 i = 1;
     677           0 :                 pos = _arg;
     678           0 :                 while (i < MAX_ARG && pos && *pos) {
     679           0 :                         while (*pos == ' ')
     680           0 :                                 pos++;
     681           0 :                         if (*pos == '\0')
     682           0 :                                 break;
     683           0 :                         argv[i++] = pos;
     684           0 :                         pos = os_strchr(pos, ' ');
     685           0 :                         if (pos)
     686           0 :                                 *pos++ = '\0';
     687             :                 }
     688           0 :                 argv[i] = NULL;
     689             : 
     690           0 :                 execv(program, argv);
     691           0 :                 perror("execv");
     692           0 :                 os_free(_program);
     693           0 :                 os_free(_arg);
     694           0 :                 exit(0);
     695             :                 return -1;
     696             :         }
     697             : 
     698           0 :         if (wait_completion) {
     699             :                 /* wait for the child process to complete in the parent */
     700           0 :                 waitpid(pid, &pid_status, 0);
     701             :         }
     702             : 
     703           0 :         return 0;
     704             : }

Generated by: LCOV version 1.10