diff options
Diffstat (limited to 'main')
-rw-r--r-- | main/asterisk.c | 50 |
1 files changed, 39 insertions, 11 deletions
diff --git a/main/asterisk.c b/main/asterisk.c index 937259cda..539a37ee5 100644 --- a/main/asterisk.c +++ b/main/asterisk.c @@ -1264,14 +1264,17 @@ static void *netconsole(void *vconsole) { struct console *con = vconsole; char hostname[MAXHOSTNAMELEN] = ""; - char tmp[512]; + char inbuf[512]; + char outbuf[512]; + const char *end_buf = inbuf + sizeof(inbuf); + char *start_read = inbuf; int res; struct pollfd fds[2]; if (gethostname(hostname, sizeof(hostname)-1)) ast_copy_string(hostname, "<Unknown>", sizeof(hostname)); - snprintf(tmp, sizeof(tmp), "%s/%ld/%s\n", hostname, (long)ast_mainpid, ast_get_version()); - fdprint(con->fd, tmp); + snprintf(outbuf, sizeof(outbuf), "%s/%ld/%s\n", hostname, (long)ast_mainpid, ast_get_version()); + fdprint(con->fd, outbuf); for (;;) { fds[0].fd = con->fd; fds[0].events = POLLIN; @@ -1287,24 +1290,49 @@ static void *netconsole(void *vconsole) continue; } if (fds[0].revents) { - res = read_credentials(con->fd, tmp, sizeof(tmp) - 1, con); - if (res < 1) { + int cmds_read, bytes_read; + if ((bytes_read = read_credentials(con->fd, start_read, end_buf - start_read, con)) < 1) { break; } - tmp[res] = 0; - if (strncmp(tmp, "cli quit after ", 15) == 0) { - ast_cli_command_multiple_full(con->uid, con->gid, con->fd, res - 15, tmp + 15); + /* XXX This will only work if it is the first command, and I'm not sure fixing it is worth the effort. */ + if (strncmp(inbuf, "cli quit after ", 15) == 0) { + ast_cli_command_multiple_full(con->uid, con->gid, con->fd, bytes_read - 15, inbuf + 15); break; } - ast_cli_command_multiple_full(con->uid, con->gid, con->fd, res, tmp); + /* ast_cli_command_multiple_full will only process individual commands terminated by a + * NULL and not trailing partial commands. */ + if (!(cmds_read = ast_cli_command_multiple_full(con->uid, con->gid, con->fd, bytes_read + start_read - inbuf, inbuf))) { + /* No commands were read. We either have a short read on the first command + * with space left, or a command that is too long */ + if (start_read + bytes_read < end_buf) { + start_read += bytes_read; + } else { + ast_log(LOG_ERROR, "Command too long! Skipping\n"); + start_read = inbuf; + } + continue; + } + if (start_read[bytes_read - 1] == '\0') { + /* The read ended on a command boundary, start reading again at the head of inbuf */ + start_read = inbuf; + continue; + } + /* If we get this far, we have left over characters that have not been processed. + * Advance to the character after the last command read by ast_cli_command_multiple_full. + * We are guaranteed to have at least cmds_read NULLs */ + while (cmds_read-- && (start_read = rawmemchr(start_read, '\0'))) { + start_read++; + } + memmove(inbuf, start_read, end_buf - start_read); + start_read = end_buf - start_read + inbuf; } if (fds[1].revents) { - res = read_credentials(con->p[0], tmp, sizeof(tmp), con); + res = read_credentials(con->p[0], outbuf, sizeof(outbuf), con); if (res < 1) { ast_log(LOG_ERROR, "read returned %d\n", res); break; } - res = write(con->fd, tmp, res); + res = write(con->fd, outbuf, res); if (res < 1) break; } |