compat FEATURE use standalone compat "library"
diff --git a/compat/compat.c b/compat/compat.c
new file mode 100644
index 0000000..c056484
--- /dev/null
+++ b/compat/compat.c
@@ -0,0 +1,178 @@
+/**
+ * @file compat.c
+ * @author Michal Vasko <mvasko@cesnet.cz>
+ * @brief compatibility functions
+ *
+ * Copyright (c) 2020 CESNET, z.s.p.o.
+ *
+ * This source code is licensed under BSD 3-Clause License (the "License").
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://opensource.org/licenses/BSD-3-Clause
+ */
+#include "compat.h"
+
+#define _POSIX_C_SOURCE 1 /* fdopen, _POSIX_PATH_MAX */
+#define _ISOC99_SOURCE /* vsnprintf */
+#define _XOPEN_SOURCE 500 /* strdup */
+
+#include <errno.h>
+#include <limits.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#ifndef HAVE_VDPRINTF
+int
+vdprintf(int fd, const char *format, va_list ap)
+{
+    FILE *stream;
+    int count;
+
+    stream = fdopen(dup(fd), "a+");
+    if (stream) {
+        count = vfprintf(stream, format, ap);
+        fclose(stream);
+    }
+    return count;
+}
+#endif
+
+#ifndef HAVE_ASPRINTF
+int
+asprintf(char **strp, const char *fmt, ...)
+{
+    int ret;
+    va_list ap;
+
+    va_start(ap, fmt);
+    ret = vasprintf(strp, fmt, ap);
+    va_end(ap);
+    return ret;
+}
+#endif
+
+#ifndef HAVE_VASPRINTF
+int
+vasprintf(char **strp, const char *fmt, va_list ap)
+{
+    va_list ap2;
+    va_copy(ap2, ap);
+    int l = vsnprintf(0, 0, fmt, ap2);
+    va_end(ap2);
+
+    if (l < 0 || !(*strp = malloc(l + 1U))) {
+        return -1;
+    }
+
+    return vsnprintf(*strp, l + 1U, fmt, ap);
+}
+#endif
+
+#ifndef HAVE_STRNDUP
+char *
+strndup(const char *s, size_t n)
+{
+    char *buf;
+    size_t len = 0;
+
+    /* strnlen */
+    for (; (len < n) && (s[len] != '\0'); ++len);
+
+    if (!(buf = malloc(len + 1U))) {
+        return NULL;
+    }
+
+    memcpy(buf, s, len);
+    buf[len] = '\0';
+    return buf;
+}
+#endif
+
+#ifndef HAVE_STRNSTR
+char *
+strnstr(const char *s, const char *find, size_t slen)
+{
+    char c, sc;
+    size_t len;
+
+    if ((c = *find++) != '\0') {
+        len = strlen(find);
+        do {
+            do {
+                if ((slen-- < 1) || ((sc = *s++) == '\0')) {
+                    return NULL;
+                }
+            } while (sc != c);
+            if (len > slen) {
+                return NULL;
+            }
+        } while (strncmp(s, find, len));
+        s--;
+    }
+    return (char *)s;
+}
+#endif
+
+#ifndef HAVE_GETLINE
+ssize_t
+getline(char **lineptr, size_t *n, FILE *stream)
+{
+    static char line[256];
+    char *ptr;
+    unsigned int len;
+
+    if (!lineptr || !n) {
+        errno = EINVAL;
+        return -1;
+    }
+
+    if (ferror(stream) || feof(stream)) {
+        return -1;
+    }
+
+    if (!fgets(line, 256, stream)) {
+        return -1;
+    }
+
+    ptr = strchr(line, '\n');
+    if (ptr) {
+        *ptr = '\0';
+    }
+
+    len = strlen(line);
+
+    if (len + 1 < 256) {
+        ptr = realloc(*lineptr, 256);
+        if (!ptr) {
+            return -1;
+        }
+        *lineptr = ptr;
+        *n = 256;
+    }
+
+    strcpy(*lineptr, line);
+    return len;
+}
+#endif
+
+#ifndef HAVE_GET_CURRENT_DIR_NAME
+char *
+get_current_dir_name(void)
+{
+    char tmp[_POSIX_PATH_MAX];
+    char *retval = NULL;
+
+    if (getcwd(tmp, sizeof(tmp))) {
+        retval = strdup(tmp);
+        if (!retval) {
+            errno = ENOMEM;
+        }
+    }
+
+    return retval;
+}
+#endif