From 40255a01422c99a2a46b5cc9330b79a27982e932 Mon Sep 17 00:00:00 2001 From: "nancy.wang" Date: Wed, 11 May 2022 15:19:29 +0800 Subject: [PATCH 1/7] Fix compile error for linux. --- Makefile | 8 +- httpd.c | 684 +++++++++++++++++++++++++++---------------------------- 2 files changed, 338 insertions(+), 354 deletions(-) diff --git a/Makefile b/Makefile index f4017f2..fbe36a3 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,7 @@ -all: httpd client -LIBS = -lpthread #-lsocket +all: httpd + httpd: httpd.c - gcc -g -W -Wall $(LIBS) -o $@ $< + gcc -W -Wall -lpthread -o httpd httpd.c -client: simpleclient.c - gcc -W -Wall -o $@ $< clean: rm httpd diff --git a/httpd.c b/httpd.c index d4eb456..ef3359d 100644 --- a/httpd.c +++ b/httpd.c @@ -22,19 +22,15 @@ #include #include #include -#include +//#include #include #include -#include #define ISspace(x) isspace((int)(x)) #define SERVER_STRING "Server: jdbhttpd/0.1.0\r\n" -#define STDIN 0 -#define STDOUT 1 -#define STDERR 2 -void accept_request(void *); +void accept_request(int); void bad_request(int); void cat(int, FILE *); void cannot_execute(int); @@ -52,85 +48,83 @@ void unimplemented(int); * return. Process the request appropriately. * Parameters: the socket connected to the client */ /**********************************************************************/ -void accept_request(void *arg) +void accept_request(int client) { - int client = (intptr_t)arg; - char buf[1024]; - size_t numchars; - char method[255]; - char url[255]; - char path[512]; - size_t i, j; - struct stat st; - int cgi = 0; /* becomes true if server decides this is a CGI - * program */ - char *query_string = NULL; - - numchars = get_line(client, buf, sizeof(buf)); - i = 0; j = 0; - while (!ISspace(buf[i]) && (i < sizeof(method) - 1)) - { - method[i] = buf[i]; - i++; - } - j=i; - method[i] = '\0'; - - if (strcasecmp(method, "GET") && strcasecmp(method, "POST")) - { - unimplemented(client); - return; - } - - if (strcasecmp(method, "POST") == 0) - cgi = 1; - - i = 0; - while (ISspace(buf[j]) && (j < numchars)) - j++; - while (!ISspace(buf[j]) && (i < sizeof(url) - 1) && (j < numchars)) - { - url[i] = buf[j]; - i++; j++; - } - url[i] = '\0'; - - if (strcasecmp(method, "GET") == 0) - { - query_string = url; - while ((*query_string != '?') && (*query_string != '\0')) - query_string++; - if (*query_string == '?') - { - cgi = 1; - *query_string = '\0'; - query_string++; - } - } - - sprintf(path, "htdocs%s", url); - if (path[strlen(path) - 1] == '/') - strcat(path, "index.html"); - if (stat(path, &st) == -1) { - while ((numchars > 0) && strcmp("\n", buf)) /* read & discard headers */ - numchars = get_line(client, buf, sizeof(buf)); - not_found(client); - } - else - { - if ((st.st_mode & S_IFMT) == S_IFDIR) - strcat(path, "/index.html"); - if ((st.st_mode & S_IXUSR) || - (st.st_mode & S_IXGRP) || - (st.st_mode & S_IXOTH) ) - cgi = 1; - if (!cgi) - serve_file(client, path); - else - execute_cgi(client, path, method, query_string); - } - - close(client); + char buf[1024]; + int numchars; + char method[255]; + char url[255]; + char path[512]; + size_t i, j; + struct stat st; + int cgi = 0; /* becomes true if server decides this is a CGI + * program */ + char *query_string = NULL; + + numchars = get_line(client, buf, sizeof(buf)); + i = 0; j = 0; + while (!ISspace(buf[j]) && (i < sizeof(method) - 1)) + { + method[i] = buf[j]; + i++; j++; + } + method[i] = '\0'; + + if (strcasecmp(method, "GET") && strcasecmp(method, "POST")) + { + unimplemented(client); + return; + } + + if (strcasecmp(method, "POST") == 0) + cgi = 1; + + i = 0; + while (ISspace(buf[j]) && (j < sizeof(buf))) + j++; + while (!ISspace(buf[j]) && (i < sizeof(url) - 1) && (j < sizeof(buf))) + { + url[i] = buf[j]; + i++; j++; + } + url[i] = '\0'; + + if (strcasecmp(method, "GET") == 0) + { + query_string = url; + while ((*query_string != '?') && (*query_string != '\0')) + query_string++; + if (*query_string == '?') + { + cgi = 1; + *query_string = '\0'; + query_string++; + } + } + + sprintf(path, "htdocs%s", url); + if (path[strlen(path) - 1] == '/') + strcat(path, "index.html"); + if (stat(path, &st) == -1) { + while ((numchars > 0) && strcmp("\n", buf)) /* read & discard headers */ + numchars = get_line(client, buf, sizeof(buf)); + not_found(client); + } + else + { + if ((st.st_mode & S_IFMT) == S_IFDIR) + strcat(path, "/index.html"); + if ((st.st_mode & S_IXUSR) || + (st.st_mode & S_IXGRP) || + (st.st_mode & S_IXOTH) ) + cgi = 1; + if (!cgi) + serve_file(client, path); + else + execute_cgi(client, path, method, query_string); + } + + close(client); } /**********************************************************************/ @@ -139,18 +133,18 @@ void accept_request(void *arg) /**********************************************************************/ void bad_request(int client) { - char buf[1024]; - - sprintf(buf, "HTTP/1.0 400 BAD REQUEST\r\n"); - send(client, buf, sizeof(buf), 0); - sprintf(buf, "Content-type: text/html\r\n"); - send(client, buf, sizeof(buf), 0); - sprintf(buf, "\r\n"); - send(client, buf, sizeof(buf), 0); - sprintf(buf, "

