summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main/asterisk.c50
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;
}