diff --git a/a/.gitignore b/a/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..567609b1234a9b8806c5a05da6c866e480aa148d --- /dev/null +++ b/a/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/a/CMakeLists.txt b/a/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..85ad5351dbe8971feb8b05dbb28869ffe8e62545 --- /dev/null +++ b/a/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.16) + +add_definitions(-D_GNU_SOURCE) + +add_executable(conf_demo + main.c + conf.c + parse_args.c + read_conf.c +) diff --git a/a/conf.c b/a/conf.c new file mode 100644 index 0000000000000000000000000000000000000000..457394f59cb4fcfb42896c332ded07b7dca7f42b --- /dev/null +++ b/a/conf.c @@ -0,0 +1,67 @@ +#include "conf.h" +#include +#include +#include + +conf_opts *Config = NULL; + +conf_opts *create_conf() { + conf_opts *ret = malloc(sizeof(conf_opts)); + // set default config here + set_config(ret, CONF_CGI_ROOT, "/usr/local/var/www/cgi-bin"); + set_config(ret, CONF_DEFAULT_FILE, "*"); + set_config(ret, CONF_DOCUMENT_ROOT, "/usr/local/var/www"); + set_config(ret, CONF_CONFIG_FILE, "/etc/SHTTPD.conf"); + set_config(ret, CONF_LISTEN_PORT, "8080"); + set_config(ret, CONF_MAX_CLIENT, "4"); + set_config(ret, CONF_TIMEOUT, "3"); + return ret; +} + +void set_config(conf_opts *conf, conf_type key, const char *value) { + switch (key) { + case CONF_CGI_ROOT: + free(conf->cgi_root); + conf->cgi_root = strdup(value); + break; + case CONF_DEFAULT_FILE: + free(conf->default_file); + conf->default_file = strdup(value); + break; + case CONF_DOCUMENT_ROOT: + free(conf->document_root); + conf->document_root = strdup(value); + break; + case CONF_CONFIG_FILE: + free(conf->config_file); + conf->config_file = strdup(value); + break; + case CONF_LISTEN_PORT: + conf->listen_port = atoi(value); + break; + case CONF_MAX_CLIENT: + conf->max_client = atoi(value); + break; + case CONF_TIMEOUT: + conf->timeout = atoi(value); + break; + } +} + +void print_config(conf_opts *conf) { + printf("CGIRoot=%s\n", conf->cgi_root); + printf("DefaultFile=%s\n", conf->default_file); + printf("ConfigFile=%s\n", conf->config_file); + printf("DocumentRoot=%s\n", conf->document_root); + printf("ListenPort=%d\n", conf->listen_port); + printf("MaxClient=%d\n", conf->max_client); + printf("TimeOut=%d\n", conf->timeout); +} + +void free_conf(conf_opts *conf) { + free(conf->config_file); + free(conf->cgi_root); + free(conf->default_file); + free(conf->document_root); + free(conf); +} diff --git a/a/conf.h b/a/conf.h new file mode 100644 index 0000000000000000000000000000000000000000..598a887a8a3056e6b84a1a690f63634124f7c2c5 --- /dev/null +++ b/a/conf.h @@ -0,0 +1,30 @@ +#pragma once + +struct conf_opts { + char *cgi_root; + char *default_file; + char *document_root; + char *config_file; + int listen_port; + int max_client; + int timeout; +}; + +typedef struct conf_opts conf_opts; + +typedef enum { + CONF_CGI_ROOT, + CONF_DEFAULT_FILE, + CONF_DOCUMENT_ROOT, + CONF_CONFIG_FILE, + CONF_LISTEN_PORT, + CONF_MAX_CLIENT, + CONF_TIMEOUT, +} conf_type; + +conf_opts *create_conf(); +void set_config(conf_opts *conf, conf_type key, const char *value); +void print_config(conf_opts *conf); +void free_conf(conf_opts *conf); + +extern conf_opts *Config; diff --git a/a/main.c b/a/main.c index 6c0e70db03a6e45bca365cb8681e801b2c8318ec..f0b47591ddd98d7c874146d9ebef1a6d8ca322be 100644 --- a/a/main.c +++ b/a/main.c @@ -1,6 +1,23 @@ +#include "conf.h" #include #include +extern void read_conf(const char *conf_file); +extern void parse_arg(int argc, char **argv); + int main(int argc, char **argv) { + Config = create_conf(); + print_config(Config); + + static const char *conf_file = "./conf.ini"; + printf("\nRead Config from %s\n\n", conf_file); + read_conf(conf_file); + print_config(Config); + + puts("\nParsing args\n"); + parse_arg(argc, argv); + print_config(Config); + + free_conf(Config); return 0; } diff --git a/a/parse_args.c b/a/parse_args.c new file mode 100644 index 0000000000000000000000000000000000000000..bd148f2e92b02bd68209ea01072e8a9220d2e009 --- /dev/null +++ b/a/parse_args.c @@ -0,0 +1,69 @@ +#include +#include + +#include "conf.h" + +static const char *help_msg = "This is help message."; + +void parse_arg(int argc, char **argv) { + int c; + int digit_optind = 0; + + while (1) { + int this_option_optind = optind ? optind : 1; + int option_index = 0; + static struct option long_options[] = { + {"CGIRoot", required_argument, NULL, 'c'}, + {"DefaultFile", required_argument, NULL, 'd'}, + {"ConfigFile", required_argument, NULL, 'f'}, + {"DocumentRoot", required_argument, NULL, 'o'}, + {"ListenPort", required_argument, NULL, 'l'}, + {"MaxClient", required_argument, NULL, 'm'}, + {"TimeOut", required_argument, NULL, 't'}, + {"Help", no_argument, NULL, 'h'}, + {0, 0, 0, 0}}; + + c = getopt_long(argc, argv, "c:d:f:o:l:m:t:h", long_options, &option_index); + if (c == -1) break; + + switch (c) { + case 'c': + set_config(Config, CONF_CGI_ROOT, optarg); + break; + + case 'd': + set_config(Config, CONF_DEFAULT_FILE, optarg); + break; + + case 'f': + set_config(Config, CONF_CONFIG_FILE, optarg); + break; + + case 'o': + set_config(Config, CONF_DOCUMENT_ROOT, optarg); + break; + + case 'l': + set_config(Config, CONF_LISTEN_PORT, optarg); + break; + + case 'm': + set_config(Config, CONF_MAX_CLIENT, optarg); + break; + + case 't': + set_config(Config, CONF_TIMEOUT, optarg); + break; + + case 'h': + puts(help_msg); + break; + + case '?': + break; + + default: + printf("?? getopt returned character code 0%o ??\n", c); + } + } +} diff --git a/a/read_conf.c b/a/read_conf.c new file mode 100644 index 0000000000000000000000000000000000000000..c34275dfa844cff1e00f9557d8a7e6a08de6127b --- /dev/null +++ b/a/read_conf.c @@ -0,0 +1,56 @@ +#include "conf.h" +#include +#include +#include + +void read_conf(const char *conf_file) { + char *line = NULL; + size_t length; + FILE *f = fopen(conf_file, "r"); + if (!f) return; + + while (1) { + int l = getline(&line, &length, f); + if (l <= 0) { + free(line); + break; + } + + if (line[0] == '#') { + free(line); + continue; + } + + char *p = NULL; + line[strlen(line) - 1] = 0; + + for (int i = 0; i < strlen(line); i++) { + if (line[i] == '=') { + line[i] = 0; + p = line + i + 1; + break; + } + } + + if (p) { + if (!strcmp(line, "CGIRoot")) { + set_config(Config, CONF_CGI_ROOT, p); + } else if (!strcmp(line, "DefaultFile")) { + set_config(Config, CONF_DEFAULT_FILE, p); + } else if (!strcmp(line, "ConfigFile")) { + set_config(Config, CONF_CONFIG_FILE, p); + } else if (!strcmp(line, "DocumentRoot")) { + set_config(Config, CONF_DOCUMENT_ROOT, p); + } else if (!strcmp(line, "ListenPort")) { + set_config(Config, CONF_LISTEN_PORT, p); + } else if (!strcmp(line, "MaxClient")) { + set_config(Config, CONF_MAX_CLIENT, p); + } else if (!strcmp(line, "TimeOut")) { + set_config(Config, CONF_TIMEOUT, p); + } + } + + free(line); + line = NULL; + } +}