Squashed 'third_party/rawrtc/re/' content from commit f3163ce8b

Change-Id: I6a235e6ac0f03269d951026f9d195da05c40fdab
git-subtree-dir: third_party/rawrtc/re
git-subtree-split: f3163ce8b526a13b35ef71ce4dd6f43585064d8a
diff --git a/src/sys/daemon.c b/src/sys/daemon.c
new file mode 100644
index 0000000..7ba14db
--- /dev/null
+++ b/src/sys/daemon.c
@@ -0,0 +1,62 @@
+/**
+ * @file daemon.c  Daemonize process
+ *
+ * Copyright (C) 2010 Creytiv.com
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <stdlib.h>
+#include <signal.h>
+#include <stdio.h>
+#include <re_types.h>
+#include <re_mbuf.h>
+#include <re_sys.h>
+
+
+/**
+ * Daemonize process
+ *
+ * @return 0 if success, otherwise errorcode
+ */
+int sys_daemon(void)
+{
+#ifdef HAVE_FORK
+	pid_t pid;
+
+	pid = fork();
+	if (-1 == pid)
+		return errno;
+	else if (pid > 0)
+		exit(0);
+
+	if (-1 == setsid())
+		return errno;
+
+	(void)signal(SIGHUP, SIG_IGN);
+
+	pid = fork();
+	if (-1 == pid)
+		return errno;
+	else if (pid > 0)
+		exit(0);
+
+	if (-1 == chdir("/"))
+		return errno;
+	(void)umask(0);
+
+	/* Redirect standard files to /dev/null */
+	if (freopen("/dev/null", "r", stdin) == NULL)
+		return errno;
+	if (freopen("/dev/null", "w", stdout) == NULL)
+		return errno;
+	if (freopen("/dev/null", "w", stderr) == NULL)
+		return errno;
+
+	return 0;
+#else
+	return ENOSYS;
+#endif
+}
diff --git a/src/sys/endian.c b/src/sys/endian.c
new file mode 100644
index 0000000..c43c262
--- /dev/null
+++ b/src/sys/endian.c
@@ -0,0 +1,143 @@
+/**
+ * @file endian.c  Endianness converting routines
+ *
+ * Copyright (C) 2010 Creytiv.com
+ */
+#include <re_types.h>
+#include <re_mbuf.h>
+#include <re_sys.h>
+
+
+/*
+ * These routes are working on both little-endian and big-endian platforms.
+ */
+
+
+/**
+ * Convert a 16-bit value from host order to little endian
+ *
+ * @param v 16-bit in host order
+ *
+ * @return 16-bit little endian value
+ */
+uint16_t sys_htols(uint16_t v)
+{
+	uint8_t *p = (uint8_t *)&v;
+	uint16_t l = 0;
+
+	l |= (uint16_t)*p++ << 0;
+	l |= (uint16_t)*p   << 8;
+
+	return l;
+}
+
+
+/**
+ * Convert a 32-bit value from host order to little endian
+ *
+ * @param v 32-bit in host order
+ *
+ * @return 32-bit little endian value
+ */
+uint32_t sys_htoll(uint32_t v)
+{
+	uint8_t *p = (uint8_t *)&v;
+	uint32_t l = 0;
+
+	l |= (uint32_t)*p++ << 0;
+	l |= (uint32_t)*p++ << 8;
+	l |= (uint32_t)*p++ << 16;
+	l |= (uint32_t)*p   << 24;
+
+	return l;
+}
+
+
+/**
+ * Convert a 16-bit value from little endian to host order
+ *
+ * @param v 16-bit little endian value
+ *
+ * @return 16-bit value in host order
+ */
+uint16_t sys_ltohs(uint16_t v)
+{
+	uint16_t s;
+	uint8_t *p = (uint8_t *)&s;
+
+	*p++ = v>>0 & 0xff;
+	*p   = v>>8 & 0xff;
+
+	return s;
+}
+
+
+/**
+ * Convert a 32-bit value from little endian to host order
+ *
+ * @param v 32-bit little endian value
+ *
+ * @return 32-bit value in host order
+ */
+uint32_t sys_ltohl(uint32_t v)
+{
+	uint32_t h;
+	uint8_t *p = (uint8_t *)&h;
+
+	*p++ = v>>0  & 0xff;
+	*p++ = v>>8  & 0xff;
+	*p++ = v>>16 & 0xff;
+	*p   = v>>24 & 0xff;
+
+	return h;
+}
+
+
+/**
+ * Convert a 64-bit value from host to network byte-order
+ *
+ * @param v 64-bit host byte-order value
+ *
+ * @return 64-bit value in network byte-order
+ */
+uint64_t sys_htonll(uint64_t v)
+{
+	uint64_t h = 0;
+	uint8_t *p = (uint8_t *)&v;
+
+	h |= (uint64_t)*p++ << 56;
+	h |= (uint64_t)*p++ << 48;
+	h |= (uint64_t)*p++ << 40;
+	h |= (uint64_t)*p++ << 32;
+	h |= (uint64_t)*p++ << 24;
+	h |= (uint64_t)*p++ << 16;
+	h |= (uint64_t)*p++ << 8;
+	h |= (uint64_t)*p   << 0;
+
+	return h;
+}
+
+
+/**
+ * Convert a 64-bit value from network to host byte-order
+ *
+ * @param v 64-bit network byte-order value
+ *
+ * @return 64-bit value in host byte-order
+ */
+uint64_t sys_ntohll(uint64_t v)
+{
+	uint64_t h;
+	uint8_t *p = (uint8_t *)&h;
+
+	*p++ = (uint8_t) (v>>56 & 0xff);
+	*p++ = (uint8_t) (v>>48 & 0xff);
+	*p++ = (uint8_t) (v>>40 & 0xff);
+	*p++ = (uint8_t) (v>>32 & 0xff);
+	*p++ = (uint8_t) (v>>24 & 0xff);
+	*p++ = (uint8_t) (v>>16 & 0xff);
+	*p++ = (uint8_t) (v>>8  & 0xff);
+	*p   = (uint8_t) (v>>0  & 0xff);
+
+	return h;
+}
diff --git a/src/sys/fs.c b/src/sys/fs.c
new file mode 100644
index 0000000..033e636
--- /dev/null
+++ b/src/sys/fs.c
@@ -0,0 +1,107 @@
+/**
+ * @file fs.c  File-system functions
+ *
+ * Copyright (C) 2010 Creytiv.com
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+#ifdef WIN32
+#include <windows.h>
+#include <shlobj.h>
+#include <direct.h>
+#include <lmaccess.h>
+#endif
+#include <re_types.h>
+#include <re_fmt.h>
+#include <re_sys.h>
+
+
+/**
+ * Create a directory with full path
+ *
+ * @param path Directory path
+ * @param mode Access permissions
+ *
+ * @return 0 if success, otherwise errorcode
+ */
+int fs_mkdir(const char *path, uint16_t mode)
+{
+	int ret;
+
+	if (!path)
+		return EINVAL;
+
+#if defined (WIN32)
+	(void)mode;
+	ret = _mkdir(path);
+#else
+	ret = mkdir(path, mode);
+#endif
+	if (ret < 0)
+		return errno;
+
+	return 0;
+}
+
+
+/**
+ * Get the home directory for the current user
+ *
+ * @param path String to write home directory
+ * @param sz   Size of path string
+ *
+ * @return 0 if success, otherwise errorcode
+ */
+int fs_gethome(char *path, size_t sz)
+{
+#ifdef WIN32
+	char win32_path[MAX_PATH];
+
+	if (!path || !sz)
+		return EINVAL;
+
+	if (S_OK != SHGetFolderPath(NULL,
+				    CSIDL_APPDATA | CSIDL_FLAG_CREATE,
+				    NULL,
+				    0,
+				    win32_path)) {
+		return ENOENT;
+	}
+
+	str_ncpy(path, win32_path, sz);
+
+	return 0;
+
+#elif defined(HAVE_PWD_H)
+	const char *loginname;
+	struct passwd *pw;
+
+	if (!path || !sz)
+		return EINVAL;
+
+	loginname = sys_username();
+	if (!loginname)
+		return ENOENT;
+
+	pw = getpwnam(loginname);
+	if (!pw)
+		return errno;
+
+	str_ncpy(path, pw->pw_dir, sz);
+
+	return 0;
+#else
+	(void)path;
+	(void)sz;
+	return ENOSYS;
+#endif
+}
diff --git a/src/sys/mod.mk b/src/sys/mod.mk
new file mode 100644
index 0000000..616751e
--- /dev/null
+++ b/src/sys/mod.mk
@@ -0,0 +1,12 @@
+#
+# mod.mk
+#
+# Copyright (C) 2010 Creytiv.com
+#
+
+SRCS	+= sys/daemon.c
+SRCS	+= sys/endian.c
+SRCS	+= sys/fs.c
+SRCS	+= sys/rand.c
+SRCS	+= sys/sleep.c
+SRCS	+= sys/sys.c
diff --git a/src/sys/rand.c b/src/sys/rand.c
new file mode 100644
index 0000000..d09fb93
--- /dev/null
+++ b/src/sys/rand.c
@@ -0,0 +1,180 @@
+/**
+ * @file rand.c  Random generator
+ *
+ * Copyright (C) 2010 Creytiv.com
+ */
+#include <stdlib.h>
+#ifdef USE_OPENSSL
+#include <openssl/rand.h>
+#include <openssl/err.h>
+#endif
+#include <re_types.h>
+#include <re_mbuf.h>
+#include <re_list.h>
+#include <re_tmr.h>
+#include <re_sys.h>
+
+
+#define DEBUG_MODULE "rand"
+#define DEBUG_LEVEL 5
+#include <re_dbg.h>
+
+
+#ifndef RELEASE
+#define RAND_DEBUG 1  /**< Enable random debugging */
+#endif
+
+static const char alphanum[] =
+	"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+	"abcdefghijklmnopqrstuvwxyz"
+	"0123456789";
+
+#if RAND_DEBUG
+static bool inited = false;
+/** Check random state */
+#define RAND_CHECK							\
+	if (!inited) {							\
+		DEBUG_WARNING("%s: random not inited\n", __REFUNC__);	\
+	}
+#else
+#define RAND_CHECK if (0) {}
+#endif
+
+
+/**
+ * Initialise random number generator
+ */
+void rand_init(void)
+{
+#ifndef USE_OPENSSL
+	srand((uint32_t) tmr_jiffies());
+#endif
+
+#if RAND_DEBUG
+	inited = true;
+#endif
+}
+
+
+/**
+ * Generate an unsigned 16-bit random value
+ *
+ * @return 16-bit random value
+ */
+uint16_t rand_u16(void)
+{
+	RAND_CHECK;
+
+	/* Use higher-order bits (see man 3 rand) */
+	return rand_u32() >> 16;
+}
+
+
+/**
+ * Generate an unsigned 32-bit random value
+ *
+ * @return 32-bit random value
+ */
+uint32_t rand_u32(void)
+{
+	uint32_t v;
+
+	RAND_CHECK;
+
+#ifdef USE_OPENSSL
+	v = 0;
+	if (RAND_bytes((unsigned char *)&v, sizeof(v)) <= 0) {
+		DEBUG_WARNING("RAND_bytes() error: %i\n",
+			      ERR_GET_REASON(ERR_get_error()));
+		ERR_clear_error();
+	}
+#elif defined(HAVE_ARC4RANDOM)
+	v = arc4random();
+#elif defined(WIN32)
+	v = (rand() << 16) + rand(); /* note: 16-bit rand */
+#else
+	v = rand();
+#endif
+
+	return v;
+}
+
+
+/**
+ * Generate an unsigned 64-bit random value
+ *
+ * @return 64-bit random value
+ */
+uint64_t rand_u64(void)
+{
+	RAND_CHECK;
+
+	return (uint64_t)rand_u32()<<32 | rand_u32();
+}
+
+
+/**
+ * Generate a random printable character
+ *
+ * @return Random printable character
+ */
+char rand_char(void)
+{
+	char s[2];
+
+	RAND_CHECK;
+
+	rand_str(s, sizeof(s));
+
+	return s[0];
+}
+
+
+/**
+ * Generate a string of random characters
+ *
+ * @param str  Pointer to string
+ * @param size Size of string
+ */
+void rand_str(char *str, size_t size)
+{
+	size_t i;
+
+	if (!str || !size)
+		return;
+
+	RAND_CHECK;
+
+	--size;
+
+	rand_bytes((uint8_t *)str, size);
+
+	for (i=0; i<size; i++)
+		str[i] = alphanum[((uint8_t)str[i]) % (sizeof(alphanum)-1)];
+
+	str[size] = '\0';
+}
+
+
+/**
+ * Generate a set of random bytes
+ *
+ * @param p    Pointer to buffer
+ * @param size Size of buffer
+ */
+void rand_bytes(uint8_t *p, size_t size)
+{
+#ifdef USE_OPENSSL
+	if (RAND_bytes(p, (int)size) <= 0) {
+		DEBUG_WARNING("RAND_bytes() error: %i\n",
+			      ERR_GET_REASON(ERR_get_error()));
+		ERR_clear_error();
+	}
+#elif defined (HAVE_ARC4RANDOM)
+	arc4random_buf(p, size);
+#else
+	while (size--) {
+		p[size] = rand_u32();
+	}
+#endif
+}
diff --git a/src/sys/sleep.c b/src/sys/sleep.c
new file mode 100644
index 0000000..33cdc08
--- /dev/null
+++ b/src/sys/sleep.c
@@ -0,0 +1,45 @@
+/**
+ * @file sleep.c  System sleep functions
+ *
+ * Copyright (C) 2010 Creytiv.com
+ */
+#include <re_types.h>
+#include <re_fmt.h>
+#include <re_sys.h>
+#ifdef WIN32
+#include <windows.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#define _BSD_SOURCE 1
+#include <unistd.h>
+#endif
+#ifdef HAVE_SELECT_H
+#include <sys/select.h>
+#endif
+
+
+/**
+ * Blocking sleep for [us] number of microseconds
+ *
+ * @param us Number of microseconds to sleep
+ */
+void sys_usleep(unsigned int us)
+{
+	if (!us)
+		return;
+
+#ifdef WIN32
+	Sleep(us / 1000);
+#elif defined(HAVE_SELECT)
+	do {
+		struct timeval tv;
+
+		tv.tv_sec  = us / 1000000;
+		tv.tv_usec = us % 1000000;
+
+		(void)select(0, NULL, NULL, NULL, &tv);
+	} while (0);
+#else
+	(void)usleep(us);
+#endif
+}
diff --git a/src/sys/sys.c b/src/sys/sys.c
new file mode 100644
index 0000000..a68f377
--- /dev/null
+++ b/src/sys/sys.c
@@ -0,0 +1,233 @@
+/**
+ * @file sys.c  System information
+ *
+ * Copyright (C) 2010 Creytiv.com
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <re_types.h>
+#include <re_fmt.h>
+#include <re_sys.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_UNAME
+#include <sys/utsname.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_SETRLIMIT
+#include <sys/resource.h>
+#endif
+
+
+/**
+ * Get system release version
+ *
+ * @param rel   Binary encoded release
+ * @param maj   Major version number
+ * @param min   Minor version number
+ * @param patch Patch number
+ *
+ * @return 0 if success, otherwise errorcode
+ */
+int sys_rel_get(uint32_t *rel, uint32_t *maj, uint32_t *min, uint32_t *patch)
+{
+#ifdef HAVE_UNAME
+	struct utsname u;
+	struct pl pl_mj, pl_mn, pl_p;
+	uint32_t mj, mn, p;
+	int err;
+
+	if (0 != uname(&u))
+		return errno;
+
+	err = re_regex(u.release, strlen(u.release),
+		       "[0-9]+.[0-9]+[.\\-]1[0-9]+",
+		       &pl_mj, &pl_mn, NULL, &pl_p);
+	if (err)
+		return err;
+
+	mj = pl_u32(&pl_mj);
+	mn = pl_u32(&pl_mn);
+	p  = pl_u32(&pl_p);
+
+	if (rel)
+		*rel = mj<<16 | mn<<8 | p;
+	if (maj)
+		*maj = mj;
+	if (min)
+		*min = mn;
+	if (patch)
+		*patch = p;
+
+	return 0;
+#else
+	(void)rel;
+	(void)maj;
+	(void)min;
+	(void)patch;
+	return EINVAL;
+#endif
+}
+
+
+/**
+ * Get kernel name and version
+ *
+ * @param pf     Print function for output
+ * @param unused Unused parameter
+ *
+ * @return 0 if success, otherwise errorcode
+ */
+int sys_kernel_get(struct re_printf *pf, void *unused)
+{
+#ifdef HAVE_UNAME
+	struct utsname u;
+
+	(void)unused;
+
+	if (0 != uname(&u))
+		return errno;
+
+	return re_hprintf(pf, "%s %s %s %s %s", u.sysname, u.nodename,
+			  u.release, u.version, u.machine);
+#else
+	const char *str;
+
+	(void)unused;
+
+#if defined(WIN32)
+	str = "Win32";
+#else
+	str = "?";
+#endif
+
+	return re_hprintf(pf, "%s", str);
+#endif
+}
+
+
+/**
+ * Get build info
+ *
+ * @param pf     Print function for output
+ * @param unused Unused parameter
+ *
+ * @return 0 if success, otherwise errorcode
+ */
+int sys_build_get(struct re_printf *pf, void *unused)
+{
+	const unsigned int bus_width = 8*sizeof(void *);
+	const char *endian = "unknown";
+
+	const uint32_t a = 0x12345678;
+	const uint8_t b0 = ((uint8_t *)&a)[0];
+	const uint8_t b1 = ((uint8_t *)&a)[1];
+	const uint8_t b2 = ((uint8_t *)&a)[2];
+	const uint8_t b3 = ((uint8_t *)&a)[3];
+
+	(void)unused;
+
+	if (0x12==b0 && 0x34==b1 && 0x56==b2 && 0x78==b3)
+		endian = "big";
+	else if (0x12==b3 && 0x34==b2 && 0x56==b1 && 0x78==b0)
+		endian = "little";
+
+	return re_hprintf(pf, "%u-bit %s endian", bus_width, endian);
+}
+
+
+/**
+ * Get architecture
+ *
+ * @return Architecture string
+ */
+const char *sys_arch_get(void)
+{
+#ifdef ARCH
+	return ARCH;
+#else
+	return "?";
+#endif
+}
+
+
+/**
+ * Get name of Operating System
+ *
+ * @return Operating System string
+ */
+const char *sys_os_get(void)
+{
+#ifdef OS
+	return OS;
+#else
+	return "?";
+#endif
+}
+
+
+/**
+ * Get libre version
+ *
+ * @return libre version string
+ */
+const char *sys_libre_version_get(void)
+{
+#ifdef VERSION
+	return VERSION;
+#else
+	return "?";
+#endif
+}
+
+
+/**
+ * Return the username (login name) for the current user
+ *
+ * @return Username or NULL if not available
+ */
+const char *sys_username(void)
+{
+#ifdef HAVE_PWD_H
+	char *login;
+
+	login = getenv("LOGNAME");
+	if (!login)
+		login = getenv("USER");
+#ifdef HAVE_UNISTD_H
+	if (!login) {
+		login = getlogin();
+	}
+#endif
+
+	return str_isset(login) ? login : NULL;
+#else
+	return NULL;
+#endif
+}
+
+
+/**
+ * Enable or disable coredump
+ *
+ * @param enable true to enable, false to disable coredump
+ *
+ * @return 0 if success, otherwise errorcode
+ */
+int sys_coredump_set(bool enable)
+{
+#ifdef HAVE_SETRLIMIT
+	const struct rlimit rlim = {
+		enable ? RLIM_INFINITY : 0,
+		enable ? RLIM_INFINITY : 0
+	};
+
+	return 0 == setrlimit(RLIMIT_CORE, &rlim) ? 0 : errno;
+#else
+	(void)enable;
+	return ENOSYS;
+#endif
+}