--- a/src/unac/unac.c
+++ b/src/unac/unac.c
@@ -36,6 +36,7 @@
#include <stdio.h>
#include <stdarg.h>
#endif /* HAVE_VSNPRINTF */
+#include <pthread.h>
#include "unac.h"
#include "unac_version.h"
@@ -10555,8 +10556,6 @@
outp, out_lengthp, 1);
}
-#define MAXOUT 1024
-
static int convert(const char* from, const char* to,
const char* in, size_t in_length,
char** outp, size_t* out_lengthp);
@@ -10564,6 +10563,14 @@
static const char *utf16be = "UTF-16BE";
static iconv_t u8tou16_cd = (iconv_t)-1;
static iconv_t u16tou8_cd = (iconv_t)-1;
+static pthread_mutex_t o_unac_mutex;
+static int unac_mutex_is_init;
+// Call this or take your chances with the auto init.
+void unac_init_mt()
+{
+ pthread_mutex_init(&o_unac_mutex, 0);
+ unac_mutex_is_init = 1;
+}
/*
* Convert buffer <in> containing string encoded in charset <from> into
@@ -10576,6 +10583,7 @@
const char* in, size_t in_length,
char** outp, size_t* out_lengthp)
{
+ int ret = -1;
iconv_t cd;
char* out;
size_t out_remain;
@@ -10583,6 +10591,15 @@
char* out_base;
int from_utf16, from_utf8, to_utf16, to_utf8, u8tou16, u16tou8;
const char space[] = { 0x00, 0x20 };
+
+ /* Note: better call explicit unac_init_mt() before starting threads than
+ rely on this.
+ */
+ if (unac_mutex_is_init == 0) {
+ pthread_mutex_init(&o_unac_mutex, 0);
+ unac_mutex_is_init = 1;
+ }
+ pthread_mutex_lock(&o_unac_mutex);
if (!strcmp(utf16be, from)) {
from_utf8 = 0;
@@ -10614,7 +10631,7 @@
/* *outp still valid, no freeing */
if(debug_level >= UNAC_DEBUG_LOW)
DEBUG("realloc %d bytes failed\n", out_size+1);
- return -1;
+ goto out;
}
} else {
/* +1 for null */
@@ -10622,7 +10639,7 @@
if(out == 0) {
if(debug_level >= UNAC_DEBUG_LOW)
DEBUG("malloc %d bytes failed\n", out_size+1);
- return -1;
+ goto out;
}
}
out_remain = out_size;
@@ -10631,7 +10648,7 @@
if (u8tou16) {
if (u8tou16_cd == (iconv_t)-1) {
if((u8tou16_cd = iconv_open(to, from)) == (iconv_t)-1) {
- return -1;
+ goto out;
}
} else {
iconv(u8tou16_cd, 0, 0, 0, 0);
@@ -10640,7 +10657,7 @@
} else if (u16tou8) {
if (u16tou8_cd == (iconv_t)-1) {
if((u16tou8_cd = iconv_open(to, from)) == (iconv_t)-1) {
- return -1;
+ goto out;
}
} else {
iconv(u16tou8_cd, 0, 0, 0, 0);
@@ -10648,7 +10665,7 @@
cd = u16tou8_cd;
} else {
if((cd = iconv_open(to, from)) == (iconv_t)-1) {
- return -1;
+ goto out;
}
}
@@ -10682,7 +10699,7 @@
if(errno == E2BIG)
/* fall thru to the E2BIG case below */;
else
- return -1;
+ goto out;
} else {
/* The offending character was replaced by a SPACE, skip it. */
in += 2;
@@ -10691,7 +10708,7 @@
break;
}
} else {
- return -1;
+ goto out;
}
case E2BIG:
{
@@ -10711,7 +10728,7 @@
DEBUG("realloc %d bytes failed\n", out_size+1);
free(saved);
*outp = 0;
- return -1;
+ goto out;
}
}
out = out_base + length;
@@ -10719,7 +10736,7 @@
}
break;
default:
- return -1;
+ goto out;
break;
}
}
@@ -10732,7 +10749,10 @@
*out_lengthp = out - out_base;
(*outp)[*out_lengthp] = '\0';
- return 0;
+ ret = 0;
+out:
+ pthread_mutex_unlock(&o_unac_mutex);
+ return ret;
}
int unacmaybefold_string(const char* charset,