diff --git a/html/system.html b/html/system.html
index 9c07fdc1..f538d3ee 100644
--- a/html/system.html
+++ b/html/system.html
@@ -88,6 +88,8 @@
Be careful when entering console commands, you can lock yourself out!
+
+
diff --git a/html/system.js b/html/system.js
index f9fd37eb..c52acd03 100644
--- a/html/system.js
+++ b/html/system.js
@@ -35,14 +35,28 @@ async function ipSub() {
}
async function cmdSub() {
- var cmd = document.getElementById('console_cmd').value;
+ const input = document.getElementById('console_cmd');
+ const out = document.getElementById('console_out');
+ const cmd = input.value;
try {
const response = await fetch('/cmd', {
method: 'POST',
body: cmd
});
- console.log('Completed!', response);
+ if (response.status == 401) {
+ window.location.href = 'login.html';
+ return;
+ }
+ let text = await response.text();
+ if (text != "" && !text.endsWith("\n"))
+ text += "\n";
+ if (out.textContent.length > 20000)
+ out.textContent = out.textContent.slice(-16000);
+ out.textContent += "> " + cmd + "\n" + text;
+ out.scrollTop = out.scrollHeight;
+ input.value = "";
} catch(err) {
+ out.textContent += "> " + cmd + "\n" + err + "\n";
console.error(`Error: ${err}`);
}
}
diff --git a/httpd/httpd.c b/httpd/httpd.c
index 4537eefe..7c0542b2 100644
--- a/httpd/httpd.c
+++ b/httpd/httpd.c
@@ -21,6 +21,7 @@
extern volatile __xdata uint8_t sfr_data[4];
extern volatile __xdata uint32_t ticks;
+extern __xdata uint8_t cmd_capture; /* owned by rtlplayground.c, see write_char_no_syslog() */
extern __code uint8_t * __code hex;
extern __code struct f_data f_data[];
extern __code char * __code mime_strings[];
@@ -625,12 +626,29 @@ static void handle_firmware_fragment(__xdata uint8_t *p)
static void run_cmd_body(__xdata uint8_t *body)
{
+ uint16_t hdr_len = strtox(outbuf, HTTP_RESPONCE_TXT);
+
+ slen = hdr_len;
+ cmd_capture = 1;
execute_commands(body);
+ if (cmd_capture == 2)
+ slen += strtox(outbuf + slen, CMD_TRUNCATED);
+ cmd_capture = 0;
+ /* Commands that configure something print nothing at all. Saying
+ * so beats an empty body, which reads the same as "nothing ran".
+ * Only on success: a silent failure must not answer with "OK". */
+ if (err_status == ERR_OK && slen == hdr_len)
+ slen += strtox(outbuf + slen, "OK\n");
+ /* On a parse error keep what the parser printed, because that text
+ * is the explanation, and only restate the status. "400 NO" is as
+ * long as "200 OK", so the header does not have to be rebuilt. */
if (err_status != ERR_OK) {
- send_bad_request();
- return;
+ outbuf[9] = '4';
+ outbuf[10] = '0';
+ outbuf[11] = '0';
+ outbuf[13] = 'N';
+ outbuf[14] = 'O';
}
- send_ok();
}
diff --git a/httpd/page_impl.c b/httpd/page_impl.c
index 695a6291..8c10572f 100644
--- a/httpd/page_impl.c
+++ b/httpd/page_impl.c
@@ -48,7 +48,7 @@ extern __xdata char sfp_module_serial[2][17];
extern __xdata uint8_t sfp_options[2];
__code uint8_t * __code HTTP_RESPONCE_JSON = "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Type: application/json\r\n\r\n";
-__code uint8_t * __code HTTP_RESPONCE_TXT = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n";
+__code uint8_t * __code HTTP_RESPONCE_TXT = "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Type: text/plain\r\n\r\n";
// Convert uint8_t to ascii HEX char push on html-buffer.
void charhex_to_html(char c)
diff --git a/httpd/page_impl.h b/httpd/page_impl.h
index 31a6e08d..cad4cd6f 100644
--- a/httpd/page_impl.h
+++ b/httpd/page_impl.h
@@ -3,6 +3,8 @@
#include
+extern __code uint8_t * __code HTTP_RESPONCE_TXT;
+
bool send_counters(uint8_t phys_port);
void send_status(void);
void send_vlan(uint16_t vlan);
diff --git a/rtl837x_common.h b/rtl837x_common.h
index 83b0ea13..0d4ccc01 100644
--- a/rtl837x_common.h
+++ b/rtl837x_common.h
@@ -37,6 +37,10 @@ extern __xdata uint8_t sbuf[SBUF_SIZE];
// Size of the TCP Output buffer
#define TCP_OUTBUF_SIZE 2500
+// Appended when a captured command wrote more than the output buffer holds,
+// so a clipped listing is visibly clipped instead of silently short.
+#define CMD_TRUNCATED "\n[output truncated]\n"
+
// Size of the port name, including the terminating null byte
#define PORT_NAME_SIZE 32
diff --git a/rtlplayground.c b/rtlplayground.c
index 2766501d..b3710c76 100644
--- a/rtlplayground.c
+++ b/rtlplayground.c
@@ -240,8 +240,25 @@ void isr_serial(void) __interrupt(4)
}
+/* Set by the httpd while it runs a command that arrived over the network, so
+ * that everything the command prints lands in the response as well. */
+__xdata uint8_t cmd_capture;
+extern __xdata uint8_t outbuf[TCP_OUTBUF_SIZE];
+extern __xdata uint16_t slen;
+
void write_char_no_syslog(char c)
{
+ /* Capturing sits here rather than in write_char() so that the messages
+ * printed through print_string_no_syslog() are captured too: those are
+ * the replies of the syslog commands, which must not generate a syslog
+ * packet but do belong in the answer to a command sent over HTTP. */
+ if (cmd_capture) {
+ if (slen < TCP_OUTBUF_SIZE - sizeof(CMD_TRUNCATED))
+ outbuf[slen++] = c;
+ else
+ cmd_capture = 2; /* out of room, httpd says so */
+ }
+
do {
} while (tx_buf_empty == 0);
if (c =='\n') {