Reorg of compat code.
authorMarko Kreen <markokr@gmail.com>
Wed, 2 Sep 2009 12:19:05 +0000 (15:19 +0300)
committerMarko Kreen <markokr@gmail.com>
Wed, 2 Sep 2009 16:16:17 +0000 (19:16 +0300)
Instead if usual/compat.[ch] and usual/win32.h, the compat code is
now merged with 'theme' modules:

  <usual/base.h>
  <usual/fileutil.h>
  <usual/signal.h>
  <usual/socket.h>
  <usual/string.h>
  <usual/time.h>

New 'theme include' concept mean those include bunch of related
system includes, provide compat funtions for missing system
functionality in addition to providing new APIs.

End result should be that user code does not need have several
'#ifdef HAVE..H' around system includes, instead it can just
include theme include to get all related functionality.

27 files changed:
m4/usual.m4
test/compile.c
usual/alloc.h [deleted file]
usual/base.h
usual/base_win32.h [new file with mode: 0644]
usual/cbtree.c
usual/compat.c [deleted file]
usual/compat.h [deleted file]
usual/daemon.c
usual/fileutil.c
usual/fileutil.h
usual/logging.c
usual/logging.h
usual/mbuf.h
usual/md5.c
usual/safeio.c
usual/safeio.h
usual/signal.c [new file with mode: 0644]
usual/signal.h [new file with mode: 0644]
usual/slab.c
usual/socket.c
usual/socket.h
usual/socket_win32.h [moved from usual/win32.h with 53% similarity]
usual/string.c
usual/string.h
usual/time.c
usual/time.h

