FLAGS = PWD=$(PWD) PLATFORM=$(PLATFORM) PREFIX=$(PREFIX)
-.PHONY: all format clean ./Server ./Common ./Module ./Manpage get-version
+.PHONY: all format clean ./Server ./Common ./Module get-version
all: ./Server ./Module ./Manpage ./Tool/genconf ./Tool/itworks
./Common::
$(MAKE) -C $@ $(FLAGS)
-./Manpage::
- $(MAKE) -C $@ $(FLAGS)
-
-./README: ./README.tmpl
+./README: ./README.tmpl ./Server/tw_version.h
sed "s/@VERSION@/`grep "define TW_VERSION" Server/tw_version.h | grep -Eo '"[^\]+' | sed -E 's/^"//g'`/g" ./README.tmpl > $@
install: all ./Tool/genconf ./Tool/itworks
if [ ! -e $(PREFIX)/www/pbtewi.gif ]; then ( cp Binary/pbtewi.gif $(PREFIX)/www/ || ( rm $(PREFIX)/www/pbtewi.gif ; exit 1 ) ) ; fi
cp ./Server/tewi $(PREFIX)/bin/
cp ./Module/*.so $(PREFIX)/lib/tewi/
- cp ./Manpage/tewi.8 $(PREFIX)/share/man/man8/
format:
clang-format --verbose -i `find ./Server ./Common ./Module ./Tool "(" -name "*.c" -or -name "*.h" ")" -and -not -name "strptime.*"` config.h
$(MAKE) -C ./Server $(FLAGS) clean
$(MAKE) -C ./Module $(FLAGS) clean
$(MAKE) -C ./Common $(FLAGS) clean
- $(MAKE) -C ./Manpage $(FLAGS) clean
rm -f ./Tool/option ./Tool/genconf
+++ /dev/null
-# $Id$
-
-.PHONY: all clean
-
-all: tewi.8
-
-tewi.8: tewi.8.tmpl
- sed "s%@PREFIX@%$(PREFIX)%g" tewi.8.tmpl > $@ || rm -f $@
-
-clean:
- rm -f tewi.8
+++ /dev/null
-\" $Id$
-.Dd 2024 Sep 16th
-.Dt TEWI 8
-.Os
-.Sh NAME
-.Nm tewi ,
-.Nm tewi.conf
-.Nd Tewi HTTPd
-.Sh DESCRIPTION
-.Nm
-is a simple public domain HTTP daemon written in C.
-.Sh CONFIGURATION
-.Ss "General settings"
-.Bl -tag -width 20 -compact
-.It Pa "Listen"
-Specifies the port(s) to be listened on.
-.It Pa "ServerRoot"
-Specifies the server root.
-.It Pa "ServerAdmin"
-Specifies the server admin.
-.It Pa "DocumentRoot"
-Specifies the document root.
-.It Pa "LoadModule"
-Loads the module.
-.It Pa "HidePort" "ShowPort"
-Shows/Hides the port in directory listing, and the default error page.
-.It Pa "MIMEType"
-Specifies the MIME type for files.
-\fBall\fR can be used instead of the extension if you want to make all extensions appear as same MIME.
-Later rules will override the MIME.
-
-Example:
-
-.Vb 1
-\& MIMEType all application/octet-stream
-
-\& MIMEType .html text/html
-.Ve
-
-.It Pa "BeginVirtualHost"
-Begins the virtual host section.
-.It Pa "EndVirtualHost"
-Ends the virtual host section.
-.El
-.Ss "TLS/SSL settings"
-.Bl -tag -width 20 -compact
-.It Pa "ListenSSL"
-Specifies the port(s) to be listened on, but with TLS/SSL.
-.It Pa "SSLKey"
-Specifies the TLS/SSL private key.
-This works in the virtual host section too, and can be used to switch key depending on the virtual host.
-.It Pa "SSLCertificate"
-Specifies the TLS/SSL certificate.
-This works in the virtual host section too, and can be used to switch certificate depending on the virtual host.
-.El
-.Ss "Access settings"
-.Bl -tag -width 20 -compact
-Default access is "Deny all".
-
-.It Pa "BeginDirectory"
-Begins the directory section.
-.It Pa "EndDirectory"
-Ends the directory section.
-.It Pa "Allow"
-Allows the connection. Only works with \fBall\fR for now.
-Will not work outside of the directory section.
-.It Pa "Deny"
-Denies the connection. Only works with \fBall\fR for now.
-Will not work outside of the directory section.
-.El
-.Ss "Directory settings"
-.Bl -tag -width 20 -compact
-.It Pa "DirectoryIndex"
-Specifies the directory index.
-.It Pa "Readme"
-Specifies the README file for directory listing.
-.It Pa "Icon"
-Sets the icon for the MIME type.
-\fBall\fR can be used instead of the MIME if you want to make all MIMEs appear as same icon.
-Later rules will override the icon.
-
-Example:
-
-.Vb 1
-\& Icon all /icons/unknown.png
-
-\& Icon text/* /icons/text.png
-.Ve
-.El
-.Sh FILES
-.Bl -tag -width @PREFIX@/etc/tewi.conf -compact
-.It Pa @PREFIX@/etc/tewi.conf
-Default path for the config
-.El
-.Sh AUTHORS
-.An Nishi Aq Mt nishi@nishi.boats
-Tewi HTTPd version 1.06C
+Tewi HTTPd version 1.07
Original by Nishi <nishi@nishi.boats>
config.ports[i] = -1;
}
for(i = 0; i < MAX_VHOSTS; i++) {
+#ifndef NO_SSL
config.vhosts[i].sslkey = NULL;
config.vhosts[i].sslcert = NULL;
+#endif
config.vhosts[i].root = NULL;
+#ifdef HAS_CHROOT
+ config.vhosts[i].chroot_path = NULL;
+#endif
}
+#ifndef NO_SSL
config.root.sslkey = NULL;
config.root.sslcert = NULL;
+#endif
config.root.root = NULL;
config.root.mime_count = 0;
config.root.dir_count = 0;
config.root.index_count = 0;
config.root.readme_count = 0;
config.root.hideport = 0;
+#ifdef HAS_CHROOT
+ config.root.chroot_path = NULL;
+#endif
config.vhost_count = 0;
config.module_count = 0;
config.extension = NULL;
config.server_root = cm_strdup(PREFIX);
config.server_admin = cm_strdup(SERVER_ADMIN);
+ config.defined[0] = NULL;
gethostname(config.hostname, 1024);
}
char cbuf[2];
cbuf[1] = 0;
int ln = 0;
+ int ifbr = 0;
+ int ignore = -1;
FILE* f = fopen(path, "r");
if(f != NULL) {
char* line = malloc(1);
if(strlen(l) > 0 && l[0] != '#') {
char** r = cm_split(l, " \t");
int i;
- if(cm_strcaseequ(r[0], "Include") || cm_strcaseequ(r[0], "IncludeOptional")) {
+ if(ignore != -1 && ifbr >= ignore) {
+ if(cm_strcaseequ(r[0], "EndIf")) ifbr--;
+ if(ifbr == 0) {
+ ignore = -1;
+ }
+ } else if(cm_strcaseequ(r[0], "Include") || cm_strcaseequ(r[0], "IncludeOptional")) {
for(i = 1; r[i] != NULL; i++) {
if(tw_config_read(r[i]) != 0 && cm_strcaseequ(r[0], "Include")) {
stop = 1;
break;
}
}
+ } else if(cm_strcaseequ(r[0], "Define")) {
+ if(r[1] == NULL) {
+ cm_log("Config", "Missing name at line %d", ln);
+ stop = 1;
+ } else {
+ tw_add_define(r[1]);
+ }
+ } else if(cm_strcaseequ(r[0], "Undefine")) {
+ if(r[1] == NULL) {
+ cm_log("Config", "Missing name at line %d", ln);
+ stop = 1;
+ } else {
+ tw_delete_define(r[1]);
+ }
} else if(cm_strcaseequ(r[0], "BeginDirectory")) {
if(dir != NULL) {
cm_log("Config", "Already in directory section at line %d", ln);
current->hideport = 1;
} else if(cm_strcaseequ(r[0], "ShowPort")) {
current->hideport = 0;
+#ifndef NO_SSL
} else if(cm_strcaseequ(r[0], "SSLKey")) {
if(r[1] == NULL) {
cm_log("Config", "Missing path at line %d", ln);
if(current->sslcert != NULL) free(current->sslcert);
current->sslcert = cm_strdup(r[1]);
}
+#endif
+ } else if(cm_strcaseequ(r[0], "ForceLog")) {
+ if(r[1] == NULL) {
+ cm_log("Config", "Missing log at line %d", ln);
+ stop = 1;
+ } else {
+ cm_force_log(r[1]);
+ }
+ } else if(cm_strcaseequ(r[0], "EndIf")) {
+ if(ifbr == 0) {
+ cm_log("Config", "Missing BeginIf at line %d", ln);
+ stop = 1;
+ }
+ ifbr--;
+ } else if(cm_strcaseequ(r[0], "BeginIf") || cm_strcaseequ(r[0], "BeginIfNot")) {
+ if(r[1] == NULL) {
+ cm_log("Config", "Missing condition type at line %d", ln);
+ } else {
+ ifbr++;
+ bool ign = false;
+ if(cm_strcaseequ(r[1], "False")) {
+ ign = true;
+ } else if(cm_strcaseequ(r[1], "True")) {
+ } else if(cm_strcaseequ(r[1], "Defined")) {
+ if(r[2] == NULL) {
+ cm_log("Config", "Missing name at line %d", ln);
+ stop = 1;
+ } else {
+ int i;
+ bool fndit = false;
+ for(i = 0; config.defined[i] != NULL; i++) {
+ if(strcmp(config.defined[i], r[2]) == 0) {
+ fndit = true;
+ break;
+ }
+ }
+ if(!fndit) {
+ ign = true;
+ }
+ }
+ } else {
+ cm_log("Config", "Unknown condition type at line %d", ln);
+ stop = 1;
+ }
+ if(cm_strcaseequ(r[0], "BeginIfNot")) ign = !ign;
+ if(ign) {
+ ignore = ifbr - 1;
+ }
+ }
} else if(cm_strcaseequ(r[0], "ServerRoot")) {
if(r[1] == NULL) {
cm_log("Config", "Missing path at line %d", ln);
#include <cm_string.h>
#include <cm_log.h>
+#include <string.h>
#include <unistd.h>
#include <stdlib.h>
}
}
+void tw_add_define(const char* string) {
+ int i;
+ for(i = 0; config.defined[i] != NULL; i++)
+ ;
+ config.defined[i] = cm_strdup(string);
+ config.defined[i + 1] = NULL;
+}
+
+void tw_delete_define(const char* string) {
+ int i;
+ for(i = 0; config.defined[i] != NULL; i++) {
+ if(strcmp(config.defined[i], string) == 0) {
+ free(config.defined[i]);
+ for(; config.defined[i] != NULL; i++) {
+ config.defined[i] = config.defined[i + 1];
+ }
+ }
+ }
+}
+
void tw_init_tools(struct tw_tool* tools) {
tools->log = cm_log;
tools->add_version = tw_add_version;
+ tools->add_define = tw_add_define;
}
int tw_module_init(void* mod) {
extern "C" {
#endif
+#include "../config.h"
+
#include "tw_http.h"
#include <stdint.h>
struct tw_config_entry {
char* name;
int port;
+#ifndef NO_SSL
char* sslkey;
char* sslcert;
+#endif
char* root;
int hideport;
struct tw_dir_entry dirs[MAX_DIRS];
int index_count;
char* readmes[MAX_README];
int readme_count;
+#ifdef HAS_CHROOT
+ char* chroot_path;
+#endif
};
struct tw_config {
uint64_t ports[MAX_PORTS + 1]; /* If port & (1 << 32) is non-zero, it is SSL */
char hostname[1025];
+ char* defined[1025];
struct tw_config_entry root;
struct tw_config_entry vhosts[MAX_VHOSTS];
void* modules[MAX_MODULES];
struct tw_tool {
void (*log)(const char* name, const char* log, ...);
void (*add_version)(const char* string);
+ void (*add_define)(const char* string);
+ void (*delete_define)(const char* string);
};
enum TW_MODULE_RETURN {
void* tw_module_symbol(void* mod, const char* sym);
void tw_init_tools(struct tw_tool* tools);
int tw_module_init(void* mod);
+
+void tw_add_version(const char* string);
+void tw_add_define(const char* string);
+void tw_delete_define(const char* string);
#endif
#ifdef __cplusplus
extern "C" {
#endif
-#define TW_VERSION "1.06C\0"
+#define TW_VERSION "1.07\0"
const char* tw_get_version(void);
const char* tw_get_platform(void);
#undef NO_SSL
#define USE_POLL
+#define HAS_CHROOT
/* DO NOT EDIT BELOW THIS LINE */
/* Force select(2) for Windows */
#endif
+#if defined(__MINGW32__) && defined(HAS_CHROOT)
+#undef HAS_CHROOT
+/* Windows should not have chroot */
+#endif
+
#endif
/*
ServerRoot /home/nishi/SVN/tewi/trunk
#LoadModule Module/mod_cgi.so
-LoadModule Module/mod_proxy.so
+#LoadModule Module/mod_proxy.so
Listen 80
ListenSSL 443
DocumentRoot /var/www
-#ProxyPass
+Define test
+Undefine test
+
+BeginIf Defined test
+ ForceLog "defined"
+EndIf
+BeginIfNot Defined test
+ ForceLog "not defined"
+EndIf