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
