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__);],
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
#include <usual/aatree.h>
-#include <usual/alloc.h>
#include <usual/base.h>
#include <usual/cbtree.h>
#include <usual/cfparser.h>
#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>
+++ /dev/null
-/*
- * 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
-
#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
#define ALIGN(x) CUSTOM_ALIGN(x, sizeof(long))
#endif
+#define _PACKED __attribute__((packed))
/*
* make compiler do something useful
/* 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 { \
#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
--- /dev/null
+/*
+ * 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
#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.
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;
}
+++ /dev/null
-#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
-
+++ /dev/null
-#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
-
#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.
* 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.
*/
}
#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
+
#include <usual/base.h>
+#include <stdio.h>
+
struct MappedFile {
int fd;
unsigned len;
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
#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;
}
}
+#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
+
#include <usual/base.h>
-#include <stdlib.h>
-
/*
* 0 - show only info level msgs (default)
* 1 - show debug msgs (log_debug)
#include <usual/base.h>
-#include <stdlib.h>
#include <string.h>
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.
*/
return buf->write_pos;
}
+static inline const void *mbuf_data(const struct MBuf *buf)
+{
+ return buf->data;
+}
+
/*
* Read functions.
*/
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)
{
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)
{
* 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>
#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)
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)
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;
}
#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;
--- /dev/null
+/*
+ * 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
+
--- /dev/null
+/*
+ * 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
#include <sys/param.h>
#include <string.h>
-#include <stdlib.h>
#include <usual/statlist.h>
/*
- * 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 */
{
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;
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
/*
- * 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
-#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
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;
};
}
/* 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));
}
#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)
{
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
*/
}
}
-/*
- * 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
+/*
+ * 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>
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
+
+
/*
- * 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);
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
#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;
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;
}
_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
/*
- * Common time functions.
+ * Theme include for time.
*
* Copyright (c) 2007-2009 Marko Kreen, Skype Technologies OÜ
*
#include <usual/base.h>
+#include <sys/time.h>
+#include <time.h>
+
typedef uint64_t usec_t;
#define USEC 1000000ULL
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