summaryrefslogtreecommitdiff
path: root/source3/lib
diff options
context:
space:
mode:
Diffstat (limited to 'source3/lib')
-rw-r--r--source3/lib/charcnv.c95
-rw-r--r--source3/lib/dprintf.c104
-rw-r--r--source3/lib/iconv.c4
3 files changed, 167 insertions, 36 deletions
diff --git a/source3/lib/charcnv.c b/source3/lib/charcnv.c
index 9bbb8a8507..ebcceef816 100644
--- a/source3/lib/charcnv.c
+++ b/source3/lib/charcnv.c
@@ -26,32 +26,56 @@ extern int DEBUGLEVEL;
static pstring cvtbuf;
-static smb_iconv_t
- ucs2_to_unix=(smb_iconv_t)-1, /*ucs2 (MS) <-> unix format */
- unix_to_ucs2=(smb_iconv_t)-1,
- dos_to_unix=(smb_iconv_t)-1, /*unix format <-> dos codepage*/
- unix_to_dos=(smb_iconv_t)-1; /*for those clients who does not support unicode*/
+static smb_iconv_t conv_handles[NUM_CHARSETS][NUM_CHARSETS];
+
+/****************************************************************************
+return the name of a charset to give to iconv()
+****************************************************************************/
+static char *charset_name(charset_t ch)
+{
+ char *ret = NULL;
+
+ if (ch == CH_UCS2) ret = "UCS-2LE";
+ else if (ch == CH_UNIX) ret = lp_unix_charset();
+ else if (ch == CH_DOS) ret = lp_dos_charset();
+ else if (ch == CH_DISPLAY) ret = lp_display_charset();
+
+ if (!ret || !*ret) ret = "ASCII";
+ return ret;
+}
/****************************************************************************
Initialize iconv conversion descriptors
****************************************************************************/
-void init_iconv(char *unix_charset, char *dos_charset)
+void init_iconv(void)
{
-#define ICONV(descr, from_name, to_name)\
- if(descr!=(smb_iconv_t)-1) smb_iconv_close(descr);\
- descr = smb_iconv_open(to_name, from_name);\
- if(descr==(smb_iconv_t)-1)\
- DEBUG(0,("Conversion from %s to %s is not supported\n",from_name,to_name));
-
- if (!unix_charset || !*unix_charset) unix_charset = "ASCII";
- if (!dos_charset || !*dos_charset) dos_charset = "ASCII";
+ int c1, c2;
+
+ /* so that charset_name() works we need to get the UNIX<->UCS2 going
+ first */
+ if (!conv_handles[CH_UNIX][CH_UCS2]) {
+ conv_handles[CH_UNIX][CH_UCS2] = smb_iconv_open("UCS-2LE", "ASCII");
+ }
+ if (!conv_handles[CH_UCS2][CH_UNIX]) {
+ conv_handles[CH_UCS2][CH_UNIX] = smb_iconv_open("ASCII", "UCS-2LE");
+ }
- ICONV(ucs2_to_unix, "UCS-2LE", unix_charset)
- ICONV(unix_to_ucs2, unix_charset, "UCS-2LE")
- ICONV(dos_to_unix, dos_charset, unix_charset)
- ICONV(unix_to_dos, unix_charset, dos_charset)
-#undef ICONV
+ for (c1=0;c1<NUM_CHARSETS;c1++) {
+ for (c2=0;c2<NUM_CHARSETS;c2++) {
+ char *n1 = charset_name(c1);
+ char *n2 = charset_name(c2);
+ if (conv_handles[c1][c2]) {
+ smb_iconv_close(conv_handles[c1][c2]);
+ }
+ conv_handles[c1][c2] = smb_iconv_open(n2,n1);
+ if (conv_handles[c1][c2] == (smb_iconv_t)-1) {
+ DEBUG(0,("Conversion from %s to %s not supported\n",
+ charset_name(c1), charset_name(c2)));
+ conv_handles[c1][c2] = NULL;
+ }
+ }
+ }
}
/****************************************************************************
@@ -64,22 +88,25 @@ void init_iconv(char *unix_charset, char *dos_charset)
destlen - maximal length allowed for string
return the number of bytes occupied in the destination
****************************************************************************/
-static size_t convert_string(smb_iconv_t *descriptor,
- void const *src, size_t srclen,
- void *dest, size_t destlen)
+size_t convert_string(charset_t from, charset_t to,
+ void const *src, size_t srclen,
+ void *dest, size_t destlen)
{
size_t i_len, o_len;
size_t retval;
char* inbuf = (char*)src;
char* outbuf = (char*)dest;
static int initialised;
-
+ smb_iconv_t descriptor;
+
if (!initialised) {
initialised = 1;
- init_iconv(NULL, NULL);
+ init_iconv();
}
- if (*descriptor == (smb_iconv_t)-1) {
+ descriptor = conv_handles[from][to];
+
+ if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
/* conversion not supported, use as is */
int len = MIN(srclen,destlen);
memcpy(dest,src,len);
@@ -88,7 +115,7 @@ static size_t convert_string(smb_iconv_t *descriptor,
i_len=srclen;
o_len=destlen;
- retval=smb_iconv(*descriptor,&inbuf, &i_len, &outbuf, &o_len);
+ retval=smb_iconv(descriptor,&inbuf, &i_len, &outbuf, &o_len);
if(retval==-1)
{ char *reason="unknown error";
switch(errno)
@@ -109,20 +136,20 @@ int unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen)
{
int size,len;
smb_ucs2_t *buffer=(smb_ucs2_t*)cvtbuf;
- size=convert_string(&unix_to_ucs2, src, srclen, buffer, sizeof(cvtbuf));
+ size=convert_string(CH_UNIX, CH_UCS2, src, srclen, buffer, sizeof(cvtbuf));
len=size/2;
strupper_w(buffer);
- return convert_string(&ucs2_to_unix, buffer, size, dest, destlen);
+ return convert_string(CH_UCS2, CH_UNIX, buffer, size, dest, destlen);
}
int unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
{
int size,len;
smb_ucs2_t *buffer=(smb_ucs2_t*)cvtbuf;
- size=convert_string(&unix_to_ucs2, src, srclen, buffer, sizeof(cvtbuf));
+ size=convert_string(CH_UNIX, CH_UCS2, src, srclen, buffer, sizeof(cvtbuf));
len=size/2;
strlower_w(buffer);
- return convert_string(&ucs2_to_unix, buffer, size, dest, destlen);
+ return convert_string(CH_UCS2, CH_UNIX, buffer, size, dest, destlen);
}
@@ -162,7 +189,7 @@ int push_ascii(void *dest, const char *src, int dest_len, int flags)
src_len++;
}
- return convert_string(&unix_to_dos, src, src_len, dest, dest_len);
+ return convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len);
}
int push_ascii_fstring(void *dest, const char *src)
@@ -200,7 +227,7 @@ int pull_ascii(char *dest, const void *src, int dest_len, int src_len, int flags
if (flags & STR_TERMINATE) src_len = strlen(src)+1;
- ret = convert_string(&dos_to_unix, src, src_len, dest, dest_len);
+ ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len);
if (dest_len) dest[MIN(ret, dest_len-1)] = 0;
@@ -258,7 +285,7 @@ int push_ucs2(const void *base_ptr, void *dest, const char *src, int dest_len, i
/* ucs2 is always a multiple of 2 bytes */
dest_len &= ~1;
- len += convert_string(&unix_to_ucs2, src, src_len, dest, dest_len);
+ len += convert_string(CH_UNIX, CH_UCS2, src, src_len, dest, dest_len);
return len;
}
@@ -291,7 +318,7 @@ int pull_ucs2(const void *base_ptr, char *dest, const void *src, int dest_len, i
/* ucs2 is always a multiple of 2 bytes */
src_len &= ~1;
- ret = convert_string(&ucs2_to_unix, src, src_len, dest, dest_len);
+ ret = convert_string(CH_UCS2, CH_UNIX, src, src_len, dest, dest_len);
if (dest_len) dest[MIN(ret, dest_len-1)] = 0;
return src_len;
diff --git a/source3/lib/dprintf.c b/source3/lib/dprintf.c
new file mode 100644
index 0000000000..59e1859c43
--- /dev/null
+++ b/source3/lib/dprintf.c
@@ -0,0 +1,104 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 3.0
+ display print functions
+ Copyright (C) Andrew Tridgell 2001
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+
+/*
+ this module provides functions for printing internal strings in the "display charset"
+ This charset may be quite different from the chosen unix charset
+
+ Eventually these functions will need to take care of column count constaints
+
+ The d_ prefix on print functions in Samba refers to the display character set
+ conversion
+*/
+
+#include "includes.h"
+
+int d_vfprintf(FILE *f, const char *format, va_list ap)
+{
+ char *p, *p2;
+ int ret, maxlen, clen;
+
+ ret = vasprintf(&p, format, ap);
+
+ if (ret <= 0) return ret;
+
+ /* now we have the string in unix format, convert it to the display
+ charset, but beware of it growing */
+ maxlen = ret*2;
+again:
+ p2 = malloc(maxlen);
+ if (!p2) {
+ free(p);
+ return -1;
+ }
+ clen = convert_string(CH_UNIX, CH_DISPLAY, p, ret, p2, maxlen);
+
+ if (clen >= maxlen) {
+ /* it didn't fit - try a larger buffer */
+ maxlen *= 2;
+ free(p2);
+ goto again;
+ }
+
+ /* good, its converted OK */
+ free(p);
+ ret = fwrite(p2, 1, clen, f);
+ free(p2);
+
+ return ret;
+}
+
+
+int d_fprintf(FILE *f, const char *format, ...)
+{
+ int ret;
+ va_list ap;
+
+ va_start(ap, format);
+ ret = d_vfprintf(f, format, ap);
+ va_end(ap);
+
+ return ret;
+}
+
+static FILE *outfile;
+
+int d_printf(const char *format, ...)
+{
+ int ret;
+ va_list ap;
+
+ if (!outfile) outfile = stdout;
+
+ va_start(ap, format);
+ ret = d_vfprintf(outfile, format, ap);
+ va_end(ap);
+
+ return ret;
+}
+
+/* interactive programs need a way of tell d_*() to write to stderr instead
+ of stdout */
+void display_set_stderr(void)
+{
+ outfile = stderr;
+}
diff --git a/source3/lib/iconv.c b/source3/lib/iconv.c
index 2285d8debf..46507dd624 100644
--- a/source3/lib/iconv.c
+++ b/source3/lib/iconv.c
@@ -142,12 +142,12 @@ smb_iconv_t smb_iconv_open(const char *tocode, const char *fromcode)
if (!charsets[from].name) {
ret->pull = sys_iconv;
ret->cd_pull = iconv_open("UCS-2LE", fromcode);
- if (!ret->cd_pull) goto failed;
+ if (ret->cd_pull == (iconv_t)-1) goto failed;
}
if (!charsets[to].name) {
ret->push = sys_iconv;
ret->cd_push = iconv_open(tocode, "UCS-2LE");
- if (!ret->cd_push) goto failed;
+ if (ret->cd_push == (iconv_t)-1) goto failed;
}
#else
if (!charsets[from].name || !charsets[to].name) {