Your browser sent a bad request, "); - send(client, buf, sizeof(buf), 0); - sprintf(buf, "such as a POST without a Content-Length.\r\n"); - send(client, buf, sizeof(buf), 0); + char buf[1024]; + + sprintf(buf, "HTTP/1.0 400 BAD REQUEST\r\n"); + send(client, buf, sizeof(buf), 0); + sprintf(buf, "Content-type: text/html\r\n"); + send(client, buf, sizeof(buf), 0); + sprintf(buf, "\r\n"); + send(client, buf, sizeof(buf), 0); + sprintf(buf, "

Your browser sent a bad request, "); + send(client, buf, sizeof(buf), 0); + sprintf(buf, "such as a POST without a Content-Length.\r\n"); + send(client, buf, sizeof(buf), 0); } /**********************************************************************/ @@ -162,14 +156,14 @@ void bad_request(int client) /**********************************************************************/ void cat(int client, FILE *resource) { - char buf[1024]; - - fgets(buf, sizeof(buf), resource); - while (!feof(resource)) - { - send(client, buf, strlen(buf), 0); - fgets(buf, sizeof(buf), resource); - } + char buf[1024]; + + fgets(buf, sizeof(buf), resource); + while (!feof(resource)) + { + send(client, buf, strlen(buf), 0); + fgets(buf, sizeof(buf), resource); + } } /**********************************************************************/ @@ -178,16 +172,16 @@ void cat(int client, FILE *resource) /**********************************************************************/ void cannot_execute(int client) { - char buf[1024]; - - sprintf(buf, "HTTP/1.0 500 Internal Server Error\r\n"); - send(client, buf, strlen(buf), 0); - sprintf(buf, "Content-type: text/html\r\n"); - send(client, buf, strlen(buf), 0); - sprintf(buf, "\r\n"); - send(client, buf, strlen(buf), 0); - sprintf(buf, "

Error prohibited CGI execution.\r\n"); - send(client, buf, strlen(buf), 0); + char buf[1024]; + + sprintf(buf, "HTTP/1.0 500 Internal Server Error\r\n"); + send(client, buf, strlen(buf), 0); + sprintf(buf, "Content-type: text/html\r\n"); + send(client, buf, strlen(buf), 0); + sprintf(buf, "\r\n"); + send(client, buf, strlen(buf), 0); + sprintf(buf, "

