Changeset: 278c09670f76 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=278c09670f76
Modified Files:
        clients/mapiclient/mclient.1
        clients/mapiclient/mclient.c
Branch: default
Log Message:

Merge with Aug2011 branch.


diffs (198 lines):

diff --git a/clients/ChangeLog.Aug2011 b/clients/ChangeLog.Aug2011
--- a/clients/ChangeLog.Aug2011
+++ b/clients/ChangeLog.Aug2011
@@ -1,6 +1,10 @@
 # ChangeLog file for clients
 # This file is updated with Maddlog
 
+* Wed Oct 12 2011 Sjoerd Mullender <[email protected]>
+- mclient now checks the result of encoding conversions using the iconv
+  library.
+
 * Mon Oct 10 2011 Sjoerd Mullender <[email protected]>
 - Fixed a source of crashes in mclient when a query on the command line
   using the -s option is combined with input on standard input (e.g. in
diff --git a/clients/mapiclient/mclient.1 b/clients/mapiclient/mclient.1
--- a/clients/mapiclient/mclient.1
+++ b/clients/mapiclient/mclient.1
@@ -91,6 +91,22 @@ to the empty string in the environment.
 .SS
 General Options
 .TP
+\fB\-\-help\fP (\fB\-?\fP)
+Print usage information and exit.
+.TP
+\fB\-\-encoding=\fP\fIencoding\fP (\fB\-E\fP \fIencoding\fP)
+Specify the character encoding of the input.  The option applies to
+both the standard input of
+.I mclient
+and to the argument of the
+.B \-\-statement
+.RB ( \-s )
+option but not to the contents of files specified on the command line
+or files specified using the
+.B \e<
+command (those must be encoded using UTF-8).  The default encoding is
+taken from the locale.
+.TP
 \fB\-\-language=\fP\fIlanguage\fP (\fB\-l\fP \fIlanguage\fP)
 Specify the query language.  The following languages are recognized:
 .B mal
@@ -103,11 +119,6 @@ option is omitted, the default of
 .B sql
 is assumed.
 .TP
-\fB\-\-help\fP (\fB\-?\fP)
-Print usage information and exit.  If preceded by the
-.B \-\-language
-option, give language-specific help and continue.
-.TP
 \fB\-\-database=\fP\fIdatabase\fP (\fB\-d\fP \fIdatabase\fP)
 Specify the name of the database to connect to.  The \fB-d\fP can be
 omitted if an equally named file does not exist in the current
diff --git a/clients/mapiclient/mclient.c b/clients/mapiclient/mclient.c
--- a/clients/mapiclient/mclient.c
+++ b/clients/mapiclient/mclient.c
@@ -1736,6 +1736,7 @@ doFileByLines(Mapi mid, FILE *fp, const 
        char *line = NULL;
        char *oldbuf = NULL, *buf = NULL;
        size_t length;
+       size_t bufsiz = 0;
        MapiHdl hdl = mapi_get_active(mid);
        MapiMsg rc = MOK;
        int lineno = 1;
@@ -1744,7 +1745,10 @@ doFileByLines(Mapi mid, FILE *fp, const 
 #ifdef HAVE_LIBREADLINE
        if (prompt == NULL)
 #endif
-               oldbuf = buf = malloc(READBLOCK);
+       {
+               bufsiz = READBLOCK;
+               oldbuf = buf = malloc(bufsiz);
+       }
 
        do {
                if (prompt) {
@@ -1791,8 +1795,7 @@ doFileByLines(Mapi mid, FILE *fp, const 
                                free(buf);
                        buf = oldbuf;
                        line = buf;
-                       while (line < buf + READBLOCK - 1 &&
-                              (c = getc(fp)) != EOF) {
+                       while ((c = getc(fp)) != EOF) {
                                if (c == 0) {
                                        fprintf(stderr, "NULL byte in input on 
line %d of input\n", lineno);
                                        /* read away rest of line */
@@ -1807,6 +1810,11 @@ doFileByLines(Mapi mid, FILE *fp, const 
                                        }
                                        break;
                                }
+                               if (line == buf + bufsiz - 1) {
+                                       bufsiz += READBLOCK;
+                                       buf = realloc(buf, bufsiz);
+                                       line = buf + bufsiz - 1 - READBLOCK;
+                               }
                                *line++ = c;
                                if (c == '\n')
                                        break;
@@ -1824,23 +1832,52 @@ doFileByLines(Mapi mid, FILE *fp, const 
                if (line != NULL && encoding != NULL && cd_in != (iconv_t) -1) {
                        ICONV_CONST char *from = line;
                        size_t fromlen = strlen(from);
-                       size_t tolen = 4 * fromlen + 1;
+                       int factor = 4;
+                       size_t tolen = factor * fromlen + 1;
                        char *to = malloc(tolen);
 
+                 try_again:
                        line = to;
-                       iconv(cd_in, &from, &fromlen, &to, &tolen);
+                       if (iconv(cd_in, &from, &fromlen, &to, &tolen) == 
(size_t) -1) {
+                               /* error */
+                               switch (errno) {
+                               case EILSEQ:
+                                       /* invalid multibyte sequence */
+                                       fprintf(stderr, "Illegal input sequence 
on line %d of input\n", lineno);
+                                       errseen = 1;
+                                       free(line);
+                                       continue;
+                               case E2BIG:
+                                       /* output buffer too small */
+                                       from = buf;
+                                       fromlen = strlen(from);
+                                       factor *= 2;
+                                       tolen = factor * fromlen + 1;
+                                       free(line);
+                                       to = malloc(tolen);
+                                       goto try_again;
+                               case EINVAL:
+                                       /* incomplete multibyte sequence */
+                                       /* shouldn't happen since we
+                                        * grow the input buffer */
+                                       break;
+                               default:
+                                       /* cannot happen according to docs */
+                                       break;
+                               }
+                       }
                        *to = 0;
-                       if (!oldbuf)
+                       if (oldbuf == NULL)
                                free(buf);
                        buf = line;
                } else
 #endif
-                       if (line != NULL &&
+               if (line != NULL &&
 #ifdef HAVE_ICONV
-                           encoding == NULL &&
+                   encoding == NULL &&
 #endif
-                           lineno == 1 &&
-                           strncmp(line, UTF8BOM, UTF8BOMLENGTH) == 0)
+                   lineno == 1 &&
+                   strncmp(line, UTF8BOM, UTF8BOMLENGTH) == 0)
                        line += UTF8BOMLENGTH;  /* skip Byte Order Mark (BOM) */
                lineno++;
                if (line == NULL) {
@@ -2878,13 +2915,38 @@ main(int argc, char **argv)
        if (command != NULL) {
 #ifdef HAVE_ICONV
                if (encoding != NULL && cd_in != (iconv_t) -1) {
+                       char *savecommand = command;
                        ICONV_CONST char *from = command;
                        size_t fromlen = strlen(from);
-                       size_t tolen = 4 * fromlen + 1;
+                       int factor = 4;
+                       size_t tolen = factor * fromlen + 1;
                        char *to = malloc(tolen);
 
+                 try_again:
                        command = to;
-                       iconv(cd_in, &from, &fromlen, &to, &tolen);
+                       if (iconv(cd_in, &from, &fromlen, &to, &tolen) == 
(size_t) -1) {
+                               switch (errno) {
+                               case EILSEQ:
+                                       /* invalid multibyte sequence */
+                                       fprintf(stderr, "Illegal input sequence 
in command line\n");
+                                       exit(-1);
+                               case E2BIG:
+                                       /* output buffer too small */
+                                       from = savecommand;
+                                       fromlen = strlen(from);
+                                       factor *= 2;
+                                       tolen = factor * fromlen + 1;
+                                       free(command);
+                                       to = malloc(tolen);
+                                       goto try_again;
+                               case EINVAL:
+                                       /* incomplete multibyte sequence */
+                                       fprintf(stderr, "Incomplete input 
sequence on command line\n");
+                                       exit(-1);
+                               default:
+                                       break;
+                               }
+                       }
                        *to = 0;
                }
 #endif
_______________________________________________
Checkin-list mailing list
[email protected]
http://mail.monetdb.org/mailman/listinfo/checkin-list

Reply via email to