diff --git a/Makefile b/Makefile index 7fd3b64..ebc0392 100644 --- a/Makefile +++ b/Makefile @@ -219,19 +219,19 @@ distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print -ACLOCAL = ${SHELL} /home/ziggi/Projects/jcomp/missing aclocal +ACLOCAL = ${SHELL} /home/ziggi/Projects/cworker/missing aclocal AMTAR = $${TAR-tar} AM_DEFAULT_VERBOSITY = 1 -APP_CACHEDIR = /home/ziggi/Projects/jcomp/cache -APP_CONFIGDIR = /home/ziggi/Projects/jcomp/ -APP_DATABASEDIR = /home/ziggi/Projects/jcomp/data -APP_LIBDIR = /home/ziggi/Projects/jcomp/lib -APP_LOGDIR = /home/ziggi/Projects/jcomp/log -APP_RUNDIR = /home/ziggi/Projects/jcomp/run +APP_CACHEDIR = /home/ziggi/Projects/cworker/cache +APP_CONFIGDIR = /home/ziggi/Projects/cworker/ +APP_DATABASEDIR = /home/ziggi/Projects/cworker/data +APP_LIBDIR = /home/ziggi/Projects/cworker/lib +APP_LOGDIR = /home/ziggi/Projects/cworker/log +APP_RUNDIR = /home/ziggi/Projects/cworker/run APP_USER = ziggi -AUTOCONF = ${SHELL} /home/ziggi/Projects/jcomp/missing autoconf -AUTOHEADER = ${SHELL} /home/ziggi/Projects/jcomp/missing autoheader -AUTOMAKE = ${SHELL} /home/ziggi/Projects/jcomp/missing automake +AUTOCONF = ${SHELL} /home/ziggi/Projects/cworker/missing autoconf +AUTOHEADER = ${SHELL} /home/ziggi/Projects/cworker/missing autoheader +AUTOMAKE = ${SHELL} /home/ziggi/Projects/cworker/missing automake AWK = gawk CC = clang CCDEPMODE = depmode=none @@ -255,7 +255,7 @@ LDFLAGS = LIBOBJS = LIBS = LTLIBOBJS = -MAKEINFO = ${SHELL} /home/ziggi/Projects/jcomp/missing makeinfo +MAKEINFO = ${SHELL} /home/ziggi/Projects/cworker/missing makeinfo MKDIR_P = /usr/local/bin/gmkdir -p OBJEXT = o PACKAGE = cworker @@ -271,23 +271,23 @@ SHELL = /bin/sh STRIP = VALGRIND = /usr/local/bin/valgrind VERSION = 0.0.1 -abs_builddir = /home/ziggi/Projects/jcomp -abs_srcdir = /home/ziggi/Projects/jcomp -abs_top_builddir = /home/ziggi/Projects/jcomp -abs_top_srcdir = /home/ziggi/Projects/jcomp +abs_builddir = /home/ziggi/Projects/cworker +abs_srcdir = /home/ziggi/Projects/cworker +abs_top_builddir = /home/ziggi/Projects/cworker +abs_top_srcdir = /home/ziggi/Projects/cworker ac_ct_CC = clang am__include = include am__leading_dot = . am__quote = am__tar = $${TAR-tar} chof - "$$tardir" am__untar = $${TAR-tar} xf - -app_cachedir = /home/ziggi/Projects/jcomp/cache -app_configdir = /home/ziggi/Projects/jcomp/ -app_databasedir = /home/ziggi/Projects/jcomp/data -app_libdir = /home/ziggi/Projects/jcomp/lib -app_logdir = /home/ziggi/Projects/jcomp/log +app_cachedir = /home/ziggi/Projects/cworker/cache +app_configdir = /home/ziggi/Projects/cworker/ +app_databasedir = /home/ziggi/Projects/cworker/data +app_libdir = /home/ziggi/Projects/cworker/lib +app_logdir = /home/ziggi/Projects/cworker/log app_name = cworker -app_rundir = /home/ziggi/Projects/jcomp/run +app_rundir = /home/ziggi/Projects/cworker/run app_user = ziggi bindir = ${exec_prefix}/bin build = amd64-unknown-freebsd12.4 @@ -309,7 +309,7 @@ host_vendor = unknown htmldir = ${docdir} includedir = ${prefix}/include infodir = ${datarootdir}/info -install_sh = ${SHELL} /home/ziggi/Projects/jcomp/install-sh +install_sh = ${SHELL} /home/ziggi/Projects/cworker/install-sh libdir = ${exec_prefix}/lib libexecdir = ${exec_prefix}/libexec localedir = ${datarootdir}/locale @@ -895,6 +895,7 @@ valgrind: $(bin_TESTS) clean-local: rm -rf autom4te.cache rm -rf *~ + rm -rf run log #install-data-local: # test -z $(DESTDIR)$(APP_LIBDIR) || $(MKDIR_P) $(DESTDIR)$(APP_LIBDIR) diff --git a/Makefile.in b/Makefile.in index 002dedd..c2a8d48 100644 --- a/Makefile.in +++ b/Makefile.in @@ -895,6 +895,7 @@ valgrind: $(bin_TESTS) clean-local: rm -rf autom4te.cache rm -rf *~ + rm -rf run log #install-data-local: # test -z $(DESTDIR)$(APP_LIBDIR) || $(MKDIR_P) $(DESTDIR)$(APP_LIBDIR) diff --git a/cflexer.c b/cflexer.c index 65d5f79..b1385df 100644 --- a/cflexer.c +++ b/cflexer.c @@ -11,6 +11,16 @@ #include +#define CFLEXCONT_COMM 1 +#define CFLEXCONT_END 2 +#define CFLEXCONT_LWORD 3 +#define CFLEXCONT_SEPAR 4 +#define CFLEXCONT_SPACE 5 +#define CFLEXCONT_UNDEF 6 +#define CFLEXCONT_UNKNOW 7 +#define CFLEXCONT_WORD 8 +#define CFLEXCONT_NEWLN 9 + #define CFLEXTYPE_CHAR 1 #define CFLEXTYPE_COMM 2 #define CFLEXTYPE_EOF 3 diff --git a/cflexer.h b/cflexer.h index ace04ab..7705b30 100644 --- a/cflexer.h +++ b/cflexer.h @@ -16,17 +16,6 @@ typedef struct { } cflexer_t; -#define CFLEXCONT_COMM 1 -#define CFLEXCONT_END 2 -#define CFLEXCONT_LWORD 3 -#define CFLEXCONT_SEPAR 4 -#define CFLEXCONT_SPACE 5 -#define CFLEXCONT_UNDEF 6 -#define CFLEXCONT_UNKNOW 7 -#define CFLEXCONT_WORD 8 -#define CFLEXCONT_NEWLN 9 - - #define CFLEXTOK_BLOCKB 1 #define CFLEXTOK_COMM 2 #define CFLEXTOK_END 3 diff --git a/cllexer.c b/cllexer.c index 53e10f8..d0a0959 100644 --- a/cllexer.c +++ b/cllexer.c @@ -9,6 +9,14 @@ #include +#define CLLEXCONT_UNDEF 0 +#define CLLEXCONT_KEY 1 +#define CLLEXCONT_WORD 2 +#define CLLEXCONT_SPACE 3 +#define CLLEXCONT_SEP 4 +#define CLLEXCONT_END 5 +#define CLLEXCONT_LWORD 6 + #define CLLEXTYPE_UNDEF 0 #define CLLEXTYPE_KEY 1 #define CLLEXTYPE_CHAR 2 diff --git a/cllexer.h b/cllexer.h index 01ba077..d8b1723 100644 --- a/cllexer.h +++ b/cllexer.h @@ -15,13 +15,6 @@ typedef struct { bool screen; } cllexer_t; -#define CLLEXCONT_UNDEF 0 -#define CLLEXCONT_KEY 1 -#define CLLEXCONT_WORD 2 -#define CLLEXCONT_SPACE 3 -#define CLLEXCONT_SEP 4 -#define CLLEXCONT_END 5 -#define CLLEXCONT_LWORD 6 #define CLLEXTOK_UNDEF 0 #define CLLEXTOK_KEY 1 diff --git a/config.h b/config.h index 4a4f9a1..135d01d 100644 --- a/config.h +++ b/config.h @@ -2,8 +2,8 @@ #ifndef CONFIG_H_QWER #define CONFIG_H_QWER -static const char *srv_runpath = "/home/ziggi/Projects/jcomp/run/cworker.pid"; -static const char *srv_logpath = "/home/ziggi/Projects/jcomp/log/cworker.log"; -static const char *srv_configpath = "/home/ziggi/Projects/jcomp//cworker.conf"; +static const char *srv_runpath = "/home/ziggi/Projects/cworker/run/cworker.pid"; +static const char *srv_logpath = "/home/ziggi/Projects/cworker/log/cworker.log"; +static const char *srv_configpath = "/home/ziggi/Projects/cworker//cworker.conf"; #endif diff --git a/config.status b/config.status index 4e767de..fcd6f18 100755 --- a/config.status +++ b/config.status @@ -430,7 +430,7 @@ Copyright (C) 2021 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." -ac_pwd='/home/ziggi/Projects/jcomp' +ac_pwd='/home/ziggi/Projects/cworker' srcdir='.' INSTALL='/usr/bin/install -c' MKDIR_P='/usr/local/bin/gmkdir -p' @@ -612,20 +612,20 @@ S["am__EXEEXT_FALSE"]="" S["am__EXEEXT_TRUE"]="#" S["LTLIBOBJS"]="" S["app_name"]="cworker" -S["app_cachedir"]="/home/ziggi/Projects/jcomp/cache" -S["APP_CACHEDIR"]="/home/ziggi/Projects/jcomp/cache" -S["app_databasedir"]="/home/ziggi/Projects/jcomp/data" -S["APP_DATABASEDIR"]="/home/ziggi/Projects/jcomp/data" +S["app_cachedir"]="/home/ziggi/Projects/cworker/cache" +S["APP_CACHEDIR"]="/home/ziggi/Projects/cworker/cache" +S["app_databasedir"]="/home/ziggi/Projects/cworker/data" +S["APP_DATABASEDIR"]="/home/ziggi/Projects/cworker/data" S["app_user"]="ziggi" S["APP_USER"]="ziggi" -S["app_libdir"]="/home/ziggi/Projects/jcomp/lib" -S["APP_LIBDIR"]="/home/ziggi/Projects/jcomp/lib" -S["app_rundir"]="/home/ziggi/Projects/jcomp/run" -S["APP_RUNDIR"]="/home/ziggi/Projects/jcomp/run" -S["app_logdir"]="/home/ziggi/Projects/jcomp/log" -S["APP_LOGDIR"]="/home/ziggi/Projects/jcomp/log" -S["app_configdir"]="/home/ziggi/Projects/jcomp/" -S["APP_CONFIGDIR"]="/home/ziggi/Projects/jcomp/" +S["app_libdir"]="/home/ziggi/Projects/cworker/lib" +S["APP_LIBDIR"]="/home/ziggi/Projects/cworker/lib" +S["app_rundir"]="/home/ziggi/Projects/cworker/run" +S["APP_RUNDIR"]="/home/ziggi/Projects/cworker/run" +S["app_logdir"]="/home/ziggi/Projects/cworker/log" +S["APP_LOGDIR"]="/home/ziggi/Projects/cworker/log" +S["app_configdir"]="/home/ziggi/Projects/cworker/" +S["APP_CONFIGDIR"]="/home/ziggi/Projects/cworker/" S["SYSTEMD_FALSE"]="" S["SYSTEMD_TRUE"]="#" S["LINUX_OS_FALSE"]="" @@ -676,12 +676,12 @@ S["mkdir_p"]="$(MKDIR_P)" S["MKDIR_P"]="/usr/local/bin/gmkdir -p" S["INSTALL_STRIP_PROGRAM"]="$(install_sh) -c -s" S["STRIP"]="" -S["install_sh"]="${SHELL} /home/ziggi/Projects/jcomp/install-sh" -S["MAKEINFO"]="${SHELL} /home/ziggi/Projects/jcomp/missing makeinfo" -S["AUTOHEADER"]="${SHELL} /home/ziggi/Projects/jcomp/missing autoheader" -S["AUTOMAKE"]="${SHELL} /home/ziggi/Projects/jcomp/missing automake" -S["AUTOCONF"]="${SHELL} /home/ziggi/Projects/jcomp/missing autoconf" -S["ACLOCAL"]="${SHELL} /home/ziggi/Projects/jcomp/missing aclocal" +S["install_sh"]="${SHELL} /home/ziggi/Projects/cworker/install-sh" +S["MAKEINFO"]="${SHELL} /home/ziggi/Projects/cworker/missing makeinfo" +S["AUTOHEADER"]="${SHELL} /home/ziggi/Projects/cworker/missing autoheader" +S["AUTOMAKE"]="${SHELL} /home/ziggi/Projects/cworker/missing automake" +S["AUTOCONF"]="${SHELL} /home/ziggi/Projects/cworker/missing autoconf" +S["ACLOCAL"]="${SHELL} /home/ziggi/Projects/cworker/missing aclocal" S["VERSION"]="0.0.1" S["PACKAGE"]="cworker" S["CYGPATH_W"]="echo" @@ -813,13 +813,13 @@ D["HAVE_MEMSET"]=" 1" D["HAVE_MKDIR"]=" 1" D["HAVE_SETLOCALE"]=" 1" D["HAVE_SOCKET"]=" 1" -D["APP_CONFIGDIR"]=" \"/home/ziggi/Projects/jcomp/\"" -D["APP_LOGDIR"]=" \"/home/ziggi/Projects/jcomp/log\"" -D["APP_RUNDIR"]=" \"/home/ziggi/Projects/jcomp/run\"" -D["APP_LIBDIR"]=" \"/home/ziggi/Projects/jcomp/lib\"" +D["APP_CONFIGDIR"]=" \"/home/ziggi/Projects/cworker/\"" +D["APP_LOGDIR"]=" \"/home/ziggi/Projects/cworker/log\"" +D["APP_RUNDIR"]=" \"/home/ziggi/Projects/cworker/run\"" +D["APP_LIBDIR"]=" \"/home/ziggi/Projects/cworker/lib\"" D["APP_USER"]=" \"ziggi\"" -D["APP_DATABASEDIR"]=" \"/home/ziggi/Projects/jcomp/data\"" -D["APP_CACHEDIR"]=" \"/home/ziggi/Projects/jcomp/cache\"" +D["APP_DATABASEDIR"]=" \"/home/ziggi/Projects/cworker/data\"" +D["APP_CACHEDIR"]=" \"/home/ziggi/Projects/cworker/cache\"" for (key in D) D_is_set[key] = 1 FS = "" } diff --git a/cworker.c b/cworker.c index 5e8ee27..8e8938d 100644 --- a/cworker.c +++ b/cworker.c @@ -4,15 +4,26 @@ * */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include #include #include #include #include #include #include -#include -#include -#include +#include +#include +#include #include #include @@ -20,16 +31,312 @@ #include #include #include +#include +#include + #include #include #include -int log_fd = 0; +static const int64_t default_port = 9701; +static cworker_t* pworker = NULL; + +static int mkdirall(const char* path, mode_t mode); +void sighandler(int signum); + +static int cworker_readconf(const cworker_t* worker) { + log_debug("Configuration reading"); + + int conffd = -1; + if ((conffd = open(srv_configpath, O_RDONLY)) < 0) { + log_error("Configuration file opening error: %s %s", strerror(errno), srv_configpath); + return -1; + } + + rcache_t cache; + cflexer_t lexer; + cfparser_t parser; + + rcache_init(&cache, conffd); + cflexer_init(&lexer, &cache); + cfparser_init(&parser, &lexer); + + if (cfparser_parse(&parser) < 0) { + log_error("Configuration parsing error"); + return -1; + } + + cfparser_bind(&parser, CFVALTYPE_INT, "port", (void *)&(worker->port)); + cfparser_bind(&parser, CFVALTYPE_BOOL, "nofork", (void *)&(worker->nofork)); + + cfparser_destroy(&parser); + cflexer_destroy(&lexer); + rcache_destroy(&cache); + + return 0; +} + +static int cworker_readopts(const cworker_t* worker, char** argv, int argc) { + log_debug("Reading options"); + + cllexer_t lexer; + clparser_t parser; + + cllexer_init(&lexer); + clparser_init(&parser, &lexer); + + clparser_bind(&parser, CLVALTYPE_INT, "port", (void *)&(worker->port)); + clparser_bind(&parser, CLVALTYPE_BOOL, "nofork", (void *)&(worker->nofork)); + + if (clparser_parse(&parser, &argv[1], argc - 1) < 0) { + log_error("Args parsing error"); + return -1; + } + + return 0; +} + +static int cworker_openlog(cworker_t* worker) { + if (!worker->nofork) { + log_debug("Redirect output"); + if (mkdirall(srv_logpath, S_IRWXU|S_IRGRP|S_IXGRP) < 0) { + log_error("Log dir creating error: %s %s", strerror(errno), srv_logpath); + } + + if ((worker->logfd = open(srv_logpath, O_WRONLY|O_APPEND|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP)) < 0) { + log_error("Log file opening error: %s %s", strerror(errno), srv_logpath); + return -1; + } + dup2(worker->logfd, STDOUT_FILENO); + dup2(worker->logfd, STDERR_FILENO); + } + return 0; +} + +int cworker_writepid(const cworker_t* worker) { + if (!worker->nofork) { + + log_debug("Write pid file"); + + if (mkdirall(srv_runpath, S_IRWXU|S_IRGRP|S_IXGRP) < 0) { + log_error("Run directory creating error: %s %s", strerror(errno), srv_runpath); + } + + int pid_fd = -1; + if ((pid_fd = open(srv_runpath, O_WRONLY|O_TRUNC|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP)) < 0) { + log_error("Process ID file opening error: %s %s", strerror(errno), srv_runpath); + return -1; + } + if (dprintf(pid_fd, "%d", getpid()) < 0) { + log_error("Process ID file writing error: %s %s", strerror(errno), srv_runpath); + close(pid_fd); + return -1; + } + close(pid_fd); + } + return 0; +} + + +int cworker_init(cworker_t* worker, char** argv, int argc) { + log_init(); + + log_debug("Init service"); + worker->port = default_port; + worker->nofork = true; + worker->socket = 0; + worker->logfd = 0; + pworker = worker; + + if (cworker_readconf(worker) < 0) { + log_error("Config reading error"); + return -1; + } + if (cworker_readopts(worker, argv, argc) < 0) { + log_error("Options reading error"); + return -1; + } + if (!worker->nofork) { + if (cworker_openlog(worker) < 0) { + log_error("Log opening error"); + return -1; + } + } + log_debug("Listening port: %d", worker->port); + + return 0; +} + +int cworker_detach(const cworker_t* worker) { + if (!worker->nofork) { + log_debug("Service detaching"); + int childpid = -1; + if((childpid = fork()) < 0) { + log_error("Fork error %d: %s ", errno, strerror(errno)); + return -1; + } + if (childpid == 0) { + log_debug("Service forked"); + return 0; + // child + } else { + // parent + exit(0); + } + } + return 0; +} + +int cworker_build(cworker_t* worker) { + log_debug("Service building"); + + signal(SIGCHLD, SIG_IGN); + signal(SIGHUP, sighandler); + signal(SIGTERM, sighandler); + + if((worker->socket = socket(PF_INET, SOCK_STREAM, 0)) < 0) { + log_debug("Socket creating error %d: %s", errno, strerror(errno)); + return -1; + } + int optval = 1; + if (setsockopt(worker->socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0) { + log_debug("Socket option setting error %d: %s", errno, strerror(errno)); + return -1; + } + + struct sockaddr addr; + struct sockaddr_in* paddr = (struct sockaddr_in*)&addr; + paddr->sin_family = AF_INET; + paddr->sin_addr.s_addr = INADDR_ANY; + paddr->sin_port = htons(worker->port); + paddr->sin_len = sizeof(struct sockaddr_in); + + if (bind(worker->socket, (struct sockaddr*)paddr, paddr->sin_len) < 0) { + log_debug("Socket binding error %d: %s ", errno, strerror(errno)); + return -1; + } + int backlog = 100; + if (listen(worker->socket, backlog) < 0) { + log_debug("Socket listening error %d: %s ", errno, strerror(errno)); + return -1; + } + return 0; +} + +int cworker_handler(const cworker_t* worker, int socket); + +int cworker_run(const cworker_t* worker) { + log_debug("Service running"); + + while (1) { + int newsocket = 0; + if ((newsocket = accept(worker->socket, NULL, 0)) > 3) { + + int childpid = -1; + if((childpid = fork()) < 0) { + log_error("Fork error %d: %s ", errno, strerror(errno)); + continue; + } + if (childpid == 0) { + // child + log_debug("Service %d forked", getpid()); + signal(SIGHUP, SIG_IGN); + signal(SIGTERM, SIG_IGN); + + struct timeval tv = { .tv_sec = 5, .tv_usec = 0 }; + if (setsockopt(newsocket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval)) < 0) { + log_debug("Socket option setting error %d: %s ", errno, strerror(errno)); + return -1; + } + cworker_handler(worker, newsocket); + log_debug("Handler %d done", getpid()); + close(newsocket); + return 0; + } else { + // parent + close(newsocket); + } + } + } + close(worker->socket); + + return 0; +} + + +int cworker_handler(const cworker_t* worker, int socket) { + int err = 0; + + rcache_t cache; + jlexer_t lexer; + jparser_t parser; + + rcache_init(&cache, socket); + jlexer_init(&lexer, &cache); + jparser_init(&parser, &lexer); + + if (jparser_parse(&parser) < 0) { + log_error("Cannot parse json"); + err = -1; + goto exit; + } + + int64_t id = 0; + char* name = "none"; + + if (jparser_bind(&parser, JVALTYPE_NUM, "id", (void *)&id) < 0) { + log_error("Cannot bind id"); + } + if (jparser_bind(&parser, JVALTYPE_STR, "name", (void *)&name) < 0) { + log_error("Cannot bind name"); + } + dprintf(socket, "{}"); + + free(name); + exit: + jparser_destroy(&parser); + jlexer_destroy(&lexer); + rcache_destroy(&cache); + return err; +} + +void cworker_shutdown(cworker_t* worker) { + log_warning("Shutdown service %d", getpid()); + if (worker->socket != 0) { + close(worker->socket); + worker->logfd = 0; + } + if (worker->logfd != 0) { + close(worker->logfd); + worker->logfd = 0; + } + wait(NULL); + log_destroy(); +} + + +void sighandler(int signum) { + log_warning("Handle signal %d", signum); + if (signum == SIGHUP) { + log_warning("Handle HUP signal"); + } else if (signum == SIGTERM) { + log_warning("Handle TERM signal"); + if (pworker != NULL) { + cworker_shutdown(pworker); + sleep(1); + exit(0); + } + } +} + static int mkdirall(const char* path, mode_t mode) { - char buffer[1024]; + char buffer[PATH_MAX]; size_t psize = strlen(path); + if (psize > PATH_MAX) { + return -1; + } if (psize == 0) return 0; if (psize == 1 && path[0] == '/') { return 0; @@ -47,187 +354,3 @@ static int mkdirall(const char* path, mode_t mode) { } return 0; } - -char* path_last(const char* path) { - char buffer[1024]; - size_t psize = strlen(path); - strcpy(buffer, path); - buffer[psize] = '\0'; - if (buffer[psize - 1] == '/') { - buffer[--psize] = '\0'; - } - size_t pos = psize; - for (size_t i = 1; i < psize; i++) { - if (buffer[i] == '/') pos = i; - } - char* b = &buffer[++pos]; - int bsize = strlen(b); - char* res = malloc(bsize + 1); - strcpy(res, b); - //printf("\n%s\n", res); - return res; -} - -char* path_file(const char* path) { - char buffer[1024]; - size_t psize = strlen(path); - strcpy(buffer, path); - buffer[psize] = '\0'; - //if (buffer[psize - 1] == '/') { - // buffer[--psize] = '\0'; - //} - size_t pos = psize; - for (size_t i = 1; i < psize; i++) { - if (buffer[i] == '/') pos = i; - } - char* b = &buffer[++pos]; - int bsize = strlen(b); - char* res = malloc(bsize + 1); - strcpy(res, b); - //printf("\n%s\n", res); - return res; -} - - -static int cworker_readconf(const cworker_t* worker) { - log_debug("reading configiration"); - - int conf_fd = -1; - if ((conf_fd = open(srv_configpath, O_RDONLY)) < 0) { - log_error("cannot open config file %s", srv_configpath); - return -1; - } - - rcache_t cache; - cflexer_t lexer; - cfparser_t parser; - - rcache_init(&cache, conf_fd); - cflexer_init(&lexer, &cache); - cfparser_init(&parser, &lexer); - - if (cfparser_parse(&parser) < 0) { - log_error("parse config error\n"); - return -1; - } - - cfparser_bind(&parser, CFVALTYPE_INT, "port", (void *)&(worker->port)); - - cfparser_destroy(&parser); - cflexer_destroy(&lexer); - rcache_destroy(&cache); - - return 0; -} - -static int cworker_readopts(const cworker_t* worker, char** argv, int argc) { - log_debug("reading options"); - - cllexer_t lexer; - clparser_t parser; - - cllexer_init(&lexer); - clparser_init(&parser, &lexer); - - clparser_bind(&parser, CLVALTYPE_INT, "port", (void *)&(worker->port)); - - if (clparser_parse(&parser, &argv[1], argc - 1) < 0) { - log_error("parse args error"); - return -1; - } - - return 0; -} - -static int cworker_openlog(const cworker_t* worker) { - log_debug("redirect output"); - - if (mkdirall(srv_logpath, S_IRWXU|S_IRGRP|S_IXGRP) < 0) { - log_error("creating log dir error: %s %s", strerror(errno), srv_logpath); - } - - if ((log_fd = open(srv_logpath, O_WRONLY|O_APPEND|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP)) < 0) { - log_error("open log file error %s %s", strerror(errno), srv_logpath); - return -1; - } - dup2(log_fd, STDOUT_FILENO); - dup2(log_fd, STDERR_FILENO); - - return 0; -} - -int cworker_writepid(const cworker_t* worker) { - log_debug("write pid file"); - - if (mkdirall(srv_runpath, S_IRWXU|S_IRGRP|S_IXGRP) < 0) { - log_error("createing run dir error: %s %s", strerror(errno), srv_runpath); - } - - int pid_fd = -1; - if ((pid_fd = open(srv_runpath, O_WRONLY|O_TRUNC|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP)) < 0) { - log_error("open pid file error %s %s", strerror(errno), srv_runpath); - return -1; - } - if (dprintf(pid_fd, "%d", getpid()) < 0) { - log_error("cannon write pid, error %s %s", strerror(errno), srv_runpath); - close(pid_fd); - return -1; - } - close(pid_fd); - return 0; -} - -const int64_t default_port = 9701; - -int cworker_init(cworker_t* worker, char** argv, int argc) { - if (cworker_openlog(worker) < 0) { - log_error("openlog error"); - return -1; - } - log_debug("init service"); - worker->port = default_port; - - if (cworker_readconf(worker) < 0) { - log_error("reading config error"); - return -1; - } - - if (cworker_readopts(worker, argv, argc) < 0) { - log_error("reading config error"); - return -1; - } - - log_debug("port: %d", worker->port); - - return 0; -} - -int cworker_detach(const cworker_t* worker) { - log_debug("detach service"); - - int childpid = -1; - if((childpid = fork()) < 0) { - log_error("fork error: %s", strerror(errno)); - return -1; - } - - if (childpid == 0) { - log_debug("service forkerd"); - return 0; - // child - } else { - // parent - exit(0); - } - return 0; -} - -int cworker_build(const cworker_t* worker) { - log_debug("build service"); - return 0; -} - -int cworker_run(const cworker_t* worker) { - log_debug("run service"); - return 0; -} diff --git a/cworker.h b/cworker.h index e2a62ad..58d1ced 100644 --- a/cworker.h +++ b/cworker.h @@ -6,6 +6,9 @@ typedef struct { int64_t port; + int socket; + int nofork; + int logfd; } cworker_t; int cworker_init(cworker_t* worker, char** argv, int argc); @@ -13,7 +16,7 @@ int cworker_init(cworker_t* worker, char** argv, int argc); int cworker_detach(const cworker_t* worker); int cworker_writepid(const cworker_t* worker); int cworker_configure(const cworker_t* worker); -int cworker_build(const cworker_t* worker); +int cworker_build(cworker_t* worker); int cworker_run(const cworker_t* worker); diff --git a/defines.h b/defines.h index 49bcb20..6e80b10 100644 --- a/defines.h +++ b/defines.h @@ -2,22 +2,22 @@ /* defines.h.in. Generated from configure.ac by autoheader. */ /* location of cache dir */ -#define APP_CACHEDIR "/home/ziggi/Projects/jcomp/cache" +#define APP_CACHEDIR "/home/ziggi/Projects/cworker/cache" /* location of configuration files for ${PACKAGE} */ -#define APP_CONFIGDIR "/home/ziggi/Projects/jcomp/" +#define APP_CONFIGDIR "/home/ziggi/Projects/cworker/" /* location of database dir */ -#define APP_DATABASEDIR "/home/ziggi/Projects/jcomp/data" +#define APP_DATABASEDIR "/home/ziggi/Projects/cworker/data" /* location of libs */ -#define APP_LIBDIR "/home/ziggi/Projects/jcomp/lib" +#define APP_LIBDIR "/home/ziggi/Projects/cworker/lib" /* location of ${PACKAGE} logdir */ -#define APP_LOGDIR "/home/ziggi/Projects/jcomp/log" +#define APP_LOGDIR "/home/ziggi/Projects/cworker/log" /* location of pid file */ -#define APP_RUNDIR "/home/ziggi/Projects/jcomp/run" +#define APP_RUNDIR "/home/ziggi/Projects/cworker/run" /* effective user */ #define APP_USER "ziggi" diff --git a/jlexer.c b/jlexer.c index dd6fd35..f288216 100644 --- a/jlexer.c +++ b/jlexer.c @@ -10,6 +10,15 @@ #include #include +#define JLEXCONT_UNDEF 0 +#define JLEXCONT_WORD 1 +#define JLEXCONT_BLOCKB 2 +#define JLEXCONT_BLOCKE 3 +#define JLEXCONT_SEPAR 4 +#define JLEXCONT_NUM 5 +#define JLEXCONT_UNKNOW 6 +#define JLEXCONT_END 9 + #define JLEXTYPE_UNDEF 0 #define JLEXTYPE_BLOCKB 1 #define JLEXTYPE_BLOCKE 2 @@ -83,8 +92,8 @@ int jlexer_gettoken(jlexer_t * lexer, char* token) { case JLEXCONT_END:{ lexer->context = JLEXCONT_END; lexer->tokpos = 0; - lexer->rewind = true; - strcpy(token, "END"); + //lexer->rewind = true; + strcpy(token, "EOF"); return JLEXTOK_END; } case JLEXCONT_UNDEF:{ @@ -95,12 +104,12 @@ int jlexer_gettoken(jlexer_t * lexer, char* token) { break; } case JLEXTYPE_BLOCKB:{ - strcpy(token, "BEGIN"); + strcpy(token, "BLOCK BEGIN"); lexer->context = JLEXCONT_UNDEF; return JLEXTOK_BLOCKB; } case JLEXTYPE_BLOCKE:{ - strcpy(token, "END"); + strcpy(token, "BLOCK END"); lexer->context = JLEXCONT_UNDEF; return JLEXTOK_BLOCKE; } diff --git a/jlexer.h b/jlexer.h index 46694c5..18dc773 100644 --- a/jlexer.h +++ b/jlexer.h @@ -14,14 +14,6 @@ typedef struct { bool rewind; } jlexer_t; -#define JLEXCONT_UNDEF 0 -#define JLEXCONT_WORD 1 -#define JLEXCONT_BLOCKB 2 -#define JLEXCONT_BLOCKE 3 -#define JLEXCONT_SEPAR 4 -#define JLEXCONT_NUM 5 -#define JLEXCONT_UNKNOW 6 -#define JLEXCONT_END 9 #define JLEXTOK_BLOCKB 1 diff --git a/jparser.c b/jparser.c index 2ec345a..eba39b3 100644 --- a/jparser.c +++ b/jparser.c @@ -40,11 +40,16 @@ int jparser_parse(jparser_t * parser) { char* key = ""; while ((type = jlexer_gettoken(lex, token)) != JLEXTOK_END) { + //printf("pos %d %d: %s\n", pos, type, token); switch (pos) { // POS 0 case 0:{ + if (type == JLEXTOK_END) { + log_error("End token received in position %d", pos); + return -1; + } if (type != JLEXTOK_BLOCKB) { - log_error("wrong block token: %s", token); + log_error("Wrong block token: %s", token); return -1; } pos++; @@ -52,6 +57,10 @@ int jparser_parse(jparser_t * parser) { } // POS 1 case 1:{ + if (type == JLEXTOK_END) { + log_error("End token received in position %d", pos); + //return -1; + } if (type == JLEXTOK_SPACE) continue; if (type == JLEXTOK_NEXT) @@ -59,7 +68,7 @@ int jparser_parse(jparser_t * parser) { if (type == JLEXTOK_BLOCKE) return 0; if (type != JLEXTOK_WORD) { - log_error("wrong word token: %s", token); + log_error("Wrong word token: %s", token); return -1; } key = strcopy(token); @@ -68,10 +77,14 @@ int jparser_parse(jparser_t * parser) { } // POS 2 case 2:{ + if (type == JLEXTOK_END) { + log_error("End token received in position %d", pos); + return -1; + } if (type == JLEXTOK_SPACE) continue; if (type != JLEXTOK_SEPAR) { - log_error("wrong delimeter token: %s", token); + log_error("Wrong delimeter token: %s", token); return -1; } pos++; @@ -79,10 +92,18 @@ int jparser_parse(jparser_t * parser) { } // POS 3 case 3:{ + if (type == JLEXTOK_END) { + log_error("End token received in position %d", pos); + return -1; + } if (type == JLEXTOK_SPACE) continue; + if (type == JLEXTOK_BLOCKB) { + pos = 1; + continue; + } if (type != JLEXTOK_WORD && type != JLEXTOK_NUMB) { - log_error("wrong delimeter token: %s", token); + log_error("Wrong value token: %s", token); return -1; } char* val = strcopy(token); @@ -106,17 +127,28 @@ int jparser_parse(jparser_t * parser) { } // POS 4 case 4:{ - if (type == JLEXTOK_SPACE) + if (type == JLEXTOK_END) { + log_error("End token received in position %d", pos); + return -1; + } + if (type == JLEXTOK_SPACE) { continue; - if (type != JLEXTOK_NEXT && type != JLEXTOK_BLOCKE) { - log_error("wrong next token: %s", token); + } else if (type == JLEXTOK_BLOCKE) { + //log_debug("Block ended: %s", token); + return 0; + } else if (type != JLEXTOK_NEXT && type != JLEXTOK_BLOCKE) { + log_error("Wrong next token: %s", token); return -1; } pos = 1; break; } default:{ - log_error("wrong parser stage: %s", token); + log_error("Wrong parser stage: %s", token); + if (type == JLEXTOK_END) { + log_error("End token received in position %d", pos); + return -1; + } return -1; } } diff --git a/jparser.h b/jparser.h index 5cdc9f2..445cb47 100644 --- a/jparser.h +++ b/jparser.h @@ -1,6 +1,6 @@ -#ifndef CLPARSER_H_QWERTY -#define CLPARSER_H_QWERTY +#ifndef JPARSER_H_QWERTY +#define JPARSER_H_QWERTY #include #include diff --git a/logger.c b/logger.c index 713df12..7438937 100644 --- a/logger.c +++ b/logger.c @@ -8,12 +8,27 @@ #include #include #include +#include -#define _CLOCK_SOURCE CLOCK_MONOTONIC -//#define CLOCK_SOURCE CLOCK_REALTIME_PRECISE +#define CLOCK_SOURCE CLOCK_MONOTONIC #define MAX_TS_LEN 256 + +static pthread_mutex_t logmutex = NULL; +static pthread_mutexattr_t logmutex_attrs; + +void log_init(void) { + pthread_mutexattr_init(&logmutex_attrs); + pthread_mutexattr_setpshared(&logmutex_attrs, PTHREAD_PROCESS_SHARED); + pthread_mutex_init(&logmutex, &logmutex_attrs); +} + +void log_destroy(void) { + pthread_mutex_destroy(&logmutex); + pthread_mutexattr_destroy(&logmutex_attrs); +} + void static set_timestamp(char* buffer) { time_t now = time(NULL); if (now < 0) { @@ -25,7 +40,7 @@ void static set_timestamp(char* buffer) { } struct timespec tv; - clock_gettime(_CLOCK_SOURCE, &tv); + clock_gettime(CLOCK_SOURCE, &tv); memset(buffer, '\0', MAX_TS_LEN); sprintf(buffer, "%04d-%02d-%02dT%02d:%02d:%02d.%ld+%s", ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour, @@ -37,23 +52,43 @@ void log_error(const char* format, ...) { char timestamp[MAX_TS_LEN]; set_timestamp(timestamp); + pthread_mutex_lock(&logmutex); va_list args; fprintf(stderr, "%s error: ", timestamp); va_start(args, format); vfprintf(stderr, format, args); va_end(args); fprintf(stderr, "\n"); + pthread_mutex_unlock(&logmutex); } +void log_warning(const char* format, ...) { + + char timestamp[MAX_TS_LEN]; + set_timestamp(timestamp); + + pthread_mutex_lock(&logmutex); + va_list args; + fprintf(stderr, "%s warning: ", timestamp); + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fprintf(stderr, "\n"); + pthread_mutex_unlock(&logmutex); +} + + void log_debug(const char* format, ...) { char timestamp[MAX_TS_LEN]; set_timestamp(timestamp); + pthread_mutex_lock(&logmutex); va_list args; fprintf(stderr, "%s debug: ", timestamp); va_start(args, format); vfprintf(stderr, format, args); va_end(args); fprintf(stderr, "\n"); + pthread_mutex_unlock(&logmutex); } diff --git a/logger.h b/logger.h index 53787ec..2939561 100644 --- a/logger.h +++ b/logger.h @@ -1,6 +1,11 @@ #ifndef LOGGER_H_QWERTY #define LOGGER_H_QWERTY +void log_init(void); +void log_destroy(void); + void log_error(const char* format, ... ); void log_debug(const char* format, ... ); +void log_warning(const char* format, ... ); + #endif diff --git a/rcache.c b/rcache.c index 5a6111f..adc2d41 100644 --- a/rcache.c +++ b/rcache.c @@ -33,8 +33,10 @@ char rcache_getc(rcache_t * cache) { if (unread == 0) { char* buffer[BUFFER_SIZE]; - size_t rsize = read(cache->fd, buffer, sizeof(buffer)); - + ssize_t rsize = read(cache->fd, buffer, sizeof(buffer)); + if (rsize < 0) { + return EOF; + } if (rsize == 0) { return EOF; } @@ -51,6 +53,7 @@ char rcache_getc(rcache_t * cache) { memcpy(&(cache->data[cache->wpos]), buffer, (size_t)rsize); cache->wpos += rsize; } + //printf("[%c]", (char)cache->data[cache->rpos]); return (char)cache->data[cache->rpos++]; } diff --git a/works/fileoper.c b/works/fileoper.c new file mode 100644 index 0000000..f56cb5b --- /dev/null +++ b/works/fileoper.c @@ -0,0 +1,40 @@ + +char* path_last(const char* path) { + char buffer[1024]; + size_t psize = strlen(path); + strcpy(buffer, path); + buffer[psize] = '\0'; + if (buffer[psize - 1] == '/') { + buffer[--psize] = '\0'; + } + size_t pos = psize; + for (size_t i = 1; i < psize; i++) { + if (buffer[i] == '/') pos = i; + } + char* b = &buffer[++pos]; + int bsize = strlen(b); + char* res = malloc(bsize + 1); + strcpy(res, b); + //printf("\n%s\n", res); + return res; +} + +char* path_file(const char* path) { + char buffer[1024]; + size_t psize = strlen(path); + strcpy(buffer, path); + buffer[psize] = '\0'; + //if (buffer[psize - 1] == '/') { + // buffer[--psize] = '\0'; + //} + size_t pos = psize; + for (size_t i = 1; i < psize; i++) { + if (buffer[i] == '/') pos = i; + } + char* b = &buffer[++pos]; + int bsize = strlen(b); + char* res = malloc(bsize + 1); + strcpy(res, b); + //printf("\n%s\n", res); + return res; +} diff --git a/works/handlers.c b/works/handlers.c new file mode 100644 index 0000000..78b6ecb --- /dev/null +++ b/works/handlers.c @@ -0,0 +1,74 @@ + + +int handler4(int socket) { + int err = 0; + rcache_t cache; + jlexer_t lexer; + + struct timeval tv; + tv.tv_sec = 1; + tv.tv_usec = 0; + setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv); + + rcache_init(&cache, socket); + jlexer_init(&lexer, &cache); + + char token[1024]; + int type = 0; + while ((type = jlexer_gettoken(&lexer, token)) != JLEXTOK_END) { + printf("%d: %s\n", type, token); + } + printf("= %d: %s\n", type, token); + //rcache_destroy(&cache); + + return 0; +} + +int handler5(int socket) { + int err = 0; + rcache_t cache; + + rcache_init(&cache, socket); + char c = '\0'; + while ((c = rcache_getc(&cache)) != EOF) { + printf("%c", c); + if (c == '}') { + dprintf(socket, "good bay!\n"); + close(socket); + } + } + rcache_destroy(&cache); + return 0; +} + + + +int handler3(int socket) { + + //struct timeval tv; + //tv.tv_sec = 1; + //tv.tv_usec = 0; + //setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv); + + const int bsize = 1024; + char buffer[bsize]; + ssize_t rsize = 0; + ssize_t tsize = 0; + while(true) { + memset(buffer, '\0', bsize); + rsize = read(socket, buffer, bsize); + if (rsize < 0) { + log_debug("Socket error: %s", strerror(errno)); + if (errno != EAGAIN) { + return -1; + } + } else if (rsize == 0) { + log_debug("Socket rsize is zero"); + return 0; + } else { + tsize += rsize; + printf("%ld:%s\n", rsize, buffer); + } + } + return 0; +}