index 86d03f9923fa084bd3499536cc3bb01f18be6bf9..970fb5121d0eb45fe57f6ed04690dd2eda5f28c3 100644 (file)
@@ -35,6 +35,7 @@ dnl
 AC_DEFUN([AC_USUAL_PROGRAM_CHECK], [
 AC_PROG_CC
 AC_PROG_CPP
+AC_GNU_SOURCE
 dnl Check if compiler supports __func__
 AC_CACHE_CHECK([whether compiler supports __func__], pgac_cv_funcname_func,
   [AC_TRY_COMPILE([#include <stdio.h>], [printf("%s\n", __func__);],
@@ -121,11 +122,12 @@ AC_DEFUN([AC_USUAL_FUNCTION_CHECK], [
 AC_CHECK_FUNCS(basename strlcpy strlcat getpeereid sigaction)
 AC_CHECK_FUNCS(inet_ntop poll getline)
 ### Functions provided only on win32
-AC_CHECK_FUNCS(locatime_r recvmsg sendmsg strerror_r)
+AC_CHECK_FUNCS(locatime_r recvmsg sendmsg)
 ### Functions used by libusual itself
 AC_CHECK_FUNCS(syslog mmap recvmsg sendmsg getpeerucred)
 ### win32: link with ws2_32
 AC_SEARCH_LIBS(WSAGetLastError, ws2_32)
+AC_FUNC_STRERROR_R
 ])
 
 dnl
index 36430daf21c253eea53681d6225c3f74d8c07e7c..490ae6afead78662543cf5904cb6c9e434e17712 100644 (file)
@@ -1,5 +1,4 @@
 #include <usual/aatree.h>
-#include <usual/alloc.h>
 #include <usual/base.h>
 #include <usual/cbtree.h>
 #include <usual/cfparser.h>
@@ -12,6 +11,7 @@
 #include <usual/md5.h>
 #include <usual/safeio.h>
 #include <usual/slab.h>
+#include <usual/signal.h>
 #include <usual/socket.h>
 #include <usual/statlist.h>
 #include <usual/string.h>
diff --git a/usual/alloc.h b/usual/alloc.h
deleted file mode 100644 (file)
index 781dd69..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Alloc helpers.
- *
- * Copyright (c) 2009 Marko Kreen
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */ 
-
-#ifndef _USUAL_ALLOC_
-#define _USUAL_ALLOC_
-
-#include <usual/base.h>
-
-#include <stdlib.h>
-
-/*
- * Function: free
- *
- * Fix posix bug by accepting const pointer.
- */
-static inline void sane_free(const void *p)
-{
-       free((void *)p);
-}
-#define free(x) sane_free(x)
-
-/*
- * Function: zmalloc
- *
- * Zeroing malloc
- */
-_MUSTCHECK
-static inline void *zmalloc(size_t len)
-{
-       return calloc(1, len);
-}
-
-#endif
-
index fb6be69cbe26114bf3ceb460892a32fb36138137..185ec57b51f4ccad2823941b5ebb686b182bf5a3 100644 (file)
 #ifndef _USUAL_BASE_H_
 #define _USUAL_BASE_H_
 
+#ifdef WIN32
+#define WIN32_LEAN_AND_MEAN
+#define _WIN32_WINNT 0x0400
+#include <windows.h>
+#endif
+
 #include <usual/config.h>
 
 #include <sys/types.h>
 #include <stddef.h>
 #include <stdint.h>
 #include <stdbool.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+
+#ifdef WIN32
+#include <usual/base_win32.h>
+#endif
 
 /* give offset of a field inside struct */
 #ifndef offsetof
@@ -46,6 +59,7 @@
 #define ALIGN(x)  CUSTOM_ALIGN(x, sizeof(long))
 #endif
 
+#define _PACKED                        __attribute__((packed))
 
 /*
  * make compiler do something useful
@@ -83,7 +97,6 @@
 /* assert() that uses our logging */
 #ifndef Assert
 #ifdef CASSERT
-#include <stdlib.h>
 void log_fatal(const char *file, int line, const char *func, bool show_perror, const char *s, ...) _PRINTF(5, 6);
 #define Assert(e) \
        do { \
@@ -98,5 +111,19 @@ void log_fatal(const char *file, int line, const char *func, bool show_perror, c
 #endif
 #endif
 
+/* Fix posix bug by accepting const pointer.  */
+static inline void _const_free(const void *p)
+{
+       free((void *)p);
+}
+#define free(x) _const_free(x)
+
+/* Zeroing malloc */
+_MUSTCHECK
+static inline void *zmalloc(size_t len)
+{
+       return calloc(1, len);
+}
+
 #endif
 
diff --git a/usual/base_win32.h b/usual/base_win32.h
new file mode 100644 (file)
index 0000000..459ffd5
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Random win32 compat.
+ * 
+ * Copyright (c) 2007-2009  Marko Kreen, Skype Technologies OÜ
+ * 
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _USUAL_BASE_WIN32_H_
+#define _USUAL_BASE_WIN32_H_
+
+#define ECONNABORTED WSAECONNABORTED
+#define EMSGSIZE WSAEMSGSIZE
+#define EINPROGRESS WSAEWOULDBLOCK // WSAEINPROGRESS
+
+#undef EAGAIN
+#define EAGAIN WSAEWOULDBLOCK // WSAEAGAIN
+
+/* dummy types / functions */
+#define hstrerror strerror
+#define getuid() (6667)
+#define setsid() getpid()
+#define setgid(x) (-1)
+#define setuid(x) (-1)
+#define fork() (-1)
+#define geteuid() getuid()
+#define setgroups(s, p) (-1)
+
+#define srandom(s) srand(s)
+#define random() rand()
+
+
+/* getrlimit() */
+#define RLIMIT_NOFILE -1
+struct rlimit {
+       int rlim_cur;
+       int rlim_max;
+};
+static inline int getrlimit(int res, struct rlimit *dst)
+{
+       dst->rlim_cur = dst->rlim_max = -1;
+       return 0;
+}
+
+/* dummy getpwnam() */
+struct passwd {
+       char *pw_name;
+       char *pw_passwd;
+       int pw_uid;
+       int pw_gid;
+};
+static inline const struct passwd * getpwnam(const char *u) { return NULL; }
+
+#endif
index f94d407e3e319ddf9ff36264643651ab0c85d034..0525fcb173aa347321bd25529a28bea16debacc6 100644 (file)
 
 #include <usual/cbtree.h>
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-#include <unistd.h>
+#include <usual/string.h>
 
 /*
  * - Childs are either other nodes or user pointers.
@@ -110,12 +106,9 @@ static unsigned find_crit_bit(const char *a, const char *b)
        c = a[i] ^ b[i];
 
        /* find the first one */
-       pos = i * 8;
-       while ((c & 0x80) == 0) {
-               c <<= 1;
-               pos++;
-       }
-       return pos;
+       pos = 8 - fls(c);
+
+       return i * 8 + pos;
 }
 
 
diff --git a/usual/compat.c b/usual/compat.c
deleted file mode 100644 (file)
index d48a94d..0000000
+++ /dev/null
@@ -1,389 +0,0 @@
-#define _GNU_SOURCE
-
-#include <usual/compat.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <errno.h>
-
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-#ifdef HAVE_UCRED_H
-#include <ucred.h>
-#endif
-#ifdef HAVE_SYS_UCRED_H
-#include <sys/ucred.h>
-#endif
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#ifdef HAVE_SYS_UN_H
-#include <sys/un.h>
-#endif
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-#ifdef HAVE_NETINET_TCP_H
-#include <netinet/tcp.h>
-#endif
-
-#include <usual/logging.h>
-
-#ifndef HAVE_GETLINE
-/*
- * Read line from FILE with dynamic allocation.
- */
-int getline(char **line_p, size_t *size_p, void *_f)
-{
-       FILE *f = _f;
-       char *p;
-       int len = 0;
-
-       if (!*line_p || *size_p < 128) {
-               p = realloc(*line_p, 512);
-               if (!p) return -1;
-               *line_p = p;
-               *size_p = 512;
-       }
-
-       while (1) {
-               p = fgets(*line_p + len, *size_p - len, f);
-               if (!p)
-                       return len ? len : -1;
-               len += strlen(p);
-               if ((*line_p)[len - 1] == '\n')
-                       return len;
-               p = realloc(*line_p, *size_p * 2);
-               if (!p)
-                       return -1;
-               *line_p = p;
-               *size_p *= 2;
-       }
-}
-#endif
-
-#ifndef HAVE_GETPEEREID
-/*
- * Get other side's uid for UNIX socket.
- *
- * Standardise on getpeereid() from BSDs.
- */
-int getpeereid(int fd, uid_t *uid_p, gid_t *gid_p)
-{
-#ifdef SO_PEERCRED
-       struct ucred cred;
-       socklen_t len = sizeof(cred);
-       if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &len) >= 0) {
-               *uid_p = cred.uid;
-               *gid_p = cred.gid;
-               return 0;
-       }
-#else /* !SO_PEERCRED */
-#ifdef HAVE_GETPEERUCRED
-       ucred_t *cred = NULL;
-       if (getpeerucred(fd, &cred) >= 0) {
-               *uid_p = ucred_geteuid(cred);
-               *gid_p = ucred_getegid(cred);
-               ucred_free(cred);
-               if (*uid_p >= 0 && *gid_p >= 0)
-                       return 0;
-       }
-#else
-       errno = ENOSYS;
-#endif /* HAVE_GETPEERUCRED */
-#endif /* !SO_PEERCRED */
-       return -1;
-}
-#endif
-
-#ifndef HAVE_BASENAME
-const char *basename(const char *path)
-{
-       const char *p;
-       if (path == NULL || path[0] == 0)
-               return ".";
-       if ((p = strrchr(path, '/')) != NULL)
-               return p[1] ? p + 1 : p;
-       return path;
-}
-#endif
-
-#ifndef HAVE_INET_NTOP
-const char *inet_ntop(int af, const void *src, char *dst, int cnt)
-{
-       const unsigned char *p = src;
-       if (af != AF_INET)
-               return NULL;
-       snprintf(dst, cnt, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
-       return dst;
-}
-#endif
-
-#ifndef HAVE_POLL
-/*
- * Emulate poll() with select()
- */
-#include <sys/time.h>
-
-#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-
-/*
- * dynamic buffer for fd_set to avoid depending on FD_SETSIZE
- */
-
-struct fd_buf {
-       fd_set *set;
-       int alloc_bytes;
-};
-
-static void fdbuf_zero(struct fd_buf *buf)
-{
-       if (buf->set)
-               memset(buf->set, 0, buf->alloc_bytes);
-}
-
-static bool fdbuf_resize(struct fd_buf *buf, int fd)
-{
-       /* get some extra room for quaranteed alignment */
-       int need_bytes = fd/8 + 32;
-       /* default - 2048 fds */
-       int alloc = 256;
-       unsigned char *ptr;
-
-       if (buf->alloc_bytes < need_bytes)
-       {
-               while (alloc < need_bytes)
-                       alloc *= 2;
-
-               if (!buf->set)
-                       ptr = malloc(alloc);
-               else
-                       ptr = realloc(buf->set, alloc);
-
-               if (!ptr)
-                       return false;
-
-               /* clean new area */
-               memset(ptr + buf->alloc_bytes, 0, alloc - buf->alloc_bytes);
-
-               buf->set = (fd_set *)ptr;
-               buf->alloc_bytes = alloc;
-       }
-       return true;
-}
-
-int poll(struct pollfd *fds, nfds_t nfds, int timeout_ms)
-{
-       static struct fd_buf readfds = { NULL, 0 };
-       static struct fd_buf writefds = { NULL, 0 };
-
-       struct pollfd *pf;
-       int res, fd_max = 0;
-       struct timeval *tv = NULL;
-       struct timeval tvreal;
-       unsigned i;
-
-       /* convert timeout_ms to timeval */
-       if (timeout_ms >= 0)
-       {
-               tvreal.tv_sec = timeout_ms / 1000;
-               tvreal.tv_usec = (timeout_ms % 1000) * 1000;
-               tv = &tvreal;
-       } else if (timeout_ms < -1)
-               goto err_inval;
-
-       /*
-        * Convert pollfds to fd sets.
-        */
-       fdbuf_zero(&readfds);
-       fdbuf_zero(&writefds);
-       for (i = 0; i < nfds; i++)
-       {
-               pf = fds + i;
-               if (pf->fd < 0)
-                       goto err_badf;
-
-               /* sets must be equal size */
-               if (!fdbuf_resize(&readfds, pf->fd))
-                       goto err_nomem;
-               if (!fdbuf_resize(&writefds, pf->fd))
-                       goto err_nomem;
-
-               if (pf->events & POLLIN)
-                       FD_SET((unsigned)pf->fd, readfds.set);
-               if (pf->events & POLLOUT)
-                       FD_SET((unsigned)pf->fd, writefds.set);
-               if (pf->fd > fd_max)
-                       fd_max = pf->fd;
-       }
-
-       res = select(fd_max + 1, readfds.set, writefds.set, NULL, tv);
-       if (res <= 0)
-               return res;
-
-       /*
-        * select() and poll() count fd-s differently,
-        * need to recount them here.
-        */
-       res = 0;
-
-       for (i = 0; i < nfds; i++)
-       {
-               pf = fds + i;
-               pf->revents = 0;
-               if ((pf->events & POLLIN) && FD_ISSET(pf->fd, readfds.set))
-                       pf->revents |= POLLIN;
-               if ((pf->events & POLLOUT) && FD_ISSET(pf->fd, writefds.set))
-                       pf->revents |= POLLOUT;
-               if (pf->revents)
-                       res += 1;
-       }
-       return res;
-
-err_nomem:
-       errno = ENOMEM;
-       return -1;
-
-err_badf:
-       errno = EBADF;
-       return -1;
-err_inval:
-       errno = EINVAL;
-       return -1;
-}
-
-#endif /* PLPROXY_POLL_COMPAT */
-
-#ifndef HAVE_SIGACTION
-#include <signal.h>
-int sigaction(int sig, const struct sigaction *sa, struct sigaction *old)
-{
-       old->sa_handler = signal(sig, sa->sa_handler);
-       if (old->sa_handler == SIG_ERR)
-               return -1;
-       return 0;
-}
-#endif
-
-#ifdef WIN32
-const char *win32_strerror(int e)
-{
-       static char buf[1024];
-       FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, e,
-                     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-                     buf, sizeof(buf), NULL);
-       return buf;
-}
-
-void win32_eventlog(int level, const char *fmt, ...)
-{
-       static HANDLE evtHandle = INVALID_HANDLE_VALUE;
-       int elevel;
-       char buf[1024];
-       const char *strlist[1] = { buf };
-       va_list ap;
-
-       va_start(ap, fmt);
-       vsnprintf(buf, sizeof(buf), fmt, ap);
-       va_end(ap);
-
-       switch (level) {
-       case LOG_CRIT:
-       case LOG_ERR:
-               elevel = EVENTLOG_ERROR_TYPE;
-               break;
-       case LOG_WARNING:
-               elevel = EVENTLOG_WARNING_TYPE;
-               break;
-       default:
-               elevel = EVENTLOG_INFORMATION_TYPE;
-       }
-
-       if (evtHandle == INVALID_HANDLE_VALUE) {
-               evtHandle = RegisterEventSource(NULL, cf_syslog_ident);
-               if (evtHandle == NULL || evtHandle == INVALID_HANDLE_VALUE) {
-                       evtHandle = INVALID_HANDLE_VALUE;
-                       return;
-               }
-       }
-       ReportEvent(evtHandle, elevel, 0, 0, NULL, 1, 0, strlist, NULL);
-}
-
-/* create local TCP socket, idea from libevent/Tor */
-int win32_socketpair(int d, int typ, int proto, int sv[2])
-{
-       int list = -1, s1 = -1, s2 = -1;
-       struct sockaddr_in sa1, sa2;
-       socklen_t slen = sizeof(sa1);
-       int res;
-
-       if (d != AF_INET && d != AF_UNIX)
-               goto err_inval;
-       if (proto || !sv)
-               goto err_inval;
-
-       /* prepare sockaddr for bind */
-       memset(&sa1, 0, sizeof(sa1));
-       sa1.sin_family = AF_INET;
-       sa1.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-       sa1.sin_port = htons(0);
-
-       /* create listen socket */
-       list = socket(AF_INET, typ, 0);
-       if (list == -1)
-               return -1;
-       res = bind(list, (struct sockaddr *)&sa1, sizeof(sa1));
-       if (res == -1)
-               goto failed;
-       res = listen(list, 1);
-       if (res == -1)
-               goto failed;
-
-       /* read listen port */
-       res = getsockname(list, (struct sockaddr *)&sa1, &slen);
-       if (res == -1 || slen != sizeof(sa1))
-               goto failed;
-
-       /* connect to it */
-       s1 = socket(AF_INET, typ, 0);
-       if (s1 == -1)
-               goto failed;
-       res = connect(s1, (struct sockaddr *)&sa1, sizeof(sa1));
-       if (res == -1)
-               goto failed;
-
-       /* and accept from other end */
-       s2 = accept(list, (struct sockaddr *)&sa2, &slen);
-       if (s2 == -1 || slen != sizeof(sa2))
-               goto failed;
-
-       /* sanity check */
-       res = getsockname(s1, (struct sockaddr *)&sa1, &slen);
-       if (res == -1 || slen != sizeof(sa1))
-               goto failed;
-       if (sa1.sin_port != sa2.sin_port)
-               goto failed;
-
-       closesocket(list);
-       sv[0] = s1;
-       sv[1] = s2;
-       return 0;
-
-failed:
-       errno = (res == -1) ? WSAGetLastError() : EFAULT;
-       if (list != -1) closesocket(list);
-       if (s1 != -1) closesocket(s1);
-       if (s2 != -1) closesocket(s2);
-       return -1;
-
-err_inval:
-       errno = EINVAL;
-       return -1;
-}
-
-#endif
-
diff --git a/usual/compat.h b/usual/compat.h
deleted file mode 100644 (file)
index 46f5196..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-#ifndef _USUAL_COMPAT_H_
-#define _USUAL_COMPAT_H_
-
-#include <usual/base.h>
-
-#ifdef WIN32
-#include <usual/win32.h>
-#endif
-
-#if !defined(HAVE_GETLINE)
-#define getline(a,b,c) compat_getline(a,b,c)
-int getline(char **line_p, size_t *size_p, void *f);
-#endif
-
-
-#if !defined(HAVE_POLL)
-#define POLLIN         (1 << 0)
-#define POLLOUT                (1 << 1)
-#define POLLHUP                (1 << 2)
-#define POLLPRI                (1 << 3)
-#define POLLNVAL       (1 << 4)
-#define POLLERR                (1 << 5)
-#define poll(a,b,c)    compat_poll(a,b,c)
-struct pollfd {
-       int fd;
-       short events;
-       short revents;
-};
-typedef unsigned long nfds_t;
-int poll(struct pollfd *fds, nfds_t nfds, int timeout_ms);
-#endif
-
-
-#ifndef HAVE_INET_NTOP
-#define inet_ntop(a,b,c,d) compat_inet_ntop(a,b,c,d)
-const char *inet_ntop(int af, const void *src, char *dst, int cnt);
-#endif
-
-
-#ifndef HAVE_GETPEEREID
-#define getpeereid(a,b,c) compat_getpeereid(a,b,c)
-int getpeereid(int fd, uid_t *uid_p, gid_t *gid_p);
-#endif
-
-
-#ifndef HAVE_BASENAME
-#define basename(a) compat_basename(a)
-const char *basename(const char *path);
-#endif
-
-
-#ifndef HAVE_SIGACTION
-#define SA_SIGINFO 1
-#define SA_RESTART 2
-typedef struct siginfo_t siginfo_t;
-struct sigaction {
-       union {
-               void     (*sa_handler)(int);
-               void     (*sa_sigaction)(int, siginfo_t *, void *);
-       };
-       int sa_flags;
-       int sa_mask;
-};
-#define sigemptyset(s)
-#define sigfillset(s)
-#define sigaddset(s, sig)
-#define sigdelset(s, sig)
-#define sigaction(a,b,c) compat_sigaction(a,b,c)
-int sigaction(int sig, const struct sigaction *sa, struct sigaction *old);
-#endif
-
-#ifdef WIN32
-#define socketpair(a,b,c,d) win32_socketpair(a,b,c,d)
-int win32_socketpair(int d, int typ, int proto, int sv[2]);
-#endif
-
-#endif
-
index 812ddafccad395664c30bb2f749875cf704df87a..fa94d228267835c1a1c26740db752b13f5137422 100644 (file)
 
 #include <usual/daemon.h>
 
-#include <sys/types.h>
 #include <sys/stat.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <errno.h>
 #include <fcntl.h>
-#include <signal.h>
 #include <string.h>
 #include <stdio.h>
 
 #include <usual/logging.h>
-#include <usual/compat.h>
+#include <usual/signal.h>
 
 /*
  * pidfile management.
index d479031e4ca318668be4967150aa4e11aa6aa8f0..3eb34e2455889df4f75da6c48e952cb9b5e19fbd 100644 (file)
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */ 
 
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
 #include <usual/fileutil.h>
 
 #ifdef HAVE_SYS_MMAN_H
 #endif
 
 #include <sys/stat.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
 #include <fcntl.h>
 
-#include <usual/compat.h>
-
 /*
  * Load text file into C string.
  */
@@ -138,3 +129,38 @@ void unmap_file(struct MappedFile *m)
 }
 
 #endif
+
+
+#ifndef HAVE_GETLINE
+/*
+ * Read line from FILE with dynamic allocation.
+ */
+int getline(char **line_p, size_t *size_p, void *_f)
+{
+       FILE *f = _f;
+       char *p;
+       int len = 0;
+
+       if (!*line_p || *size_p < 128) {
+               p = realloc(*line_p, 512);
+               if (!p) return -1;
+               *line_p = p;
+               *size_p = 512;
+       }
+
+       while (1) {
+               p = fgets(*line_p + len, *size_p - len, f);
+               if (!p)
+                       return len ? len : -1;
+               len += strlen(p);
+               if ((*line_p)[len - 1] == '\n')
+                       return len;
+               p = realloc(*line_p, *size_p * 2);
+               if (!p)
+                       return -1;
+               *line_p = p;
+               *size_p *= 2;
+       }
+}
+#endif
+
index 753cc97b86ea6808ac7105995eaf2ed407791d9c..3186faf7aec6ed77e115b321e2622c87a9881906 100644 (file)
@@ -21,6 +21,8 @@
 
 #include <usual/base.h>
 
+#include <stdio.h>
+
 struct MappedFile {
        int fd;
        unsigned len;
@@ -38,5 +40,11 @@ ssize_t file_size(const char *fn);
 int map_file(struct MappedFile *m, const char *fname, int rw) _MUSTCHECK;
 void unmap_file(struct MappedFile *m);
 
+#if !defined(HAVE_GETLINE)
+#define getline(a,b,c) compat_getline(a,b,c)
+int getline(char **line_p, size_t *size_p, void *f);
+#endif
+
+
 #endif
 
index 2c9ebb159b0a066ec295db4b20fb22a0142b5e33..40ae5bd052975fda4fcfa12e227a5d661327a42e 100644 (file)
 
 #include <usual/logging.h>
 
-#include <sys/types.h>
-#include <errno.h>
 #include <stdio.h>
-#include <stdlib.h>
 #include <stdarg.h>
 #include <string.h>
-#include <unistd.h>
+
+#include <usual/time.h>
 
 #ifdef HAVE_SYSLOG_H
 #include <syslog.h>
 #endif
 
-#include <usual/compat.h>
-#include <usual/time.h>
+#ifdef WIN32
+#define LOG_EMERG       0
+#define LOG_ALERT       1
+#define LOG_CRIT        2
+#define LOG_ERR         3
+#define LOG_WARNING     4
+#define LOG_NOTICE      5
+#define LOG_INFO        6
+#define LOG_DEBUG       7
+
+#define LOG_PID 0
+#define LOG_DAEMON 0
+
+#define openlog(a,b,c)
+#define syslog win32_eventlog
+#define closelog()
+static void win32_eventlog(int level, const char *fmt, ...);
+#endif
 
 int cf_quiet = 0;
 int cf_verbose = 0;
@@ -142,3 +156,41 @@ void log_fatal(const char *file, int line, const char *func, bool show_perror, c
        }
 }
 
+#ifdef WIN32
+
+static void win32_eventlog(int level, const char *fmt, ...)
+{
+       static HANDLE evtHandle = INVALID_HANDLE_VALUE;
+       int elevel;
+       char buf[1024];
+       const char *strlist[1] = { buf };
+       va_list ap;
+
+       va_start(ap, fmt);
+       vsnprintf(buf, sizeof(buf), fmt, ap);
+       va_end(ap);
+
+       switch (level) {
+       case LOG_CRIT:
+       case LOG_ERR:
+               elevel = EVENTLOG_ERROR_TYPE;
+               break;
+       case LOG_WARNING:
+               elevel = EVENTLOG_WARNING_TYPE;
+               break;
+       default:
+               elevel = EVENTLOG_INFORMATION_TYPE;
+       }
+
+       if (evtHandle == INVALID_HANDLE_VALUE) {
+               evtHandle = RegisterEventSource(NULL, cf_syslog_ident);
+               if (evtHandle == NULL || evtHandle == INVALID_HANDLE_VALUE) {
+                       evtHandle = INVALID_HANDLE_VALUE;
+                       return;
+               }
+       }
+       ReportEvent(evtHandle, elevel, 0, 0, NULL, 1, 0, strlist, NULL);
+}
+
+#endif
+
index 027ca94f17fcae05fa7ffd81eaca13f42491eb43..b10fc4abc5afc87a7101bffa5358515ff19f704a 100644 (file)
@@ -21,8 +21,6 @@
 
 #include <usual/base.h>
 
-#include <stdlib.h>
-
 /*
  * 0 - show only info level msgs (default)
  * 1 - show debug msgs (log_debug)
index f0512bff7f9aaaaf70fb6414e0e6fcf98861e5d8..fac69d71a982ac7c4efc6fddf29fddf08d715070 100644 (file)
@@ -8,7 +8,6 @@
 
 #include <usual/base.h>
 
-#include <stdlib.h>
 #include <string.h>
 
 struct MBuf {
@@ -20,6 +19,10 @@ struct MBuf {
        bool fixed;
 };
 
+/* helpers for *printf() */
+#define MBUF_FMT       ".*s"
+#define MBUF_ARG(m)    (m) ? mbuf_written(m) : 6, (m) ? (const char *)mbuf_data(m) : "(null)"
+
 /*
  * Init functions.
  */
@@ -101,6 +104,11 @@ static inline unsigned mbuf_written(const struct MBuf *buf)
        return buf->write_pos;
 }
 
+static inline const void *mbuf_data(const struct MBuf *buf)
+{
+       return buf->data;
+}
+
 /*
  * Read functions.
  */
@@ -114,6 +122,32 @@ static inline bool mbuf_get_byte(struct MBuf *buf, uint8_t *dst_p)
        return true;
 }
 
+_MUSTCHECK
+static inline bool mbuf_get_uint16be(struct MBuf *buf, uint16_t *dst_p)
+{
+       unsigned a, b;
+       if (buf->read_pos + 2 > buf->write_pos)
+               return false;
+       a = buf->data[buf->read_pos++];
+       b = buf->data[buf->read_pos++];
+       *dst_p = (a << 8) | b;
+       return true;
+}
+
+_MUSTCHECK
+static inline bool mbuf_get_uint32be(struct MBuf *buf, uint32_t *dst_p)
+{
+       unsigned a, b, c, d;
+       if (buf->read_pos + 4 > buf->write_pos)
+               return false;
+       a = buf->data[buf->read_pos++];
+       b = buf->data[buf->read_pos++];
+       c = buf->data[buf->read_pos++];
+       d = buf->data[buf->read_pos++];
+       *dst_p = (a << 24) | (b << 16) | (c << 8) | d;
+       return true;
+}
+
 _MUSTCHECK
 static inline bool mbuf_get_bytes(struct MBuf *buf, unsigned len, const uint8_t **dst_p)
 {
@@ -171,6 +205,20 @@ static inline bool mbuf_write_raw_mbuf(struct MBuf *dst, struct MBuf *src)
        return mbuf_write(dst, src->data, src->write_pos);
 }
 
+/* writes partial contents of another mbuf, with touching it */
+_MUSTCHECK
+static inline bool mbuf_write_mbuf(struct MBuf *dst, struct MBuf *src, unsigned len)
+{
+       const uint8_t *data;
+       if (!mbuf_get_bytes(src, len, &data))
+               return false;
+       if (!mbuf_write(dst, data, len)) {
+               src->read_pos -= len;
+               return false;
+       }
+       return true;
+}
+
 _MUSTCHECK
 static inline bool mbuf_fill(struct MBuf *buf, uint8_t byte, unsigned len)
 {
index 190306b3e025e115d586bf2e4f615668c6861d7e..69a81c6563bffabaf673a57bfa6a45165f57466e 100644 (file)
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
 #include <usual/md5.h>
-#include <usual/base.h>
 
 #include <string.h>
 
index 9ecd1d29c144794a0019d17036f6a0e549ad93f8..44f1b126f1d9cf64421795fff7a075e9f515cd58 100644 (file)
@@ -39,7 +39,7 @@
 #include <sys/un.h>
 #endif
 
-#include <usual/compat.h>
+#include <usual/socket.h>
 #include <usual/logging.h>
 
 int safe_read(int fd, void *buf, int len)
@@ -151,39 +151,25 @@ loop:
        return res;
 }
 
-static const char *sa2str(const struct sockaddr *sa)
-{
-       static char buf[256];
-
-       if (sa->sa_family == AF_INET) {
-               struct sockaddr_in *in = (struct sockaddr_in *)sa;
-               snprintf(buf, sizeof(buf), "%s:%d", inet_ntoa(in->sin_addr), ntohs(in->sin_port));
-       } if (sa->sa_family == AF_UNIX) {
-               struct sockaddr_un *un = (struct sockaddr_un *)sa;
-               snprintf(buf, sizeof(buf), "unix:%s", un->sun_path);
-       } else {
-               snprintf(buf, sizeof(buf), "sa2str: unknown proto");
-       }
-       return buf;
-}
-
 int safe_connect(int fd, const struct sockaddr *sa, socklen_t sa_len)
 {
        int res;
+       char buf[128];
 loop:
        res = connect(fd, sa, sa_len);
        if (res < 0 && errno == EINTR)
                goto loop;
        if (res < 0 && (errno != EINPROGRESS || cf_verbose > 2))
-               log_noise("connect(%d, %s) = %s", fd, sa2str(sa), strerror(errno));
+               log_noise("connect(%d, %s) = %s", fd, sa2str(sa, buf, sizeof(buf)), strerror(errno));
        else if (cf_verbose > 2)
-               log_noise("connect(%d, %s) = %d", fd, sa2str(sa), res);
+               log_noise("connect(%d, %s) = %d", fd, sa2str(sa, buf, sizeof(buf)), res);
        return res;
 }
 
 int safe_accept(int fd, struct sockaddr *sa, socklen_t *sa_len_p)
 {
        int res;
+       char buf[128];
 loop:
        res = accept(fd, sa, sa_len_p);
        if (res < 0 && errno == EINTR)
@@ -191,7 +177,7 @@ loop:
        if (res < 0)
                log_noise("safe_accept(%d) = %s", fd, strerror(errno));
        else if (cf_verbose > 2)
-               log_noise("safe_accept(%d) = %d (%s)", fd, res, sa2str(sa));
+               log_noise("safe_accept(%d) = %d (%s)", fd, res, sa2str(sa, buf, sizeof(buf)));
        return res;
 }
 
index 4c5f3fee52c8f2cd193b40780e5d5e2c8e50a3c8..e65cc5cf9728f8cca1d6cf509192a7cc712e2b32 100644 (file)
 #ifndef _USUAL_SAFEIO_H_
 #define _USUAL_SAFEIO_H_
 
-#include <usual/compat.h>
-
-
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
+#include <usual/socket.h>
 
 int safe_read(int fd, void *buf, int len)                       _MUSTCHECK;
 int safe_write(int fd, const void *buf, int len)                _MUSTCHECK;
diff --git a/usual/signal.c b/usual/signal.c
new file mode 100644 (file)
index 0000000..8d5f3b7
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Signal compat.
+ *
+ * Copyright (c) 2009  Marko Kreen
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <usual/signal.h>
+
+/*
+ * alarm() for win32
+ */
+
+#ifdef WIN32
+
+struct AlarmCtx {
+       struct sigaction sa;
+       HANDLE event;
+       HANDLE thread;
+       int secs;
+
+};
+static volatile struct AlarmCtx actx;
+
+static DWORD WINAPI w32_alarm_thread(LPVOID arg)
+{
+       DWORD wres;
+       unsigned msecs;
+
+loop:
+       if (actx.secs > 0) {
+               msecs = actx.secs * 1000;
+       } else {
+               msecs = INFINITE;
+       }
+
+       wres = WaitForSingleObject(actx.event, msecs);
+       if (wres == WAIT_OBJECT_0) {
+               goto loop;
+       } else if (wres == WAIT_TIMEOUT) {
+               actx.secs = 0;
+               if (actx.sa.sa_handler)
+                       actx.sa.sa_handler(SIGALRM);
+               goto loop;
+       } else {
+               Sleep(1000);
+               goto loop;
+       }
+       return 0;
+}
+
+unsigned int alarm(unsigned int secs)
+{
+       actx.secs = secs;
+
+       /* create event */
+       if (!actx.event) {
+               actx.event = CreateEvent(NULL, FALSE, FALSE, NULL);
+               if (!actx.event)
+                       return 0;
+       }
+
+       /* create or notify thread */
+       if (!actx.thread) {
+               actx.thread = CreateThread(NULL, 0, w32_alarm_thread, NULL, 0, NULL);
+       } else {
+               SetEvent(actx.event);
+       }
+       return 0;
+}
+
+#endif
+
+#ifndef HAVE_SIGACTION
+int sigaction(int sig, const struct sigaction *sa, struct sigaction *old)
+{
+#ifdef WIN32
+       if (sig == SIGALRM) {
+               if (old)
+                       *old = actx.sa;
+               if (sa)
+                       actx.sa = *sa;
+               else
+                       actx.sa.sa_handler = NULL;
+               return 0;
+       }
+#endif
+       old->sa_handler = signal(sig, sa->sa_handler);
+       if (old->sa_handler == SIG_ERR)
+               return -1;
+       return 0;
+}
+#endif
+
+#ifdef WIN32
+/* Only sig=0 is supported, to detect if process is running (ESRCH->not) */
+int kill(int pid, int sig)
+{
+       HANDLE hProcess;
+       DWORD exitCode;
+       int ret = 0;
+
+       /* handle only sig == 0 */
+       if (sig != 0) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
+       if (hProcess == NULL) {
+               if (GetLastError() == ERROR_INVALID_PARAMETER)
+                       ret = ESRCH;
+               else
+                       ret = EPERM;
+       } else {
+               /* OpenProcess may succed for exited processes */
+               if (GetExitCodeProcess(hProcess, &exitCode)) {
+                       if (exitCode != STILL_ACTIVE)
+                               ret = ESRCH;
+               }
+               CloseHandle(hProcess);
+       }
+
+       if (ret) {
+               errno = ret;
+               return -1;
+       } else
+               return  0;
+}
+#endif
+
diff --git a/usual/signal.h b/usual/signal.h
new file mode 100644 (file)
index 0000000..1e37ab8
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Theme include for signals.
+ *
+ * Copyright (c) 2009 Marko Kreen
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _USUAL_SIGNAL_H_
+#define _USUAL_SIGNAL_H_
+
+#include <usual/base.h>
+
+#include <signal.h>
+
+/*
+ * Compat sigaction()
+ */
+
+#ifndef HAVE_SIGACTION
+#define SA_SIGINFO 1
+#define SA_RESTART 2
+typedef struct siginfo_t siginfo_t;
+struct sigaction {
+       union {
+               void     (*sa_handler)(int);
+               void     (*sa_sigaction)(int, siginfo_t *, void *);
+       };
+       int sa_flags;
+       int sa_mask;
+};
+#define sigemptyset(s)
+#define sigfillset(s)
+#define sigaddset(s, sig)
+#define sigdelset(s, sig)
+#define sigaction(a,b,c) compat_sigaction(a,b,c)
+int sigaction(int sig, const struct sigaction *sa, struct sigaction *old);
+#endif
+
+/*
+ * win32 compat:
+ * kill(), alarm, SIGALRM
+ */
+
+#ifdef WIN32
+
+#define SIGALRM 1023
+unsigned alarm(unsigned);
+
+int kill(int pid, int sig);
+
+typedef void (*_sighandler_t)(int);
+
+static inline _sighandler_t wrap_signal(int sig, _sighandler_t func)
+{
+       /* sigaction has custom handling for SIGALRM */
+       if (sig == SIGALRM) {
+               struct sigaction sa, oldsa;
+               sa.sa_handler = func;
+               sa.sa_flags = sa.sa_mask = 0;
+               sigaction(SIGALRM, &sa, &oldsa);
+               return oldsa.sa_handler;
+       }
+       return signal(sig, func);
+}
+#define signal(a,b) wrap_signal(a,b)
+#endif
+
+#endif
index 0d8ff32ece802462deabfaf89e113abe9c01ace7..bfba6d0603ad3ea77e9bd1bccd1c4bf7f2b08651 100644 (file)
@@ -28,7 +28,6 @@
 
 #include <sys/param.h>
 #include <string.h>
-#include <stdlib.h>
 
 #include <usual/statlist.h>
 
index 88dd5eaf3a8e9906453431b4c600d19934e3175a..f6599684f3853d37672c9c5c1454c29ff87e05f8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * socket helpers.
+ * Socket helpers and compat.
  *
  * Copyright (c) 2007-2009 Marko Kreen, Skype Technologies OÜ
  *
 
 #include <string.h>
 #include <stdio.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
 
-#ifdef HAVE_SYS_UN_H
-#include <sys/un.h>
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
 #endif
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
+#ifdef HAVE_UCRED_H
+#include <ucred.h>
 #endif
-#ifdef HAVE_NETINET_TCP_H
-#include <netinet/tcp.h>
-#endif
-#ifdef HAVE_ARPA_INET_H
-#include <arpa/inet.h>
+#ifdef HAVE_SYS_UCRED_H
+#include <sys/ucred.h>
 #endif
 
-#include <usual/compat.h>
 #include <usual/logging.h>
 
 /* toggle non-blocking flag */
@@ -67,19 +60,19 @@ bool socket_setup(int sock, bool non_block)
 {
        int res;
 
+       /* close fd on exec */
+       res = fcntl(sock, F_SETFD, FD_CLOEXEC);
+       if (res < 0)
+               return false;
+
 #ifdef SO_NOSIGPIPE
        /* disallow SIGPIPE, if possible */
-       int val = 1;
+       val = 1;
        res = setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof(val));
        if (res < 0)
                return false;
 #endif
 
-       /* close fd on exec */
-       res = fcntl(sock, F_SETFD, FD_CLOEXEC);
-       if (res < 0)
-               return false;
-
        /* when no data available, return EAGAIN instead blocking */
        if (!socket_set_nonblocking(sock, non_block))
                return false;
@@ -87,3 +80,311 @@ bool socket_setup(int sock, bool non_block)
        return true;
 }
 
+/*
+ * Convert sockaddr to string.  Supports ipv4, ipv6 and unix sockets.
+ */
+const char *sa2str(const struct sockaddr *sa, char *dst, int dstlen)
+{
+       const struct sockaddr_in *in;
+       const struct sockaddr_in6 *in6;
+       const struct sockaddr_un *un;
+       const char *tmp;
+       char buf[128];
+       switch (sa->sa_family) {
+       case AF_INET:
+               in = (struct sockaddr_in *)sa;
+               tmp = inet_ntop(AF_INET, &in->sin_addr, buf, sizeof(buf));
+               if (!tmp)
+                       return NULL;
+               snprintf(dst, dstlen, "%s:%d", tmp, ntohs(in->sin_port));
+               break;
+       case AF_INET6:
+               in6 = (struct sockaddr_in6 *)sa;
+               tmp = inet_ntop(AF_INET6, &in6->sin6_addr, buf, sizeof(buf));
+               if (!tmp)
+                       return NULL;
+               snprintf(dst, dstlen, "%s/%d", tmp, ntohs(in6->sin6_port));
+               break;
+       case AF_UNIX:
+               un = (struct sockaddr_un *)sa;
+               snprintf(dst, dstlen, "unix:%s", un->sun_path);
+               break;
+       default:
+               snprintf(dst, dstlen, "sa2str(%d): unknown proto", sa->sa_family);
+               break;
+       }
+       return dst;
+}
+
+#ifndef HAVE_GETPEEREID
+/*
+ * Get other side's uid for UNIX socket.
+ *
+ * Standardise on getpeereid() from BSDs.
+ */
+int getpeereid(int fd, uid_t *uid_p, gid_t *gid_p)
+{
+#ifdef SO_PEERCRED
+       struct ucred cred;
+       socklen_t len = sizeof(cred);
+       if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &len) >= 0) {
+               *uid_p = cred.uid;
+               *gid_p = cred.gid;
+               return 0;
+       }
+#else /* !SO_PEERCRED */
+#ifdef HAVE_GETPEERUCRED
+       ucred_t *cred = NULL;
+       if (getpeerucred(fd, &cred) >= 0) {
+               *uid_p = ucred_geteuid(cred);
+               *gid_p = ucred_getegid(cred);
+               ucred_free(cred);
+               if (*uid_p >= 0 && *gid_p >= 0)
+                       return 0;
+       }
+#else
+       errno = ENOSYS;
+#endif /* HAVE_GETPEERUCRED */
+#endif /* !SO_PEERCRED */
+       return -1;
+}
+#endif
+
+
+#ifndef HAVE_INET_NTOP
+const char *inet_ntop(int af, const void *src, char *dst, int dstlen)
+{
+       const unsigned char *p = src;
+       if (dstlen < 0) {
+               errno = EINVAL;
+               return NULL;
+       }
+       switch (af) {
+       case AF_INET:
+               snprintf(dst, dstlen, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
+               break;
+       case AF_INET6:
+               snprintf(dst, dstlen,
+                        "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:"
+                        "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
+                        p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
+                        p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
+               break;
+       default:
+               errno = EINVAL;
+               return NULL;
+       }
+       return dst;
+}
+#endif
+
+
+#ifndef HAVE_POLL
+/*
+ * Emulate poll() with select()
+ */
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+/*
+ * dynamic buffer for fd_set to avoid depending on FD_SETSIZE
+ */
+
+struct fd_buf {
+       fd_set *set;
+       int alloc_bytes;
+};
+
+static void fdbuf_zero(struct fd_buf *buf)
+{
+       if (buf->set)
+               memset(buf->set, 0, buf->alloc_bytes);
+}
+
+static bool fdbuf_resize(struct fd_buf *buf, int fd)
+{
+       /* get some extra room for quaranteed alignment */
+       int need_bytes = fd/8 + 32;
+       /* default - 2048 fds */
+       int alloc = 256;
+       unsigned char *ptr;
+
+       if (buf->alloc_bytes < need_bytes)
+       {
+               while (alloc < need_bytes)
+                       alloc *= 2;
+
+               if (!buf->set)
+                       ptr = malloc(alloc);
+               else
+                       ptr = realloc(buf->set, alloc);
+
+               if (!ptr)
+                       return false;
+
+               /* clean new area */
+               memset(ptr + buf->alloc_bytes, 0, alloc - buf->alloc_bytes);
+
+               buf->set = (fd_set *)ptr;
+               buf->alloc_bytes = alloc;
+       }
+       return true;
+}
+
+int poll(struct pollfd *fds, nfds_t nfds, int timeout_ms)
+{
+       static struct fd_buf readfds = { NULL, 0 };
+       static struct fd_buf writefds = { NULL, 0 };
+
+       struct pollfd *pf;
+       int res, fd_max = 0;
+       struct timeval *tv = NULL;
+       struct timeval tvreal;
+       unsigned i;
+
+       /* convert timeout_ms to timeval */
+       if (timeout_ms >= 0)
+       {
+               tvreal.tv_sec = timeout_ms / 1000;
+               tvreal.tv_usec = (timeout_ms % 1000) * 1000;
+               tv = &tvreal;
+       } else if (timeout_ms < -1)
+               goto err_inval;
+
+       /*
+        * Convert pollfds to fd sets.
+        */
+       fdbuf_zero(&readfds);
+       fdbuf_zero(&writefds);
+       for (i = 0; i < nfds; i++)
+       {
+               pf = fds + i;
+               if (pf->fd < 0)
+                       goto err_badf;
+
+               /* sets must be equal size */
+               if (!fdbuf_resize(&readfds, pf->fd))
+                       goto err_nomem;
+               if (!fdbuf_resize(&writefds, pf->fd))
+                       goto err_nomem;
+
+               if (pf->events & POLLIN)
+                       FD_SET((unsigned)pf->fd, readfds.set);
+               if (pf->events & POLLOUT)
+                       FD_SET((unsigned)pf->fd, writefds.set);
+               if (pf->fd > fd_max)
+                       fd_max = pf->fd;
+       }
+
+       res = select(fd_max + 1, readfds.set, writefds.set, NULL, tv);
+       if (res <= 0)
+               return res;
+
+       /*
+        * select() and poll() count fd-s differently,
+        * need to recount them here.
+        */
+       res = 0;
+
+       for (i = 0; i < nfds; i++)
+       {
+               pf = fds + i;
+               pf->revents = 0;
+               if ((pf->events & POLLIN) && FD_ISSET(pf->fd, readfds.set))
+                       pf->revents |= POLLIN;
+               if ((pf->events & POLLOUT) && FD_ISSET(pf->fd, writefds.set))
+                       pf->revents |= POLLOUT;
+               if (pf->revents)
+                       res += 1;
+       }
+       return res;
+
+err_nomem:
+       errno = ENOMEM;
+       return -1;
+
+err_badf:
+       errno = EBADF;
+       return -1;
+err_inval:
+       errno = EINVAL;
+       return -1;
+}
+
+#endif /* PLPROXY_POLL_COMPAT */
+
+#ifdef WIN32
+/* create local TCP socket, idea from libevent/Tor */
+int win32_socketpair(int d, int typ, int proto, int sv[2])
+{
+       int list = -1, s1 = -1, s2 = -1;
+       struct sockaddr_in sa1, sa2;
+       socklen_t slen = sizeof(sa1);
+       int res;
+
+       if (d != AF_INET && d != AF_UNIX)
+               goto err_inval;
+       if (proto || !sv)
+               goto err_inval;
+
+       /* prepare sockaddr for bind */
+       memset(&sa1, 0, sizeof(sa1));
+       sa1.sin_family = AF_INET;
+       sa1.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+       sa1.sin_port = htons(0);
+
+       /* create listen socket */
+       list = socket(AF_INET, typ, 0);
+       if (list == -1)
+               return -1;
+       res = bind(list, (struct sockaddr *)&sa1, sizeof(sa1));
+       if (res == -1)
+               goto failed;
+       res = listen(list, 1);
+       if (res == -1)
+               goto failed;
+
+       /* read listen port */
+       res = getsockname(list, (struct sockaddr *)&sa1, &slen);
+       if (res == -1 || slen != sizeof(sa1))
+               goto failed;
+
+       /* connect to it */
+       s1 = socket(AF_INET, typ, 0);
+       if (s1 == -1)
+               goto failed;
+       res = connect(s1, (struct sockaddr *)&sa1, sizeof(sa1));
+       if (res == -1)
+               goto failed;
+
+       /* and accept from other end */
+       s2 = accept(list, (struct sockaddr *)&sa2, &slen);
+       if (s2 == -1 || slen != sizeof(sa2))
+               goto failed;
+
+       /* sanity check */
+       res = getsockname(s1, (struct sockaddr *)&sa1, &slen);
+       if (res == -1 || slen != sizeof(sa1))
+               goto failed;
+       if (sa1.sin_port != sa2.sin_port)
+               goto failed;
+
+       closesocket(list);
+       sv[0] = s1;
+       sv[1] = s2;
+       return 0;
+
+failed:
+       errno = (res == -1) ? WSAGetLastError() : EFAULT;
+       if (list != -1) closesocket(list);
+       if (s1 != -1) closesocket(s1);
+       if (s2 != -1) closesocket(s2);
+       return -1;
+
+err_inval:
+       errno = EINVAL;
+       return -1;
+}
+#endif
index ac01382cd541e35c59afcbbf55d6c3cb66086302..1ad5cc254bb19fc455043a077199de4e74216abe 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * socket helpers.
+ * Theme include for sockets.
  *
  * Copyright (c) 2007-2009 Marko Kreen, Skype Technologies OÜ
  *
 
 #include <usual/base.h>
 
+
+#ifdef WIN32
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <usual/socket_win32.h>
+#endif
+
+#include <fcntl.h>
+
 #ifdef HAVE_SYS_SOCKET_H
 #include <sys/socket.h>
 #endif
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
+#ifdef HAVE_SYS_POLL_H
+#include <sys/poll.h>
+#endif
+#ifdef HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETINET_TCP_H
+#include <netinet/tcp.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
 
 bool socket_setup(int sock, bool non_block);
 bool socket_set_nonblocking(int sock, bool non_block);
 
+const char *sa2str(const struct sockaddr *sa, char *buf, int buflen);
+
+#ifndef HAVE_INET_NTOP
+#define inet_ntop(a,b,c,d) compat_inet_ntop(a,b,c,d)
+const char *inet_ntop(int af, const void *src, char *dst, int cnt);
+#endif
+
+#ifndef HAVE_GETPEEREID
+#define getpeereid(a,b,c) compat_getpeereid(a,b,c)
+int getpeereid(int fd, uid_t *uid_p, gid_t *gid_p);
+#endif
+
+#if !defined(HAVE_POLL)
+#define POLLIN         (1 << 0)
+#define POLLOUT                (1 << 1)
+#define POLLHUP                (1 << 2)
+#define POLLPRI                (1 << 3)
+#define POLLNVAL       (1 << 4)
+#define POLLERR                (1 << 5)
+#define poll(a,b,c)    compat_poll(a,b,c)
+struct pollfd {
+       int fd;
+       short events;
+       short revents;
+};
+typedef unsigned long nfds_t;
+int poll(struct pollfd *fds, nfds_t nfds, int timeout_ms);
+#endif
+
+#ifdef WIN32
+int win32_socketpair(int d, int typ, int proto, int sv[2]);
+#define socketpair(a,b,c,d) win32_socketpair(a,b,c,d)
+#endif
+
 #endif
 
similarity index 53%
rename from usual/win32.h
rename to usual/socket_win32.h
index fd157b5d7a2641aa17a861c32f8aab01a04e75ea..337a1cd6163d9b219dd60a66ef224619bb6fdcd7 100644 (file)
@@ -1,34 +1,25 @@
-#ifndef _USUAL_WIN32_
-#define _USUAL_WIN32_
-
-#define WIN32_LEAN_AND_MEAN
-
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#include <time.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#define ECONNABORTED WSAECONNABORTED
-#define EMSGSIZE WSAEMSGSIZE
-#define EINPROGRESS WSAEWOULDBLOCK // WSAEINPROGRESS
-
-#undef EAGAIN
-#define EAGAIN WSAEWOULDBLOCK // WSAEAGAIN
-
-/* dummy types / functions */
-#define hstrerror strerror
-#define getuid() (6667)
-#define setsid() getpid()
-#define setgid(x) (-1)
-#define setuid(x) (-1)
-#define fork() (-1)
-#define geteuid() getuid()
-#define setgroups(s, p) (-1)
-
-#define srandom(s) srand(s)
-#define random() rand()
+/*
+ * Socket compat code for win32.
+ *
+ * Copyright (c) 2007-2009  Marko Kreen, Skype Technologies OÜ
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */ 
+
+#ifndef _USUAL_SOCKET_WIN32_H_
+#define _USUAL_SOCKET_WIN32_H_
+
+typedef int socklen_t;
 
 #define in_addr_t   uint32_t
 
@@ -43,16 +34,16 @@ struct iovec {
 
 struct msghdr {
        void         *msg_name;
-       socklen_t     msg_namelen;
+       int          msg_namelen;
        struct iovec *msg_iov;
        int           msg_iovlen;
        void         *msg_control;
-       socklen_t     msg_controllen;
+       int           msg_controllen;
        int           msg_flags;
 };
 
 struct cmsghdr {
-       socklen_t       cmsg_len;
+       int             cmsg_len;
        int             cmsg_level;
        int             cmsg_type;
 };
@@ -88,7 +79,7 @@ static inline int ewrap(int res) {
 }
 
 /* proper signature for setsockopt */
-static inline int w_setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen)
+static inline int w_setsockopt(int fd, int level, int optname, const void *optval, int optlen)
 {
        return ewrap(setsockopt(fd, level, optname, optval, optlen));
 }
@@ -124,78 +115,12 @@ static inline struct hostent *w_gethostbyname(const char *n) {
 #define gethostbyname(a) w_gethostbyname(a)
 
 
-/* gettimeoutday() */
-static inline int win32_gettimeofday(struct timeval * tp, void * tzp)
-{
-       FILETIME file_time;
-       SYSTEMTIME system_time;
-       ULARGE_INTEGER ularge;
-       __int64 epoch = 116444736000000000LL;
-
-       GetSystemTime(&system_time);
-       SystemTimeToFileTime(&system_time, &file_time);
-       ularge.LowPart = file_time.dwLowDateTime;
-       ularge.HighPart = file_time.dwHighDateTime;
-
-       tp->tv_sec = (long) ((ularge.QuadPart - epoch) / 10000000L);
-       tp->tv_usec = (long) (system_time.wMilliseconds * 1000);
-
-       return 0;
-}
-#define gettimeofday(a,b) win32_gettimeofday(a,b)
-
 /* make unix socket related code compile */
 struct sockaddr_un {
        int sun_family;
        char sun_path[128];
 };
 
-/* getrlimit() */
-#define RLIMIT_NOFILE -1
-struct rlimit {
-       int rlim_cur;
-       int rlim_max;
-};
-static inline int getrlimit(int res, struct rlimit *dst)
-{
-       dst->rlim_cur = dst->rlim_max = -1;
-       return 0;
-}
-
-/* kill is only used to detect if process is running (ESRCH->not) */
-static inline int kill(int pid, int sig)
-{
-       HANDLE hProcess;
-       DWORD exitCode;
-       int ret = 0;
-
-       if (sig != 0) {
-               errno = EINVAL;
-               return -1;
-       }
-
-       hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
-       if (hProcess == NULL) {
-               if (GetLastError() == ERROR_INVALID_PARAMETER)
-                       ret = ESRCH;
-               else
-                       ret = EPERM;
-       } else {
-               /* OpenProcess may succed for exited processes */
-               if (GetExitCodeProcess(hProcess, &exitCode)) {
-                       if (exitCode != STILL_ACTIVE)
-                               ret = ESRCH;
-               }
-               CloseHandle(hProcess);
-       }
-
-       if (ret) {
-               errno = ret;
-               return -1;
-       } else
-               return  0;
-}
-
 /* sendmsg is not used */
 static inline int sendmsg(int s, const struct msghdr *m, int flags)
 {
@@ -220,15 +145,6 @@ static inline int recvmsg(int s, struct msghdr *m, int flags)
                    m->msg_iov[0].iov_len, flags);
 }
 
-/* dummy getpwnam() */
-struct passwd {
-       char *pw_name;
-       char *pw_passwd;
-       int pw_uid;
-       int pw_gid;
-};
-static inline const struct passwd * getpwnam(const char *u) { return NULL; }
-
 /*
  * fcntl
  */
@@ -273,60 +189,4 @@ static inline int fcntl(int fd, int cmd, long arg)
        }
 }
 
