@@ -9,7 +9,9 @@
#include <stdarg.h>
#include <stdlib.h>
#include <memory.h>
+#if !defined(__APPLE__) && !defined(__FreeBSD__)
#include <malloc.h>
+#endif
#include <string.h>
#include <ctype.h>
#include <unistd.h>
@@ -33,50 +35,52 @@
* read/write functions required for each ..
*/
int read(int fd, void *buf, unsigned int count) {
- return recv(fd,buf,count,0);
-
+ return recv(fd, buf, count, 0);
}
+
int write(int fd,const void *buf, unsigned int count) {
- return send(fd,buf,count,0);
+ return send(fd, buf, count, 0);
}
+
int vasprintf(char **strp, const char *fmt, va_list args) {
- int size;
+ int size;
- size = vsnprintf(NULL,0,fmt,args);
- if ((*strp=malloc(size+1))==NULL) {
- return -1;
- }
+ size = vsnprintf(NULL, 0, fmt, args);
+ if ((*strp = malloc(size + 1)) == NULL) {
+ return -1;
+ }
- size = vsnprintf(*strp,size+1,fmt,args);
- return size;
+ size = vsnprintf(*strp, size + 1, fmt, args);
+ return size;
}
+
int asprintf(char **strp, const char *fmt, ...) {
- va_list args;
- int size;
+ va_list args;
+ int size;
- va_start(args,fmt);
- size = vasprintf(strp,fmt,args);
+ va_start(args, fmt);
+ size = vasprintf(strp, fmt, args);
- va_end(args);
- return size;
+ va_end(args);
+ return size;
}
int fprintf(FILE *stream, const char *fmt, ...) {
- va_list args;
- int size;
- char *buf;
-
- va_start(args,fmt);
- size = vasprintf(&buf,fmt,args);
- if (size <0) {
- goto out;
- }
- size = write(stream->_file,buf,size);
- free(buf);
+ va_list args;
+ int size;
+ char *buf;
+
+ va_start(args, fmt);
+ size = vasprintf(&buf, fmt, args);
+ if (size < 0) {
+ goto out;
+ }
+ size = write(stream->_file, buf, size);
+ free(buf);
out:
- va_end(args);
- return size;
+ va_end(args);
+ return size;
}
/*
@@ -514,6 +518,12 @@
return CLI_OK;
}
+int cli_int_idle_timeout(struct cli_def *cli)
+{
+ cli_print(cli, "Idle timeout");
+ return CLI_QUIT;
+}
+
int cli_int_configure_terminal(struct cli_def *cli, UNUSED(char *command), UNUSED(char *argv[]), UNUSED(int argc))
{
cli_set_configmode(cli, MODE_CONFIG, NULL);
@@ -553,6 +563,9 @@
// Default to 1 second timeout intervals
cli->timeout_tm.tv_sec = 1;
cli->timeout_tm.tv_usec = 0;
+
+ // Set default idle timeout callback, but no timeout
+ cli_set_idle_timeout_callback(cli, 0, cli_int_idle_timeout);
return cli;
}
@@ -750,7 +763,7 @@
int l = strlen(words[start_word])-1;
if (commands->parent && commands->parent->callback)
- cli_error(cli, "%-20s %s", cli_command_name(cli, commands->parent), commands->parent->help ? : "");
+ cli_error(cli, "%-20s %s", cli_command_name(cli, commands->parent), commands->parent->help ? : "");
for (c = commands; c; c = c->next)
{
@@ -942,8 +955,8 @@
{
int r;
unsigned int num_words, i, f;
- char *words[128] = {0};
- int filters[128] = {0};
+ char *words[CLI_MAX_LINE_WORDS] = {0};
+ int filters[CLI_MAX_LINE_WORDS] = {0};
if (!command) return CLI_ERROR;
while (isspace(*command))
@@ -951,8 +964,8 @@
if (!*command) return CLI_OK;
- num_words = cli_parse_line(command, words, sizeof(words) / sizeof(words[0]));
- for (i = f = 0; i < num_words && f < sizeof(filters) / sizeof(filters[0]) - 1; i++)
+ num_words = cli_parse_line(command, words, CLI_MAX_LINE_WORDS);
+ for (i = f = 0; i < num_words && f < CLI_MAX_LINE_WORDS - 1; i++)
{
if (words[i][0] == '|')
filters[f++] = i;
@@ -979,7 +992,7 @@
struct cli_command *c;
struct cli_command *n;
int num_words, i, k=0;
- char *words[128] = {0};
+ char *words[CLI_MAX_LINE_WORDS] = {0};
int filter = 0;
if (!command) return 0;
@@ -1132,7 +1145,7 @@
cli_free_history(cli);
write(sockfd, negotiate, strlen(negotiate));
- if ((cmd = malloc(4096)) == NULL)
+ if ((cmd = malloc(CLI_MAX_LINE_LENGTH)) == NULL)
return CLI_ERROR;
#ifdef WIN32
@@ -1181,7 +1194,7 @@
}
else
{
- memset(cmd, 0, 4096);
+ memset(cmd, 0, CLI_MAX_LINE_LENGTH);
l = 0;
cursor = 0;
}
@@ -1247,7 +1260,7 @@
/* timeout every second */
if (cli->regular_callback && cli->regular_callback(cli) != CLI_OK)
{
- strncpy(cmd, "quit", 4096);
+ l = -1;
break;
}
@@ -1255,8 +1268,18 @@
{
if (time(NULL) - cli->last_action >= cli->idle_timeout)
{
- cli_print(cli, "Idle timeout");
- strncpy(cmd, "quit", 4095);
+ if (cli->idle_timeout_callback)
+ {
+ // Call the callback and continue on if successful
+ if (cli->idle_timeout_callback(cli) == CLI_OK)
+ {
+ // Reset the idle timeout counter
+ time(&cli->last_action);
+ continue;
+ }
+ }
+ // Otherwise, break out of the main loop
+ l = -1;
break;
}
}
@@ -1499,9 +1522,7 @@
if (l)
continue;
- strcpy(cmd, "quit");
- l = cursor = strlen(cmd);
- write(sockfd, "quit\r\n", l + 2);
+ l = -1;
break;
}
@@ -1521,7 +1542,7 @@
/* TAB completion */
if (c == CTRL('I'))
{
- char *completions[128];
+ char *completions[CLI_MAX_LINE_WORDS];
int num_completions = 0;
if (cli->state == STATE_LOGIN || cli->state == STATE_PASSWORD || cli->state == STATE_ENABLE_PASSWORD)
@@ -1529,7 +1550,7 @@
if (cursor != l) continue;
- num_completions = cli_get_completions(cli, cmd, completions, 128);
+ num_completions = cli_get_completions(cli, cmd, completions, CLI_MAX_LINE_WORDS);
if (num_completions == 0)
{
write(sockfd, "\a", 1);
@@ -1627,8 +1648,8 @@
{
// Show history item
cli_clear_line(sockfd, cmd, l, cursor);
- memset(cmd, 0, 4096);
- strncpy(cmd, cli->history[in_history], 4095);
+ memset(cmd, 0, CLI_MAX_LINE_LENGTH);
+ strncpy(cmd, cli->history[in_history], CLI_MAX_LINE_LENGTH - 1);
l = cursor = strlen(cmd);
write(sockfd, cmd, l);
}
@@ -1699,7 +1720,7 @@
{
/* append to end of line */
cmd[cursor] = c;
- if (l < 4095)
+ if (l < CLI_MAX_LINE_LENGTH - 1)
{
l++;
cursor++;
@@ -1717,7 +1738,7 @@
{
int i;
// Move everything one character to the right
- if (l >= 4094) l--;
+ if (l >= CLI_MAX_LINE_LENGTH - 2) l--;
for (i = l; i >= cursor; i--)
cmd[i + 1] = cmd[i];
// Write what we've just added
@@ -1753,7 +1774,6 @@
}
if (l < 0) break;
- if (!strcasecmp(cmd, "quit")) break;
if (cli->state == STATE_LOGIN)
{
@@ -1866,7 +1886,7 @@
{
int oldpriv = cli_set_privilege(cli, privilege);
int oldmode = cli_set_configmode(cli, mode, NULL);
- char buf[4096];
+ char buf[CLI_MAX_LINE_LENGTH];
while (1)
{
@@ -1874,7 +1894,7 @@
char *cmd;
char *end;
- if (fgets(buf, sizeof(buf), fh) == NULL)
+ if (fgets(buf, CLI_MAX_LINE_LENGTH - 1, fh) == NULL)
break; /* end of file */
if ((p = strpbrk(buf, "#\r\n")))
@@ -1907,30 +1927,33 @@
static void _print(struct cli_def *cli, int print_mode, char *format, va_list ap)
{
- static char *buffer;
- static int size, len;
- char *p;
+ va_list aq;
int n;
+ char *p;
if (!cli) return; // sanity check
- buffer = cli->buffer;
- size = cli->buf_size;
- len = strlen(buffer);
-
- while ((n = vsnprintf(buffer+len, size-len, format, ap)) >= size-len)
+ while (1)
{
- if (!(buffer = realloc(buffer, size += 1024)))
- return;
-
- cli->buffer = buffer;
- cli->buf_size = size;
+ va_copy(aq, ap);
+ n = vsnprintf(cli->buffer, cli->buf_size, format, ap);
+ if (n >= cli->buf_size)
+ {
+ cli->buf_size = n + 1;
+ cli->buffer = realloc(cli->buffer, cli->buf_size);
+ if (!cli->buffer)
+ return;
+ va_end(ap);
+ va_copy(ap, aq);
+ continue;
+ }
+ break;
}
- if (n < 0) // vaprintf failed
+ if (n < 0) // vsnprintf failed
return;
- p = buffer;
+ p = cli->buffer;
do
{
char *next = strchr(p, '\n');
@@ -1960,10 +1983,10 @@
if (p && *p)
{
- if (p != buffer)
- memmove(buffer, p, strlen(p));
+ if (p != cli->buffer)
+ memmove(cli->buffer, p, strlen(p));
}
- else *buffer = 0;
+ else *cli->buffer = 0;
}
void cli_bufprint(struct cli_def *cli, char *format, ...)
@@ -2260,3 +2283,9 @@
cli->idle_timeout = seconds;
time(&cli->last_action);
}
+
+void cli_set_idle_timeout_callback(struct cli_def *cli, unsigned int seconds, int (*callback)(struct cli_def *))
+{
+ cli_set_idle_timeout(cli, seconds);
+ cli->idle_timeout_callback = callback;
+}
|