Error prohibited CGI execution.\r\n"); + send(client, buf, strlen(buf), 0); } /**********************************************************************/ @@ -197,8 +191,8 @@ void cannot_execute(int client) /**********************************************************************/ void error_die(const char *sc) { - perror(sc); - exit(1); + perror(sc); + exit(1); } /**********************************************************************/ @@ -208,94 +202,91 @@ void error_die(const char *sc) * path to the CGI script */ /**********************************************************************/ void execute_cgi(int client, const char *path, - const char *method, const char *query_string) + const char *method, const char *query_string) { - char buf[1024]; - int cgi_output[2]; - int cgi_input[2]; - pid_t pid; - int status; - int i; - char c; - int numchars = 1; - int content_length = -1; - - buf[0] = 'A'; buf[1] = '\0'; - if (strcasecmp(method, "GET") == 0) - while ((numchars > 0) && strcmp("\n", buf)) /* read & discard headers */ - numchars = get_line(client, buf, sizeof(buf)); - else if (strcasecmp(method, "POST") == 0) /*POST*/ - { - numchars = get_line(client, buf, sizeof(buf)); - while ((numchars > 0) && strcmp("\n", buf)) - { - buf[15] = '\0'; - if (strcasecmp(buf, "Content-Length:") == 0) - content_length = atoi(&(buf[16])); - numchars = get_line(client, buf, sizeof(buf)); - } - if (content_length == -1) { - bad_request(client); - return; - } - } - else/*HEAD or other*/ - { - } - - - if (pipe(cgi_output) < 0) { - cannot_execute(client); - return; - } - if (pipe(cgi_input) < 0) { - cannot_execute(client); - return; - } - - if ( (pid = fork()) < 0 ) { - cannot_execute(client); - return; - } - sprintf(buf, "HTTP/1.0 200 OK\r\n"); - send(client, buf, strlen(buf), 0); - if (pid == 0) /* child: CGI script */ - { - char meth_env[255]; - char query_env[255]; - char length_env[255]; - - dup2(cgi_output[1], STDOUT); - dup2(cgi_input[0], STDIN); - close(cgi_output[0]); - close(cgi_input[1]); - sprintf(meth_env, "REQUEST_METHOD=%s", method); - putenv(meth_env); - if (strcasecmp(method, "GET") == 0) { - sprintf(query_env, "QUERY_STRING=%s", query_string); - putenv(query_env); - } - else { /* POST */ - sprintf(length_env, "CONTENT_LENGTH=%d", content_length); - putenv(length_env); - } - execl(path, NULL); - exit(0); - } else { /* parent */ - close(cgi_output[1]); - close(cgi_input[0]); - if (strcasecmp(method, "POST") == 0) - for (i = 0; i < content_length; i++) { - recv(client, &c, 1, 0); - write(cgi_input[1], &c, 1); - } - while (read(cgi_output[0], &c, 1) > 0) - send(client, &c, 1, 0); - - close(cgi_output[0]); - close(cgi_input[1]); - waitpid(pid, &status, 0); - } + char buf[1024]; + int cgi_output[2]; + int cgi_input[2]; + pid_t pid; + int status; + int i; + char c; + int numchars = 1; + int content_length = -1; + + buf[0] = 'A'; buf[1] = '\0'; + if (strcasecmp(method, "GET") == 0) + while ((numchars > 0) && strcmp("\n", buf)) /* read & discard headers */ + numchars = get_line(client, buf, sizeof(buf)); + else /* POST */ + { + numchars = get_line(client, buf, sizeof(buf)); + while ((numchars > 0) && strcmp("\n", buf)) + { + buf[15] = '\0'; + if (strcasecmp(buf, "Content-Length:") == 0) + content_length = atoi(&(buf[16])); + numchars = get_line(client, buf, sizeof(buf)); + } + if (content_length == -1) { + bad_request(client); + return; + } + } + + sprintf(buf, "HTTP/1.0 200 OK\r\n"); + send(client, buf, strlen(buf), 0); + + if (pipe(cgi_output) < 0) { + cannot_execute(client); + return; + } + if (pipe(cgi_input) < 0) { + cannot_execute(client); + return; + } + + if ( (pid = fork()) < 0 ) { + cannot_execute(client); + return; + } + if (pid == 0) /* child: CGI script */ + { + char meth_env[255]; + char query_env[255]; + char length_env[255]; + + dup2(cgi_output[1], 1); + dup2(cgi_input[0], 0); + close(cgi_output[0]); + close(cgi_input[1]); + sprintf(meth_env, "REQUEST_METHOD=%s", method); + putenv(meth_env); + if (strcasecmp(method, "GET") == 0) { + sprintf(query_env, "QUERY_STRING=%s", query_string); + putenv(query_env); + } + else { /* POST */ + sprintf(length_env, "CONTENT_LENGTH=%d", content_length); + putenv(length_env); + } + execl(path, path, NULL); + exit(0); + } else { /* parent */ + close(cgi_output[1]); + close(cgi_input[0]); + if (strcasecmp(method, "POST") == 0) + for (i = 0; i < content_length; i++) { + recv(client, &c, 1, 0); + write(cgi_input[1], &c, 1); + } + while (read(cgi_output[0], &c, 1) > 0) + send(client, &c, 1, 0); + + close(cgi_output[0]); + close(cgi_input[1]); + waitpid(pid, &status, 0); + } } /**********************************************************************/ @@ -313,34 +304,34 @@ void execute_cgi(int client, const char *path, /**********************************************************************/ int get_line(int sock, char *buf, int size) { - int i = 0; - char c = '\0'; - int n; - - while ((i < size - 1) && (c != '\n')) - { - n = recv(sock, &c, 1, 0); - /* DEBUG printf("%02X\n", c); */ - if (n > 0) - { - if (c == '\r') - { - n = recv(sock, &c, 1, MSG_PEEK); - /* DEBUG printf("%02X\n", c); */ - if ((n > 0) && (c == '\n')) - recv(sock, &c, 1, 0); - else - c = '\n'; - } - buf[i] = c; - i++; - } - else - c = '\n'; - } - buf[i] = '\0'; - - return(i); + int i = 0; + char c = '\0'; + int n; + + while ((i < size - 1) && (c != '\n')) + { + n = recv(sock, &c, 1, 0); + /* DEBUG printf("%02X\n", c); */ + if (n > 0) + { + if (c == '\r') + { + n = recv(sock, &c, 1, MSG_PEEK); + /* DEBUG printf("%02X\n", c); */ + if ((n > 0) && (c == '\n')) + recv(sock, &c, 1, 0); + else + c = '\n'; + } + buf[i] = c; + i++; + } + else + c = '\n'; + } + buf[i] = '\0'; + + return(i); } /**********************************************************************/ @@ -350,17 +341,17 @@ int get_line(int sock, char *buf, int size) /**********************************************************************/ void headers(int client, const char *filename) { - char buf[1024]; - (void)filename; /* could use filename to determine file type */ - - strcpy(buf, "HTTP/1.0 200 OK\r\n"); - send(client, buf, strlen(buf), 0); - strcpy(buf, SERVER_STRING); - send(client, buf, strlen(buf), 0); - sprintf(buf, "Content-Type: text/html\r\n"); - send(client, buf, strlen(buf), 0); - strcpy(buf, "\r\n"); - send(client, buf, strlen(buf), 0); + char buf[1024]; + (void)filename; /* could use filename to determine file type */ + + strcpy(buf, "HTTP/1.0 200 OK\r\n"); + send(client, buf, strlen(buf), 0); + strcpy(buf, SERVER_STRING); + send(client, buf, strlen(buf), 0); + sprintf(buf, "Content-Type: text/html\r\n"); + send(client, buf, strlen(buf), 0); + strcpy(buf, "\r\n"); + send(client, buf, strlen(buf), 0); } /**********************************************************************/ @@ -368,26 +359,26 @@ void headers(int client, const char *filename) /**********************************************************************/ void not_found(int client) { - char buf[1024]; - - sprintf(buf, "HTTP/1.0 404 NOT FOUND\r\n"); - send(client, buf, strlen(buf), 0); - sprintf(buf, SERVER_STRING); - send(client, buf, strlen(buf), 0); - sprintf(buf, "Content-Type: text/html\r\n"); - send(client, buf, strlen(buf), 0); - sprintf(buf, "\r\n"); - send(client, buf, strlen(buf), 0); - sprintf(buf, "Not Found\r\n"); - send(client, buf, strlen(buf), 0); - sprintf(buf, "