-/*
- * syslog
- */
-
-#define LOG_EMERG      0
-#define LOG_ALERT      1
-#define LOG_CRIT       2
-#define LOG_ERR                3
-#define LOG_WARNING    4
-#define LOG_NOTICE     5
-#define LOG_INFO       6
-#define LOG_DEBUG      7
-
-#define LOG_PID 0
-
-#define LOG_KERN 0
-#define LOG_USER 0
-#define LOG_MAIL 0
-#define LOG_DAEMON 0
-#define LOG_AUTH 0
-#define LOG_SYSLOG 0
-#define LOG_LPR 0
-#define LOG_NEWS 0
-#define LOG_UUCP 0
-#define LOG_CRON 0
-#define LOG_AUTHPRIV 0
-#define LOG_FTP 0
-#define LOG_LOCAL0 0
-#define LOG_LOCAL1 0
-#define LOG_LOCAL2 0
-#define LOG_LOCAL3 0
-#define LOG_LOCAL4 0
-#define LOG_LOCAL5 0
-#define LOG_LOCAL6 0
-#define LOG_LOCAL7 0
-
-static inline void openlog(const char *ident, int option, int facility) {}
-static inline void closelog(void) {}
-void win32_eventlog(int priority, const char *format, ...);
-#define syslog win32_eventlog
-
-static inline struct tm *localtime_r(const time_t *tp, struct tm *buf)
-{
-       struct tm *r = localtime(tp);
-       *buf = *r;
-       return buf;
-}
-
-const char *win32_strerror(int e);
-static inline const char *w_strerror(int e) {
-       if (e > 900)
-               return win32_strerror(e);
-       return strerror(e);
-}
-#define strerror(x) w_strerror(x)
-
 #endif
