- int retval;
- int i;
- ssize_t rlen;
- const char *result;
- int reslen;
- tcl_connection_t *tclc;
- char in[256];
-
- rlen = read_socket(connection->fd, &in, sizeof(in));
- if (rlen <= 0) {
- if (rlen < 0)
- LOG_ERROR("error during read: %s", strerror(errno));
- return ERROR_SERVER_REMOTE_CLOSED;
- }
-
- tclc = connection->priv;
- if (tclc == NULL)
- return ERROR_CONNECTION_REJECTED;
-
- /* push as much data into the line as possible */
- for (i = 0; i < rlen; i++)
- {
- if (!isprint(in[i]) && !isspace(in[i]))
- {
- /* drop this line */
- tclc->tc_linedrop = 1;
- continue;
- }
-
- /* buffer the data */
- tclc->tc_line[tclc->tc_lineoffset] = in[i];
- if (tclc->tc_lineoffset < TCL_MAX_LINE)
- tclc->tc_lineoffset++;
- else
- tclc->tc_linedrop = 1;
-
- if (in[i] != '\n')
- continue;
-
- /* process the line */
- if (tclc->tc_linedrop) {
+ Jim_Interp *interp = (Jim_Interp *)connection->cmd_ctx->interp;
+ int retval;
+ int i;
+ ssize_t rlen;
+ const char *result;
+ int reslen;
+ struct tcl_connection *tclc;
+ unsigned char in[256];
+ char *tc_line_new;
+ int tc_line_size_new;
+
+ rlen = connection_read(connection, &in, sizeof(in));
+ if (rlen <= 0) {
+ if (rlen < 0)
+ LOG_ERROR("error during read: %s", strerror(errno));
+ return ERROR_SERVER_REMOTE_CLOSED;
+ }
+
+ tclc = connection->priv;
+ if (tclc == NULL)
+ return ERROR_CONNECTION_REJECTED;
+
+ /* push as much data into the line as possible */
+ for (i = 0; i < rlen; i++) {
+ /* buffer the data */
+ tclc->tc_line[tclc->tc_lineoffset] = in[i];
+ if (tclc->tc_lineoffset < tclc->tc_line_size) {
+ tclc->tc_lineoffset++;
+ } else if (tclc->tc_line_size >= TCL_LINE_MAX) {
+ /* maximum line size reached, drop line */
+ tclc->tc_linedrop = 1;
+ } else {
+ /* grow line buffer: exponential below 1 MB, linear above */
+ if (tclc->tc_line_size <= 1*1024*1024)
+ tc_line_size_new = tclc->tc_line_size * 2;
+ else
+ tc_line_size_new = tclc->tc_line_size + 1*1024*1024;
+
+ if (tc_line_size_new > TCL_LINE_MAX)
+ tc_line_size_new = TCL_LINE_MAX;
+
+ tc_line_new = realloc(tclc->tc_line, tc_line_size_new);
+ if (tc_line_new == NULL) {
+ tclc->tc_linedrop = 1;
+ } else {
+ tclc->tc_line = tc_line_new;
+ tclc->tc_line_size = tc_line_size_new;
+ tclc->tc_lineoffset++;
+ }
+
+ }
+
+ /* ctrl-z is end of command. When testing from telnet, just
+ * press ctrl-z a couple of times first to put telnet into the
+ * mode where it will send 0x1a in response to pressing ctrl-z
+ */
+ if (in[i] != '\x1a')
+ continue;
+
+ /* process the line */
+ if (tclc->tc_linedrop) {