Skip to content

Commit dd6a761

Browse files
authored
Merge pull request #162 from vax-r/Integrate_linenoise_web
Integrate linenoise with web server
2 parents 39c85e9 + b13335b commit dd6a761

File tree

5 files changed

+79
-46
lines changed

5 files changed

+79
-46
lines changed

console.c

+11-43
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,7 @@ static bool do_web(int argc, char *argv[])
405405
web_fd = web_open(port);
406406
if (web_fd > 0) {
407407
printf("listen on port %d, fd is %d\n", port, web_fd);
408+
line_set_eventmux_callback(web_eventmux);
408409
use_linenoise = false;
409410
} else {
410411
perror("ERROR");
@@ -560,13 +561,13 @@ static int cmd_select(int nfds,
560561
fd_set *exceptfds,
561562
struct timeval *timeout)
562563
{
563-
int infd;
564564
fd_set local_readset;
565565

566566
if (cmd_done())
567567
return 0;
568568

569569
if (!block_flag) {
570+
int infd;
570571
/* Process any commands in input buffer */
571572
if (!readfds)
572573
readfds = &local_readset;
@@ -581,51 +582,18 @@ static int cmd_select(int nfds,
581582
FD_SET(web_fd, readfds);
582583

583584
if (infd == STDIN_FILENO && prompt_flag) {
584-
printf("%s", prompt);
585+
char *cmdline = linenoise(prompt);
586+
if (cmdline)
587+
interpret_cmd(cmdline);
585588
fflush(stdout);
586589
prompt_flag = true;
590+
} else if (infd != STDIN_FILENO) {
591+
char *cmdline = readline();
592+
if (cmdline)
593+
interpret_cmd(cmdline);
587594
}
588-
589-
if (infd >= nfds)
590-
nfds = infd + 1;
591-
if (web_fd >= nfds)
592-
nfds = web_fd + 1;
593595
}
594-
if (nfds == 0)
595-
return 0;
596-
597-
int result = select(nfds, readfds, writefds, exceptfds, timeout);
598-
if (result <= 0)
599-
return result;
600-
601-
infd = buf_stack->fd;
602-
if (readfds && FD_ISSET(infd, readfds)) {
603-
/* Commandline input available */
604-
FD_CLR(infd, readfds);
605-
result--;
606-
607-
set_echo(0);
608-
char *cmdline = readline();
609-
if (cmdline)
610-
interpret_cmd(cmdline);
611-
} else if (readfds && FD_ISSET(web_fd, readfds)) {
612-
FD_CLR(web_fd, readfds);
613-
result--;
614-
struct sockaddr_in clientaddr;
615-
socklen_t clientlen = sizeof(clientaddr);
616-
web_connfd =
617-
accept(web_fd, (struct sockaddr *) &clientaddr, &clientlen);
618-
619-
char *p = web_recv(web_connfd, &clientaddr);
620-
char *buffer = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n";
621-
web_send(web_connfd, buffer);
622-
623-
if (p)
624-
interpret_cmd(p);
625-
free(p);
626-
close(web_connfd);
627-
}
628-
return result;
596+
return 0;
629597
}
630598

631599
bool finish_cmd()
@@ -706,4 +674,4 @@ bool run_console(char *infile_name)
706674
}
707675

708676
return err_cnt == 0;
709-
}
677+
}

linenoise.c

+22-1
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ static char *unsupported_term[] = {"dumb", "cons25", "emacs", NULL};
124124
static line_completion_callback_t *completion_callback = NULL;
125125
static line_hints_callback_t *hints_callback = NULL;
126126
static line_free_hints_callback_t *free_hints_callback = NULL;
127+
static line_eventmux_callback_t *eventmux_callback = NULL;
127128

128129
static struct termios orig_termios; /* In order to restore at exit.*/
129130
static bool maskmode = false; /* Show "***" instead of input. For passwords. */
@@ -472,6 +473,20 @@ void line_set_free_hints_callback(line_free_hints_callback_t *fn)
472473
free_hints_callback = fn;
473474
}
474475