index 9270dd1629d3bc1ee8b7295a94006f119677d133..50816b711b3d31879d4981731abcacbb05575844 100644 (file)
@@ -1,6 +1,23 @@
+/*
+ * Random win32 compat.
+ *
+ * Copyright (c) 2009  Marko Kreen
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
 #include <usual/string.h>
 
-#include <usual/alloc.h>
 #include <usual/mbuf.h>
 #include <usual/statlist.h>
 
@@ -154,3 +171,71 @@ failed:
        return false;
 }
 
+/*
+ * Minimal spec-conforming implementations of strlcpy(), strlcat().
+ */
+
+#ifndef HAVE_STRLCPY
+size_t strlcpy(char *dst, const char *src, size_t n)
+{
+       size_t len = strlen(src);
+       if (len < n) {
+               memcpy(dst, src, len + 1);
+       } else if (n > 0) {
+               memcpy(dst, src, n - 1);
+               dst[n - 1] = 0;
+       }
+       return len;
+}
+#endif
+
+#ifndef HAVE_STRLCAT
+size_t strlcat(char *dst, const char *src, size_t n)
+{
+       size_t pos = 0;
+       while (pos < n && dst[pos])
+               pos++;
+       return pos + strlcpy(dst + pos, src, n - pos);
+}
+#endif
+
+#ifndef HAVE_BASENAME
+const char *basename(const char *path)
+{
+       const char *p;
+       if (path == NULL || path[0] == 0)
+               return ".";
+       if ((p = strrchr(path, '/')) != NULL)
+               return p[1] ? p + 1 : p;
+       return path;
+}
+#endif
+
+#ifdef WIN32
+const char *win32_strerror(int e)
+{
+       static char buf[1024];
+       return strerror_r(e, buf, sizeof(buf));
+}
+const char *win32_strerror_r(int e, char *dst, size_t dstlen)
+{
+       FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, e,
+                     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                     dst, dstlen, NULL);
+       return dst;
+}
+#else
+const char *wrap_strerror_r(int e, char *dst, size_t dstlen)
+{
+#undef strerror_r
+#ifdef STRERROR_R_CHAR_P
+       return strerror_r(e, dst, dstlen);
+#else
+       if (strerror_r(e, dst, dstlen) != 0)
+               strlcpy(dst, "ERR", dstlen);
+       return dst;
+#endif
+}
+#endif
+
+
index 4d7a5a83bd43c872ce41e618e857f10dd6522815..356679bcce2b67be756a79aca944f552e6bfd77c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Basic C strings.
+ * Theme include for strings.
  * 
  * Copyright (c) 2007-2009  Marko Kreen, Skype Technologies OÜ
  * 
 
 #include <string.h>
 
