+static int telnet_output(struct command_context *cmd_ctx, const char *line)
+{
+ struct connection *connection = cmd_ctx->output_handler_priv;
+
+ return telnet_outputline(connection, line);
+}
+
+static void telnet_log_callback(void *priv, const char *file, unsigned line,
+ const char *function, const char *string)
+{
+ struct connection *connection = priv;
+ struct telnet_connection *t_con = connection->priv;
+ size_t i;
+ size_t tmp;
+
+ /* If the prompt is not visible, simply output the message. */
+ if (!t_con->prompt_visible) {
+ telnet_outputline(connection, string);
+ return;
+ }
+
+ /* Clear the command line. */
+ tmp = strlen(t_con->prompt) + t_con->line_size;
+
+ for (i = 0; i < tmp; i += 16)
+ telnet_write(connection, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b",
+ MIN(tmp - i, 16));
+
+ for (i = 0; i < tmp; i += 16)
+ telnet_write(connection, " ", MIN(tmp - i, 16));
+
+ for (i = 0; i < tmp; i += 16)
+ telnet_write(connection, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b",
+ MIN(tmp - i, 16));
+
+ telnet_outputline(connection, string);
+
+ /* Put the command line to its previous state. */
+ telnet_prompt(connection);
+ telnet_write(connection, t_con->line, t_con->line_size);
+
+ for (i = t_con->line_cursor; i < t_con->line_size; i++)
+ telnet_write(connection, "\b", 1);
+}
+
+static void telnet_load_history(struct telnet_connection *t_con)
+{
+ FILE *histfp;
+ char buffer[TELNET_BUFFER_SIZE];
+ int i = 0;
+
+ char *history = get_home_dir(TELNET_HISTORY);
+
+ if (history == NULL) {
+ LOG_INFO("unable to get user home directory, telnet history will be disabled");
+ return;
+ }
+
+ histfp = fopen(history, "rb");
+
+ if (histfp) {
+
+ while (fgets(buffer, sizeof(buffer), histfp) != NULL) {
+
+ char *p = strchr(buffer, '\n');
+ if (p)
+ *p = '\0';
+ if (buffer[0] && i < TELNET_LINE_HISTORY_SIZE)
+ t_con->history[i++] = strdup(buffer);
+ }
+
+ t_con->next_history = i;
+ t_con->next_history %= TELNET_LINE_HISTORY_SIZE;
+ /* try to set to last entry - 1, that way we skip over any exit/shutdown cmds */
+ t_con->current_history = t_con->next_history > 0 ? i - 1 : 0;
+ fclose(histfp);
+ }
+
+ free(history);
+}
+
+static void telnet_save_history(struct telnet_connection *t_con)
+{
+ FILE *histfp;
+ int i;
+ int num;
+
+ char *history = get_home_dir(TELNET_HISTORY);
+
+ if (history == NULL) {
+ LOG_INFO("unable to get user home directory, telnet history will be disabled");
+ return;
+ }
+
+ histfp = fopen(history, "wb");
+
+ if (histfp) {
+
+ num = TELNET_LINE_HISTORY_SIZE;
+ i = t_con->current_history + 1;
+ i %= TELNET_LINE_HISTORY_SIZE;
+
+ while (t_con->history[i] == NULL && num > 0) {
+ i++;
+ i %= TELNET_LINE_HISTORY_SIZE;
+ num--;
+ }
+
+ if (num > 0) {
+ for (; num > 0; num--) {
+ fprintf(histfp, "%s\n", t_con->history[i]);
+ i++;
+ i %= TELNET_LINE_HISTORY_SIZE;
+ }
+ }
+ fclose(histfp);
+ }
+
+ free(history);
+}
+
+static int telnet_new_connection(struct connection *connection)