The server could not fulfill\r\n"); - send(client, buf, strlen(buf), 0); - sprintf(buf, "your request because the resource specified\r\n"); - send(client, buf, strlen(buf), 0); - sprintf(buf, "is unavailable or nonexistent.\r\n"); - send(client, buf, strlen(buf), 0); - sprintf(buf, "\r\n"); - send(client, buf, strlen(buf), 0); + char buf[1024]; + + sprintf(buf, "HTTP/1.0 404 NOT FOUND\r\n"); + send(client, buf, strlen(buf), 0); + sprintf(buf, SERVER_STRING); + send(client, buf, strlen(buf), 0); + sprintf(buf, "Content-Type: text/html\r\n"); + send(client, buf, strlen(buf), 0); + sprintf(buf, "\r\n"); + send(client, buf, strlen(buf), 0); + sprintf(buf, "Not Found\r\n"); + send(client, buf, strlen(buf), 0); + sprintf(buf, "

The server could not fulfill\r\n"); + send(client, buf, strlen(buf), 0); + sprintf(buf, "your request because the resource specified\r\n"); + send(client, buf, strlen(buf), 0); + sprintf(buf, "is unavailable or nonexistent.\r\n"); + send(client, buf, strlen(buf), 0); + sprintf(buf, "\r\n"); + send(client, buf, strlen(buf), 0); } /**********************************************************************/ @@ -399,23 +390,23 @@ void not_found(int client) /**********************************************************************/ void serve_file(int client, const char *filename) { - FILE *resource = NULL; - int numchars = 1; - char buf[1024]; - - buf[0] = 'A'; buf[1] = '\0'; - while ((numchars > 0) && strcmp("\n", buf)) /* read & discard headers */ - numchars = get_line(client, buf, sizeof(buf)); - - resource = fopen(filename, "r"); - if (resource == NULL) - not_found(client); - else - { - headers(client, filename); - cat(client, resource); - } - fclose(resource); + FILE *resource = NULL; + int numchars = 1; + char buf[1024]; + + buf[0] = 'A'; buf[1] = '\0'; + while ((numchars > 0) && strcmp("\n", buf)) /* read & discard headers */ + numchars = get_line(client, buf, sizeof(buf)); + + resource = fopen(filename, "r"); + if (resource == NULL) + not_found(client); + else + { + headers(client, filename); + cat(client, resource); + } + fclose(resource); } /**********************************************************************/ @@ -428,33 +419,28 @@ void serve_file(int client, const char *filename) /**********************************************************************/ int startup(u_short *port) { - int httpd = 0; - int on = 1; - struct sockaddr_in name; - - httpd = socket(PF_INET, SOCK_STREAM, 0); - if (httpd == -1) - error_die("socket"); - memset(&name, 0, sizeof(name)); - name.sin_family = AF_INET; - name.sin_port = htons(*port); - name.sin_addr.s_addr = htonl(INADDR_ANY); - if ((setsockopt(httpd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) < 0) - { - error_die("setsockopt failed"); - } - if (bind(httpd, (struct sockaddr *)&name, sizeof(name)) < 0) - error_die("bind"); - if (*port == 0) /* if dynamically allocating a port */ - { - socklen_t namelen = sizeof(name); - if (getsockname(httpd, (struct sockaddr *)&name, &namelen) == -1) - error_die("getsockname"); - *port = ntohs(name.sin_port); - } - if (listen(httpd, 5) < 0) - error_die("listen"); - return(httpd); + int httpd = 0; + struct sockaddr_in name; + + httpd = socket(PF_INET, SOCK_STREAM, 0); + if (httpd == -1) + error_die("socket"); + memset(&name, 0, sizeof(name)); + name.sin_family = AF_INET; + name.sin_port = htons(*port); + name.sin_addr.s_addr = htonl(INADDR_ANY); + if (bind(httpd, (struct sockaddr *)&name, sizeof(name)) < 0) + error_die("bind"); + if (*port == 0) /* if dynamically allocating a port */ + { + int namelen = sizeof(name); + if (getsockname(httpd, (struct sockaddr *)&name, &namelen) == -1) + error_die("getsockname"); + *port = ntohs(name.sin_port); + } + if (listen(httpd, 5) < 0) + error_die("listen"); + return(httpd); } /**********************************************************************/ @@ -464,53 +450,53 @@ int startup(u_short *port) /**********************************************************************/ void unimplemented(int client) { - char buf[1024]; - - sprintf(buf, "HTTP/1.0 501 Method Not Implemented\r\n"); - send(client, buf, strlen(buf), 0); - sprintf(buf, SERVER_STRING); - send(client, buf, strlen(buf), 0); - sprintf(buf, "Content-Type: text/html\r\n"); - send(client, buf, strlen(buf), 0); - sprintf(buf, "\r\n"); - send(client, buf, strlen(buf), 0); - sprintf(buf, "Method Not Implemented\r\n"); - send(client, buf, strlen(buf), 0); - sprintf(buf, "\r\n"); - send(client, buf, strlen(buf), 0); - sprintf(buf, "

