From cec5179a7eeff005cdd04840701bd11813f8c9b7 Mon Sep 17 00:00:00 2001 From: scc Date: Fri, 1 Mar 2024 01:28:04 +0800 Subject: [PATCH 1/5] Suppress Cppcheck checking level Refine the pre-commit hook to enforce a minimum Cppcheck version of 1.90, alerting users with an error message and providing guidance on compiling Cppcheck from source if their version is outdated. Additionally, upgrade the hook for "--check-level=exhaustive" option against Cppcheck versions 2.11 and above, ensuring a comprehensive analysis. This adjustment leverages the enhanced capabilities available from version 2.11, promoting more detailed code quality checks. This commit is aiming for fixing commit #3aa0d55's misinformed title. We just add comments to explain why this changes. --- scripts/pre-commit.hook | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/pre-commit.hook b/scripts/pre-commit.hook index f8467cc75..4f45a7628 100755 --- a/scripts/pre-commit.hook +++ b/scripts/pre-commit.hook @@ -5,6 +5,8 @@ for f in *.c; do CPPCHECK_unmatched="$CPPCHECK_unmatched --suppress=unmatchedSuppression:$f" done +# We suppress the checkLevelNormal warning for Cppcheck versions 2.11 and above. +# Please refer to issues/153 for more details. CPPCHECK_suppresses="--inline-suppr harness.c \ --suppress=missingIncludeSystem \ --suppress=noValidConfiguration \ From b13335b841d9fc482f532f441d64e7729594d204 Mon Sep 17 00:00:00 2001 From: vax-r Date: Thu, 29 Feb 2024 19:33:19 +0800 Subject: [PATCH 2/5] Introduce eventmux callback function for linenoise In the previous version of console implementation, we tried to integrate tiny-web-server to enable the ability of processing commands from web requests. As the result, the package linenoise which is responsible for command-line auto-complete needs to be disabled during the running time of tiny-web-server. Because the main loop in "line_edit()" function in linenoise doesn't have the ability to handle web requests correctly. When we start the web server, we use "cmd_select" in console.c and use "select" function to monitor web socket file descriptor and stdin_fd at the same time. I re-design the control flow of web request and command-line input by implement the function "web_eventmux()", and register it as a hook function of type "line_eventmux_callback_t" inside linenoise package. As the result, we can utilize function inside the main loop of linenoise which is located inside the function "line_edit()". "web_eventmux()" is a function which use the function "select()" to monitor both input file descriptor and web file descriptor and modify "line_edit()" to use "eventmux_callback()" so we can process command-line input as normal and provide the command-line auto-complete feature alongside with the abitlity to deal with inputs from different input sources, such as web request. One may wonder why don't we simply modify the function "line_edit()", the reason is that linenoise is an upstream package so we only want to do the miminal changes to this package. --- console.c | 54 +++++++++++------------------------------------------ linenoise.c | 23 ++++++++++++++++++++++- linenoise.h | 4 +++- web.c | 40 +++++++++++++++++++++++++++++++++++++++ web.h | 4 +++- 5 files changed, 79 insertions(+), 46 deletions(-) diff --git a/console.c b/console.c index 4470bbd27..009ce5c8d 100644 --- a/console.c +++ b/console.c @@ -405,6 +405,7 @@ static bool do_web(int argc, char *argv[]) web_fd = web_open(port); if (web_fd > 0) { printf("listen on port %d, fd is %d\n", port, web_fd); + line_set_eventmux_callback(web_eventmux); use_linenoise = false; } else { perror("ERROR"); @@ -560,13 +561,13 @@ static int cmd_select(int nfds, fd_set *exceptfds, struct timeval *timeout) { - int infd; fd_set local_readset; if (cmd_done()) return 0; if (!block_flag) { + int infd; /* Process any commands in input buffer */ if (!readfds) readfds = &local_readset; @@ -581,51 +582,18 @@ static int cmd_select(int nfds, FD_SET(web_fd, readfds); if (infd == STDIN_FILENO && prompt_flag) { - printf("%s", prompt); + char *cmdline = linenoise(prompt); + if (cmdline) + interpret_cmd(cmdline); fflush(stdout); prompt_flag = true; + } else if (infd != STDIN_FILENO) { + char *cmdline = readline(); + if (cmdline) + interpret_cmd(cmdline); } - - if (infd >= nfds) - nfds = infd + 1; - if (web_fd >= nfds) - nfds = web_fd + 1; } - if (nfds == 0) - return 0; - - int result = select(nfds, readfds, writefds, exceptfds, timeout); - if (result <= 0) - return result; - - infd = buf_stack->fd; - if (readfds && FD_ISSET(infd, readfds)) { - /* Commandline input available */ - FD_CLR(infd, readfds); - result--; - - set_echo(0); - char *cmdline = readline(); - if (cmdline) - interpret_cmd(cmdline); - } else if (readfds && FD_ISSET(web_fd, readfds)) { - FD_CLR(web_fd, readfds); - result--; - struct sockaddr_in clientaddr; - socklen_t clientlen = sizeof(clientaddr); - web_connfd = - accept(web_fd, (struct sockaddr *) &clientaddr, &clientlen); - - char *p = web_recv(web_connfd, &clientaddr); - char *buffer = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n"; - web_send(web_connfd, buffer); - - if (p) - interpret_cmd(p); - free(p); - close(web_connfd); - } - return result; + return 0; } bool finish_cmd() @@ -706,4 +674,4 @@ bool run_console(char *infile_name) } return err_cnt == 0; -} +} \ No newline at end of file diff --git a/linenoise.c b/linenoise.c index aa1f362e8..eee1cc55c 100644 --- a/linenoise.c +++ b/linenoise.c @@ -124,6 +124,7 @@ static char *unsupported_term[] = {"dumb", "cons25", "emacs", NULL}; static line_completion_callback_t *completion_callback = NULL; static line_hints_callback_t *hints_callback = NULL; static line_free_hints_callback_t *free_hints_callback = NULL; +static line_eventmux_callback_t *eventmux_callback = NULL; static struct termios orig_termios; /* In order to restore at exit.*/ 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) free_hints_callback = fn; } +/* Register a function to perform I/O multiplexing to monitor multiple file + * descriptor from different input at the same time, so we can allow the ability + * of receiving commands from different input sources and still provides the + * command-line auto-complete feature of this package. For example, the main + * loop of this package can only deal with standard input file descriptor + * originally. When this callback function is invoked, it allows the main loop + * of this package to deal with multiple file descriptors from different input + * alongside with the origin feature to deal with the standard input. + */ +void line_set_eventmux_callback(line_eventmux_callback_t *fn) +{ + eventmux_callback = fn; +} + /* This function is used by the callback function registered by the user * in order to add completion options given the input string when the * user typed . @@ -932,6 +947,12 @@ static int line_edit(int stdin_fd, int nread; char seq[5]; + if (eventmux_callback != NULL) { + int result = eventmux_callback(l.buf); + if (result != 0) + return result; + } + nread = read(l.ifd, &c, 1); if (nread <= 0) return l.len; @@ -1362,4 +1383,4 @@ int line_history_load(const char *filename) } fclose(fp); return 0; -} +} \ No newline at end of file diff --git a/linenoise.h b/linenoise.h index 4468e8bbd..86b73d7e6 100644 --- a/linenoise.h +++ b/linenoise.h @@ -54,9 +54,11 @@ typedef struct { typedef void(line_completion_callback_t)(const char *, line_completions_t *); typedef char *(line_hints_callback_t)(const char *, int *color, int *bold); typedef void(line_free_hints_callback_t)(void *); +typedef int(line_eventmux_callback_t)(char *); void line_set_completion_callback(line_completion_callback_t *); void line_set_hints_callback(line_hints_callback_t *); void line_set_free_hints_callback(line_free_hints_callback_t *); +void line_set_eventmux_callback(line_eventmux_callback_t *); void line_add_completion(line_completions_t *, const char *); /* clang-format on */ @@ -74,4 +76,4 @@ void line_mask_mode_disable(void); } #endif -#endif /* __LINENOISE_H */ +#endif /* __LINENOISE_H */ \ No newline at end of file diff --git a/web.c b/web.c index 0994a47f5..5c573040d 100644 --- a/web.c +++ b/web.c @@ -23,6 +23,8 @@ #define TCP_CORK TCP_NOPUSH #endif +static int server_fd; + typedef struct { int fd; /* descriptor for this buf */ int count; /* unread byte in this buf */ @@ -153,6 +155,9 @@ int web_open(int port) /* Make it a listening socket ready to accept connection requests */ if (listen(listenfd, LISTENQ) < 0) return -1; + + server_fd = listenfd; + return listenfd; } @@ -228,3 +233,38 @@ char *web_recv(int fd, struct sockaddr_in *clientaddr) return ret; } + +int web_eventmux(char *buf) +{ + fd_set listenset; + + FD_ZERO(&listenset); + FD_SET(STDIN_FILENO, &listenset); + int max_fd = STDIN_FILENO; + if (server_fd > 0) { + FD_SET(server_fd, &listenset); + max_fd = max_fd > server_fd ? max_fd : server_fd; + } + int result = select(max_fd + 1, &listenset, NULL, NULL, NULL); + if (result < 0) + return -1; + + if (server_fd > 0 && FD_ISSET(server_fd, &listenset)) { + FD_CLR(server_fd, &listenset); + struct sockaddr_in clientaddr; + socklen_t clientlen = sizeof(clientaddr); + int web_connfd = + accept(server_fd, (struct sockaddr *) &clientaddr, &clientlen); + + char *p = web_recv(web_connfd, &clientaddr); + char *buffer = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n"; + web_send(web_connfd, buffer); + strncpy(buf, p, strlen(p) + 1); + free(p); + close(web_connfd); + return strlen(buf); + } + + FD_CLR(STDIN_FILENO, &listenset); + return 0; +} \ No newline at end of file diff --git a/web.h b/web.h index b04bc179d..3f5982a04 100644 --- a/web.h +++ b/web.h @@ -9,4 +9,6 @@ char *web_recv(int fd, struct sockaddr_in *clientaddr); void web_send(int out_fd, char *buffer); -#endif +int web_eventmux(char *buf); + +#endif \ No newline at end of file From 5d1b7f191cd8478ed45a927bc0f457084ac4c4bc Mon Sep 17 00:00:00 2001 From: Kuan-Wei Chiu Date: Wed, 6 Mar 2024 22:53:57 +0800 Subject: [PATCH 3/5] Enforce newline at the end of files Ensure that all the files conform to the standard of having a newline character at the end. Link: https://medium.com/@alexey.inkin/how-to-force-newline-at-end-of-files-and-why-you-should-do-it-fdf76d1d090e --- console.c | 2 +- linenoise.c | 2 +- linenoise.h | 2 +- web.c | 2 +- web.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/console.c b/console.c index 009ce5c8d..3745c9666 100644 --- a/console.c +++ b/console.c @@ -674,4 +674,4 @@ bool run_console(char *infile_name) } return err_cnt == 0; -} \ No newline at end of file +} diff --git a/linenoise.c b/linenoise.c index eee1cc55c..69048e9e6 100644 --- a/linenoise.c +++ b/linenoise.c @@ -1383,4 +1383,4 @@ int line_history_load(const char *filename) } fclose(fp); return 0; -} \ No newline at end of file +} diff --git a/linenoise.h b/linenoise.h index 86b73d7e6..0e61e125a 100644 --- a/linenoise.h +++ b/linenoise.h @@ -76,4 +76,4 @@ void line_mask_mode_disable(void); } #endif -#endif /* __LINENOISE_H */ \ No newline at end of file +#endif /* __LINENOISE_H */ diff --git a/web.c b/web.c index 5c573040d..30b336276 100644 --- a/web.c +++ b/web.c @@ -267,4 +267,4 @@ int web_eventmux(char *buf) FD_CLR(STDIN_FILENO, &listenset); return 0; -} \ No newline at end of file +} diff --git a/web.h b/web.h index 3f5982a04..6b6b8ab04 100644 --- a/web.h +++ b/web.h @@ -11,4 +11,4 @@ void web_send(int out_fd, char *buffer); int web_eventmux(char *buf); -#endif \ No newline at end of file +#endif From b1fbeb7ae6b4249b0d5195ad3a9f78cbd4e6684e Mon Sep 17 00:00:00 2001 From: "W.S. Wang" Date: Fri, 8 Mar 2024 08:35:50 +0800 Subject: [PATCH 4/5] Fix typo (#169) --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f419f6acb..531846e62 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -319,7 +319,7 @@ level, e.g.: } ``` -If the case bock does not break, then it is strongly recommended to add a +If the case block does not break, then it is strongly recommended to add a comment containing "fallthrough" to indicate it. Modern compilers can also be configured to require such comment (see gcc `-Wimplicit-fallthrough`). From 6c80a7d79d18dfa802914c98e90d70b6856f8985 Mon Sep 17 00:00:00 2001 From: Lin Chun Yeh <81501423+backink@users.noreply.github.com> Date: Sun, 10 Mar 2024 23:05:04 +0800 Subject: [PATCH 5/5] Fix typo (#171) "qcontext_t" in the description of q_merge should be queue_contex_t. --- queue.h | 6 +++--- scripts/checksums | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/queue.h b/queue.h index bbea8ec4d..09dd3adfb 100644 --- a/queue.h +++ b/queue.h @@ -239,9 +239,9 @@ int q_descend(struct list_head *head); * This function merge the second to the last queues in the chain into the first * queue. The queues are guaranteed to be sorted before this function is called. * No effect if there is only one queue in the chain. Allocation is disallowed - * in this function. There is no need to free the 'qcontext_t' and its member - * 'q' since they will be released externally. However, q_merge() is responsible - * for making the queues to be NULL-queue, except the first one. + * in this function. There is no need to free the 'queue_contex_t' and its + * member 'q' since they will be released externally. However, q_merge() is + * responsible for making the queues to be NULL-queue, except the first one. * * Reference: * https://leetcode.com/problems/merge-k-sorted-lists/ diff --git a/scripts/checksums b/scripts/checksums index 5effd9900..521c3774e 100644 --- a/scripts/checksums +++ b/scripts/checksums @@ -1,2 +1,2 @@ -fc83d2142cdebd29bf8dbf01d2c21c59f8c6a7ce queue.h +444bab14cb8ad4c949f61b3c10a22a3ed2401425 queue.h 3337dbccc33eceedda78e36cc118d5a374838ec7 list.h