Index: include/asterisk/cli.h =================================================================== --- include/asterisk/cli.h (revision 128342) +++ include/asterisk/cli.h (working copy) @@ -278,6 +278,12 @@ */ char *ast_complete_channels(const char *line, const char *word, int pos, int state, int rpos); +/* + * \brief The next CLI command will be the last one (close the connection when done). + * \param fd Console file descriptor. + */ +void ast_console_set_nextislast(int fd); + #if defined(__cplusplus) || defined(c_plusplus) } #endif Index: main/asterisk.c =================================================================== --- main/asterisk.c (revision 128342) +++ main/asterisk.c (working copy) @@ -181,6 +181,7 @@ int p[2]; /*!< Pipe */ pthread_t t; /*!< Thread of handler */ int mute; /*!< Is the console muted for logs */ + int nextislast; /*!< The next executed command will close the socket */ int levels[NUMLOGLEVELS]; /*!< Which log levels are enabled for the console */ }; @@ -971,6 +972,23 @@ } /*! + * \brief Sets the nextislast bit in a console. + * This is used to tell asterisk that the next CLI command is + * the last one, so it must close the socketi connection. + * \param fd Console file descriptor. + */ +void ast_console_set_nextislast(int fd) +{ + int x; + for (x=0;x < AST_MAX_CONNECTS; x++) { + if (fd == consoles[x].fd) { + consoles[x].nextislast = 1; + return; + } + } +} + +/*! * \brief write the string to all attached console clients */ static void ast_network_puts(const char *string) @@ -1005,7 +1023,7 @@ struct console *con = vconsole; char hostname[MAXHOSTNAMELEN] = ""; char tmp[512]; - int res; + int res, lastcommand=0; struct pollfd fds[2]; if (gethostname(hostname, sizeof(hostname)-1)) @@ -1020,6 +1038,9 @@ fds[1].events = POLLIN; fds[1].revents = 0; + if (con->nextislast) + lastcommand = 1; + res = poll(fds, 2, -1); if (res < 0) { if (errno != EINTR) @@ -1044,6 +1065,8 @@ if (res < 1) break; } + if (lastcommand) + break; } ast_verb(3, "Remote UNIX connection disconnected\n"); close(con->fd); @@ -1093,6 +1116,7 @@ fcntl(consoles[x].p[1], F_SETFL, flags | O_NONBLOCK); consoles[x].fd = s; consoles[x].mute = 1; /* Default is muted, we will un-mute if necessary */ + consoles[x].nextislast = 0; if (ast_pthread_create_detached_background(&consoles[x].t, NULL, netconsole, &consoles[x])) { ast_log(LOG_ERROR, "Unable to spawn thread to handle connection: %s\n", strerror(errno)); close(consoles[x].p[0]); @@ -2439,8 +2463,14 @@ int num = 0; read(ast_consock, buf, sizeof(buf)); - if (data) + if (data) { + /* Sending this command will say to asterisk that the next CLI command + is the last one, and must close the socket. */ + snprintf(tmp, sizeof(tmp), "_command nextislast"); + fdsend(ast_consock, tmp); + read(ast_consock, tmp, sizeof(tmp)); write(ast_consock, data, strlen(data) + 1); + } stringp = buf; hostname = strsep(&stringp, "/"); cpid = strsep(&stringp, "/"); @@ -2480,7 +2510,7 @@ fds.fd = ast_consock; fds.events = POLLIN; fds.revents = 0; - while (poll(&fds, 1, 500) > 0) { + while (poll(&fds, 1, -1) > 0) { char buf[512] = "", *curline = buf, *nextline; int not_written = 1; Index: main/cli.c =================================================================== --- main/cli.c (revision 128342) +++ main/cli.c (working copy) @@ -899,6 +899,26 @@ return CLI_SUCCESS; } +static char *handle_commandnextislast(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) +{ + switch (cmd) { + case CLI_INIT: + e->command = "_command nextislast"; + e->usage = + "Usage: _command nextislast\n" + " This function is used internally to help with 'asterisk -rx' and should" + " never be called by the user directly"; + return NULL; + case CLI_GENERATE: + return NULL; + } + ast_console_set_nextislast(a->fd); + + /* return something to be sure the command was executed */ + ast_cli(a->fd, "nextislast\n"); + return CLI_SUCCESS; +} + static char *handle_core_set_debug_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { struct ast_channel *c = NULL; @@ -1201,6 +1221,7 @@ AST_CLI_DEFINE(handle_commandcomplete, "Command complete"), AST_CLI_DEFINE(handle_commandnummatches, "Returns number of command matches"), AST_CLI_DEFINE(handle_commandmatchesarray, "Returns command matches array"), + AST_CLI_DEFINE(handle_commandnextislast, "The next command is the last to be executed by this session"), AST_CLI_DEFINE(handle_nodebugchan_deprecated, "Disable debugging on channel(s)"),