-/*
- * Minimal spec-conforming implementations of strlcpy(), strlcat().
- */
-
 #ifndef HAVE_STRLCPY
 #define strlcpy(a,b,c) usual_strlcpy(a,b,c)
-
-static inline size_t strlcpy(char *dst, const char *src, size_t n)
-{
-       size_t len = strlen(src);
-       if (len < n) {
-               memcpy(dst, src, len + 1);
-       } else if (n > 0) {
-               memcpy(dst, src, n - 1);
-               dst[n - 1] = 0;
-       }
-       return len;
-}
-
-#endif /* !HAVE_STRLCPY */
+size_t strlcpy(char *dst, const char *src, size_t n);
+#endif
 
 #ifndef HAVE_STRLCAT
 #define strlcat(a,b,c) usual_strlcat(a,b,c)
-
-static inline size_t strlcat(char *dst, const char *src, size_t n)
-{
-       size_t pos = 0;
-       while (pos < n && dst[pos])
-               pos++;
-       return pos + strlcpy(dst + pos, src, n - pos);
-}
-
-#endif /* !HAVE_STRLCAT */
+size_t strlcat(char *dst, const char *src, size_t n);
+#endif
 
 typedef bool (*str_cb)(void *arg, const char *s);
 
@@ -69,6 +45,57 @@ const char *strlist_pop(struct StrList *slist);
 
 bool parse_word_list(const char *s, str_cb cb_func, void *cb_arg);
 
