jlink: Make use of debug level for I/O messages
[fw/openocd] / src / server / telnet_server.c
index ecdb2bfa247edcf37e1f30afc55305b8b7e8ec2a..7507afea8d688613eeadff39940e22ba743cc911 100644 (file)
@@ -19,9 +19,7 @@
  *   GNU General Public License for more details.                          *
  *                                                                         *
  *   You should have received a copy of the GNU General Public License     *
- *   along with this program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
  ***************************************************************************/
 
 #ifdef HAVE_CONFIG_H
@@ -32,7 +30,7 @@
 #include <target/target_request.h>
 #include <helper/configuration.h>
 
-static const char *telnet_port;
+static char *telnet_port;
 
 static char *negotiate =
        "\xFF\xFB\x03"                  /* IAC WILL Suppress Go Ahead */
@@ -207,17 +205,23 @@ static void telnet_save_history(struct telnet_connection *t_con)
 
 static int telnet_new_connection(struct connection *connection)
 {
-       struct telnet_connection *telnet_connection = malloc(sizeof(struct telnet_connection));
+       struct telnet_connection *telnet_connection;
        struct telnet_service *telnet_service = connection->service->priv;
        int i;
 
+       telnet_connection = malloc(sizeof(struct telnet_connection));
+
+       if (!telnet_connection) {
+               LOG_ERROR("Failed to allocate telnet connection.");
+               return ERROR_FAIL;
+       }
+
        connection->priv = telnet_connection;
 
        /* initialize telnet connection information */
        telnet_connection->closed = 0;
        telnet_connection->line_size = 0;
        telnet_connection->line_cursor = 0;
-       telnet_connection->option_size = 0;
        telnet_connection->prompt = strdup("> ");
        telnet_connection->state = TELNET_STATE_DATA;
 
@@ -266,6 +270,39 @@ static void telnet_clear_line(struct connection *connection,
        t_con->line_cursor = 0;
 }
 
+static void telnet_history_go(struct connection *connection, int idx)
+{
+       struct telnet_connection *t_con = connection->priv;
+
+       if (t_con->history[idx]) {
+               telnet_clear_line(connection, t_con);
+               t_con->line_size = strlen(t_con->history[idx]);
+               t_con->line_cursor = t_con->line_size;
+               memcpy(t_con->line, t_con->history[idx], t_con->line_size);
+               telnet_write(connection, t_con->line, t_con->line_size);
+               t_con->current_history = idx;
+       }
+       t_con->state = TELNET_STATE_DATA;
+}
+
+static void telnet_history_up(struct connection *connection)
+{
+       struct telnet_connection *t_con = connection->priv;
+
+       int last_history = (t_con->current_history > 0) ?
+                               t_con->current_history - 1 :
+                               TELNET_LINE_HISTORY_SIZE-1;
+       telnet_history_go(connection, last_history);
+}
+
+static void telnet_history_down(struct connection *connection)
+{
+       struct telnet_connection *t_con = connection->priv;
+
+       int next_history = (t_con->current_history + 1) % TELNET_LINE_HISTORY_SIZE;
+       telnet_history_go(connection, next_history);
+}
+
 static int telnet_input(struct connection *connection)
 {
        int bytes_read;
@@ -441,7 +478,11 @@ static int telnet_input(struct connection *connection)
                                                        if (t_con->line_cursor < t_con->line_size)
                                                                telnet_write(connection, t_con->line + t_con->line_cursor++, 1);
                                                        t_con->state = TELNET_STATE_DATA;
-                                               } else
+                                               } else if (*buf_p == CTRL('P'))         /* cursor up */
+                                                       telnet_history_up(connection);
+                                               else if (*buf_p == CTRL('N'))           /* cursor down */
+                                                       telnet_history_down(connection);
+                                               else
                                                        LOG_DEBUG("unhandled nonprintable: %2.2x", *buf_p);
                                        }
                                }
@@ -486,28 +527,9 @@ static int telnet_input(struct connection *connection)
                                                                        t_con->line + t_con->line_cursor++, 1);
                                                t_con->state = TELNET_STATE_DATA;
                                        } else if (*buf_p == 'A') {     /* cursor up */
-                                               int last_history = (t_con->current_history > 0) ?
-                                                               t_con->current_history - 1 : TELNET_LINE_HISTORY_SIZE-1;
-                                               if (t_con->history[last_history]) {
-                                                       telnet_clear_line(connection, t_con);
-                                                       t_con->line_size = strlen(t_con->history[last_history]);
-                                                       t_con->line_cursor = t_con->line_size;
-                                                       memcpy(t_con->line, t_con->history[last_history], t_con->line_size);
-                                                       telnet_write(connection, t_con->line, t_con->line_size);
-                                                       t_con->current_history = last_history;
-                                               }
-                                               t_con->state = TELNET_STATE_DATA;
+                                               telnet_history_up(connection);
                                        } else if (*buf_p == 'B') {     /* cursor down */
-                                               int next_history = (t_con->current_history + 1) % TELNET_LINE_HISTORY_SIZE;
-                                               if (t_con->history[next_history]) {
-                                                       telnet_clear_line(connection, t_con);
-                                                       t_con->line_size = strlen(t_con->history[next_history]);
-                                                       t_con->line_cursor = t_con->line_size;
-                                                       memcpy(t_con->line, t_con->history[next_history], t_con->line_size);
-                                                       telnet_write(connection, t_con->line, t_con->line_size);
-                                                       t_con->current_history = next_history;
-                                               }
-                                               t_con->state = TELNET_STATE_DATA;
+                                               telnet_history_down(connection);
                                        } else if (*buf_p == '3')
                                                t_con->last_escape = *buf_p;
                                        else
@@ -550,7 +572,7 @@ static int telnet_input(struct connection *connection)
                                break;
                        default:
                                LOG_ERROR("unknown telnet state");
-                               exit(-1);
+                               return ERROR_FAIL;
                }
 
                bytes_read--;
@@ -601,17 +623,26 @@ int telnet_init(char *banner)
                return ERROR_OK;
        }
 
-       struct telnet_service *telnet_service = malloc(sizeof(struct telnet_service));
+       struct telnet_service *telnet_service =
+               malloc(sizeof(struct telnet_service));
+
+       if (!telnet_service) {
+               LOG_ERROR("Failed to allocate telnet service.");
+               return ERROR_FAIL;
+       }
 
        telnet_service->banner = banner;
 
-       return add_service("telnet",
-               telnet_port,
-               1,
-               telnet_new_connection,
-               telnet_input,
-               telnet_connection_closed,
+       int ret = add_service("telnet", telnet_port, CONNECTION_LIMIT_UNLIMITED,
+               telnet_new_connection, telnet_input, telnet_connection_closed,
                telnet_service);
+
+       if (ret != ERROR_OK) {
+               free(telnet_service);
+               return ret;
+       }
+
+       return ERROR_OK;
 }
 
 /* daemon configuration command telnet_port */