xref: /freebsd/contrib/wpa/src/utils/os_unix.c (revision 39beb93c3f8bdbf72a61fda42300b5ebed7390c8)
139beb93cSSam Leffler /*
239beb93cSSam Leffler  * wpa_supplicant/hostapd / OS specific functions for UNIX/POSIX systems
339beb93cSSam Leffler  * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi>
439beb93cSSam Leffler  *
539beb93cSSam Leffler  * This program is free software; you can redistribute it and/or modify
639beb93cSSam Leffler  * it under the terms of the GNU General Public License version 2 as
739beb93cSSam Leffler  * published by the Free Software Foundation.
839beb93cSSam Leffler  *
939beb93cSSam Leffler  * Alternatively, this software may be distributed under the terms of BSD
1039beb93cSSam Leffler  * license.
1139beb93cSSam Leffler  *
1239beb93cSSam Leffler  * See README and COPYING for more details.
1339beb93cSSam Leffler  */
1439beb93cSSam Leffler 
1539beb93cSSam Leffler #include "includes.h"
1639beb93cSSam Leffler 
1739beb93cSSam Leffler #include "os.h"
1839beb93cSSam Leffler 
1939beb93cSSam Leffler void os_sleep(os_time_t sec, os_time_t usec)
2039beb93cSSam Leffler {
2139beb93cSSam Leffler 	if (sec)
2239beb93cSSam Leffler 		sleep(sec);
2339beb93cSSam Leffler 	if (usec)
2439beb93cSSam Leffler 		usleep(usec);
2539beb93cSSam Leffler }
2639beb93cSSam Leffler 
2739beb93cSSam Leffler 
2839beb93cSSam Leffler int os_get_time(struct os_time *t)
2939beb93cSSam Leffler {
3039beb93cSSam Leffler 	int res;
3139beb93cSSam Leffler 	struct timeval tv;
3239beb93cSSam Leffler 	res = gettimeofday(&tv, NULL);
3339beb93cSSam Leffler 	t->sec = tv.tv_sec;
3439beb93cSSam Leffler 	t->usec = tv.tv_usec;
3539beb93cSSam Leffler 	return res;
3639beb93cSSam Leffler }
3739beb93cSSam Leffler 
3839beb93cSSam Leffler 
3939beb93cSSam Leffler int os_mktime(int year, int month, int day, int hour, int min, int sec,
4039beb93cSSam Leffler 	      os_time_t *t)
4139beb93cSSam Leffler {
4239beb93cSSam Leffler 	struct tm tm, *tm1;
4339beb93cSSam Leffler 	time_t t_local, t1, t2;
4439beb93cSSam Leffler 	os_time_t tz_offset;
4539beb93cSSam Leffler 
4639beb93cSSam Leffler 	if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
4739beb93cSSam Leffler 	    hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 ||
4839beb93cSSam Leffler 	    sec > 60)
4939beb93cSSam Leffler 		return -1;
5039beb93cSSam Leffler 
5139beb93cSSam Leffler 	memset(&tm, 0, sizeof(tm));
5239beb93cSSam Leffler 	tm.tm_year = year - 1900;
5339beb93cSSam Leffler 	tm.tm_mon = month - 1;
5439beb93cSSam Leffler 	tm.tm_mday = day;
5539beb93cSSam Leffler 	tm.tm_hour = hour;
5639beb93cSSam Leffler 	tm.tm_min = min;
5739beb93cSSam Leffler 	tm.tm_sec = sec;
5839beb93cSSam Leffler 
5939beb93cSSam Leffler 	t_local = mktime(&tm);
6039beb93cSSam Leffler 
6139beb93cSSam Leffler 	/* figure out offset to UTC */
6239beb93cSSam Leffler 	tm1 = localtime(&t_local);
6339beb93cSSam Leffler 	if (tm1) {
6439beb93cSSam Leffler 		t1 = mktime(tm1);
6539beb93cSSam Leffler 		tm1 = gmtime(&t_local);
6639beb93cSSam Leffler 		if (tm1) {
6739beb93cSSam Leffler 			t2 = mktime(tm1);
6839beb93cSSam Leffler 			tz_offset = t2 - t1;
6939beb93cSSam Leffler 		} else
7039beb93cSSam Leffler 			tz_offset = 0;
7139beb93cSSam Leffler 	} else
7239beb93cSSam Leffler 		tz_offset = 0;
7339beb93cSSam Leffler 
7439beb93cSSam Leffler 	*t = (os_time_t) t_local - tz_offset;
7539beb93cSSam Leffler 	return 0;
7639beb93cSSam Leffler }
7739beb93cSSam Leffler 
7839beb93cSSam Leffler 
7939beb93cSSam Leffler #ifdef __APPLE__
8039beb93cSSam Leffler #include <fcntl.h>
8139beb93cSSam Leffler static int os_daemon(int nochdir, int noclose)
8239beb93cSSam Leffler {
8339beb93cSSam Leffler 	int devnull;
8439beb93cSSam Leffler 
8539beb93cSSam Leffler 	if (chdir("/") < 0)
8639beb93cSSam Leffler 		return -1;
8739beb93cSSam Leffler 
8839beb93cSSam Leffler 	devnull = open("/dev/null", O_RDWR);
8939beb93cSSam Leffler 	if (devnull < 0)
9039beb93cSSam Leffler 		return -1;
9139beb93cSSam Leffler 
9239beb93cSSam Leffler 	if (dup2(devnull, STDIN_FILENO) < 0) {
9339beb93cSSam Leffler 		close(devnull);
9439beb93cSSam Leffler 		return -1;
9539beb93cSSam Leffler 	}
9639beb93cSSam Leffler 
9739beb93cSSam Leffler 	if (dup2(devnull, STDOUT_FILENO) < 0) {
9839beb93cSSam Leffler 		close(devnull);
9939beb93cSSam Leffler 		return -1;
10039beb93cSSam Leffler 	}
10139beb93cSSam Leffler 
10239beb93cSSam Leffler 	if (dup2(devnull, STDERR_FILENO) < 0) {
10339beb93cSSam Leffler 		close(devnull);
10439beb93cSSam Leffler 		return -1;
10539beb93cSSam Leffler 	}
10639beb93cSSam Leffler 
10739beb93cSSam Leffler 	return 0;
10839beb93cSSam Leffler }
10939beb93cSSam Leffler #else /* __APPLE__ */
11039beb93cSSam Leffler #define os_daemon daemon
11139beb93cSSam Leffler #endif /* __APPLE__ */
11239beb93cSSam Leffler 
11339beb93cSSam Leffler 
11439beb93cSSam Leffler int os_daemonize(const char *pid_file)
11539beb93cSSam Leffler {
11639beb93cSSam Leffler #ifdef __uClinux__
11739beb93cSSam Leffler 	return -1;
11839beb93cSSam Leffler #else /* __uClinux__ */
11939beb93cSSam Leffler 	if (os_daemon(0, 0)) {
12039beb93cSSam Leffler 		perror("daemon");
12139beb93cSSam Leffler 		return -1;
12239beb93cSSam Leffler 	}
12339beb93cSSam Leffler 
12439beb93cSSam Leffler 	if (pid_file) {
12539beb93cSSam Leffler 		FILE *f = fopen(pid_file, "w");
12639beb93cSSam Leffler 		if (f) {
12739beb93cSSam Leffler 			fprintf(f, "%u\n", getpid());
12839beb93cSSam Leffler 			fclose(f);
12939beb93cSSam Leffler 		}
13039beb93cSSam Leffler 	}
13139beb93cSSam Leffler 
13239beb93cSSam Leffler 	return -0;
13339beb93cSSam Leffler #endif /* __uClinux__ */
13439beb93cSSam Leffler }
13539beb93cSSam Leffler 
13639beb93cSSam Leffler 
13739beb93cSSam Leffler void os_daemonize_terminate(const char *pid_file)
13839beb93cSSam Leffler {
13939beb93cSSam Leffler 	if (pid_file)
14039beb93cSSam Leffler 		unlink(pid_file);
14139beb93cSSam Leffler }
14239beb93cSSam Leffler 
14339beb93cSSam Leffler 
14439beb93cSSam Leffler int os_get_random(unsigned char *buf, size_t len)
14539beb93cSSam Leffler {
14639beb93cSSam Leffler 	FILE *f;
14739beb93cSSam Leffler 	size_t rc;
14839beb93cSSam Leffler 
14939beb93cSSam Leffler 	f = fopen("/dev/urandom", "rb");
15039beb93cSSam Leffler 	if (f == NULL) {
15139beb93cSSam Leffler 		printf("Could not open /dev/urandom.\n");
15239beb93cSSam Leffler 		return -1;
15339beb93cSSam Leffler 	}
15439beb93cSSam Leffler 
15539beb93cSSam Leffler 	rc = fread(buf, 1, len, f);
15639beb93cSSam Leffler 	fclose(f);
15739beb93cSSam Leffler 
15839beb93cSSam Leffler 	return rc != len ? -1 : 0;
15939beb93cSSam Leffler }
16039beb93cSSam Leffler 
16139beb93cSSam Leffler 
16239beb93cSSam Leffler unsigned long os_random(void)
16339beb93cSSam Leffler {
16439beb93cSSam Leffler 	return random();
16539beb93cSSam Leffler }
16639beb93cSSam Leffler 
16739beb93cSSam Leffler 
16839beb93cSSam Leffler char * os_rel2abs_path(const char *rel_path)
16939beb93cSSam Leffler {
17039beb93cSSam Leffler 	char *buf = NULL, *cwd, *ret;
17139beb93cSSam Leffler 	size_t len = 128, cwd_len, rel_len, ret_len;
17239beb93cSSam Leffler 	int last_errno;
17339beb93cSSam Leffler 
17439beb93cSSam Leffler 	if (rel_path[0] == '/')
17539beb93cSSam Leffler 		return strdup(rel_path);
17639beb93cSSam Leffler 
17739beb93cSSam Leffler 	for (;;) {
17839beb93cSSam Leffler 		buf = malloc(len);
17939beb93cSSam Leffler 		if (buf == NULL)
18039beb93cSSam Leffler 			return NULL;
18139beb93cSSam Leffler 		cwd = getcwd(buf, len);
18239beb93cSSam Leffler 		if (cwd == NULL) {
18339beb93cSSam Leffler 			last_errno = errno;
18439beb93cSSam Leffler 			free(buf);
18539beb93cSSam Leffler 			if (last_errno != ERANGE)
18639beb93cSSam Leffler 				return NULL;
18739beb93cSSam Leffler 			len *= 2;
18839beb93cSSam Leffler 			if (len > 2000)
18939beb93cSSam Leffler 				return NULL;
19039beb93cSSam Leffler 		} else {
19139beb93cSSam Leffler 			buf[len - 1] = '\0';
19239beb93cSSam Leffler 			break;
19339beb93cSSam Leffler 		}
19439beb93cSSam Leffler 	}
19539beb93cSSam Leffler 
19639beb93cSSam Leffler 	cwd_len = strlen(cwd);
19739beb93cSSam Leffler 	rel_len = strlen(rel_path);
19839beb93cSSam Leffler 	ret_len = cwd_len + 1 + rel_len + 1;
19939beb93cSSam Leffler 	ret = malloc(ret_len);
20039beb93cSSam Leffler 	if (ret) {
20139beb93cSSam Leffler 		memcpy(ret, cwd, cwd_len);
20239beb93cSSam Leffler 		ret[cwd_len] = '/';
20339beb93cSSam Leffler 		memcpy(ret + cwd_len + 1, rel_path, rel_len);
20439beb93cSSam Leffler 		ret[ret_len - 1] = '\0';
20539beb93cSSam Leffler 	}
20639beb93cSSam Leffler 	free(buf);
20739beb93cSSam Leffler 	return ret;
20839beb93cSSam Leffler }
20939beb93cSSam Leffler 
21039beb93cSSam Leffler 
21139beb93cSSam Leffler int os_program_init(void)
21239beb93cSSam Leffler {
21339beb93cSSam Leffler 	return 0;
21439beb93cSSam Leffler }
21539beb93cSSam Leffler 
21639beb93cSSam Leffler 
21739beb93cSSam Leffler void os_program_deinit(void)
21839beb93cSSam Leffler {
21939beb93cSSam Leffler }
22039beb93cSSam Leffler 
22139beb93cSSam Leffler 
22239beb93cSSam Leffler int os_setenv(const char *name, const char *value, int overwrite)
22339beb93cSSam Leffler {
22439beb93cSSam Leffler 	return setenv(name, value, overwrite);
22539beb93cSSam Leffler }
22639beb93cSSam Leffler 
22739beb93cSSam Leffler 
22839beb93cSSam Leffler int os_unsetenv(const char *name)
22939beb93cSSam Leffler {
23039beb93cSSam Leffler #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__)
23139beb93cSSam Leffler 	unsetenv(name);
23239beb93cSSam Leffler 	return 0;
23339beb93cSSam Leffler #else
23439beb93cSSam Leffler 	return unsetenv(name);
23539beb93cSSam Leffler #endif
23639beb93cSSam Leffler }
23739beb93cSSam Leffler 
23839beb93cSSam Leffler 
23939beb93cSSam Leffler char * os_readfile(const char *name, size_t *len)
24039beb93cSSam Leffler {
24139beb93cSSam Leffler 	FILE *f;
24239beb93cSSam Leffler 	char *buf;
24339beb93cSSam Leffler 
24439beb93cSSam Leffler 	f = fopen(name, "rb");
24539beb93cSSam Leffler 	if (f == NULL)
24639beb93cSSam Leffler 		return NULL;
24739beb93cSSam Leffler 
24839beb93cSSam Leffler 	fseek(f, 0, SEEK_END);
24939beb93cSSam Leffler 	*len = ftell(f);
25039beb93cSSam Leffler 	fseek(f, 0, SEEK_SET);
25139beb93cSSam Leffler 
25239beb93cSSam Leffler 	buf = malloc(*len);
25339beb93cSSam Leffler 	if (buf == NULL) {
25439beb93cSSam Leffler 		fclose(f);
25539beb93cSSam Leffler 		return NULL;
25639beb93cSSam Leffler 	}
25739beb93cSSam Leffler 
25839beb93cSSam Leffler 	if (fread(buf, 1, *len, f) != *len) {
25939beb93cSSam Leffler 		fclose(f);
26039beb93cSSam Leffler 		free(buf);
26139beb93cSSam Leffler 		return NULL;
26239beb93cSSam Leffler 	}
26339beb93cSSam Leffler 
26439beb93cSSam Leffler 	fclose(f);
26539beb93cSSam Leffler 
26639beb93cSSam Leffler 	return buf;
26739beb93cSSam Leffler }
26839beb93cSSam Leffler 
26939beb93cSSam Leffler 
27039beb93cSSam Leffler void * os_zalloc(size_t size)
27139beb93cSSam Leffler {
27239beb93cSSam Leffler 	return calloc(1, size);
27339beb93cSSam Leffler }
27439beb93cSSam Leffler 
27539beb93cSSam Leffler 
27639beb93cSSam Leffler size_t os_strlcpy(char *dest, const char *src, size_t siz)
27739beb93cSSam Leffler {
27839beb93cSSam Leffler 	const char *s = src;
27939beb93cSSam Leffler 	size_t left = siz;
28039beb93cSSam Leffler 
28139beb93cSSam Leffler 	if (left) {
28239beb93cSSam Leffler 		/* Copy string up to the maximum size of the dest buffer */
28339beb93cSSam Leffler 		while (--left != 0) {
28439beb93cSSam Leffler 			if ((*dest++ = *s++) == '\0')
28539beb93cSSam Leffler 				break;
28639beb93cSSam Leffler 		}
28739beb93cSSam Leffler 	}
28839beb93cSSam Leffler 
28939beb93cSSam Leffler 	if (left == 0) {
29039beb93cSSam Leffler 		/* Not enough room for the string; force NUL-termination */
29139beb93cSSam Leffler 		if (siz != 0)
29239beb93cSSam Leffler 			*dest = '\0';
29339beb93cSSam Leffler 		while (*s++)
29439beb93cSSam Leffler 			; /* determine total src string length */
29539beb93cSSam Leffler 	}
29639beb93cSSam Leffler 
29739beb93cSSam Leffler 	return s - src - 1;
29839beb93cSSam Leffler }
299