+/*
+ * fls(int)
+ * flsl(long)
+ * flsll(long long)
+ *
+ *   find MSB bit set, 1-based ofs, 0 if arg == 0
+ */
+
+#if defined(__GNUC__) && (__GNUC__ >= 4)
+#define _FLS(sfx, type) \
+       return (8*sizeof(type)) - __builtin_clz ## sfx(x)
+#else
+#define _FLS(sfx, type) \
+       unsigned type z = x; \
+       unsigned int bit; \
+       if (!z) return 0; \
+       /* count from smallest bit, assuming small values */ \
+       for (bit = 1; z > 1; bit++) z >>= 1; \
+       return bit
+#endif
+
+#ifndef HAVE_FLS
+static inline int fls(int x) { _FLS(, int); }
+#endif
+#ifndef HAVE_FLSL
+static inline int flsl(long x) { _FLS(l, long); }
+#endif
+#ifndef HAVE_FLS
+static inline long long flsll(long long x) { _FLS(ll, long long); }
+#endif
+#undef _FLS
+
+
+#ifndef HAVE_BASENAME
+#define basename(a) compat_basename(a)
+const char *basename(const char *path);
+#endif
+
+/*
+ * strerror, strerror_r
+ */
+#ifdef WIN32
+const char *win32_strerror(int e);
+#define strerror(x) win32_strerror(x)
+const char *win32_strerror_r(int e, char *dst, size_t dstlen);
+#define strerror_r(x) win32_strerror_r(x)
+#else
+/* otherwise convert native strerror_r() to GNU signature */
+const char *wrap_strerror_r(int e, char *dst, size_t dstlen);
+#define strerror_r(a,b,c) wrap_strerror_r(a,b,c)
+#endif
 
 #endif
 
