summaryrefslogtreecommitdiff
path: root/compat
diff options
context:
space:
mode:
Diffstat (limited to 'compat')
-rw-r--r--compat/bswap.h60
-rw-r--r--compat/cygwin.c19
-rw-r--r--compat/cygwin.h2
-rw-r--r--compat/fopen.c4
-rw-r--r--compat/mingw.c151
-rw-r--r--compat/mingw.h6
-rw-r--r--compat/obstack.c5
-rw-r--r--compat/obstack.h5
-rw-r--r--compat/poll/poll.c7
-rw-r--r--compat/poll/poll.h3
-rw-r--r--compat/precompose_utf8.c1
-rw-r--r--compat/regex/regcomp.c5
-rw-r--r--compat/regex/regex.c5
-rw-r--r--compat/regex/regex.h5
-rw-r--r--compat/regex/regex_internal.c9
-rw-r--r--compat/regex/regex_internal.h5
-rw-r--r--compat/regex/regexec.c9
-rw-r--r--compat/win32/lazyload.h57
-rw-r--r--compat/win32/syslog.c2
-rw-r--r--compat/winansi.c12
20 files changed, 255 insertions, 117 deletions
diff --git a/compat/bswap.h b/compat/bswap.h
index d47c003544..5078ce5ecc 100644
--- a/compat/bswap.h
+++ b/compat/bswap.h
@@ -158,23 +158,55 @@ static inline uint64_t git_bswap64(uint64_t x)
#define get_be16(p) ntohs(*(unsigned short *)(p))
#define get_be32(p) ntohl(*(unsigned int *)(p))
+#define get_be64(p) ntohll(*(uint64_t *)(p))
#define put_be32(p, v) do { *(unsigned int *)(p) = htonl(v); } while (0)
+#define put_be64(p, v) do { *(uint64_t *)(p) = htonll(v); } while (0)
#else
-#define get_be16(p) ( \
- (*((unsigned char *)(p) + 0) << 8) | \
- (*((unsigned char *)(p) + 1) << 0) )
-#define get_be32(p) ( \
- (*((unsigned char *)(p) + 0) << 24) | \
- (*((unsigned char *)(p) + 1) << 16) | \
- (*((unsigned char *)(p) + 2) << 8) | \
- (*((unsigned char *)(p) + 3) << 0) )
-#define put_be32(p, v) do { \
- unsigned int __v = (v); \
- *((unsigned char *)(p) + 0) = __v >> 24; \
- *((unsigned char *)(p) + 1) = __v >> 16; \
- *((unsigned char *)(p) + 2) = __v >> 8; \
- *((unsigned char *)(p) + 3) = __v >> 0; } while (0)
+static inline uint16_t get_be16(const void *ptr)
+{
+ const unsigned char *p = ptr;
+ return (uint16_t)p[0] << 8 |
+ (uint16_t)p[1] << 0;
+}
+
+static inline uint32_t get_be32(const void *ptr)
+{
+ const unsigned char *p = ptr;
+ return (uint32_t)p[0] << 24 |
+ (uint32_t)p[1] << 16 |
+ (uint32_t)p[2] << 8 |
+ (uint32_t)p[3] << 0;
+}
+
+static inline uint64_t get_be64(const void *ptr)
+{
+ const unsigned char *p = ptr;
+ return (uint64_t)get_be32(&p[0]) << 32 |
+ (uint64_t)get_be32(&p[4]) << 0;
+}
+
+static inline void put_be32(void *ptr, uint32_t value)
+{
+ unsigned char *p = ptr;
+ p[0] = value >> 24;
+ p[1] = value >> 16;
+ p[2] = value >> 8;
+ p[3] = value >> 0;
+}
+
+static inline void put_be64(void *ptr, uint64_t value)
+{
+ unsigned char *p = ptr;
+ p[0] = value >> 56;
+ p[1] = value >> 48;
+ p[2] = value >> 40;
+ p[3] = value >> 32;
+ p[4] = value >> 24;
+ p[5] = value >> 16;
+ p[6] = value >> 8;
+ p[7] = value >> 0;
+}
#endif
diff --git a/compat/cygwin.c b/compat/cygwin.c
new file mode 100644
index 0000000000..b9862d606d
--- /dev/null
+++ b/compat/cygwin.c
@@ -0,0 +1,19 @@
+#include "../git-compat-util.h"
+#include "../cache.h"
+
+int cygwin_offset_1st_component(const char *path)
+{
+ const char *pos = path;
+ /* unc paths */
+ if (is_dir_sep(pos[0]) && is_dir_sep(pos[1])) {
+ /* skip server name */
+ pos = strchr(pos + 2, '/');
+ if (!pos)
+ return 0; /* Error: malformed unc path */
+
+ do {
+ pos++;
+ } while (*pos && pos[0] != '/');
+ }
+ return pos + is_dir_sep(*pos) - path;
+}
diff --git a/compat/cygwin.h b/compat/cygwin.h
new file mode 100644
index 0000000000..8e52de4644
--- /dev/null
+++ b/compat/cygwin.h
@@ -0,0 +1,2 @@
+int cygwin_offset_1st_component(const char *path);
+#define offset_1st_component cygwin_offset_1st_component
diff --git a/compat/fopen.c b/compat/fopen.c
index b5ca142fed..107b3e8182 100644
--- a/compat/fopen.c
+++ b/compat/fopen.c
@@ -1,14 +1,14 @@
/*
* The order of the following two lines is important.
*
- * FREAD_READS_DIRECTORIES is undefined before including git-compat-util.h
+ * SUPPRESS_FOPEN_REDEFINITION is defined before including git-compat-util.h
* to avoid the redefinition of fopen within git-compat-util.h. This is
* necessary since fopen is a macro on some platforms which may be set
* based on compiler options. For example, on AIX fopen is set to fopen64
* when _LARGE_FILES is defined. The previous technique of merely undefining
* fopen after including git-compat-util.h is inadequate in this case.
*/
-#undef FREAD_READS_DIRECTORIES
+#define SUPPRESS_FOPEN_REDEFINITION
#include "../git-compat-util.h"
FILE *git_fopen(const char *path, const char *mode)
diff --git a/compat/mingw.c b/compat/mingw.c
index 3fbfda5978..2d44d21aca 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -423,6 +423,8 @@ FILE *mingw_fopen (const char *filename, const char *otype)
return NULL;
}
file = _wfopen(wfilename, wotype);
+ if (!file && GetLastError() == ERROR_INVALID_NAME)
+ errno = ENOENT;
if (file && hide && set_hidden_flag(wfilename, 1))
warning("could not mark '%s' as hidden.", filename);
return file;
@@ -941,64 +943,14 @@ static const char *parse_interpreter(const char *cmd)
}
/*
- * Splits the PATH into parts.
- */
-static char **get_path_split(void)
-{
- char *p, **path, *envpath = mingw_getenv("PATH");
- int i, n = 0;
-
- if (!envpath || !*envpath)
- return NULL;
-
- envpath = xstrdup(envpath);
- p = envpath;
- while (p) {
- char *dir = p;
- p = strchr(p, ';');
- if (p) *p++ = '\0';
- if (*dir) { /* not earlier, catches series of ; */
- ++n;
- }
- }
- if (!n)
- return NULL;
-
- ALLOC_ARRAY(path, n + 1);
- p = envpath;
- i = 0;
- do {
- if (*p)
- path[i++] = xstrdup(p);
- p = p+strlen(p)+1;
- } while (i < n);
- path[i] = NULL;
-
- free(envpath);
-
- return path;
-}
-
-static void free_path_split(char **path)
-{
- char **p = path;
-
- if (!path)
- return;
-
- while (*p)
- free(*p++);
- free(path);
-}
-
-/*
* exe_only means that we only want to detect .exe files, but not scripts
* (which do not have an extension)
*/
-static char *lookup_prog(const char *dir, const char *cmd, int isexe, int exe_only)
+static char *lookup_prog(const char *dir, int dirlen, const char *cmd,
+ int isexe, int exe_only)
{
char path[MAX_PATH];
- snprintf(path, sizeof(path), "%s/%s.exe", dir, cmd);
+ snprintf(path, sizeof(path), "%.*s\\%s.exe", dirlen, dir, cmd);
if (!isexe && access(path, F_OK) == 0)
return xstrdup(path);
@@ -1013,17 +965,29 @@ static char *lookup_prog(const char *dir, const char *cmd, int isexe, int exe_on
* Determines the absolute path of cmd using the split path in path.
* If cmd contains a slash or backslash, no lookup is performed.
*/
-static char *path_lookup(const char *cmd, char **path, int exe_only)
+static char *path_lookup(const char *cmd, int exe_only)
{
+ const char *path;
char *prog = NULL;
int len = strlen(cmd);
int isexe = len >= 4 && !strcasecmp(cmd+len-4, ".exe");
if (strchr(cmd, '/') || strchr(cmd, '\\'))
- prog = xstrdup(cmd);
+ return xstrdup(cmd);
- while (!prog && *path)
- prog = lookup_prog(*path++, cmd, isexe, exe_only);
+ path = mingw_getenv("PATH");
+ if (!path)
+ return NULL;
+
+ while (!prog) {
+ const char *sep = strchrnul(path, ';');
+ int dirlen = sep - path;
+ if (dirlen)
+ prog = lookup_prog(path, dirlen, cmd, isexe, exe_only);
+ if (!*sep)
+ break;
+ path = sep + 1;
+ }
return prog;
}
@@ -1190,8 +1154,7 @@ pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **deltaenv,
int fhin, int fhout, int fherr)
{
pid_t pid;
- char **path = get_path_split();
- char *prog = path_lookup(cmd, path, 0);
+ char *prog = path_lookup(cmd, 0);
if (!prog) {
errno = ENOENT;
@@ -1202,7 +1165,7 @@ pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **deltaenv,
if (interpr) {
const char *argv0 = argv[0];
- char *iprog = path_lookup(interpr, path, 1);
+ char *iprog = path_lookup(interpr, 1);
argv[0] = prog;
if (!iprog) {
errno = ENOENT;
@@ -1220,21 +1183,18 @@ pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **deltaenv,
fhin, fhout, fherr);
free(prog);
}
- free_path_split(path);
return pid;
}
static int try_shell_exec(const char *cmd, char *const *argv)
{
const char *interpr = parse_interpreter(cmd);
- char **path;
char *prog;
int pid = 0;
if (!interpr)
return 0;
- path = get_path_split();
- prog = path_lookup(interpr, path, 1);
+ prog = path_lookup(interpr, 1);
if (prog) {
int argc = 0;
const char **argv2;
@@ -1253,7 +1213,6 @@ static int try_shell_exec(const char *cmd, char *const *argv)
free(prog);
free(argv2);
}
- free_path_split(path);
return pid;
}
@@ -1275,8 +1234,7 @@ int mingw_execv(const char *cmd, char *const *argv)
int mingw_execvp(const char *cmd, char *const *argv)
{
- char **path = get_path_split();
- char *prog = path_lookup(cmd, path, 0);
+ char *prog = path_lookup(cmd, 0);
if (prog) {
mingw_execv(prog, argv);
@@ -1284,7 +1242,6 @@ int mingw_execvp(const char *cmd, char *const *argv)
} else
errno = ENOENT;
- free_path_split(path);
return -1;
}
@@ -2182,6 +2139,62 @@ static char *wcstoutfdup_startup(char *buffer, const wchar_t *wcs, size_t len)
return memcpy(malloc_startup(len), buffer, len);
}
+static void maybe_redirect_std_handle(const wchar_t *key, DWORD std_id, int fd,
+ DWORD desired_access, DWORD flags)
+{
+ DWORD create_flag = fd ? OPEN_ALWAYS : OPEN_EXISTING;
+ wchar_t buf[MAX_PATH];
+ DWORD max = ARRAY_SIZE(buf);
+ HANDLE handle;
+ DWORD ret = GetEnvironmentVariableW(key, buf, max);
+
+ if (!ret || ret >= max)
+ return;
+
+ /* make sure this does not leak into child processes */
+ SetEnvironmentVariableW(key, NULL);
+ if (!wcscmp(buf, L"off")) {
+ close(fd);
+ handle = GetStdHandle(std_id);
+ if (handle != INVALID_HANDLE_VALUE)
+ CloseHandle(handle);
+ return;
+ }
+ if (std_id == STD_ERROR_HANDLE && !wcscmp(buf, L"2>&1")) {
+ handle = GetStdHandle(STD_OUTPUT_HANDLE);
+ if (handle == INVALID_HANDLE_VALUE) {
+ close(fd);
+ handle = GetStdHandle(std_id);
+ if (handle != INVALID_HANDLE_VALUE)
+ CloseHandle(handle);
+ } else {
+ int new_fd = _open_osfhandle((intptr_t)handle, O_BINARY);
+ SetStdHandle(std_id, handle);
+ dup2(new_fd, fd);
+ /* do *not* close the new_fd: that would close stdout */
+ }
+ return;
+ }
+ handle = CreateFileW(buf, desired_access, 0, NULL, create_flag,
+ flags, NULL);
+ if (handle != INVALID_HANDLE_VALUE) {
+ int new_fd = _open_osfhandle((intptr_t)handle, O_BINARY);
+ SetStdHandle(std_id, handle);
+ dup2(new_fd, fd);
+ close(new_fd);
+ }
+}
+
+static void maybe_redirect_std_handles(void)
+{
+ maybe_redirect_std_handle(L"GIT_REDIRECT_STDIN", STD_INPUT_HANDLE, 0,
+ GENERIC_READ, FILE_ATTRIBUTE_NORMAL);
+ maybe_redirect_std_handle(L"GIT_REDIRECT_STDOUT", STD_OUTPUT_HANDLE, 1,
+ GENERIC_WRITE, FILE_ATTRIBUTE_NORMAL);
+ maybe_redirect_std_handle(L"GIT_REDIRECT_STDERR", STD_ERROR_HANDLE, 2,
+ GENERIC_WRITE, FILE_FLAG_NO_BUFFERING);
+}
+
void mingw_startup(void)
{
int i, maxlen, argc;
@@ -2189,6 +2202,8 @@ void mingw_startup(void)
wchar_t **wenv, **wargv;
_startupinfo si;
+ maybe_redirect_std_handles();
+
/* get wide char arguments and environment */
si.newmode = 0;
if (__wgetmainargs(&argc, &wargv, &wenv, _CRT_glob, &si) < 0)
diff --git a/compat/mingw.h b/compat/mingw.h
index 3350169555..e03aecfe2e 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -398,7 +398,11 @@ HANDLE winansi_get_osfhandle(int fd);
(isalpha(*(path)) && (path)[1] == ':' ? 2 : 0)
int mingw_skip_dos_drive_prefix(char **path);
#define skip_dos_drive_prefix mingw_skip_dos_drive_prefix
-#define is_dir_sep(c) ((c) == '/' || (c) == '\\')
+static inline int mingw_is_dir_sep(int c)
+{
+ return c == '/' || c == '\\';
+}
+#define is_dir_sep mingw_is_dir_sep
static inline char *mingw_find_last_dir_sep(const char *path)
{
char *ret = NULL;
diff --git a/compat/obstack.c b/compat/obstack.c
index e276ccd7b3..4d1d95beeb 100644
--- a/compat/obstack.c
+++ b/compat/obstack.c
@@ -14,9 +14,8 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#include "git-compat-util.h"
#include <gettext.h>
diff --git a/compat/obstack.h b/compat/obstack.h
index ceb4bdbcdd..6bc24b7644 100644
--- a/compat/obstack.h
+++ b/compat/obstack.h
@@ -14,9 +14,8 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
/* Summary:
diff --git a/compat/poll/poll.c b/compat/poll/poll.c
index b10adc780f..7ed3fbbea1 100644
--- a/compat/poll/poll.c
+++ b/compat/poll/poll.c
@@ -16,8 +16,7 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation,
- Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+ with this program; if not, see <http://www.gnu.org/licenses/>. */
/* Tell gcc not to warn about the (nfd < 0) tests, below. */
#if (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) || 4 < __GNUC__
@@ -438,6 +437,10 @@ poll (struct pollfd *pfd, nfds_t nfd, int timeout)
pfd[i].revents = happened;
rc++;
}
+ else
+ {
+ pfd[i].revents = 0;
+ }
}
return rc;
diff --git a/compat/poll/poll.h b/compat/poll/poll.h
index b7aa59d973..cd1995292a 100644
--- a/compat/poll/poll.h
+++ b/compat/poll/poll.h
@@ -16,8 +16,7 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation,
- Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+ with this program; if not, see <http://www.gnu.org/licenses/>. */
#ifndef _GL_POLL_H
#define _GL_POLL_H
diff --git a/compat/precompose_utf8.c b/compat/precompose_utf8.c
index 4293b53b17..de61c15d34 100644
--- a/compat/precompose_utf8.c
+++ b/compat/precompose_utf8.c
@@ -6,6 +6,7 @@
#define PRECOMPOSE_UNICODE_C
#include "cache.h"
+#include "config.h"
#include "utf8.h"
#include "precompose_utf8.h"
diff --git a/compat/regex/regcomp.c b/compat/regex/regcomp.c
index d8bde06f1a..51cd60baa3 100644
--- a/compat/regex/regcomp.c
+++ b/compat/regex/regcomp.c
@@ -14,9 +14,8 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301 USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
static reg_errcode_t re_compile_internal (regex_t *preg, const char * pattern,
size_t length, reg_syntax_t syntax);
diff --git a/compat/regex/regex.c b/compat/regex/regex.c
index 5cb23e5d59..f3e03a9eab 100644
--- a/compat/regex/regex.c
+++ b/compat/regex/regex.c
@@ -14,9 +14,8 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301 USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
#include "config.h"
diff --git a/compat/regex/regex.h b/compat/regex/regex.h
index 61c9683872..4d81358a83 100644
--- a/compat/regex/regex.h
+++ b/compat/regex/regex.h
@@ -18,9 +18,8 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301 USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#ifndef _REGEX_H
#define _REGEX_H 1
diff --git a/compat/regex/regex_internal.c b/compat/regex/regex_internal.c
index d4121f2f4f..59bf151336 100644
--- a/compat/regex/regex_internal.c
+++ b/compat/regex/regex_internal.c
@@ -14,9 +14,8 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301 USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
static void re_string_construct_common (const char *str, int len,
re_string_t *pstr,
@@ -613,7 +612,7 @@ re_string_reconstruct (re_string_t *pstr, int idx, int eflags)
int low = 0, high = pstr->valid_len, mid;
do
{
- mid = (high + low) / 2;
+ mid = low + (high - low) / 2;
if (pstr->offsets[mid] > offset)
high = mid;
else if (pstr->offsets[mid] < offset)
@@ -1394,7 +1393,7 @@ re_node_set_contains (const re_node_set *set, int elem)
right = set->nelem - 1;
while (idx < right)
{
- mid = (idx + right) / 2;
+ mid = idx + (right - idx) / 2;
if (set->elems[mid] < elem)
idx = mid + 1;
else
diff --git a/compat/regex/regex_internal.h b/compat/regex/regex_internal.h
index 4184d7f5a6..3ee8aae59d 100644
--- a/compat/regex/regex_internal.h
+++ b/compat/regex/regex_internal.h
@@ -14,9 +14,8 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#ifndef _REGEX_INTERNAL_H
#define _REGEX_INTERNAL_H 1
diff --git a/compat/regex/regexec.c b/compat/regex/regexec.c
index eb5e1d4439..1b5d89fd5e 100644
--- a/compat/regex/regexec.c
+++ b/compat/regex/regexec.c
@@ -14,9 +14,8 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301 USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
static reg_errcode_t match_ctx_init (re_match_context_t *cache, int eflags,
int n) internal_function;
@@ -4102,7 +4101,7 @@ extend_buffers (re_match_context_t *mctx)
if (BE (INT_MAX / 2 / sizeof (re_dfastate_t *) <= pstr->bufs_len, 0))
return REG_ESPACE;
- /* Double the lengthes of the buffers. */
+ /* Double the lengths of the buffers. */
ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2);
if (BE (ret != REG_NOERROR, 0))
return ret;
@@ -4284,7 +4283,7 @@ search_cur_bkref_entry (const re_match_context_t *mctx, int str_idx)
last = right = mctx->nbkref_ents;
for (left = 0; left < right;)
{
- mid = (left + right) / 2;
+ mid = left + (right - left) / 2;
if (mctx->bkref_ents[mid].str_idx < str_idx)
left = mid + 1;
else
diff --git a/compat/win32/lazyload.h b/compat/win32/lazyload.h
new file mode 100644
index 0000000000..9e631c8593
--- /dev/null
+++ b/compat/win32/lazyload.h
@@ -0,0 +1,57 @@
+#ifndef LAZYLOAD_H
+#define LAZYLOAD_H
+
+/*
+ * A pair of macros to simplify loading of DLL functions. Example:
+ *
+ * DECLARE_PROC_ADDR(kernel32.dll, BOOL, CreateHardLinkW,
+ * LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES);
+ *
+ * if (!INIT_PROC_ADDR(CreateHardLinkW))
+ * return error("Could not find CreateHardLinkW() function";
+ *
+ * if (!CreateHardLinkW(source, target, NULL))
+ * return error("could not create hardlink from %S to %S",
+ * source, target);
+ */
+
+struct proc_addr {
+ const char *const dll;
+ const char *const function;
+ FARPROC pfunction;
+ unsigned initialized : 1;
+};
+
+/* Declares a function to be loaded dynamically from a DLL. */
+#define DECLARE_PROC_ADDR(dll, rettype, function, ...) \
+ static struct proc_addr proc_addr_##function = \
+ { #dll, #function, NULL, 0 }; \
+ static rettype (WINAPI *function)(__VA_ARGS__)
+
+/*
+ * Loads a function from a DLL (once-only).
+ * Returns non-NULL function pointer on success.
+ * Returns NULL + errno == ENOSYS on failure.
+ * This function is not thread-safe.
+ */
+#define INIT_PROC_ADDR(function) \
+ (function = get_proc_addr(&proc_addr_##function))
+
+static inline void *get_proc_addr(struct proc_addr *proc)
+{
+ /* only do this once */
+ if (!proc->initialized) {
+ HANDLE hnd;
+ proc->initialized = 1;
+ hnd = LoadLibraryExA(proc->dll, NULL,
+ LOAD_LIBRARY_SEARCH_SYSTEM32);
+ if (hnd)
+ proc->pfunction = GetProcAddress(hnd, proc->function);
+ }
+ /* set ENOSYS if DLL or function was not found */
+ if (!proc->pfunction)
+ errno = ENOSYS;
+ return proc->pfunction;
+}
+
+#endif
diff --git a/compat/win32/syslog.c b/compat/win32/syslog.c
index 6c7c9b6053..161978d720 100644
--- a/compat/win32/syslog.c
+++ b/compat/win32/syslog.c
@@ -43,8 +43,10 @@ void syslog(int priority, const char *fmt, ...)
va_end(ap);
while ((pos = strstr(str, "%1")) != NULL) {
+ char *oldstr = str;
str = realloc(str, st_add(++str_len, 1));
if (!str) {
+ free(oldstr);
warning_errno("realloc failed");
return;
}
diff --git a/compat/winansi.c b/compat/winansi.c
index 793420f9d0..a11a0f16d2 100644
--- a/compat/winansi.c
+++ b/compat/winansi.c
@@ -105,6 +105,13 @@ static int is_console(int fd)
if (!fd) {
if (!GetConsoleMode(hcon, &mode))
return 0;
+ /*
+ * This code path is only reached if there is no console
+ * attached to stdout/stderr, i.e. we will not need to output
+ * any text to any console, therefore we might just as well
+ * use black as foreground color.
+ */
+ sbi.wAttributes = 0;
} else if (!GetConsoleScreenBufferInfo(hcon, &sbi))
return 0;
@@ -133,6 +140,11 @@ static void write_console(unsigned char *str, size_t len)
/* convert utf-8 to utf-16 */
int wlen = xutftowcsn(wbuf, (char*) str, ARRAY_SIZE(wbuf), len);
+ if (wlen < 0) {
+ wchar_t *err = L"[invalid]";
+ WriteConsoleW(console, err, wcslen(err), &dummy, NULL);
+ return;
+ }
/* write directly to console */
WriteConsoleW(console, wbuf, wlen, &dummy, NULL);