xref: /dflybsd-src/contrib/wpa_supplicant/src/utils/os_internal.c (revision 3ff40c12445a6f5918b9c6e9c7031bc0cb8786d1)
16d49e1aeSJan Lentfer /*
26d49e1aeSJan Lentfer  * wpa_supplicant/hostapd / Internal implementation of OS specific functions
36d49e1aeSJan Lentfer  * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi>
46d49e1aeSJan Lentfer  *
5*3ff40c12SJohn Marino  * This software may be distributed under the terms of the BSD license.
6*3ff40c12SJohn Marino  * See README for more details.
76d49e1aeSJan Lentfer  *
86d49e1aeSJan Lentfer  * This file is an example of operating system specific  wrapper functions.
96d49e1aeSJan Lentfer  * This version implements many of the functions internally, so it can be used
106d49e1aeSJan Lentfer  * to fill in missing functions from the target system C libraries.
116d49e1aeSJan Lentfer  *
126d49e1aeSJan Lentfer  * Some of the functions are using standard C library calls in order to keep
136d49e1aeSJan Lentfer  * this file in working condition to allow the functions to be tested on a
146d49e1aeSJan Lentfer  * Linux target. Please note that OS_NO_C_LIB_DEFINES needs to be defined for
156d49e1aeSJan Lentfer  * this file to work correctly. Note that these implementations are only
166d49e1aeSJan Lentfer  * examples and are not optimized for speed.
176d49e1aeSJan Lentfer  */
186d49e1aeSJan Lentfer 
196d49e1aeSJan Lentfer #include "includes.h"
206d49e1aeSJan Lentfer 
216d49e1aeSJan Lentfer #undef OS_REJECT_C_LIB_FUNCTIONS
226d49e1aeSJan Lentfer #include "os.h"
236d49e1aeSJan Lentfer 
246d49e1aeSJan Lentfer void os_sleep(os_time_t sec, os_time_t usec)
256d49e1aeSJan Lentfer {
266d49e1aeSJan Lentfer 	if (sec)
276d49e1aeSJan Lentfer 		sleep(sec);
286d49e1aeSJan Lentfer 	if (usec)
296d49e1aeSJan Lentfer 		usleep(usec);
306d49e1aeSJan Lentfer }
316d49e1aeSJan Lentfer 
326d49e1aeSJan Lentfer 
336d49e1aeSJan Lentfer int os_get_time(struct os_time *t)
346d49e1aeSJan Lentfer {
356d49e1aeSJan Lentfer 	int res;
366d49e1aeSJan Lentfer 	struct timeval tv;
376d49e1aeSJan Lentfer 	res = gettimeofday(&tv, NULL);
386d49e1aeSJan Lentfer 	t->sec = tv.tv_sec;
396d49e1aeSJan Lentfer 	t->usec = tv.tv_usec;
406d49e1aeSJan Lentfer 	return res;
416d49e1aeSJan Lentfer }
426d49e1aeSJan Lentfer 
436d49e1aeSJan Lentfer 
44*3ff40c12SJohn Marino int os_get_reltime(struct os_reltime *t)
45*3ff40c12SJohn Marino {
46*3ff40c12SJohn Marino 	int res;
47*3ff40c12SJohn Marino 	struct timeval tv;
48*3ff40c12SJohn Marino 	res = gettimeofday(&tv, NULL);
49*3ff40c12SJohn Marino 	t->sec = tv.tv_sec;
50*3ff40c12SJohn Marino 	t->usec = tv.tv_usec;
51*3ff40c12SJohn Marino 	return res;
52*3ff40c12SJohn Marino }
53*3ff40c12SJohn Marino 
54*3ff40c12SJohn Marino 
556d49e1aeSJan Lentfer int os_mktime(int year, int month, int day, int hour, int min, int sec,
566d49e1aeSJan Lentfer 	      os_time_t *t)
576d49e1aeSJan Lentfer {
586d49e1aeSJan Lentfer 	struct tm tm;
596d49e1aeSJan Lentfer 
606d49e1aeSJan Lentfer 	if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
616d49e1aeSJan Lentfer 	    hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 ||
626d49e1aeSJan Lentfer 	    sec > 60)
636d49e1aeSJan Lentfer 		return -1;
646d49e1aeSJan Lentfer 
656d49e1aeSJan Lentfer 	os_memset(&tm, 0, sizeof(tm));
666d49e1aeSJan Lentfer 	tm.tm_year = year - 1900;
676d49e1aeSJan Lentfer 	tm.tm_mon = month - 1;
686d49e1aeSJan Lentfer 	tm.tm_mday = day;
696d49e1aeSJan Lentfer 	tm.tm_hour = hour;
706d49e1aeSJan Lentfer 	tm.tm_min = min;
716d49e1aeSJan Lentfer 	tm.tm_sec = sec;
726d49e1aeSJan Lentfer 
736d49e1aeSJan Lentfer 	*t = (os_time_t) mktime(&tm);
746d49e1aeSJan Lentfer 	return 0;
756d49e1aeSJan Lentfer }
766d49e1aeSJan Lentfer 
776d49e1aeSJan Lentfer 
78*3ff40c12SJohn Marino int os_gmtime(os_time_t t, struct os_tm *tm)
79*3ff40c12SJohn Marino {
80*3ff40c12SJohn Marino 	struct tm *tm2;
81*3ff40c12SJohn Marino 	time_t t2 = t;
82*3ff40c12SJohn Marino 
83*3ff40c12SJohn Marino 	tm2 = gmtime(&t2);
84*3ff40c12SJohn Marino 	if (tm2 == NULL)
85*3ff40c12SJohn Marino 		return -1;
86*3ff40c12SJohn Marino 	tm->sec = tm2->tm_sec;
87*3ff40c12SJohn Marino 	tm->min = tm2->tm_min;
88*3ff40c12SJohn Marino 	tm->hour = tm2->tm_hour;
89*3ff40c12SJohn Marino 	tm->day = tm2->tm_mday;
90*3ff40c12SJohn Marino 	tm->month = tm2->tm_mon + 1;
91*3ff40c12SJohn Marino 	tm->year = tm2->tm_year + 1900;
92*3ff40c12SJohn Marino 	return 0;
93*3ff40c12SJohn Marino }
94*3ff40c12SJohn Marino 
95*3ff40c12SJohn Marino 
966d49e1aeSJan Lentfer int os_daemonize(const char *pid_file)
976d49e1aeSJan Lentfer {
986d49e1aeSJan Lentfer 	if (daemon(0, 0)) {
996d49e1aeSJan Lentfer 		perror("daemon");
1006d49e1aeSJan Lentfer 		return -1;
1016d49e1aeSJan Lentfer 	}
1026d49e1aeSJan Lentfer 
1036d49e1aeSJan Lentfer 	if (pid_file) {
1046d49e1aeSJan Lentfer 		FILE *f = fopen(pid_file, "w");
1056d49e1aeSJan Lentfer 		if (f) {
1066d49e1aeSJan Lentfer 			fprintf(f, "%u\n", getpid());
1076d49e1aeSJan Lentfer 			fclose(f);
1086d49e1aeSJan Lentfer 		}
1096d49e1aeSJan Lentfer 	}
1106d49e1aeSJan Lentfer 
1116d49e1aeSJan Lentfer 	return -0;
1126d49e1aeSJan Lentfer }
1136d49e1aeSJan Lentfer 
1146d49e1aeSJan Lentfer 
1156d49e1aeSJan Lentfer void os_daemonize_terminate(const char *pid_file)
1166d49e1aeSJan Lentfer {
1176d49e1aeSJan Lentfer 	if (pid_file)
1186d49e1aeSJan Lentfer 		unlink(pid_file);
1196d49e1aeSJan Lentfer }
1206d49e1aeSJan Lentfer 
1216d49e1aeSJan Lentfer 
1226d49e1aeSJan Lentfer int os_get_random(unsigned char *buf, size_t len)
1236d49e1aeSJan Lentfer {
1246d49e1aeSJan Lentfer 	FILE *f;
1256d49e1aeSJan Lentfer 	size_t rc;
1266d49e1aeSJan Lentfer 
1276d49e1aeSJan Lentfer 	f = fopen("/dev/urandom", "rb");
1286d49e1aeSJan Lentfer 	if (f == NULL) {
1296d49e1aeSJan Lentfer 		printf("Could not open /dev/urandom.\n");
1306d49e1aeSJan Lentfer 		return -1;
1316d49e1aeSJan Lentfer 	}
1326d49e1aeSJan Lentfer 
1336d49e1aeSJan Lentfer 	rc = fread(buf, 1, len, f);
1346d49e1aeSJan Lentfer 	fclose(f);
1356d49e1aeSJan Lentfer 
1366d49e1aeSJan Lentfer 	return rc != len ? -1 : 0;
1376d49e1aeSJan Lentfer }
1386d49e1aeSJan Lentfer 
1396d49e1aeSJan Lentfer 
1406d49e1aeSJan Lentfer unsigned long os_random(void)
1416d49e1aeSJan Lentfer {
1426d49e1aeSJan Lentfer 	return random();
1436d49e1aeSJan Lentfer }
1446d49e1aeSJan Lentfer 
1456d49e1aeSJan Lentfer 
1466d49e1aeSJan Lentfer char * os_rel2abs_path(const char *rel_path)
1476d49e1aeSJan Lentfer {
1486d49e1aeSJan Lentfer 	char *buf = NULL, *cwd, *ret;
1496d49e1aeSJan Lentfer 	size_t len = 128, cwd_len, rel_len, ret_len;
1506d49e1aeSJan Lentfer 
1516d49e1aeSJan Lentfer 	if (rel_path[0] == '/')
1526d49e1aeSJan Lentfer 		return os_strdup(rel_path);
1536d49e1aeSJan Lentfer 
1546d49e1aeSJan Lentfer 	for (;;) {
1556d49e1aeSJan Lentfer 		buf = os_malloc(len);
1566d49e1aeSJan Lentfer 		if (buf == NULL)
1576d49e1aeSJan Lentfer 			return NULL;
1586d49e1aeSJan Lentfer 		cwd = getcwd(buf, len);
1596d49e1aeSJan Lentfer 		if (cwd == NULL) {
1606d49e1aeSJan Lentfer 			os_free(buf);
1616d49e1aeSJan Lentfer 			if (errno != ERANGE) {
1626d49e1aeSJan Lentfer 				return NULL;
1636d49e1aeSJan Lentfer 			}
1646d49e1aeSJan Lentfer 			len *= 2;
1656d49e1aeSJan Lentfer 		} else {
1666d49e1aeSJan Lentfer 			break;
1676d49e1aeSJan Lentfer 		}
1686d49e1aeSJan Lentfer 	}
1696d49e1aeSJan Lentfer 
1706d49e1aeSJan Lentfer 	cwd_len = strlen(cwd);
1716d49e1aeSJan Lentfer 	rel_len = strlen(rel_path);
1726d49e1aeSJan Lentfer 	ret_len = cwd_len + 1 + rel_len + 1;
1736d49e1aeSJan Lentfer 	ret = os_malloc(ret_len);
1746d49e1aeSJan Lentfer 	if (ret) {
1756d49e1aeSJan Lentfer 		os_memcpy(ret, cwd, cwd_len);
1766d49e1aeSJan Lentfer 		ret[cwd_len] = '/';
1776d49e1aeSJan Lentfer 		os_memcpy(ret + cwd_len + 1, rel_path, rel_len);
1786d49e1aeSJan Lentfer 		ret[ret_len - 1] = '\0';
1796d49e1aeSJan Lentfer 	}
1806d49e1aeSJan Lentfer 	os_free(buf);
1816d49e1aeSJan Lentfer 	return ret;
1826d49e1aeSJan Lentfer }
1836d49e1aeSJan Lentfer 
1846d49e1aeSJan Lentfer 
1856d49e1aeSJan Lentfer int os_program_init(void)
1866d49e1aeSJan Lentfer {
1876d49e1aeSJan Lentfer 	return 0;
1886d49e1aeSJan Lentfer }
1896d49e1aeSJan Lentfer 
1906d49e1aeSJan Lentfer 
1916d49e1aeSJan Lentfer void os_program_deinit(void)
1926d49e1aeSJan Lentfer {
1936d49e1aeSJan Lentfer }
1946d49e1aeSJan Lentfer 
1956d49e1aeSJan Lentfer 
1966d49e1aeSJan Lentfer int os_setenv(const char *name, const char *value, int overwrite)
1976d49e1aeSJan Lentfer {
1986d49e1aeSJan Lentfer 	return setenv(name, value, overwrite);
1996d49e1aeSJan Lentfer }
2006d49e1aeSJan Lentfer 
2016d49e1aeSJan Lentfer 
2026d49e1aeSJan Lentfer int os_unsetenv(const char *name)
2036d49e1aeSJan Lentfer {
2046d49e1aeSJan Lentfer #if defined(__FreeBSD__) || defined(__NetBSD__)
2056d49e1aeSJan Lentfer 	unsetenv(name);
2066d49e1aeSJan Lentfer 	return 0;
2076d49e1aeSJan Lentfer #else
2086d49e1aeSJan Lentfer 	return unsetenv(name);
2096d49e1aeSJan Lentfer #endif
2106d49e1aeSJan Lentfer }
2116d49e1aeSJan Lentfer 
2126d49e1aeSJan Lentfer 
2136d49e1aeSJan Lentfer char * os_readfile(const char *name, size_t *len)
2146d49e1aeSJan Lentfer {
2156d49e1aeSJan Lentfer 	FILE *f;
2166d49e1aeSJan Lentfer 	char *buf;
2176d49e1aeSJan Lentfer 
2186d49e1aeSJan Lentfer 	f = fopen(name, "rb");
2196d49e1aeSJan Lentfer 	if (f == NULL)
2206d49e1aeSJan Lentfer 		return NULL;
2216d49e1aeSJan Lentfer 
2226d49e1aeSJan Lentfer 	fseek(f, 0, SEEK_END);
2236d49e1aeSJan Lentfer 	*len = ftell(f);
2246d49e1aeSJan Lentfer 	fseek(f, 0, SEEK_SET);
2256d49e1aeSJan Lentfer 
2266d49e1aeSJan Lentfer 	buf = os_malloc(*len);
2276d49e1aeSJan Lentfer 	if (buf == NULL) {
2286d49e1aeSJan Lentfer 		fclose(f);
2296d49e1aeSJan Lentfer 		return NULL;
2306d49e1aeSJan Lentfer 	}
2316d49e1aeSJan Lentfer 
232*3ff40c12SJohn Marino 	if (fread(buf, 1, *len, f) != *len) {
233*3ff40c12SJohn Marino 		fclose(f);
234*3ff40c12SJohn Marino 		os_free(buf);
235*3ff40c12SJohn Marino 		return NULL;
236*3ff40c12SJohn Marino 	}
237*3ff40c12SJohn Marino 
2386d49e1aeSJan Lentfer 	fclose(f);
2396d49e1aeSJan Lentfer 
2406d49e1aeSJan Lentfer 	return buf;
2416d49e1aeSJan Lentfer }
2426d49e1aeSJan Lentfer 
2436d49e1aeSJan Lentfer 
2446d49e1aeSJan Lentfer void * os_zalloc(size_t size)
2456d49e1aeSJan Lentfer {
2466d49e1aeSJan Lentfer 	void *n = os_malloc(size);
2476d49e1aeSJan Lentfer 	if (n)
2486d49e1aeSJan Lentfer 		os_memset(n, 0, size);
2496d49e1aeSJan Lentfer 	return n;
2506d49e1aeSJan Lentfer }
2516d49e1aeSJan Lentfer 
2526d49e1aeSJan Lentfer 
2536d49e1aeSJan Lentfer void * os_malloc(size_t size)
2546d49e1aeSJan Lentfer {
2556d49e1aeSJan Lentfer 	return malloc(size);
2566d49e1aeSJan Lentfer }
2576d49e1aeSJan Lentfer 
2586d49e1aeSJan Lentfer 
2596d49e1aeSJan Lentfer void * os_realloc(void *ptr, size_t size)
2606d49e1aeSJan Lentfer {
2616d49e1aeSJan Lentfer 	return realloc(ptr, size);
2626d49e1aeSJan Lentfer }
2636d49e1aeSJan Lentfer 
2646d49e1aeSJan Lentfer 
2656d49e1aeSJan Lentfer void os_free(void *ptr)
2666d49e1aeSJan Lentfer {
2676d49e1aeSJan Lentfer 	free(ptr);
2686d49e1aeSJan Lentfer }
2696d49e1aeSJan Lentfer 
2706d49e1aeSJan Lentfer 
2716d49e1aeSJan Lentfer void * os_memcpy(void *dest, const void *src, size_t n)
2726d49e1aeSJan Lentfer {
2736d49e1aeSJan Lentfer 	char *d = dest;
2746d49e1aeSJan Lentfer 	const char *s = src;
2756d49e1aeSJan Lentfer 	while (n--)
2766d49e1aeSJan Lentfer 		*d++ = *s++;
2776d49e1aeSJan Lentfer 	return dest;
2786d49e1aeSJan Lentfer }
2796d49e1aeSJan Lentfer 
2806d49e1aeSJan Lentfer 
2816d49e1aeSJan Lentfer void * os_memmove(void *dest, const void *src, size_t n)
2826d49e1aeSJan Lentfer {
2836d49e1aeSJan Lentfer 	if (dest < src)
2846d49e1aeSJan Lentfer 		os_memcpy(dest, src, n);
2856d49e1aeSJan Lentfer 	else {
2866d49e1aeSJan Lentfer 		/* overlapping areas */
2876d49e1aeSJan Lentfer 		char *d = (char *) dest + n;
2886d49e1aeSJan Lentfer 		const char *s = (const char *) src + n;
2896d49e1aeSJan Lentfer 		while (n--)
2906d49e1aeSJan Lentfer 			*--d = *--s;
2916d49e1aeSJan Lentfer 	}
2926d49e1aeSJan Lentfer 	return dest;
2936d49e1aeSJan Lentfer }
2946d49e1aeSJan Lentfer 
2956d49e1aeSJan Lentfer 
2966d49e1aeSJan Lentfer void * os_memset(void *s, int c, size_t n)
2976d49e1aeSJan Lentfer {
2986d49e1aeSJan Lentfer 	char *p = s;
2996d49e1aeSJan Lentfer 	while (n--)
3006d49e1aeSJan Lentfer 		*p++ = c;
3016d49e1aeSJan Lentfer 	return s;
3026d49e1aeSJan Lentfer }
3036d49e1aeSJan Lentfer 
3046d49e1aeSJan Lentfer 
3056d49e1aeSJan Lentfer int os_memcmp(const void *s1, const void *s2, size_t n)
3066d49e1aeSJan Lentfer {
3076d49e1aeSJan Lentfer 	const unsigned char *p1 = s1, *p2 = s2;
3086d49e1aeSJan Lentfer 
3096d49e1aeSJan Lentfer 	if (n == 0)
3106d49e1aeSJan Lentfer 		return 0;
3116d49e1aeSJan Lentfer 
3126d49e1aeSJan Lentfer 	while (*p1 == *p2) {
3136d49e1aeSJan Lentfer 		p1++;
3146d49e1aeSJan Lentfer 		p2++;
3156d49e1aeSJan Lentfer 		n--;
3166d49e1aeSJan Lentfer 		if (n == 0)
3176d49e1aeSJan Lentfer 			return 0;
3186d49e1aeSJan Lentfer 	}
3196d49e1aeSJan Lentfer 
3206d49e1aeSJan Lentfer 	return *p1 - *p2;
3216d49e1aeSJan Lentfer }
3226d49e1aeSJan Lentfer 
3236d49e1aeSJan Lentfer 
3246d49e1aeSJan Lentfer char * os_strdup(const char *s)
3256d49e1aeSJan Lentfer {
3266d49e1aeSJan Lentfer 	char *res;
3276d49e1aeSJan Lentfer 	size_t len;
3286d49e1aeSJan Lentfer 	if (s == NULL)
3296d49e1aeSJan Lentfer 		return NULL;
3306d49e1aeSJan Lentfer 	len = os_strlen(s);
3316d49e1aeSJan Lentfer 	res = os_malloc(len + 1);
3326d49e1aeSJan Lentfer 	if (res)
3336d49e1aeSJan Lentfer 		os_memcpy(res, s, len + 1);
3346d49e1aeSJan Lentfer 	return res;
3356d49e1aeSJan Lentfer }
3366d49e1aeSJan Lentfer 
3376d49e1aeSJan Lentfer 
3386d49e1aeSJan Lentfer size_t os_strlen(const char *s)
3396d49e1aeSJan Lentfer {
3406d49e1aeSJan Lentfer 	const char *p = s;
3416d49e1aeSJan Lentfer 	while (*p)
3426d49e1aeSJan Lentfer 		p++;
3436d49e1aeSJan Lentfer 	return p - s;
3446d49e1aeSJan Lentfer }
3456d49e1aeSJan Lentfer 
3466d49e1aeSJan Lentfer 
3476d49e1aeSJan Lentfer int os_strcasecmp(const char *s1, const char *s2)
3486d49e1aeSJan Lentfer {
3496d49e1aeSJan Lentfer 	/*
3506d49e1aeSJan Lentfer 	 * Ignoring case is not required for main functionality, so just use
3516d49e1aeSJan Lentfer 	 * the case sensitive version of the function.
3526d49e1aeSJan Lentfer 	 */
3536d49e1aeSJan Lentfer 	return os_strcmp(s1, s2);
3546d49e1aeSJan Lentfer }
3556d49e1aeSJan Lentfer 
3566d49e1aeSJan Lentfer 
3576d49e1aeSJan Lentfer int os_strncasecmp(const char *s1, const char *s2, size_t n)
3586d49e1aeSJan Lentfer {
3596d49e1aeSJan Lentfer 	/*
3606d49e1aeSJan Lentfer 	 * Ignoring case is not required for main functionality, so just use
3616d49e1aeSJan Lentfer 	 * the case sensitive version of the function.
3626d49e1aeSJan Lentfer 	 */
3636d49e1aeSJan Lentfer 	return os_strncmp(s1, s2, n);
3646d49e1aeSJan Lentfer }
3656d49e1aeSJan Lentfer 
3666d49e1aeSJan Lentfer 
3676d49e1aeSJan Lentfer char * os_strchr(const char *s, int c)
3686d49e1aeSJan Lentfer {
3696d49e1aeSJan Lentfer 	while (*s) {
3706d49e1aeSJan Lentfer 		if (*s == c)
3716d49e1aeSJan Lentfer 			return (char *) s;
3726d49e1aeSJan Lentfer 		s++;
3736d49e1aeSJan Lentfer 	}
3746d49e1aeSJan Lentfer 	return NULL;
3756d49e1aeSJan Lentfer }
3766d49e1aeSJan Lentfer 
3776d49e1aeSJan Lentfer 
3786d49e1aeSJan Lentfer char * os_strrchr(const char *s, int c)
3796d49e1aeSJan Lentfer {
3806d49e1aeSJan Lentfer 	const char *p = s;
3816d49e1aeSJan Lentfer 	while (*p)
3826d49e1aeSJan Lentfer 		p++;
3836d49e1aeSJan Lentfer 	p--;
3846d49e1aeSJan Lentfer 	while (p >= s) {
3856d49e1aeSJan Lentfer 		if (*p == c)
3866d49e1aeSJan Lentfer 			return (char *) p;
3876d49e1aeSJan Lentfer 		p--;
3886d49e1aeSJan Lentfer 	}
3896d49e1aeSJan Lentfer 	return NULL;
3906d49e1aeSJan Lentfer }
3916d49e1aeSJan Lentfer 
3926d49e1aeSJan Lentfer 
3936d49e1aeSJan Lentfer int os_strcmp(const char *s1, const char *s2)
3946d49e1aeSJan Lentfer {
3956d49e1aeSJan Lentfer 	while (*s1 == *s2) {
3966d49e1aeSJan Lentfer 		if (*s1 == '\0')
3976d49e1aeSJan Lentfer 			break;
3986d49e1aeSJan Lentfer 		s1++;
3996d49e1aeSJan Lentfer 		s2++;
4006d49e1aeSJan Lentfer 	}
4016d49e1aeSJan Lentfer 
4026d49e1aeSJan Lentfer 	return *s1 - *s2;
4036d49e1aeSJan Lentfer }
4046d49e1aeSJan Lentfer 
4056d49e1aeSJan Lentfer 
4066d49e1aeSJan Lentfer int os_strncmp(const char *s1, const char *s2, size_t n)
4076d49e1aeSJan Lentfer {
4086d49e1aeSJan Lentfer 	if (n == 0)
4096d49e1aeSJan Lentfer 		return 0;
4106d49e1aeSJan Lentfer 
4116d49e1aeSJan Lentfer 	while (*s1 == *s2) {
4126d49e1aeSJan Lentfer 		if (*s1 == '\0')
4136d49e1aeSJan Lentfer 			break;
4146d49e1aeSJan Lentfer 		s1++;
4156d49e1aeSJan Lentfer 		s2++;
4166d49e1aeSJan Lentfer 		n--;
4176d49e1aeSJan Lentfer 		if (n == 0)
4186d49e1aeSJan Lentfer 			return 0;
4196d49e1aeSJan Lentfer 	}
4206d49e1aeSJan Lentfer 
4216d49e1aeSJan Lentfer 	return *s1 - *s2;
4226d49e1aeSJan Lentfer }
4236d49e1aeSJan Lentfer 
4246d49e1aeSJan Lentfer 
4256d49e1aeSJan Lentfer char * os_strncpy(char *dest, const char *src, size_t n)
4266d49e1aeSJan Lentfer {
4276d49e1aeSJan Lentfer 	char *d = dest;
4286d49e1aeSJan Lentfer 
4296d49e1aeSJan Lentfer 	while (n--) {
4306d49e1aeSJan Lentfer 		*d = *src;
4316d49e1aeSJan Lentfer 		if (*src == '\0')
4326d49e1aeSJan Lentfer 			break;
4336d49e1aeSJan Lentfer 		d++;
4346d49e1aeSJan Lentfer 		src++;
4356d49e1aeSJan Lentfer 	}
4366d49e1aeSJan Lentfer 
4376d49e1aeSJan Lentfer 	return dest;
4386d49e1aeSJan Lentfer }
4396d49e1aeSJan Lentfer 
4406d49e1aeSJan Lentfer 
4416d49e1aeSJan Lentfer size_t os_strlcpy(char *dest, const char *src, size_t siz)
4426d49e1aeSJan Lentfer {
4436d49e1aeSJan Lentfer 	const char *s = src;
4446d49e1aeSJan Lentfer 	size_t left = siz;
4456d49e1aeSJan Lentfer 
4466d49e1aeSJan Lentfer 	if (left) {
4476d49e1aeSJan Lentfer 		/* Copy string up to the maximum size of the dest buffer */
4486d49e1aeSJan Lentfer 		while (--left != 0) {
4496d49e1aeSJan Lentfer 			if ((*dest++ = *s++) == '\0')
4506d49e1aeSJan Lentfer 				break;
4516d49e1aeSJan Lentfer 		}
4526d49e1aeSJan Lentfer 	}
4536d49e1aeSJan Lentfer 
4546d49e1aeSJan Lentfer 	if (left == 0) {
4556d49e1aeSJan Lentfer 		/* Not enough room for the string; force NUL-termination */
4566d49e1aeSJan Lentfer 		if (siz != 0)
4576d49e1aeSJan Lentfer 			*dest = '\0';
4586d49e1aeSJan Lentfer 		while (*s++)
4596d49e1aeSJan Lentfer 			; /* determine total src string length */
4606d49e1aeSJan Lentfer 	}
4616d49e1aeSJan Lentfer 
4626d49e1aeSJan Lentfer 	return s - src - 1;
4636d49e1aeSJan Lentfer }
4646d49e1aeSJan Lentfer 
4656d49e1aeSJan Lentfer 
4666d49e1aeSJan Lentfer char * os_strstr(const char *haystack, const char *needle)
4676d49e1aeSJan Lentfer {
4686d49e1aeSJan Lentfer 	size_t len = os_strlen(needle);
4696d49e1aeSJan Lentfer 	while (*haystack) {
4706d49e1aeSJan Lentfer 		if (os_strncmp(haystack, needle, len) == 0)
4716d49e1aeSJan Lentfer 			return (char *) haystack;
4726d49e1aeSJan Lentfer 		haystack++;
4736d49e1aeSJan Lentfer 	}
4746d49e1aeSJan Lentfer 
4756d49e1aeSJan Lentfer 	return NULL;
4766d49e1aeSJan Lentfer }
4776d49e1aeSJan Lentfer 
4786d49e1aeSJan Lentfer 
4796d49e1aeSJan Lentfer int os_snprintf(char *str, size_t size, const char *format, ...)
4806d49e1aeSJan Lentfer {
4816d49e1aeSJan Lentfer 	va_list ap;
4826d49e1aeSJan Lentfer 	int ret;
4836d49e1aeSJan Lentfer 
4846d49e1aeSJan Lentfer 	/* See http://www.ijs.si/software/snprintf/ for portable
4856d49e1aeSJan Lentfer 	 * implementation of snprintf.
4866d49e1aeSJan Lentfer 	 */
4876d49e1aeSJan Lentfer 
4886d49e1aeSJan Lentfer 	va_start(ap, format);
4896d49e1aeSJan Lentfer 	ret = vsnprintf(str, size, format, ap);
4906d49e1aeSJan Lentfer 	va_end(ap);
4916d49e1aeSJan Lentfer 	if (size > 0)
4926d49e1aeSJan Lentfer 		str[size - 1] = '\0';
4936d49e1aeSJan Lentfer 	return ret;
4946d49e1aeSJan Lentfer }
495