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