HTTP request method not supported.\r\n"); - send(client, buf, strlen(buf), 0); - sprintf(buf, "\r\n"); - send(client, buf, strlen(buf), 0); + char buf[1024]; + + sprintf(buf, "HTTP/1.0 501 Method Not Implemented\r\n"); + send(client, buf, strlen(buf), 0); + sprintf(buf, SERVER_STRING); + send(client, buf, strlen(buf), 0); + sprintf(buf, "Content-Type: text/html\r\n"); + send(client, buf, strlen(buf), 0); + sprintf(buf, "\r\n"); + send(client, buf, strlen(buf), 0); + sprintf(buf, "Method Not Implemented\r\n"); + send(client, buf, strlen(buf), 0); + sprintf(buf, "\r\n"); + send(client, buf, strlen(buf), 0); + sprintf(buf, "

HTTP request method not supported.\r\n"); + send(client, buf, strlen(buf), 0); + sprintf(buf, "\r\n"); + send(client, buf, strlen(buf), 0); } /**********************************************************************/ int main(void) { - int server_sock = -1; - u_short port = 4000; - int client_sock = -1; - struct sockaddr_in client_name; - socklen_t client_name_len = sizeof(client_name); - pthread_t newthread; - - server_sock = startup(&port); - printf("httpd running on port %d\n", port); - - while (1) - { - client_sock = accept(server_sock, - (struct sockaddr *)&client_name, - &client_name_len); - if (client_sock == -1) - error_die("accept"); - /* accept_request(&client_sock); */ - if (pthread_create(&newthread , NULL, (void *)accept_request, (void *)(intptr_t)client_sock) != 0) - perror("pthread_create"); - } - - close(server_sock); - - return(0); + int server_sock = -1; + u_short port = 0; + int client_sock = -1; + struct sockaddr_in client_name; + int client_name_len = sizeof(client_name); + //pthread_t newthread; + + server_sock = startup(&port); + printf("httpd running on port %d\n", port); + + while (1) + { + client_sock = accept(server_sock, + (struct sockaddr *)&client_name, + &client_name_len); + if (client_sock == -1) + error_die("accept"); + accept_request(client_sock); + //if (pthread_create(&newthread , NULL, accept_request, client_sock) != 0) + //perror("pthread_create"); + } + + close(server_sock); + + return(0); } From 37afe7846f67e5d2fdfd515b3aeffffaf9bff3d6 Mon Sep 17 00:00:00 2001 From: N1uNancy <99379570+N1uNancy@users.noreply.github.com> Date: Wed, 11 May 2022 15:43:42 +0800 Subject: [PATCH 2/7] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 507b3f9..57ccd9b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ A mirror for tinyhttpd(Tinyhttpd非官方镜像,Fork自[sourceForge](https://sourceforge.net/projects/tiny-httpd/),仅供学习) -测试CGI时需要本机安装PERL,同时安装perl-cgi +测试CGI时需要本机安装PERL,同时安装perl-cgi: yum install per-CGI +首先需要对htdoc文件夹下的color.cgi和index.html进行权限查看,并把color.cgi改为777,index.html改为666 +执行which perl的命令,查看perl的路径,记录下来并vim修改color.cgi的第一行代码为所在路径 ### Prepare Compile for Linux From 04849de60b56b8021cfd6863ad14869f054459f2 Mon Sep 17 00:00:00 2001 From: qian Date: Thu, 12 May 2022 17:43:51 +0800 Subject: [PATCH 3/7] Add logs --- Makefile | 2 +- httpd.c | 25 +++++++++++++------------ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/Makefile b/Makefile index fbe36a3..71e3643 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ all: httpd httpd: httpd.c - gcc -W -Wall -lpthread -o httpd httpd.c + gcc -W -Wall -lpthread -o httpd httpd.c -g clean: rm httpd diff --git a/httpd.c b/httpd.c index ef3359d..2f3da78 100644 --- a/httpd.c +++ b/httpd.c @@ -69,7 +69,7 @@ void accept_request(int client) i++; j++; } method[i] = '\0'; - + printf("accept_request: method: %s", method); if (strcasecmp(method, "GET") && strcasecmp(method, "POST")) { unimplemented(client); @@ -88,7 +88,7 @@ void accept_request(int client) i++; j++; } url[i] = '\0'; - + printf("accept_request: url: %s", url); if (strcasecmp(method, "GET") == 0) { query_string = url; @@ -100,6 +100,7 @@ void accept_request(int client) *query_string = '\0'; query_string++; } + printf("accept_request: query_string: %s", query_string); } sprintf(path, "htdocs%s", url); @@ -112,16 +113,16 @@ void accept_request(int client) } else { - if ((st.st_mode & S_IFMT) == S_IFDIR) - strcat(path, "/index.html"); - if ((st.st_mode & S_IXUSR) || - (st.st_mode & S_IXGRP) || - (st.st_mode & S_IXOTH) ) - cgi = 1; - if (!cgi) - serve_file(client, path); - else - execute_cgi(client, path, method, query_string); + if ((st.st_mode & S_IFMT) == S_IFDIR) + strcat(path, "/index.html"); + if ((st.st_mode & S_IXUSR) || + (st.st_mode & S_IXGRP) || + (st.st_mode & S_IXOTH) ) + cgi = 1; + if (!cgi) + serve_file(client, path); + else + execute_cgi(client, path, method, query_string); } close(client); From ca5ee2d6e89a5b671e57b661a32bbe13a3523f00 Mon Sep 17 00:00:00 2001 From: qian Date: Thu, 12 May 2022 17:46:51 +0800 Subject: [PATCH 4/7] Add workflow --- .github/workflows/builder.yml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 .github/workflows/builder.yml diff --git a/.github/workflows/builder.yml b/.github/workflows/builder.yml new file mode 100644 index 0000000..0c8ea8d --- /dev/null +++ b/.github/workflows/builder.yml @@ -0,0 +1,30 @@ +# This is a basic workflow that is manually triggered + +name: Builder + +# Controls when the action will run. Workflow runs when manually triggered using the UI +# or API. +on: + workflow_dispatch: + # Inputs the workflow accepts. + inputs: + name: + # Friendly description to be shown in the UI instead of 'name' + description: 'Person to greet' + # Default value if no value is explicitly provided + default: 'World' + # Input has to be provided for the workflow to run + required: true + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "greet" + greet: + # The type of runner that the job will run on + runs-on: ubuntu-latest + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + # Runs a single command using the runners shell + - name: Send greeting + run: echo "Hello ${{ github.event.inputs.name }}" \ No newline at end of file From b9158f30ed8c94190ed4b6f7f0bbcbba405765a8 Mon Sep 17 00:00:00 2001 From: qian Date: Fri, 13 May 2022 17:50:29 +0800 Subject: [PATCH 5/7] Add comment. --- httpd.c | 102 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 54 insertions(+), 48 deletions(-) diff --git a/httpd.c b/httpd.c index 2f3da78..e83f928 100644 --- a/httpd.c +++ b/httpd.c @@ -12,6 +12,9 @@ * 4) Uncomment the line that runs accept_request(). * 5) Remove -lsocket from the Makefile. */ + +//ref: https://zhuanlan.zhihu.com/p/24941375 + #include #include #include @@ -206,8 +209,8 @@ void execute_cgi(int client, const char *path, const char *method, const char *query_string) { char buf[1024]; - int cgi_output[2]; - int cgi_input[2]; + int cgi_output[2];//output pipe, 0 read, 1 write + int cgi_input[2];//input pipe, 0 read, 1 write pid_t pid; int status; int i; @@ -221,18 +224,18 @@ void execute_cgi(int client, const char *path, numchars = get_line(client, buf, sizeof(buf)); else /* POST */ { - numchars = get_line(client, buf, sizeof(buf)); - while ((numchars > 0) && strcmp("\n", buf)) - { - buf[15] = '\0'; - if (strcasecmp(buf, "Content-Length:") == 0) - content_length = atoi(&(buf[16])); - numchars = get_line(client, buf, sizeof(buf)); - } - if (content_length == -1) { - bad_request(client); - return; - } + numchars = get_line(client, buf, sizeof(buf)); + while ((numchars > 0) && strcmp("\n", buf)) + { + buf[15] = '\0'; + if (strcasecmp(buf, "Content-Length:") == 0) + content_length = atoi(&(buf[16])); + numchars = get_line(client, buf, sizeof(buf)); + } + if (content_length == -1) { + bad_request(client); + return; + } } sprintf(buf, "HTTP/1.0 200 OK\r\n"); @@ -253,40 +256,43 @@ void execute_cgi(int client, const char *path, } if (pid == 0) /* child: CGI script */ { - char meth_env[255]; - char query_env[255]; - char length_env[255]; - - dup2(cgi_output[1], 1); - dup2(cgi_input[0], 0); - close(cgi_output[0]); - close(cgi_input[1]); - sprintf(meth_env, "REQUEST_METHOD=%s", method); - putenv(meth_env); - if (strcasecmp(method, "GET") == 0) { - sprintf(query_env, "QUERY_STRING=%s", query_string); - putenv(query_env); - } - else { /* POST */ - sprintf(length_env, "CONTENT_LENGTH=%d", content_length); - putenv(length_env); - } - execl(path, path, NULL); - exit(0); - } else { /* parent */ - close(cgi_output[1]); - close(cgi_input[0]); - if (strcasecmp(method, "POST") == 0) - for (i = 0; i < content_length; i++) { - recv(client, &c, 1, 0); - write(cgi_input[1], &c, 1); - } - while (read(cgi_output[0], &c, 1) > 0) - send(client, &c, 1, 0); - - close(cgi_output[0]); - close(cgi_input[1]); - waitpid(pid, &status, 0); + char meth_env[255]; + char query_env[255]; + char length_env[255]; + dup2(cgi_output[1], 1);//1stdout0stdinϵͳ׼ضΪcgi_output[1] + dup2(cgi_input[0], 0);//ϵͳ׼ضΪcgi_input[0] + close(cgi_output[0]); + close(cgi_input[1]); + sprintf(meth_env, "REQUEST_METHOD=%s", method); + putenv(meth_env); + if (strcasecmp(method, "GET") == 0) + { + sprintf(query_env, "QUERY_STRING=%s", query_string); + putenv(query_env); + } + else + { /* POST */ + sprintf(length_env, "CONTENT_LENGTH=%d", content_length); + putenv(length_env); + } + execl(path, path, NULL); + exit(0); + } + else + { /* parent */ + close(cgi_output[1]); + close(cgi_input[0]); + if (strcasecmp(method, "POST") == 0) + for (i = 0; i < content_length; i++) { + recv(client, &c, 1, 0); + write(cgi_input[1], &c, 1); + } + while (read(cgi_output[0], &c, 1) > 0) + send(client, &c, 1, 0); + + close(cgi_output[0]); + close(cgi_input[1]); + waitpid(pid, &status, 0); } } From d7162fd6a0bc65b5be8ffea3e198f15687e723e0 Mon Sep 17 00:00:00 2001 From: qian Date: Fri, 13 May 2022 18:08:00 +0800 Subject: [PATCH 6/7] update perl path --- htdocs/color.cgi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/color.cgi b/htdocs/color.cgi index 3a56601..0893a89 100644 --- a/htdocs/color.cgi +++ b/htdocs/color.cgi @@ -1,4 +1,4 @@ -#!/usr/local/bin/perl -Tw +#!/usr/bin/perl -Tw use strict; use CGI; From 57625f72ff77b6129ab725641689c68e0ed6a01c Mon Sep 17 00:00:00 2001 From: "nancy.wang" Date: Tue, 17 May 2022 16:42:07 +0800 Subject: [PATCH 7/7] update workflow --- .github/workflows/builder.yml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/.github/workflows/builder.yml b/.github/workflows/builder.yml index 0c8ea8d..a76e6be 100644 --- a/.github/workflows/builder.yml +++ b/.github/workflows/builder.yml @@ -27,4 +27,15 @@ jobs: steps: # Runs a single command using the runners shell - name: Send greeting - run: echo "Hello ${{ github.event.inputs.name }}" \ No newline at end of file + run: echo "Hello ${{ github.event.inputs.name }}" + + - name: get the version + id: get_version + run: | + GIT_VERSION=$(git describe --tags) + echo ::set-output name=BUILD_TAG::httpd-$GIT_VERSION + + - name: create release + uses: ncipollo/release-action@v1.9.0 + with: + tag: ${{ steps.get_version.outputs.BUILD_TAG }} \ No newline at end of file