476+
/* Register a function to perform I/O multiplexing to monitor multiple file
477+
* descriptor from different input at the same time, so we can allow the ability
478+
* of receiving commands from different input sources and still provides the
479+
* command-line auto-complete feature of this package. For example, the main
480+
* loop of this package can only deal with standard input file descriptor
481+
* originally. When this callback function is invoked, it allows the main loop
482+
* of this package to deal with multiple file descriptors from different input
483+
* alongside with the origin feature to deal with the standard input.
484+
*/
485+
void line_set_eventmux_callback(line_eventmux_callback_t *fn)
486+
{
487+
eventmux_callback = fn;
488+
}
489+
475490
/* This function is used by the callback function registered by the user
476491
* in order to add completion options given the input string when the
477492
* user typed <tab>.
@@ -932,6 +947,12 @@ static int line_edit(int stdin_fd,
932947
int nread;
933948
char seq[5];
934949

950+
if (eventmux_callback != NULL) {
951+
int result = eventmux_callback(l.buf);
952+
if (result != 0)
953+
return result;
954+
}
955+
935956
nread = read(l.ifd, &c, 1);
936957
if (nread <= 0)
937958
return l.len;
@@ -1362,4 +1383,4 @@ int line_history_load(const char *filename)
13621383
}
13631384
fclose(fp);
13641385
return 0;
1365-
}
1386+
}

linenoise.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,11 @@ typedef struct {
5454
typedef void(line_completion_callback_t)(const char *, line_completions_t *);
5555
typedef char *(line_hints_callback_t)(const char *, int *color, int *bold);
5656
typedef void(line_free_hints_callback_t)(void *);
57+
typedef int(line_eventmux_callback_t)(char *);
5758
void line_set_completion_callback(line_completion_callback_t *);
5859
void line_set_hints_callback(line_hints_callback_t *);
5960
void line_set_free_hints_callback(line_free_hints_callback_t *);
61+
void line_set_eventmux_callback(line_eventmux_callback_t *);
6062
void line_add_completion(line_completions_t *, const char *);
6163
/* clang-format on */
6264

@@ -74,4 +76,4 @@ void line_mask_mode_disable(void);
7476
}
7577
#endif
7678

77-
#endif /* __LINENOISE_H */
79+
#endif /* __LINENOISE_H */

web.c

+40
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
#define TCP_CORK TCP_NOPUSH
2424
#endif
2525

26+
static int server_fd;
27+
2628
typedef struct {
2729
int fd; /* descriptor for this buf */
2830
int count; /* unread byte in this buf */
@@ -153,6 +155,9 @@ int web_open(int port)
153155
/* Make it a listening socket ready to accept connection requests */
154156
if (listen(listenfd, LISTENQ) < 0)
155157
return -1;
158+
159+
server_fd = listenfd;
160+
156161
return listenfd;
157162
}
158163

@@ -228,3 +233,38 @@ char *web_recv(int fd, struct sockaddr_in *clientaddr)
228233

229234
return ret;
230235
}
236+
237+
int web_eventmux(char *buf)
238+
{
239+
fd_set listenset;
240+
241+
FD_ZERO(&listenset);
242+
FD_SET(STDIN_FILENO, &listenset);
243+
int max_fd = STDIN_FILENO;
244+
if (server_fd > 0) {
245+
FD_SET(server_fd, &listenset);
246+
max_fd = max_fd > server_fd ? max_fd : server_fd;
247+
}
248+
int result = select(max_fd + 1, &listenset, NULL, NULL, NULL);
249+
if (result < 0)
250+
return -1;
251+
252+
if (server_fd > 0 && FD_ISSET(server_fd, &listenset)) {
253+
FD_CLR(server_fd, &listenset);
254+
struct sockaddr_in clientaddr;
255+
socklen_t clientlen = sizeof(clientaddr);
256+
int web_connfd =
257+
accept(server_fd, (struct sockaddr *) &clientaddr, &clientlen);
258+
259+
char *p = web_recv(web_connfd, &clientaddr);
260+
char *buffer = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n";
261+
web_send(web_connfd, buffer);
262+
strncpy(buf, p, strlen(p) + 1);
263+
free(p);
264+
close(web_connfd);
265+
return strlen(buf);
266+
}
267+
268+
FD_CLR(STDIN_FILENO, &listenset);
269+
return 0;
270+
}

web.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,6 @@ char *web_recv(int fd, struct sockaddr_in *clientaddr);
99

1010
void web_send(int out_fd, char *buffer);
1111

12-
#endif
12+
int web_eventmux(char *buf);
13+
14+
#endif

0 commit comments

Comments
 (0)