|
|
|
@ -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;
|
|
|
|
|
}
|
|
|
|
|