index 8aa9a904ebe3c1f0596441b4cad969b54092c47a..2e2a5a84ecf4486afd2fef1ca765827a81f9e9bd 100644 (file)
 
 #include <usual/time.h>
 
-#include <sys/time.h>
-#include <time.h>
 #include <stdio.h>
 
-#include <usual/compat.h>
-
 char *format_time_ms(usec_t time, char *dst, unsigned dstlen)
 {
        struct tm *tm, tmbuf;
@@ -58,7 +54,9 @@ char *format_time_s(usec_t time, char *dst, unsigned dstlen)
                s = time / USEC;
        }
        tm = localtime_r(&s, &tbuf);
-       strftime(dst, dstlen, "%Y-%m-%d %H:%M:%S", tm);
+       snprintf(dst, dstlen, "%04d-%02d-%02d %02d:%02d:%02d",
+                tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
+                tm->tm_hour, tm->tm_min, tm->tm_sec);
        return dst;
 }
 
@@ -87,3 +85,84 @@ void reset_time_cache(void)
        _time_cache = 0;
 }
 
+/*
+ * win32 compat
+ */
+
+#ifdef WIN32
+
+/* unix epoch (1970) in seconds from windows epoch (1601) */
+#define UNIX_EPOCH 11644473600LL
+
+/* 1 sec in 100 nsec units */
+#define FT_SEC 10000000LL
+
+static void ft2tv(FILETIME *src, struct timeval *dst, bool use_epoch)
+{
+       ULARGE_INTEGER tmp;
+       tmp.LowPart = src->dwLowDateTime;
+       tmp.HighPart = src->dwHighDateTime;
+       dst->tv_sec = (tmp.QuadPart / FT_SEC) - (use_epoch ? UNIX_EPOCH : 0);
+       dst->tv_usec = (tmp.QuadPart % FT_SEC) / 10;
+}
+
+int gettimeofday(struct timeval * tp, void * tzp)
+{
+       FILETIME file_time;
+       SYSTEMTIME system_time;
+
+       /* read UTC timestamp */
+       GetSystemTime(&system_time);
+       SystemTimeToFileTime(&system_time, &file_time);
+
+       /* convert to timeval */
+       ft2tv(&file_time, tp, true);
+
+       return 0;
+}
+
+struct tm *localtime_r(const time_t *tp, struct tm *dst)
+{
+       ULARGE_INTEGER utc;
+       FILETIME ft_utc;
+       SYSTEMTIME st_utc, st_local;
+
+       /* convert time_t to FILETIME */
+       utc.QuadPart = (*tp + UNIX_EPOCH) * FT_SEC;
+       ft_utc.dwLowDateTime = utc.LowPart;
+       ft_utc.dwHighDateTime = utc.HighPart;
+
+       /* split to parts and get local time */
+       if (!FileTimeToSystemTime(&ft_utc, &st_utc))
+               return NULL;
+       if (!SystemTimeToTzSpecificLocalTime(NULL, &st_utc, &st_local))
+               return NULL;
+
+       /* fill struct tm */
+       dst->tm_sec = st_local.wSecond;
+       dst->tm_min = st_local.wMinute;
+       dst->tm_hour = st_local.wHour;
+       dst->tm_mday = st_local.wDay;
+       dst->tm_mon = st_local.wMonth - 1;
+       dst->tm_year = st_local.wYear - 1900;
+       dst->tm_wday = st_local.wDayOfWeek;
+       dst->tm_yday = 0;
+       dst->tm_isdst = -1;
+       return dst;
+}
+
+int getrusage(int who, struct rusage *dst)
+{
+       FILETIME tcreate, texit, tkern, tuser;
+       if (who != RUSAGE_SELF) {
+               errno = EINVAL;
+               return -1;
+       }
+       if (!GetProcessTimes(GetCurrentProcess(), &tcreate, &texit, &tkern, &tuser))
+               return -1;
+       ft2tv(&tuser, &dst->ru_utime, false);
+       ft2tv(&tkern, &dst->ru_stime, false);
+       return 0;
+}
+
+#endif
index 09599f615380c4b1e8f235157e29df7ef9106581..90b7212fc9db57e16a147bb5e3a254c3e3c0ae3c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Common time functions.
+ * Theme include for time.
  *
  * Copyright (c) 2007-2009 Marko Kreen, Skype Technologies OÜ
  *
@@ -21,6 +21,9 @@
 
 #include <usual/base.h>
 
+#include <sys/time.h>
+#include <time.h>
+
 typedef uint64_t usec_t;
 #define USEC 1000000ULL
 
@@ -31,4 +34,20 @@ usec_t get_time_usec(void);
 usec_t get_cached_time(void);
 void reset_time_cache(void);
 
+#ifdef WIN32
+int gettimeofday(struct timeval * tp, void * tzp);
+struct tm *localtime_r(const time_t *tp, struct tm *buf);
+
+static inline void usleep(long usec) { Sleep(usec / 1000); }
+
+struct rusage {
+       struct timeval ru_utime;
+       struct timeval ru_stime;
+};
+
+#define RUSAGE_SELF 0
+int getrusage(int who, struct rusage *dst);
+
+#endif
+
 #endif