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 711 : void os_sleep(os_time_t sec, os_time_t usec)
51 : {
52 711 : if (sec)
53 1 : sleep(sec);
54 711 : if (usec)
55 711 : usleep(usec);
56 711 : }
57 :
58 :
59 6017587 : int os_get_time(struct os_time *t)
60 : {
61 : int res;
62 : struct timeval tv;
63 6017587 : res = gettimeofday(&tv, NULL);
64 6017587 : t->sec = tv.tv_sec;
65 6017587 : t->usec = tv.tv_usec;
66 6017587 : return res;
67 : }
68 :
69 :
70 1639395 : 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 1639395 : res = clock_gettime(clock_id, &ts);
85 1639395 : if (res == 0) {
86 1639395 : t->sec = ts.tv_sec;
87 1639395 : t->usec = ts.tv_nsec / 1000;
88 1639395 : 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 28453 : int os_get_random(unsigned char *buf, size_t len)
249 : {
250 : FILE *f;
251 : size_t rc;
252 :
253 28453 : if (TEST_FAIL())
254 19 : return -1;
255 :
256 28434 : f = fopen("/dev/urandom", "rb");
257 28434 : if (f == NULL) {
258 0 : printf("Could not open /dev/urandom.\n");
259 0 : return -1;
260 : }
261 :
262 28434 : rc = fread(buf, 1, len, f);
263 28434 : fclose(f);
264 :
265 28434 : return rc != len ? -1 : 0;
266 : }
267 :
268 :
269 5179 : unsigned long os_random(void)
270 : {
271 5179 : return random();
272 : }
273 :
274 :
275 121 : char * os_rel2abs_path(const char *rel_path)
276 : {
277 121 : char *buf = NULL, *cwd, *ret;
278 121 : size_t len = 128, cwd_len, rel_len, ret_len;
279 : int last_errno;
280 :
281 121 : if (!rel_path)
282 34 : return NULL;
283 :
284 87 : if (rel_path[0] == '/')
285 69 : 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 : #endif /* WPA_TRACE */
376 129 : }
377 :
378 :
379 2 : int os_setenv(const char *name, const char *value, int overwrite)
380 : {
381 2 : return setenv(name, value, overwrite);
382 : }
383 :
384 :
385 1 : int os_unsetenv(const char *name)
386 : {
387 : #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || \
388 : defined(__OpenBSD__)
389 : unsetenv(name);
390 : return 0;
391 : #else
392 1 : return unsetenv(name);
393 : #endif
394 : }
395 :
396 :
397 24 : char * os_readfile(const char *name, size_t *len)
398 : {
399 : FILE *f;
400 : char *buf;
401 : long pos;
402 :
403 24 : f = fopen(name, "rb");
404 24 : if (f == NULL)
405 3 : return NULL;
406 :
407 21 : if (fseek(f, 0, SEEK_END) < 0 || (pos = ftell(f)) < 0) {
408 0 : fclose(f);
409 0 : return NULL;
410 : }
411 21 : *len = pos;
412 21 : if (fseek(f, 0, SEEK_SET) < 0) {
413 0 : fclose(f);
414 0 : return NULL;
415 : }
416 :
417 21 : buf = os_malloc(*len);
418 21 : if (buf == NULL) {
419 0 : fclose(f);
420 0 : return NULL;
421 : }
422 :
423 21 : if (fread(buf, 1, *len, f) != *len) {
424 0 : fclose(f);
425 0 : os_free(buf);
426 0 : return NULL;
427 : }
428 :
429 21 : fclose(f);
430 :
431 21 : return buf;
432 : }
433 :
434 :
435 1 : int os_file_exists(const char *fname)
436 : {
437 1 : FILE *f = fopen(fname, "rb");
438 1 : if (f == NULL)
439 1 : return 0;
440 0 : fclose(f);
441 0 : return 1;
442 : }
443 :
444 :
445 5 : int os_fdatasync(FILE *stream)
446 : {
447 5 : if (!fflush(stream)) {
448 : #ifndef __MACH__
449 5 : return fdatasync(fileno(stream));
450 : #else /* __MACH__ */
451 : #ifdef F_FULLFSYNC
452 : /* OS X does not implement fdatasync(). */
453 : return fcntl(fileno(stream), F_FULLFSYNC);
454 : #else /* F_FULLFSYNC */
455 : #error Neither fdatasync nor F_FULLSYNC are defined
456 : #endif /* F_FULLFSYNC */
457 : #endif /* __MACH__ */
458 : }
459 :
460 0 : return -1;
461 : }
462 :
463 :
464 : #ifndef WPA_TRACE
465 : void * os_zalloc(size_t size)
466 : {
467 : return calloc(1, size);
468 : }
469 : #endif /* WPA_TRACE */
470 :
471 :
472 166202 : size_t os_strlcpy(char *dest, const char *src, size_t siz)
473 : {
474 166202 : const char *s = src;
475 166202 : size_t left = siz;
476 :
477 166202 : if (left) {
478 : /* Copy string up to the maximum size of the dest buffer */
479 1145311 : while (--left != 0) {
480 977107 : if ((*dest++ = *s++) == '\0')
481 164200 : break;
482 : }
483 : }
484 :
485 166202 : if (left == 0) {
486 : /* Not enough room for the string; force NUL-termination */
487 2002 : if (siz != 0)
488 2002 : *dest = '\0';
489 2002 : while (*s++)
490 : ; /* determine total src string length */
491 : }
492 :
493 166202 : return s - src - 1;
494 : }
495 :
496 :
497 27179 : int os_memcmp_const(const void *a, const void *b, size_t len)
498 : {
499 27179 : const u8 *aa = a;
500 27179 : const u8 *bb = b;
501 : size_t i;
502 : u8 res;
503 :
504 454662 : for (res = 0, i = 0; i < len; i++)
505 427483 : res |= aa[i] ^ bb[i];
506 :
507 27179 : return res;
508 : }
509 :
510 :
511 : #ifdef WPA_TRACE
512 :
513 : #if defined(WPA_TRACE_BFD) && defined(CONFIG_TESTING_OPTIONS)
514 : char wpa_trace_fail_func[256] = { 0 };
515 : unsigned int wpa_trace_fail_after;
516 :
517 3589565 : static int testing_fail_alloc(void)
518 : {
519 : const char *func[WPA_TRACE_LEN];
520 : size_t i, res, len;
521 : char *pos, *next;
522 : int match;
523 :
524 3589565 : if (!wpa_trace_fail_after)
525 3512535 : return 0;
526 :
527 77030 : res = wpa_trace_calling_func(func, WPA_TRACE_LEN);
528 77030 : i = 0;
529 77030 : if (i < res && os_strcmp(func[i], __func__) == 0)
530 77030 : i++;
531 77030 : if (i < res && os_strcmp(func[i], "os_malloc") == 0)
532 77030 : i++;
533 77030 : if (i < res && os_strcmp(func[i], "os_zalloc") == 0)
534 21926 : i++;
535 77030 : if (i < res && os_strcmp(func[i], "os_calloc") == 0)
536 2291 : i++;
537 77030 : if (i < res && os_strcmp(func[i], "os_realloc") == 0)
538 7285 : i++;
539 77030 : if (i < res && os_strcmp(func[i], "os_realloc_array") == 0)
540 7100 : i++;
541 77030 : if (i < res && os_strcmp(func[i], "os_strdup") == 0)
542 7756 : i++;
543 :
544 77030 : pos = wpa_trace_fail_func;
545 :
546 77030 : match = 0;
547 876459 : while (i < res) {
548 751432 : int allow_skip = 1;
549 751432 : int maybe = 0;
550 :
551 751432 : if (*pos == '=') {
552 1996 : allow_skip = 0;
553 1996 : pos++;
554 749436 : } else if (*pos == '?') {
555 6 : maybe = 1;
556 6 : pos++;
557 : }
558 751432 : next = os_strchr(pos, ';');
559 751432 : if (next)
560 49758 : len = next - pos;
561 : else
562 701674 : len = os_strlen(pos);
563 751432 : if (os_memcmp(pos, func[i], len) != 0) {
564 722801 : if (maybe && next) {
565 0 : pos = next + 1;
566 0 : continue;
567 : }
568 722801 : if (allow_skip) {
569 720891 : i++;
570 720891 : continue;
571 : }
572 1910 : return 0;
573 : }
574 28631 : if (!next) {
575 27123 : match = 1;
576 27123 : break;
577 : }
578 1508 : pos = next + 1;
579 1508 : i++;
580 : }
581 75120 : if (!match)
582 47997 : return 0;
583 :
584 27123 : wpa_trace_fail_after--;
585 27123 : if (wpa_trace_fail_after == 0) {
586 852 : wpa_printf(MSG_INFO, "TESTING: fail allocation at %s",
587 : wpa_trace_fail_func);
588 11550 : for (i = 0; i < res; i++)
589 10698 : wpa_printf(MSG_INFO, "backtrace[%d] = %s",
590 : (int) i, func[i]);
591 852 : return 1;
592 : }
593 :
594 26271 : return 0;
595 : }
596 :
597 :
598 : char wpa_trace_test_fail_func[256] = { 0 };
599 : unsigned int wpa_trace_test_fail_after;
600 :
601 33247 : int testing_test_fail(void)
602 : {
603 : const char *func[WPA_TRACE_LEN];
604 : size_t i, res, len;
605 : char *pos, *next;
606 : int match;
607 :
608 33247 : if (!wpa_trace_test_fail_after)
609 33145 : return 0;
610 :
611 102 : res = wpa_trace_calling_func(func, WPA_TRACE_LEN);
612 102 : i = 0;
613 102 : if (i < res && os_strcmp(func[i], __func__) == 0)
614 102 : i++;
615 :
616 102 : pos = wpa_trace_test_fail_func;
617 :
618 102 : match = 0;
619 1232 : while (i < res) {
620 1050 : int allow_skip = 1;
621 1050 : int maybe = 0;
622 :
623 1050 : if (*pos == '=') {
624 0 : allow_skip = 0;
625 0 : pos++;
626 1050 : } else if (*pos == '?') {
627 0 : maybe = 1;
628 0 : pos++;
629 : }
630 1050 : next = os_strchr(pos, ';');
631 1050 : if (next)
632 225 : len = next - pos;
633 : else
634 825 : len = os_strlen(pos);
635 1050 : if (os_memcmp(pos, func[i], len) != 0) {
636 936 : if (maybe && next) {
637 0 : pos = next + 1;
638 0 : continue;
639 : }
640 936 : if (allow_skip) {
641 936 : i++;
642 936 : continue;
643 : }
644 0 : return 0;
645 : }
646 114 : if (!next) {
647 22 : match = 1;
648 22 : break;
649 : }
650 92 : pos = next + 1;
651 92 : i++;
652 : }
653 102 : if (!match)
654 80 : return 0;
655 :
656 22 : wpa_trace_test_fail_after--;
657 22 : if (wpa_trace_test_fail_after == 0) {
658 21 : wpa_printf(MSG_INFO, "TESTING: fail at %s",
659 : wpa_trace_test_fail_func);
660 301 : for (i = 0; i < res; i++)
661 280 : wpa_printf(MSG_INFO, "backtrace[%d] = %s",
662 : (int) i, func[i]);
663 21 : return 1;
664 : }
665 :
666 1 : return 0;
667 : }
668 :
669 : #else
670 :
671 : static inline int testing_fail_alloc(void)
672 : {
673 : return 0;
674 : }
675 : #endif
676 :
677 3589565 : void * os_malloc(size_t size)
678 : {
679 : struct os_alloc_trace *a;
680 :
681 3589565 : if (testing_fail_alloc())
682 852 : return NULL;
683 :
684 3588713 : a = malloc(sizeof(*a) + size);
685 3588713 : if (a == NULL)
686 0 : return NULL;
687 3588713 : a->magic = ALLOC_MAGIC;
688 3588713 : dl_list_add(&alloc_list, &a->list);
689 3588713 : a->len = size;
690 3588713 : wpa_trace_record(a);
691 3588713 : return a + 1;
692 : }
693 :
694 :
695 650034 : void * os_realloc(void *ptr, size_t size)
696 : {
697 : struct os_alloc_trace *a;
698 : size_t copy_len;
699 : void *n;
700 :
701 650034 : if (ptr == NULL)
702 63368 : return os_malloc(size);
703 :
704 586666 : a = (struct os_alloc_trace *) ptr - 1;
705 586666 : if (a->magic != ALLOC_MAGIC) {
706 0 : wpa_printf(MSG_INFO, "REALLOC[%p]: invalid magic 0x%x%s",
707 : a, a->magic,
708 0 : a->magic == FREED_MAGIC ? " (already freed)" : "");
709 0 : wpa_trace_show("Invalid os_realloc() call");
710 0 : abort();
711 : }
712 586666 : n = os_malloc(size);
713 586666 : if (n == NULL)
714 24 : return NULL;
715 586642 : copy_len = a->len;
716 586642 : if (copy_len > size)
717 2771 : copy_len = size;
718 586642 : os_memcpy(n, a + 1, copy_len);
719 586642 : os_free(ptr);
720 586642 : return n;
721 : }
722 :
723 :
724 4326908 : void os_free(void *ptr)
725 : {
726 : struct os_alloc_trace *a;
727 :
728 4326908 : if (ptr == NULL)
729 5065115 : return;
730 3588701 : a = (struct os_alloc_trace *) ptr - 1;
731 3588701 : if (a->magic != ALLOC_MAGIC) {
732 0 : wpa_printf(MSG_INFO, "FREE[%p]: invalid magic 0x%x%s",
733 : a, a->magic,
734 0 : a->magic == FREED_MAGIC ? " (already freed)" : "");
735 0 : wpa_trace_show("Invalid os_free() call");
736 0 : abort();
737 : }
738 3588701 : dl_list_del(&a->list);
739 3588701 : a->magic = FREED_MAGIC;
740 :
741 3588701 : wpa_trace_check_ref(ptr);
742 3588701 : free(a);
743 : }
744 :
745 :
746 700584 : void * os_zalloc(size_t size)
747 : {
748 700584 : void *ptr = os_malloc(size);
749 700584 : if (ptr)
750 700206 : os_memset(ptr, 0, size);
751 700584 : return ptr;
752 : }
753 :
754 :
755 249725 : char * os_strdup(const char *s)
756 : {
757 : size_t len;
758 : char *d;
759 249725 : len = os_strlen(s);
760 249725 : d = os_malloc(len + 1);
761 249725 : if (d == NULL)
762 68 : return NULL;
763 249657 : os_memcpy(d, s, len);
764 249657 : d[len] = '\0';
765 249657 : return d;
766 : }
767 :
768 : #endif /* WPA_TRACE */
769 :
770 :
771 1 : int os_exec(const char *program, const char *arg, int wait_completion)
772 : {
773 : pid_t pid;
774 : int pid_status;
775 :
776 1 : pid = fork();
777 1 : if (pid < 0) {
778 0 : perror("fork");
779 0 : return -1;
780 : }
781 :
782 1 : if (pid == 0) {
783 : /* run the external command in the child process */
784 0 : const int MAX_ARG = 30;
785 : char *_program, *_arg, *pos;
786 0 : char *argv[MAX_ARG + 1];
787 : int i;
788 :
789 0 : _program = os_strdup(program);
790 0 : _arg = os_strdup(arg);
791 :
792 0 : argv[0] = _program;
793 :
794 0 : i = 1;
795 0 : pos = _arg;
796 0 : while (i < MAX_ARG && pos && *pos) {
797 0 : while (*pos == ' ')
798 0 : pos++;
799 0 : if (*pos == '\0')
800 0 : break;
801 0 : argv[i++] = pos;
802 0 : pos = os_strchr(pos, ' ');
803 0 : if (pos)
804 0 : *pos++ = '\0';
805 : }
806 0 : argv[i] = NULL;
807 :
808 0 : execv(program, argv);
809 0 : perror("execv");
810 0 : os_free(_program);
811 0 : os_free(_arg);
812 0 : exit(0);
813 : return -1;
814 : }
815 :
816 1 : if (wait_completion) {
817 : /* wait for the child process to complete in the parent */
818 1 : waitpid(pid, &pid_status, 0);
819 : }
820 :
821 1 : return 0;
822 : }
|