diff options
-rw-r--r-- | Makefile | 114 | ||||
-rw-r--r-- | examples/fastcgi.c (renamed from examples/fastcgi.todo) | 3 | ||||
-rw-r--r-- | examples/upload.c | 4 | ||||
-rw-r--r-- | include/magi.h | 2 | ||||
-rw-r--r-- | include/magi/cookie.h | 3 | ||||
-rw-r--r-- | include/magi/fastcgi.h | 7 | ||||
-rw-r--r-- | include/magi/file.h | 2 | ||||
-rw-r--r-- | include/magi/loadfiles.h (renamed from include/magi/loadfile.h) | 0 | ||||
-rw-r--r-- | include/magi/param.h | 2 | ||||
-rw-r--r-- | include/magi/request.h | 13 | ||||
-rw-r--r-- | include/magi/response.h | 2 | ||||
-rw-r--r-- | include/magi/session.h | 17 | ||||
-rw-r--r-- | man/magi.3 | 2 | ||||
-rw-r--r-- | src/cgi.c | 7 | ||||
-rw-r--r-- | src/cookie.c | 5 | ||||
-rw-r--r-- | src/fastcgi.c | 22 | ||||
-rw-r--r-- | src/file.c | 2 | ||||
-rw-r--r-- | src/loadfiles.c (renamed from src/loadfile.c) | 2 | ||||
-rw-r--r-- | src/multipart.c | 8 | ||||
-rw-r--r-- | src/param.c | 2 | ||||
-rw-r--r-- | src/request.c | 15 | ||||
-rw-r--r-- | src/session.c | 40 |
22 files changed, 182 insertions, 92 deletions
@@ -2,91 +2,97 @@ # Compilation Options # Debug mode [yes/no] (allowing to debug the library via gdb): DEBUG ?= no -# Specify build directory: -BUILD ?= build # Optional modules (remove unwanted ones): -MODULES ?= cgi fastcgi loadfile urlenc +MODULES ?= cgi fastcgi loadfiles urlenc # Specify your favourite C compiler here: CC ?= gcc # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Preparations -LIB = libmagi.a - # Compile under the most strict conditions: -CFLAGS = -xc -ansi -pedantic -Wall -Wextra +CFLAGS = -xc -ansi -pedantic -Wall -Wextra -MMD # Debug and optimisation are not compatible: ifeq '$(DEBUG)' 'yes' CFLAGS += -g -O0 else -CFLAGS += -O3 -static +CFLAGS += -O3 endif -# Interfacial files to compile: -INTER = cookie error file param request response $(MODULES) - -# Object files listing: -INC_DIR = include/magi -SRC_DIR = src -INTER_H = $(foreach name,$(INTER),$(INC_DIR)/$(name).h) -INTER_C = $(foreach name,$(INTER),$(SRC_DIR)/$(name).c) -INNER_H = $(wildcard $(SRC_DIR)/*.h) -INNER_C = $(INNER_H:.h=.c) -SRC = $(INTER_C) $(INNER_C) -NAMES = $(notdir $(SRC:.c=)) -OBJ = $(foreach name,$(NAMES),$(BUILD)/$(SRC_DIR)/$(name).o) - -EXDIR = examples -EXSRC = $(wildcard $(EXDIR)/*.c) -EXNAMES = $(notdir $(EXSRC:.c=)) -EXAMPLES = $(foreach ex,$(EXNAMES),$(BUILD)/$(EXDIR)/$(ex)) +# Directories definitions: +INCLUDE = include +BUILD = build +SRCDIR = src +EXADIR = examples +# Library itself: +LIB = libmagi.a +# Modules: +EXTERNAL = cookie error file param request response session $(MODULES) +INTERNAL = cookies multipart tools urlencoded + +# Default target is library: +TARGET = $(BUILD)/$(LIB) +# Determing needed object files: +EXTER_H = $(foreach x,$(EXTERNAL:=.h),$(INCLUDE)/magi/$(x)) +EXTER_C = $(foreach x,$(EXTERNAL:=.c),$(SRCDIR)/$(x)) +INTER_H = $(foreach i,$(INTERNAL:=.h),$(SRCDIR)/$(i)) +INTER_C = $(INTER_H:.h=.c) +SRC = $(INTER_C) $(EXTER_C) +OBJ = $(foreach o,$(SRC:.c=.o),$(BUILD)/$(o)) +# Example executables: +EXASRC = $(wildcard $(EXADIR)/*.c) +EXAMPLES = $(foreach x,$(EXASRC:.c=),$(BUILD)/$(x)) +# Dependency files: +DEPS = $(OBJ:.o=.d) $(EXAMPLES:=.d) + +# Flags collections: +SRCFLAGS = $(CFLAGS) -I$(INCLUDE)/magi +EXAFLAGS = $(CFLAGS) -I$(INCLUDE) +LFLAGS = -static -L$(BUILD) -lmagi + +# Build directories: +BUILDIRS = $(BUILD) $(BUILD)/$(SRCDIR) $(BUILD)/$(EXADIR) # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Targets -.PHONY: default clean examples +.PHONY: default examples clean clean-nontarget clean-deps clean-all -# 'make' produces library by default: -default: $(BUILD)/$(LIB) +default: $(TARGET) examples: $(EXAMPLES) -# Cleaning means removing everything automatically produced: -clean: +clean: clean-nontarget + rm -f $(TARGET) +clean-nontarget: clean-deps + rm -f $(OBJ) $(EXAMPLES) +clean-deps: + rm -f $(DEPS) +clean-all: rm -rf $(BUILD) # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Compilation -# Compile object files from corresponding source and header: -$(BUILD)/$(SRC_DIR)/%.o: $(SRC_DIR)/%.c - $(CC) $(CFLAGS) -I $(INC_DIR) -c $< -o $@ +# No product should be in case of cleaning: +ifneq (clean,$(MAKECMDGOAL)) # Packing object files into library: -$(BUILD)/$(LIB): $(OBJ) - ar rcs $@ $^ +$(TARGET): $(OBJ) + ar -rcs $@ $^ + +# Compile object files from corresponding source: +$(BUILD)/%.o: %.c $(BUILDIRS) + $(CC) $(SRCFLAGS) -c $< -o $@ # Compile executables from corresponding sources and library: -$(BUILD)/$(EXDIR)/%: $(EXDIR)/%.c $(BUILD)/$(LIB) - $(CC) $(CFLAGS) -I include $< -L$(BUILD) -lmagi -o $@ +$(BUILD)/%: %.c $(TARGET) $(BUILDIRS) + $(CC) $(EXAFLAGS) $< $(LFLAGS) -o $@ +$(BUILDIRS): + mkdir -p $@ -# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # -# Dependencies -$(BUILD)/deps.mk: $(SRC) $(EXSRC) - mkdir $(BUILD) $(BUILD)/$(SRC_DIR) $(BUILD)/$(EXDIR); echo '' > $@ - for t in $(NAMES); do \ - $(CC) -I $(INC_DIR) \ - -MT $(BUILD)/$(SRC_DIR)/$${t}.o \ - -MM $(SRC_DIR)/$${t}.c >> $@; \ - done - for t in $(EXNAMES); do \ - $(CC) -I include \ - -MT $(BUILD)/$(EXDIR)/$${t}.o \ - -MM $(EXDIR)/$${t}.c >> $@; \ - done - -ifneq (clean, $(MAKECMDGOALS)) --include $(BUILD)/deps.mk + +# Including dependency files: +-include $(DEPS) endif diff --git a/examples/fastcgi.todo b/examples/fastcgi.c index 5d3c4b1..16668f3 100644 --- a/examples/fastcgi.todo +++ b/examples/fastcgi.c @@ -12,13 +12,12 @@ void response(magi_request *r) "</html>"); } -int main(int argc, char const *argv[]) +int main() { magi_session session; magi_request request; magi_request_init(&request); magi_session_init(&session); - magi_session_inet(&session, "localhost", "9973"); magi_session_unix(&session, "unix.sock"); while (magi_fastcgi(&session, &request)) { if (request.error) { diff --git a/examples/upload.c b/examples/upload.c index 9a16dd1..bf8eed1 100644 --- a/examples/upload.c +++ b/examples/upload.c @@ -4,8 +4,8 @@ void response(magi_request *r) { - char *name = magi_request_param(r, "name"); - magi_file *data = magi_request_file(r, "data"); + char *name = magi_request_param(r, "name"); + const magi_file *data = magi_request_file(r, "data"); magi_response(r, "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' " "'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>" diff --git a/include/magi.h b/include/magi.h index a5b047d..d8e1245 100644 --- a/include/magi.h +++ b/include/magi.h @@ -8,7 +8,7 @@ #include "magi/error.h" #include "magi/fastcgi.h" #include "magi/file.h" -#include "magi/loadfile.h" +#include "magi/loadfiles.h" #include "magi/param.h" #include "magi/request.h" #include "magi/response.h" diff --git a/include/magi/cookie.h b/include/magi/cookie.h index 96e4273..4760b75 100644 --- a/include/magi/cookie.h +++ b/include/magi/cookie.h @@ -30,7 +30,8 @@ void magi_cookies_add(magi_cookies **cookies, magi_cookie *newitem); /* Get last from top of cookies cookie with name, null if no such cookie. * Cookies are in reversed request order, and first cookie from request is * the most accurate in terms of domain and path. */ -magi_cookie *magi_cookies_get(magi_cookies *cookies, const char *name); +const magi_cookie *magi_cookies_get(const magi_cookies *cookies, + const char *name); #endif diff --git a/include/magi/fastcgi.h b/include/magi/fastcgi.h index fb1f2e5..3d91b7b 100644 --- a/include/magi/fastcgi.h +++ b/include/magi/fastcgi.h @@ -2,10 +2,13 @@ #define MAGI_INCLUDED_FASTCGI /* Fast CGI implementation */ -/* * * TODO * * */ +#include "session.h" +#include "request.h" -enum { magi_to_avoid_warning }; +int magi_fastcgi_head(magi_session *s, magi_request *r); +int magi_fastcgi_body(magi_session *s, magi_request *r); +int magi_fastcgi(magi_session *s, magi_request *r); #endif diff --git a/include/magi/file.h b/include/magi/file.h index d4c5e98..cd3d675 100644 --- a/include/magi/file.h +++ b/include/magi/file.h @@ -25,7 +25,7 @@ void magi_files_free(magi_files *files); void magi_files_add(magi_files **files, magi_file *newitem); /* Get first from top of files file with name, null if no such file. */ -magi_file *magi_files_get(magi_files *files, const char *name); +const magi_file *magi_files_get(const magi_files *files, const char *name); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * diff --git a/include/magi/loadfile.h b/include/magi/loadfiles.h index bf3421c..bf3421c 100644 --- a/include/magi/loadfile.h +++ b/include/magi/loadfiles.h diff --git a/include/magi/param.h b/include/magi/param.h index 589db9f..c0879a9 100644 --- a/include/magi/param.h +++ b/include/magi/param.h @@ -29,7 +29,7 @@ void magi_params_set(magi_params **params, magi_param *newitem); /* Get data of the first from top of params parameter with name, * null if no such parameter. */ -char *magi_params_get(magi_params *params, const char *name); +char *magi_params_get(const magi_params *params, const char *name); #endif diff --git a/include/magi/request.h b/include/magi/request.h index 3d0d48a..7245feb 100644 --- a/include/magi/request.h +++ b/include/magi/request.h @@ -60,20 +60,21 @@ void magi_request_free(magi_request *r); /* Get value of meta-param with name. */ -char *magi_request_meta(magi_request *r, const char *name); +char *magi_request_meta(const magi_request *r, const char *name); /* Get value of form field param (prioritising body) with name. */ -char *magi_request_param(magi_request *r, const char *name); +char *magi_request_param(const magi_request *r, const char *name); /* Get value of form field param with name from url. */ -char *magi_request_urlparam(magi_request *r, const char *name); +char *magi_request_urlparam(const magi_request *r, const char *name); /* Get metadata structure of file from file field with name. */ -magi_file *magi_request_file(magi_request *r, const char *name); +const magi_file *magi_request_file(const magi_request *r, const char *name); /* Get value of cookie with name. */ -char *magi_request_cookie(magi_request *r, const char *name); +char *magi_request_cookie(const magi_request *r, const char *name); /* Get cookie with name. */ -magi_cookie *magi_request_cookie_complex(magi_request *r, const char *name); +const magi_cookie *magi_request_cookie_complex(const magi_request *r, + const char *name); #endif diff --git a/include/magi/response.h b/include/magi/response.h index 4b71ef5..11acf75 100644 --- a/include/magi/response.h +++ b/include/magi/response.h @@ -4,7 +4,7 @@ * * There are two parts of response, namely header and body. * You can directly dive into filling the body, since default headers are set. - * Defult content-type is XHTML, status is 200 (Ok). + * Defult content-type is HTML, status is 200 (OK). * * Use body related functions only after dealing with headers. * (Since storing possibly large body in memory is a bad idea, diff --git a/include/magi/session.h b/include/magi/session.h new file mode 100644 index 0000000..c1c5903 --- /dev/null +++ b/include/magi/session.h @@ -0,0 +1,17 @@ +#ifndef MAGI_INCLUDED_SESSION +#define MAGI_INCLUDED_SESSION + + +typedef struct magi_session { + int socket; +} magi_session; + + +void magi_session_init(magi_session *s); +void magi_session_free(magi_session *s); + +int magi_session_inet(magi_session *s, const char *address, int port); +int magi_session_unix(magi_session *s, const char *path); + + +#endif @@ -1,4 +1,4 @@ -.TH MAGI 3 "2020.03.14" "0.1" "Magi Library" +.TH MAGI 3 "2020-03-18" "0.1" "Magi Library" .SH NAME magi \- ANSI C dependency-free CGI and FastCGI library .SH LIBRARY @@ -161,9 +161,8 @@ static void mhead(void *any, magi_param *header) fputs("\r\n", stdout); } -static void mstart_body(void *any) +static void mstart_body() { - (void)any; fputs("\r\n", stdout); } @@ -189,7 +188,7 @@ static void mfile(void *any, FILE *file) } } -static void mclose(void *any) { (void)any; } +static void mclose() {} static void setup_response(magi_request *r) { @@ -208,7 +207,7 @@ static void setup_response(magi_request *r) r->response->head_general = 0; r->response->head_entity = 0; r->response->head_done = 0; - magi_response_content_type(r, "application/xhtml+xml"); + magi_response_content_type(r, "text/html"); magi_response_status(r, 200, "OK"); } diff --git a/src/cookie.c b/src/cookie.c index 7b40f1a..a64f5cb 100644 --- a/src/cookie.c +++ b/src/cookie.c @@ -14,9 +14,10 @@ void magi_cookies_add(magi_cookies **cookies, magi_cookie *newitem) } } -magi_cookie *magi_cookies_get(magi_cookies *cookies, const char *name) +const magi_cookie *magi_cookies_get(const magi_cookies *cookies, + const char *name) { - magi_cookie *res = 0; + const magi_cookie *res = 0; if (!cookies || !name) { return 0; } diff --git a/src/fastcgi.c b/src/fastcgi.c index 39c57ca..8959c14 100644 --- a/src/fastcgi.c +++ b/src/fastcgi.c @@ -1 +1,23 @@ #include "fastcgi.h" + + +int magi_fastcgi_head(magi_session *s, magi_request *r) +{ + (void)s; + (void)r; + return 1; +} + + +int magi_fastcgi_body(magi_session *s, magi_request *r) +{ + (void)s; + (void)r; + return 1; +} + + +int magi_fastcgi(magi_session *s, magi_request *r) +{ + return magi_fastcgi_head(s, r) && magi_fastcgi_body(s, r); +} @@ -14,7 +14,7 @@ void magi_files_add(magi_files **files, magi_file *newitem) } } -magi_file *magi_files_get(magi_files *files, const char *name) +const magi_file *magi_files_get(const magi_files *files, const char *name) { if (!files || !name) { return 0; diff --git a/src/loadfile.c b/src/loadfiles.c index d76f562..b3efff7 100644 --- a/src/loadfile.c +++ b/src/loadfiles.c @@ -1,4 +1,4 @@ -#include "loadfile.h" +#include "loadfiles.h" #include <stdio.h> #include <stdlib.h> diff --git a/src/multipart.c b/src/multipart.c index 2284ced..d2a1c7f 100644 --- a/src/multipart.c +++ b/src/multipart.c @@ -63,10 +63,10 @@ static char *extract_filename(char *n) if (!n) { return 0; } - n += strspn(n, " \t") + 1; + n += strspn(n + 1, " \t") + 1; if (*n == '"') { ++n; - return magi_str_create_copy(n, n - strchr(n, '"')); + return magi_str_create_copy(n, strchr(n, '"') - n); } else { return magi_str_create_copy(n, strcspn(n, " \t")); } @@ -78,10 +78,10 @@ static int content_disposition(automata *a) if (!n) { return 0; } - n += strspn(n, " \t") + 1; + n += strspn(n + 1, " \t") + 1; if (*n == '"') { ++n; - a->param.name = magi_str_create_copy(n, n - strchr(n, '"')); + a->param.name = magi_str_create_copy(n, strchr(n, '"') - n); if (!a->param.name || !*a->param.name) { return 0; } diff --git a/src/param.c b/src/param.c index 9c94555..dcf33d4 100644 --- a/src/param.c +++ b/src/param.c @@ -28,7 +28,7 @@ void magi_params_set(magi_params **params, magi_param *newitem) } } -char *magi_params_get(magi_params *params, const char *name) +char *magi_params_get(const magi_params *params, const char *name) { if (!params || !name) { return 0; diff --git a/src/request.c b/src/request.c index ce0f84f..d80bf20 100644 --- a/src/request.c +++ b/src/request.c @@ -69,12 +69,12 @@ void magi_request_free(magi_request *request) } -char *magi_request_meta(magi_request *r, const char *name) +char *magi_request_meta(const magi_request *r, const char *name) { return magi_params_get(r->meta, name); } -char *magi_request_param(magi_request *r, const char *name) +char *magi_request_param(const magi_request *r, const char *name) { char *res = magi_params_get(r->body, name); if (!res) { @@ -83,26 +83,27 @@ char *magi_request_param(magi_request *r, const char *name) return res; } -char *magi_request_urlparam(magi_request *r, const char *name) +char *magi_request_urlparam(const magi_request *r, const char *name) { return magi_params_get(r->head, name); } -magi_file *magi_request_file(magi_request *r, const char *name) +const magi_file *magi_request_file(const magi_request *r, const char *name) { return magi_files_get(r->files, name); } -char *magi_request_cookie(magi_request *r, const char *name) +char *magi_request_cookie(const magi_request *r, const char *name) { - magi_cookie *res = magi_cookies_get(r->cookies, name); + const magi_cookie *res = magi_cookies_get(r->cookies, name); if (!res) { return 0; } return res->data; } -magi_cookie *magi_request_cookie_complex(magi_request *r, const char *name) +const magi_cookie *magi_request_cookie_complex(const magi_request *r, + const char *name) { return magi_cookies_get(r->cookies, name); } diff --git a/src/session.c b/src/session.c new file mode 100644 index 0000000..35e9200 --- /dev/null +++ b/src/session.c @@ -0,0 +1,40 @@ +#include "session.h" + +#include <arpa/inet.h> +#include <string.h> +#include <sys/socket.h> +#include <sys/un.h> + + +void magi_session_init(magi_session *s) +{ + s->socket = 0; +} + +void magi_session_free(magi_session *s) +{ + if (s->socket) { + shutdown(s->socket, SHUT_RDWR); + s->socket = 0; + } +} + + +int magi_session_inet(magi_session *s, const char *address, int port) +{ + struct sockaddr_in addr; + s->socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = inet_addr(address); + return !connect(s->socket, (struct sockaddr *)&addr, sizeof(addr)); +} + +int magi_session_unix(magi_session *s, const char *path) +{ + struct sockaddr_un addr; + s->socket = socket(AF_UNIX, SOCK_STREAM, IPPROTO_TCP); + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1); + return !connect(s->socket, (struct sockaddr *)&addr, sizeof(addr)); +} |