-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
NotDashEscaped: You need GnuPG to verify this message
========================================================================
The following patch will turn an unchanged Motsognir v1.0.9 source tree
into a Motsognir v1.0.9+logmore1.0 source tree.
Put this file into the source directory, chdir to the same directory,
then apply the patch with:
patch -p1 < motsognir109+logmore1.0.diff
You don't need to trim any text: the patch program knows what to skip.
------------------------------------------------------------------------
Vvv====P:A:T:C:H===F:O:L:L:O:W:S====**====T:H:I:S===S:I:D:E===U:P=======
========================================================================
--- motsognir/NEWS_logmore (nonexistent)
+++ motsognir+logmore/NEWS_logmore 2018-08-14 10:24:17.355449379 +0200
@@ -0,0 +1,25 @@
+logmore1.0
+==========
+
+The logmore1.0 patch adds the following features to Motsognir v1.0.9:
+
++ New command line option '--log' allows user to specify either a log
+ file, or a syslog local facility number. This option is also available
+ as new configuration file directive 'log';
+
++ a directory specified on the command line is taken to be the
+ Gopher root;
+
++ standard options '--help', '--version'; plus '--license'.
+
+Motsognir v1.0.9+logmore1.0 was tested on the following systems:
+
++ Void Linux (x86_64), kernel 4.17.9_1 SMP PREEMPT,
+ GNU libc 2.26, gcc 7.3.0
++ CentOS Linux 7 (x86_64), kernel 3.10.0 SMP,
+ GNU libc 2.17, gcc 4.8.5
+
+--
+Dario Niedermann <dario@darioniedermann.it>, 2018-08-14
+
+gopher://darioniedermann.it/ <> https://www.darioniedermann.it/
========================================================================
--- motsognir/Makefile 2018-08-06 09:52:58.777357833 +0200
+++ motsognir+logmore/Makefile 2018-08-07 11:08:42.019332501 +0200
@@ -1,3 +1,6 @@
+# $Id: Makefile 19 2018-08-07 09:08:41Z ndr $
+
CC ?= gcc
-CFLAGS += -Wall -Wextra -O3 -std=gnu89 -pedantic -Wformat-security
+CFLAGS += -Wall -Wextra -O3 -std=c99 -pedantic -Wformat-security \
+ -D_POSIX_C_SOURCE=200809L -D_DEFAULT_SOURCE -D_BSD_SOURCE
@@ -5,4 +8,4 @@
-motsognir: motsognir.o extmap.o
- $(CC) motsognir.o extmap.o -o motsognir $(CFLAGS)
+motsognir: motsognir.o extmap.o cli.o log.o
+ $(CC) motsognir.o extmap.o cli.o log.o -o motsognir $(CFLAGS)
@@ -11,3 +14,3 @@
-motsognir.o: motsognir.c
+motsognir.o: motsognir.c motsognir.h extmap.h binary.h log.h
$(CC) -c motsognir.c -o motsognir.o $(CFLAGS)
@@ -17,2 +20,6 @@
+cli.o: cli.c log.h motsognir.h
+
+log.o: log.c log.h motsognir.h
+
extmaptest: extmaptest.c extmap.o
========================================================================
--- motsognir/cli.c (nonexistent)
+++ motsognir+logmore/cli.c 2018-08-06 08:53:02.747462626 +0200
@@ -0,0 +1,202 @@
+/*
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * * Motsognir - The mighty gopher server *
+ * * Copyright (C) 2008-2016 Mateusz Viste *
+ * * http://motsognir.sourceforge.net *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * Some changes and additions: Copyright (C) 2018 Dario Niedermann
+ * $Id: cli.c 18 2018-08-06 06:53:02Z ndr $
+ * ----------------------------------------------------------------------
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * ----------------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <err.h>
+#include <sysexits.h>
+#include <syslog.h>
+#include <libgen.h>
+#include <string.h>
+#include "log.h"
+#include "motsognir.h"
+
+#define FALSE 0
+#define TRUE 1
+
+/* declare the default config file location, if not already declared from CLI
+ * at compile-time - esp. useful for systems that store config files in other
+ * locations, like /usr/local/etc/ for FreeBSD... */
+#ifndef CONFIGFILE
+ #define CONFIGFILE "/etc/motsognir.conf"
+#endif
+
+
+static void print_version(void)
+{
+ printf("Motsognir v%s Copyright (C) Mateusz Viste et al. %s\n",
+ pVer, pDate);
+}
+
+
+static void print_usage(char *argv0)
+{
+ printf("Usage: %s [OPTIONS] [DIRECTORY]", basename(argv0));
+ printf("\n\
+Start the Motsognir Gopher server, with DIRECTORY as the Gopher root\n\n\
+Options:\n\
+ -c, --config=FILE read server configuration from FILE\n\
+ -l, --log=FILE|0..7 log to FILE or syslog local facility #\n\
+ -V, --version display version information and exit\n\
+ -L, --licence\n\
+ --license display license and exit\n\
+ -h, --help display this help text and exit\n\n\
+Command line arguments override configuration file directives.\n\
+Default Gopher root: /var/gopher/\n\
+Default configuration file: /etc/motsognir.conf\n");
+}
+
+
+static void about(void) {
+ print_version();
+
+ printf("\n\
+This program is free software: you can redistribute it and/or modify it under\n\
+the terms of the GNU General Public License as published by the Free Software\n\
+Foundation, either version 3 of the License, or (at your option) any later\n\
+version.\n");
+
+ printf("\
+This program is distributed in the hope that it will be useful, but WITHOUT ANY\n\
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A\n\
+PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n\
+Motsognir is a robust and reliable open-source gopher server for POSIX systems.\n\
+Motsognir is entirely written in ISO C99, without any external dependencies.\n\n");
+
+ printf("Homepage: %s\n", HOMEPAGE);
+}
+
+
+static int configLogging(char *dest, struct logParams *logConf)
+{
+ static char timesHere = 0;
+ int status = EXIT_SUCCESS;
+
+ if (++timesHere == 1) { /* I'll only configure ONCE: from the cmd line
+ if specified, from config file otherwise. */
+ if (dest[1] == '\0' && dest[0] <= '7' && dest[0] >= '0') {
+ /* destination is a syslog local facility number */
+ logConf->loggingType = TO_SYSLOG;
+ /* reduce the 1st -and last- char in dest to a 0 to 7 value, use
+ it as an index to look up the facility value in the array */
+ logConf->facility = logConf->localFacility[dest[0]-'0'];
+ }
+ else { /* option's arg is -arguably- a file name */
+ logConf->loggingType = TO_FILE;
+ logConf->fileName = dest;
+ }
+ }
+ else status = EX_DATAERR;
+
+ return status;
+}
+
+
+int parseCmdLine(char mode, int myArgc, char **myArgv,
+ struct MotsognirConfig *confStruct)
+{
+ #define DONE_PARSING -1 /* getopt_long() returns -1 when done */
+ static struct option long_options[] = {
+ {"config", required_argument, NULL, 'c'},
+ {"help", no_argument, NULL, 'h'},
+ {"licence", no_argument, NULL, 'L'},
+ {"license", no_argument, NULL, 'L'},
+ {"log", required_argument, NULL, 'l'},
+ {"version", no_argument, NULL, 'V'},
+ {0, 0, 0, 0 }
+ };
+ static struct logParams logConf;
+ /* since LOG_LOCALn symbols might (in theory) have any value, let's put
+ them in order into an array, where we can refer to them by index */
+ static int localFacilities[] = { LOG_LOCAL0, LOG_LOCAL1, LOG_LOCAL2,
+ LOG_LOCAL3, LOG_LOCAL4, LOG_LOCAL5,
+ LOG_LOCAL6, LOG_LOCAL7 };
+ int c, option_index, this_option = 0, status = EXIT_SUCCESS;
+
+ if (mode == FIRST_PASS) { /* Do some one-time setup: */
+ confStruct->configfile = CONFIGFILE;
+ logConf.loggingType = TO_SYSLOG;
+ logConf.facility = LOG_DAEMON;
+ logConf.fileName = NULL;
+ logConf.localFacility = localFacilities;
+ }
+
+ optind=1; while (status == EXIT_SUCCESS) {
+ this_option = optind ? optind : 1;
+ option_index = 0;
+
+ c = getopt_long(myArgc, myArgv, ":c:hLl:V", long_options, &option_index);
+ if (c == DONE_PARSING) break;
+
+ switch (c) {
+ case 'c':
+ confStruct->configfile = optarg; break;
+
+ case 'h':
+ print_usage(myArgv[0]); status = OK_EXIT_NOW; break;
+
+ case 'L':
+ about(); status = OK_EXIT_NOW; break;
+
+ case 'l':
+ if (configLogging(optarg, &logConf))
+ /* if configLogging is called >1 time, it'll error out */
+ if (mode != LAST_PASS)
+ warnx("further logging destination '%s' ignored", optarg);
+ break;
+ case 'V':
+ print_version(); status = OK_EXIT_NOW; break;
+
+ case '?':
+ warnx("unrecognized option '%s'", myArgv[this_option]);
+ print_usage(myArgv[0]); status = EX_USAGE; break;
+
+ case ':':
+ warnx("option '%s' requires an argument",
+ myArgv[this_option]);
+ status = EX_USAGE; break;
+
+ default: /* should never happen... */
+ warnx("internal error while parsing command line, char code 0%o", c);
+ status = EX_SOFTWARE;
+ }
+ }
+
+ /* init the logging functions, either with default values,
+ or values from the command line: */
+ logme(INIT, NO_MSG, &logConf);
+
+ /* non-option args at the end of cmd line? */
+ if (mode == LAST_PASS) /* only deal with them the last time I'm called */
+ for (c=0; optind < myArgc && c < 256; c++, optind++) {
+ if (!c) /* the 1st will be our gopher root */
+ confStruct->gopherroot = myArgv[optind];
+ else
+ warnx("ignoring trailing argument: '%s'", myArgv[optind]);
+ }
+
+ return status;
+}
========================================================================
--- motsognir/log.c (nonexistent)
+++ motsognir+logmore/log.c 2018-08-05 17:37:50.420143737 +0200
@@ -0,0 +1,151 @@
+/*
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * * Motsognir - The mighty gopher server *
+ * * Copyright (C) 2008-2016 Mateusz Viste *
+ * * http://motsognir.sourceforge.net *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * Some changes and additions: Copyright (C) 2018 Dario Niedermann
+ * $Id: log.c 15 2018-08-05 15:37:50Z ndr $
+ * ----------------------------------------------------------------------
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * ----------------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <syslog.h>
+#include <err.h>
+#include <sysexits.h>
+#include <assert.h>
+#include "motsognir.h"
+#include "log.h"
+
+#define MAX_MSGLEN 2048 /* max bytes in a single log entry */
+
+struct logWritersParams {
+ int level,
+ facility;
+ char *fileName,
+ *prefix,
+ *msg;
+ FILE *filePtr;
+};
+
+static int logToFile(struct logWritersParams *params)
+{
+ int status;
+
+ status = EXIT_SUCCESS;
+ if (params->filePtr == NULL)
+ if ((params->filePtr = fopen(params->fileName, "a")) == NULL)
+ return EX_CANTCREAT;
+ /* else... */
+ if (params->prefix != NULL)
+ if (fprintf(params->filePtr, "%s ", params->prefix) < 1)
+ status = EX_IOERR;
+
+ if ((fprintf(params->filePtr, "%s\n", params->msg) < 1)
+ || fflush(params->filePtr))
+ status = EX_IOERR;
+
+ if (status == EX_IOERR) fclose(params->filePtr);
+ return status;
+}
+
+
+static int logToSyslog(struct logWritersParams *params)
+{
+ assert(params->level >= LOG_EMERG && params->level <= LOG_DEBUG);
+ assert((params->facility >= LOG_LOCAL0 && params->facility <= LOG_LOCAL7)
+ || params->facility == LOG_DAEMON);
+ syslog(params->level | params->facility, "%s", params->msg);
+ return 0;
+}
+
+
+void logme(int level, const char *fmt, ...)
+{
+ va_list argPtr; /* points to the list of unnamed args */
+ static struct logWritersParams logWritersSettings;
+ static char msg[MAX_MSGLEN], whereToLog;
+ static int (*writerFunc)() = NULL;
+ struct logParams *logSettings;
+ int msgLen;
+ char *clientIP;
+
+ va_start(argPtr, fmt); /* make argPtr point to 1st unnamed arg */
+
+ switch (level) {
+ case INIT:
+ /* If I'm called with pseudo-level INIT, I won't log a message: instead
+ I'll regard 1st unnamed passed-in arg as a pointer to a logParams struct.
+ Spares the need of being passed a config struct by every func calling me
+ */
+ assert(fmt==NO_MSG); /* or there must be collision with INIT's value */
+ logWritersSettings.msg = msg; /* never to be changed */
+ logSettings = va_arg(argPtr, struct logParams *);
+ /* mk our static copys of settings (passed-in struc may be destroyd) */
+ whereToLog = logSettings->loggingType;
+ assert(whereToLog==TO_FILE||whereToLog==TO_SYSLOG);
+ logWritersSettings.facility = logSettings->facility;
+ /* no need to alloc -- points to somewhere in argv[] if it came from
+ a command line opt, or to a strdup'ed string if from config file: */
+ logWritersSettings.fileName = logSettings->fileName;
+ logWritersSettings.filePtr = NULL;
+
+ /* pick function according to message destination -- file or syslog */
+ writerFunc = (whereToLog == TO_FILE) ? logToFile : logToSyslog;
+ break;
+
+ case SET_PREFIX:
+ /* This pseudo-level means I'll set the common prefix to log entries.
+ The 1st unnamed passed-in arg must now be a connected client's IP,
+ because I only get called this way when a new client connects.
+ The 2nd unnamed arg points to a char array that will contain the prefix.
+ */
+ assert(writerFunc != NULL); /* I must've been previously INIT'ed */
+ clientIP = va_arg(argPtr, char *);
+ logWritersSettings.prefix = va_arg(argPtr, char *);
+ sprintf(logWritersSettings.prefix, fmt, clientIP);
+ if (whereToLog == TO_SYSLOG) {
+ /* set up the logging to log with PID and peer's IP address */
+ openlog(logWritersSettings.prefix, LOG_PID,
+ logWritersSettings.facility);
+ }
+ else
+ assert(whereToLog == TO_FILE);
+ break;
+
+ default: /* an actual syslog level */
+ assert(level >= LOG_EMERG && level <= LOG_DEBUG);
+ logWritersSettings.level = level;
+ /* turn fmt and any following args into a fixed string in msg: */
+ msgLen = vsnprintf(msg, MAX_MSGLEN, fmt, argPtr);
+ /* write msg to log: */
+ while ((*writerFunc)(&logWritersSettings)) {
+ /* got error. From logToFile() 'cause logToSyslog() only returns 0 */
+ whereToLog = TO_SYSLOG;
+ /* facility must still be as initially,since we were loggin'to file*/
+ assert(logWritersSettings.facility == LOG_DAEMON);
+ writerFunc = logToSyslog;
+ LOG(ERR,"Could not write to log file '%s' -- reverting to syslog",
+ logWritersSettings.fileName);
+ }
+ if (msgLen >= MAX_MSGLEN)
+ LOG(WARNING,"previous log message was truncated");
+ }
+ va_end(argPtr); /* clean up va_ stuff */
+}
========================================================================
--- motsognir/log.h (nonexistent)
+++ motsognir+logmore/log.h 2018-08-05 17:37:50.423144093 +0200
@@ -0,0 +1,29 @@
+/*
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * * Motsognir - The mighty gopher server *
+ * * Copyright (C) 2008-2016 Mateusz Viste *
+ * * http://motsognir.sourceforge.net *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * Some changes and additions: Copyright (C) 2018 Dario Niedermann
+ * $Id: log.h 15 2018-08-05 15:37:50Z ndr $
+ * ----------------------------------------------------------------------
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * ----------------------------------------------------------------------
+ */
+
+#define LOG(level, ...) logme(LOG_##level, __VA_ARGS__)
+#define NO_MSG NULL
+
+void logme(int level, const char *fmt, ...);
========================================================================
--- motsognir/motsognir.c 2018-08-06 09:52:59.080393386 +0200
+++ motsognir+logmore/motsognir.c 2018-08-05 17:37:50.430144924 +0200
@@ -7,2 +7,4 @@
*
+ * Some changes and additions: Copyright (C) 2018 Dario Niedermann
+ * $Id: motsognir.c 15 2018-08-05 15:37:50Z ndr $
* ----------------------------------------------------------------------
@@ -29,3 +31,2 @@
#include <pwd.h>
-#include <regex.h> /* regcomp(), regexec()... */
#include <signal.h>
@@ -48,47 +49,8 @@
#include "extmap.h"
+#include "motsognir.h"
+#include "log.h"
-/* Constants */
-#define pVer "1.0.9"
-#define pDate "2008-2016"
-#define HOMEPAGE "http://motsognir.sourceforge.net"
-
-/* declare the default config file location, if not already declared from CLI
- * at compile-time - esp. useful for systems that store config files in other
- * locations, like /usr/local/etc/ for FreeBSD... */
-#ifndef CONFIGFILE
- #define CONFIGFILE "/etc/motsognir.conf"
-#endif
-
-
-struct MotsognirConfig {
- char *gopherroot;
- char *userdir;
- char **pubdirlist;
- int gopherport;
- char *gopherhostname;
- char *defaultgophermap;
- int verbosemode;
- int capssupport;
- char *capsservergeolocationstring;
- char *capsserverarchitecture;
- char *capsserverdescription;
- char *capsserverdefaultencoding;
- int cgisupport;
- int phpsupport;
- int subgophermaps;
- int paranoidmode;
- char *plugin;
- regex_t *pluginfilter;
- char *runasuser;
- uid_t runasuser_uid;
- gid_t runasuser_gid;
- char *runasuser_home;
- char *chroot;
- char *httperrfile;
- char *bind;
- char *extmapfile;
- struct extmap_t *extmap;
- char securldelim;
-};
-
+/* implementation in 'cli.c': */
+int parseCmdLine(char mode, int argc, char **argv,
+ struct MotsognirConfig *confStruct);
@@ -157,3 +119,3 @@
if (initgroups(config->runasuser, config->runasuser_gid) != 0 || setgid(config->runasuser_gid) != 0 || setuid(config->runasuser_uid) != 0) {
- syslog(LOG_WARNING, "ERROR: Couldn't change to '%.32s' uid=%lu gid=%lu: %s", config->runasuser, (unsigned long)config->runasuser_uid, (unsigned long)config->runasuser_gid, strerror(errno));
+ LOG(WARNING,"ERROR: Couldn't change to '%.32s' uid=%lu gid=%lu: %s", config->runasuser, (unsigned long)config->runasuser_uid, (unsigned long)config->runasuser_gid, strerror(errno));
return(-1);
@@ -162,3 +124,3 @@
if (getuid() != config->runasuser_uid) {
- syslog(LOG_WARNING, "ERROR: For some mysterious reasons Motsognir was unable to switch to user '%s'.", config->runasuser);
+ LOG(WARNING,"ERROR: For some mysterious reasons Motsognir was unable to switch to user '%s'.", config->runasuser);
return(-1);
@@ -369,3 +331,3 @@
if (dstlen + 4 >= dstmaxlen) {
- syslog(LOG_WARNING, "WARNING: reached percent encoding length limit - aborting");
+ LOG(WARNING,"WARNING: reached percent encoding length limit - aborting");
break; /* stop the work if we reached our limit */
@@ -450,3 +412,3 @@
string[x] = 0;
- syslog(LOG_WARNING, "ERROR: detected invalid percent encoding");
+ LOG(WARNING,"ERROR: detected invalid percent encoding");
return(-1);
@@ -456,3 +418,3 @@
string[x] = 0;
- syslog(LOG_WARNING, "ERROR: detected a dangerous percent encoding (%%00)");
+ LOG(WARNING,"ERROR: detected a dangerous percent encoding (%%00)");
return(-1);
@@ -464,3 +426,3 @@
string[x - 2] = 0;
- syslog(LOG_WARNING, "ERROR: detected an invalid percent encoding");
+ LOG(WARNING,"ERROR: detected an invalid percent encoding");
return(-1);
@@ -516,23 +478,5 @@
-static void about(char *version, char *datestring, char *homepage) {
- printf("Motsognir v%s Copyright (C) Mateusz Viste %s\n\n", version, datestring);
- printf("This program is free software: you can redistribute it and/or modify it under\n"
- "the terms of the GNU General Public License as published by the Free Software\n"
- "Foundation, either version 3 of the License, or (at your option) any later\n"
- "version.\n");
- printf("This program is distributed in the hope that it will be useful, but WITHOUT ANY\n"
- "WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A\n"
- "PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n");
- printf("Motsognir is a robust and reliable open-source gopher server for POSIX systems.\n"
- "Motsognir is entirely written in ANSI C, without any external dependencies.\n\n");
- printf("Available command-line parameters:\n"
- " --config file.conf use a configuration file in a custom location\n"
- "\n");
- printf("homepage: %s\n\n", homepage);
-}
-
-
static void sendbackhttperror(int sock, struct MotsognirConfig *config) {
char txtline[1024], portstr[16];
- syslog(LOG_INFO, "HTTP request detected - a HTTP error message is returned");
+ LOG(INFO,"HTTP request detected - a HTTP error message is returned");
sendline(sock, "HTTP/1.1 400 Bad request");
@@ -574,3 +518,3 @@
char txtline[1024];
- syslog(LOG_INFO, "GOPHER+ request detected - a gopher+ fake redirector is returned");
+ LOG(INFO,"GOPHER+ request detected - a gopher+ fake redirector is returned");
sendline(sock, "+-1");
@@ -595,3 +539,3 @@
if (res == NULL) {
- syslog(LOG_ERR, "ERROR: OUT OF MEMORY ON LINE #%d", __LINE__);
+ LOG(ERR,"ERROR: OUT OF MEMORY ON LINE #%d", __LINE__);
return(res);
@@ -618,3 +562,3 @@
-static int loadconfig(struct MotsognirConfig *config, char *configfile) {
+static int loadconfig(struct MotsognirConfig *config) {
FILE *fd;
@@ -623,8 +567,6 @@
int valuebuffpos = 0;
- int bytebuff;
+ int bytebuff, priv_argc;
int state = 0; /* 0=reading token, 1=reading value, 2=reading comment */
struct passwd *pw;
-
- /* zero out the config structure, just in case */
- memset(config, 0, sizeof(*config));
+ char *priv_argv[3];
@@ -659,5 +601,5 @@
- fd = fopen(configfile, "r");
+ fd = fopen(config->configfile, "r");
if (fd == NULL) {
- syslog(LOG_WARNING, "WARNING: Failed to open the configuration file at '%s'", configfile);
+ LOG(WARNING,"WARNING: Failed to open the configuration file at '%s'", config->configfile);
return(-1);
@@ -729,5 +671,5 @@
if (config->pluginfilter == NULL) {
- syslog(LOG_ERR, "ERROR: Out of memory while trying to allocate regex space!");
+ LOG(ERR,"ERROR: Out of memory while trying to allocate regex space!");
} else if (regcomp(config->pluginfilter, valuebuff, REG_EXTENDED | REG_NOSUB) != 0) {
- syslog(LOG_ERR, "ERROR: Invalid PluginFilter regex!");
+ LOG(ERR,"ERROR: Invalid PluginFilter regex!");
free(config->pluginfilter);
@@ -743,3 +685,3 @@
config->httperrfile = readfiletomem(valuebuff);
- if (config->httperrfile == NULL) syslog(LOG_WARNING, "WARNING: Failed to load custom http error file '%s'. Default content will be used instead.", valuebuff);
+ if (config->httperrfile == NULL) LOG(WARNING,"WARNING: Failed to load custom http error file '%s'. Default content will be used instead.", valuebuff);
} else if (strcasecmp(tokenbuff, "ExtMapFile") == 0) {
@@ -748,2 +690,6 @@
config->securldelim = atoi(valuebuff);
+ } else if (strcasecmp(tokenbuff, "log") == 0) {
+ /* simulate a '-l ARG' given on command line */
+ priv_argc=3; priv_argv[1]="-l"; priv_argv[2]=strdup(valuebuff);
+ parseCmdLine(FROM_FILE, priv_argc, priv_argv, config);
}
@@ -765,3 +711,3 @@
if (config->verbosemode < 0) {
- syslog(LOG_ERR, "ERROR: Invalid verbose level found in the configuration file (%d)", config->verbosemode);
+ LOG(ERR,"ERROR: Invalid verbose level found in the configuration file (%d)", config->verbosemode);
return(-1);
@@ -770,3 +716,3 @@
if (config->gopherport < 1) {
- syslog(LOG_ERR, "ERROR: Invalid gopher port found in the configuration file (%d)", config->gopherport);
+ LOG(ERR,"ERROR: Invalid gopher port found in the configuration file (%d)", config->gopherport);
return(-1);
@@ -775,3 +721,3 @@
if (config->gopherroot[0] == 0) {
- syslog(LOG_ERR, "ERROR: Missing gopher root path in the configuration file. Please add a valid 'GopherRoot=' directive");
+ LOG(ERR,"ERROR: Missing gopher root path in the configuration file. Please add a valid 'GopherRoot=' directive");
return(-1);
@@ -782,3 +728,3 @@
if ((config->userdir[0] != '/') || (strstr(config->userdir, "%s") == NULL)) {
- syslog(LOG_ERR, "ERROR: The UserDir configuration is invalid. It shall be an absolute path (start by '/') and contain the '%%s' placeholder.");
+ LOG(ERR,"ERROR: The UserDir configuration is invalid. It shall be an absolute path (start by '/') and contain the '%%s' placeholder.");
return(-1);
@@ -788,3 +734,3 @@
if (config->gopherhostname == NULL) {
- syslog(LOG_WARNING, "WARNING: Missing gopher hostname in the configuration file. The local IP address will be used instead. Please add a valid 'GopherHostname=' directive.");
+ LOG(WARNING,"WARNING: Missing gopher hostname in the configuration file. The local IP address will be used instead. Please add a valid 'GopherHostname=' directive.");
}
@@ -794,3 +740,3 @@
if (config->extmap == NULL) {
- syslog(LOG_ERR, "ERROR: failed to load the extension mapping file '%s'", config->extmapfile);
+ LOG(ERR,"ERROR: failed to load the extension mapping file '%s'", config->extmapfile);
return(-1);
@@ -802,3 +748,3 @@
if (pw == NULL) {
- syslog(LOG_ERR, "ERROR: Could not map the username '%s' to a valid uid", config->runasuser);
+ LOG(ERR,"ERROR: Could not map the username '%s' to a valid uid", config->runasuser);
return(-1);
@@ -849,3 +795,3 @@
/* Retrieve server-side parameters */
- syslog(LOG_INFO, "Got following server-side parameters: %s | %s", res[0], res[1]);
+ LOG(INFO,"Got following server-side parameters: %s | %s", res[0], res[1]);
return(res); /* return the array with params */
@@ -893,3 +839,3 @@
if ((timeoutStartTime != NULL) && (time(NULL) - *timeoutStartTime >= 10)) {
- syslog(LOG_INFO, "Request takes too long to come. Connection aborted.");
+ LOG(INFO,"Request takes too long to come. Connection aborted.");
return(-1);
@@ -931,3 +877,3 @@
char linebuff[1024];
- syslog(LOG_INFO, "The request is asking for a URL redirection - returned a html document redirecting to '%s'", rawurl);
+ LOG(INFO,"The request is asking for a URL redirection - returned a html document redirecting to '%s'", rawurl);
sendline(sock, "<!DOCTYPE html>");
@@ -977,3 +923,3 @@
if (dirptr == NULL) {
- syslog(LOG_WARNING, "ERROR: Could not access directory '%s' (%s)", localfile, strerror(errno));
+ LOG(WARNING,"ERROR: Could not access directory '%s' (%s)", localfile, strerror(errno));
sendline(sock, "3Error: could not access directory\tfake\tfake\t0");
@@ -985,3 +931,3 @@
if (direntriescount < 0) {
- syslog(LOG_WARNING, "ERROR: Failed to scan the directory '%s': %s", localfile, strerror(errno));
+ LOG(WARNING,"ERROR: Failed to scan the directory '%s': %s", localfile, strerror(errno));
return;
@@ -989,3 +935,3 @@
- syslog(LOG_INFO, "Found %d items in '%s'", direntriescount, localfile);
+ LOG(INFO,"Found %d items in '%s'", direntriescount, localfile);
@@ -1095,5 +1041,5 @@
if ((srvsideparams[0] != NULL) || (srvsideparams[1] != NULL)) {
- syslog(LOG_INFO, "running server-side app '%s' with queries '%s' + '%s'", localfile, srvsideparams[0], srvsideparams[1]);
+ LOG(INFO,"running server-side app '%s' with queries '%s' + '%s'", localfile, srvsideparams[0], srvsideparams[1]);
} else {
- syslog(LOG_INFO, "running server-side app '%s'", localfile);
+ LOG(INFO,"running server-side app '%s'", localfile);
}
@@ -1127,3 +1073,3 @@
if (cgifd == NULL) {
- syslog(LOG_WARNING, "ERROR: failed to run the server-side app '%s'", localfile);
+ LOG(WARNING,"ERROR: failed to run the server-side app '%s'", localfile);
return(0);
@@ -1147,3 +1093,3 @@
if (explodegophermapline(tmpstring, &itemtype, itemdesc, itemselector, itemserver, &itemport) != 0) {
- syslog(LOG_WARNING, "ERROR: dynamic gophermap processing aborted due to failure to interpret its output as being a gophermap line (%s)", localfile);
+ LOG(WARNING,"ERROR: dynamic gophermap processing aborted due to failure to interpret its output as being a gophermap line (%s)", localfile);
break;
@@ -1166,5 +1112,5 @@
if (res == -1) {
- syslog(LOG_WARNING, "WARNING: call to server-side app '%s' failed (%s)", localfile, strerror(errno));
+ LOG(WARNING,"WARNING: call to server-side app '%s' failed (%s)", localfile, strerror(errno));
} else if (WEXITSTATUS(res) != 0) {
- syslog(LOG_WARNING, "WARNING: server-side app '%s' terminated with a non-zero exit code (%d)", localfile, WEXITSTATUS(res));
+ LOG(WARNING,"WARNING: server-side app '%s' terminated with a non-zero exit code (%d)", localfile, WEXITSTATUS(res));
}
@@ -1194,6 +1140,6 @@
if (gophermapfd == NULL) {
- syslog(LOG_WARNING, "ERROR: Failed to open the gophermap at '%s' (%s)", gophermapfile, strerror(errno));
+ LOG(WARNING,"ERROR: Failed to open the gophermap at '%s' (%s)", gophermapfile, strerror(errno));
return;
}
- syslog(LOG_INFO, "Response=\"Return gophermap. (%s)", gophermapfile);
+ LOG(INFO,"Response=\"Return gophermap. (%s)", gophermapfile);
@@ -1217,3 +1163,3 @@
if (realscriptname == NULL) {
- syslog(LOG_WARNING, "WARNING: Failed to resolve the path to '%s'", itemdesc);
+ LOG(WARNING,"WARNING: Failed to resolve the path to '%s'", itemdesc);
} else {
@@ -1240,3 +1186,3 @@
char gophermapfile[1024];
- syslog(LOG_INFO, "The resource is a directory");
+ LOG(INFO,"The resource is a directory");
if (lastcharofstring(localfile) != '/') strcat(localfile, "/");
@@ -1274,3 +1220,3 @@
/* no gophermap found, simply list files & directories */
- syslog(LOG_INFO, "No gophermap found. Listing directory content");
+ LOG(INFO,"No gophermap found. Listing directory content");
outputdircontent(sock, config, localfile, directorytolist);
@@ -1297,3 +1243,3 @@
if (sockmaster < 0) {
- syslog(LOG_WARNING, "FATAL ERROR: socket could not be open (%s)", strerror(errno));
+ LOG(WARNING,"FATAL ERROR: socket could not be open (%s)", strerror(errno));
return(-2);
@@ -1302,3 +1248,3 @@
/* I set the socket to be reusable, to avoid having to wait for a longish time when the server is restarted */
- if (setsockopt(sockmaster, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one)) < 0) syslog(LOG_WARNING, "WARNING: failed to set REUSEADDR on main socket");
+ if (setsockopt(sockmaster, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one)) < 0) LOG(WARNING,"WARNING: failed to set REUSEADDR on main socket");
@@ -1311,3 +1257,3 @@
if (inet_pton(AF_INET6, config->bind, &(serv_addr.sin6_addr)) != 1) {
- syslog(LOG_WARNING, "FATAL ERROR: failed to parse the IP address bind value. Please check your 'bind' configuration.");
+ LOG(WARNING,"FATAL ERROR: failed to parse the IP address bind value. Please check your 'bind' configuration.");
return(-2);
@@ -1327,3 +1273,3 @@
if (bind(sockmaster, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
- syslog(LOG_WARNING, "FATAL ERROR: binding failed (%s)", strerror(errno));
+ LOG(WARNING,"FATAL ERROR: binding failed (%s)", strerror(errno));
return(-2);
@@ -1341,3 +1287,3 @@
- syslog(LOG_INFO, "motsognir v" pVer " process started");
+ LOG(INFO,"motsognir v" pVer " process started");
@@ -1352,3 +1298,3 @@
close(sockmaster);
- syslog(LOG_WARNING, "Failed to dameonize the motsognir process (%s)", strerror(errno));
+ LOG(WARNING,"Failed to dameonize the motsognir process (%s)", strerror(errno));
return(-2);
@@ -1365,3 +1311,3 @@
/* I want to be the pack master now (aka session leader) */
- if (setsid() == -1) syslog(LOG_WARNING, "WARNING: setsid() failed (%s)", strerror(errno));
+ if (setsid() == -1) LOG(WARNING,"WARNING: setsid() failed (%s)", strerror(errno));
@@ -1371,3 +1317,3 @@
if (chroot(config->chroot) != 0) {
- syslog(LOG_WARNING, "Failed to chroot(): %s", strerror(errno));
+ LOG(WARNING,"Failed to chroot(): %s", strerror(errno));
return(-2);
@@ -1377,3 +1323,3 @@
/* set the working directory to the root directory */
- if (chdir ("/") == -1) syslog(LOG_WARNING, "WARNING: failed to switch to / directory (%s)", strerror(errno));
+ if (chdir ("/") == -1) LOG(WARNING,"WARNING: failed to switch to / directory (%s)", strerror(errno));
@@ -1385,3 +1331,3 @@
if (getuid() != 0) {
- syslog(LOG_WARNING, "A 'RunAsUser' directive has been configured, but the process has not been launched under root account. The 'RunAsUser' directive is therefore ignored.");
+ LOG(WARNING,"A 'RunAsUser' directive has been configured, but the process has not been launched under root account. The 'RunAsUser' directive is therefore ignored.");
} else { /* if I'm root, drop off privileges */
@@ -1390,3 +1336,3 @@
} else {
- syslog(LOG_WARNING, "Successfully dropped root privileges. Motsognir runs as user '%s' now.", config->runasuser);
+ LOG(WARNING,"Successfully dropped root privileges. Motsognir runs as user '%s' now.", config->runasuser);
}
@@ -1399,3 +1345,3 @@
if (sockslave < 0) {
- syslog(LOG_WARNING, "FATAL ERROR: accepting connection failed (%s)", strerror(errno));
+ LOG(WARNING,"FATAL ERROR: accepting connection failed (%s)", strerror(errno));
close(sockmaster);
@@ -1410,3 +1356,3 @@
if (inet_ntop(cli_addr.sin6_family, &cli_addr.sin6_addr, clientipaddrstr, clientipaddrstr_maxlen) == NULL) {
- syslog(LOG_WARNING, "Failed to fetch client's IP address: %s", strerror(errno));
+ LOG(WARNING,"Failed to fetch client's IP address: %s", strerror(errno));
sprintf(clientipaddrstr, "UNKNOWN");
@@ -1416,3 +1362,3 @@
if ((getsockname(sockslave, (struct sockaddr *) &serv_addr, &clilen) < 0) || (inet_ntop(serv_addr.sin6_family, &serv_addr.sin6_addr, serveripaddrstr, serveripaddrstr_maxlen) == NULL)) {
- syslog(LOG_WARNING, "Failed to fetch server's IP address: %s", strerror(errno));
+ LOG(WARNING,"Failed to fetch server's IP address: %s", strerror(errno));
sprintf(serveripaddrstr, "UNKNOWN");
@@ -1423,5 +1369,4 @@
/* set logprefix to contain the client's address */
- sprintf(logprefix, "motsognir [%s]", clientipaddrstr);
- openlog(logprefix, LOG_PID, LOG_DAEMON); /* set up the logging to log with PID and peer's IP address */
- syslog(LOG_INFO, "new connection to %s", serveripaddrstr);
+ logme(SET_PREFIX, "motsognir [%s]", clientipaddrstr, logprefix);
+ LOG(INFO,"new connection to %s", serveripaddrstr);
/* if no gopher hostname was set, use the server's address */
@@ -1435,3 +1380,3 @@
} else { /* error condition */
- syslog(LOG_WARNING, "FATAL ERROR: fork() failed!");
+ LOG(WARNING,"FATAL ERROR: fork() failed!");
close(sockslave);
@@ -1452,3 +1397,3 @@
if (linebuff == NULL) {
- syslog(LOG_WARNING, "ERROR: Out of memory while trying to allocate buffer for file");
+ LOG(WARNING,"ERROR: Out of memory while trying to allocate buffer for file");
return;
@@ -1457,3 +1402,3 @@
if (fd == NULL) { /* file could not be opened */
- syslog(LOG_WARNING, "ERROR: File '%s' could not be opened", filename);
+ LOG(WARNING,"ERROR: File '%s' could not be opened", filename);
free(linebuff);
@@ -1478,3 +1423,3 @@
if (buff == NULL) {
- syslog(LOG_WARNING, "ERROR: Out of memory while trying to allocate buffer for file");
+ LOG(WARNING,"ERROR: Out of memory while trying to allocate buffer for file");
return;
@@ -1483,3 +1428,3 @@
if (fd == NULL) { /* file could not be opened */
- syslog(LOG_WARNING, "ERROR: File '%s' could not be opened", filename);
+ LOG(WARNING,"ERROR: File '%s' could not be opened", filename);
free(buff);
@@ -1526,3 +1471,3 @@
}
- syslog(LOG_WARNING, "Evasion check: path '%s' (%s) seem to belong to neither '%s' nor any entry of the pubdir list", localfile, resolvedpath, gopherroot);
+ LOG(WARNING,"Evasion check: path '%s' (%s) seem to belong to neither '%s' nor any entry of the pubdir list", localfile, resolvedpath, gopherroot);
return(1);
@@ -1618,3 +1563,3 @@
if ((curdir == NULL) || (chdir(curdir) == -1)) {
- syslog(LOG_WARNING, "WARNING: failed to switch current directory to %s (%s), original resource: %s", curdir, strerror(errno), s);
+ LOG(WARNING,"WARNING: failed to switch current directory to %s (%s), original resource: %s", curdir, strerror(errno), s);
res = -1;
@@ -1642,4 +1587,3 @@
char gophertype;
- char *configfile = CONFIGFILE;
- int sock;
+ int sock, status;
struct MotsognirConfig config;
@@ -1647,17 +1591,11 @@
- if (argc > 1) {
- int x;
- for (x = 1; x < argc; x++) {
- if (strcmp(argv[x], "--config") == 0) {
- x++;
- if (x < argc) configfile = argv[x];
- } else { /* unknown command line */
- about(pVer, pDate, HOMEPAGE);
- return(1);
- }
- }
- }
+ /* zero out the config structure, just in case */
+ memset(&config, 0, sizeof(config));
+
+ if ((status = parseCmdLine(FIRST_PASS, argc, argv, &config)) != EXIT_SUCCESS)
+ return (status==OK_EXIT_NOW) ? EXIT_SUCCESS : status;
+ /* else... */
/* load motsognir's configuration from file */
- if (loadconfig(&config, configfile) != 0) {
+ if (loadconfig(&config) != 0) {
puts("ERROR: A configuration error has been detected. Check the logs for details.");
@@ -1665,2 +1603,7 @@
}
+ /* Again?! Yep... Command line args must override config file
+ directives. But we also needed a 1st pass to possibly learn
+ where the config file was... */
+ if ((status = parseCmdLine(LAST_PASS, argc, argv, &config)) != EXIT_SUCCESS)
+ return (status==OK_EXIT_NOW) ? EXIT_SUCCESS : status;
@@ -1676,3 +1619,3 @@
if (sockreadline(sock, directorytolist, sizeof(directorytolist), &StartTime) < 0) {
- syslog(LOG_WARNING, "Error during selector receiving phase. Connection aborted.");
+ LOG(WARNING,"Error during selector receiving phase. Connection aborted.");
close(sock);
@@ -1680,3 +1623,3 @@
}
- syslog(LOG_INFO, "Query='%s'", directorytolist);
+ LOG(INFO,"Query='%s'", directorytolist);
if (directorytolist[0] == 0) { /* Empty request means "gimme the root listing" */
@@ -1698,3 +1641,3 @@
if (res > 0) {
- syslog(LOG_INFO, "Query handled by plugin (%s)", config.plugin);
+ LOG(INFO,"Query handled by plugin (%s)", config.plugin);
drainsock(sock); /* read whatever request the peer sent us, to drain the socket before closing it (otherwise the tcp stack would trigger a ugly RST) */
@@ -1742,3 +1685,3 @@
if (percdecode(directorytolist) != 0) {
- syslog(LOG_WARNING, "Percent decoding on request failed. Query aborted.");
+ LOG(WARNING,"Percent decoding on request failed. Query aborted.");
return(0);
@@ -1749,3 +1692,3 @@
if (securitycheckresult != NULL) {
- syslog(LOG_INFO, "The gopher security module has detected a suspect condition. The query won't be processed. Reason: %s", securitycheckresult);
+ LOG(INFO,"The gopher security module has detected a suspect condition. The query won't be processed. Reason: %s", securitycheckresult);
close(sock);
@@ -1761,6 +1704,6 @@
- syslog(LOG_INFO, "Requested resource: %s / Local resource: %s", directorytolist, localfile);
+ LOG(INFO,"Requested resource: %s / Local resource: %s", directorytolist, localfile);
if (checkforevasion(rootdir, config.pubdirlist, localfile) != 0) {
- syslog(LOG_INFO, "Evasion attempt. Forbidden!");
+ LOG(INFO,"Evasion attempt. Forbidden!");
sendline(sock, "iForbidden!\tfake\tfake\t0");
@@ -1772,3 +1715,3 @@
if (is_it_a_directory(localfile) != 0) {
- if (chdir(localfile) != 0) syslog(LOG_WARNING, "WARNING: failed to switch to directory '%s'", localfile);
+ if (chdir(localfile) != 0) LOG(WARNING,"WARNING: failed to switch to directory '%s'", localfile);
outputdir(sock, &config, localfile, directorytolist, remoteclientaddr, srvsideparams);
@@ -1782,3 +1725,3 @@
if (changedir(localfile) != 0) {
- syslog(LOG_INFO, "ERROR: changedir() failure for '%s'", localfile);
+ LOG(INFO,"ERROR: changedir() failure for '%s'", localfile);
sendline(sock, "iForbidden!\tfake\tfake\t0");
@@ -1790,3 +1733,3 @@
if ((strcmp(directorytolist, "/caps.txt") == 0) && (config.capssupport != 0)) { /* If asking for /caps.txt, return it. */
- syslog(LOG_INFO, "Returned caps.txt data");
+ LOG(INFO,"Returned caps.txt data");
printcapstxt(sock, &config, pVer);
@@ -1800,3 +1743,3 @@
if ((fexist(localfile) == 0) || (islocalfileagophermap(localfile) != 0)) {
- syslog(LOG_INFO, "FileExists check: the file doesn't exists");
+ LOG(INFO,"FileExists check: the file doesn't exists");
sendline(sock, "3The selected resource doesn't exist!\tfake\tfake\t0");
@@ -1813,3 +1756,3 @@
/* error while reading attributes */
- syslog(LOG_INFO, "stat() failed: %s", strerror(errno));
+ LOG(INFO,"stat() failed: %s", strerror(errno));
sendline(sock, "3Internal error\tfake\tfake\t0");
@@ -1821,3 +1764,3 @@
/* not world-readable */
- syslog(LOG_INFO, "Paranoid mode check failed: file is not world-readable");
+ LOG(INFO,"Paranoid mode check failed: file is not world-readable");
sendline(sock, "3Permission denied\tfake\tfake\t0");
@@ -1845,3 +1788,3 @@
/* we want a normal file's content */
- syslog(LOG_INFO, "Returning file '%s'", localfile);
+ LOG(INFO,"Returning file '%s'", localfile);
gophertype = DetectGopherType(localfile, config.extmap);
@@ -1860,3 +1803,3 @@
close(sock);
- syslog(LOG_INFO, "connection closed. duration: %us", (unsigned int)(time(NULL) - StartTime));
+ LOG(INFO,"connection closed. duration: %us", (unsigned int)(time(NULL) - StartTime));
return(0);
========================================================================
--- motsognir/motsognir.h (nonexistent)
+++ motsognir+logmore/motsognir.h 2018-08-05 19:41:31.004474968 +0200
@@ -0,0 +1,83 @@
+/*
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * * Motsognir - The mighty gopher server *
+ * * Copyright (C) 2008-2016 Mateusz Viste *
+ * * http://motsognir.sourceforge.net *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * Some changes and additions: Copyright (C) 2018 Dario Niedermann
+ * $Id: motsognir.h 17 2018-08-05 17:41:30Z ndr $
+ * ----------------------------------------------------------------------
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * ----------------------------------------------------------------------
+ */
+
+#include <regex.h> /* regcomp(), regexec()... */
+
+/* Constants */
+#define pVer "1.0.9+logmore1.0"
+#define pDate "2008-2018"
+#define HOMEPAGE "http://motsognir.sourceforge.net"
+#define OK_EXIT_NOW -1
+
+ /* logging: */
+#define TO_SYSLOG 0
+#define TO_FILE 1
+#define INIT 65536 /* just needs to be a # not used in syslog.h */
+#define SET_PREFIX 65537 /* just needs to be a # not used in syslog.h */
+
+ /* parseCmdLine() operating modes: */
+#define FIRST_PASS 0
+#define FROM_FILE 1
+#define LAST_PASS 2
+
+struct MotsognirConfig {
+ char *gopherroot;
+ char *userdir;
+ char **pubdirlist;
+ int gopherport;
+ char *gopherhostname;
+ char *defaultgophermap;
+ int verbosemode;
+ int capssupport;
+ char *capsservergeolocationstring;
+ char *capsserverarchitecture;
+ char *capsserverdescription;
+ char *capsserverdefaultencoding;
+ int cgisupport;
+ int phpsupport;
+ int subgophermaps;
+ int paranoidmode;
+ char *plugin;
+ regex_t *pluginfilter;
+ char *runasuser;
+ uid_t runasuser_uid;
+ gid_t runasuser_gid;
+ char *runasuser_home;
+ char *chroot;
+ char *httperrfile;
+ char *bind;
+ char *extmapfile;
+ struct extmap_t *extmap;
+ char *configfile;
+ char securldelim;
+};
+
+struct logParams {
+ char loggingType;
+ int facility;
+ char *fileName;
+ int *localFacility; /* upon struct creation, point me to an array of
+ syslog facility values. Like in parseCmdLine() */
+};
==================================================END==OF==PATCH=*=*=***
-----BEGIN PGP SIGNATURE-----
iQIcBAEBAgAGBQJbcpi8AAoJEPJFaEEGrTgGxtgP/A4x/ff8d+WhbFL3EZeRvFSk
7sSdGObjo3NdhmJavYMcSB6EFuQ4rWH801LDlM5PeJeMJ6BNJlrfu4kQniSECoeK
GbLrA7osydjYd5EJfiUVx+UTtfF3OzIj9MyYW4MM4vaewuoXPTmS+M0f235rOuv3
ebo02yHI1f5sw6um9DfRf9lL9j2s4RAGdVjgawZSFa8ydOpHr9iiHKCtAKwZWsCY
2bv+LFbZT73asa3O7/REqmYlFkkGOdagSobdg6spAtPc8cEveAMJPOy3cHzAo08I
IDWshlYojynDfNBQ+SXMaxnqblFqegjOqv1ZX4LBz4p6KBcyjHD2e0njyk9CrCtN
LMS4WhVEfoFh5bpbbvv2PuEkXg9R4S5pdTXFPAarthNFQeSiqbc+yNQNhDmiwSFD
vmY9wjEayo03HFjp7b9xxJnzwGLmqfz5frJGXyWPEAfzdv332y+cXmCWsU9xb9FC
pMJLMvn5i3gRD4/fh8ppBqUsHrIbpCRj70+GQSxPSB4lPOuUbIonGafT3UZ5c7Xn
i7o2Kt56nhSDuiDLnEE1UqsaqkAirkI1j3nEBsEV+YyhaFLiV+DxMTqymY7CM29q
XjseWpdJx8FOxANlXBOVO+m15wntQknsdlWIqhNmKIWjY0W0HIMyE6z0eRNW9u+L
prIZZ5HQUndPIst9O/nA
=cu5F
-----END PGP SIGNATURE-----
“Logmore1.0 patch for Motsognir v1.0.9” is Copyright © Dario Niedermann —
Released with no warranty under the terms of the
GPLv3 license. Written and tested on Linux using GNU tools.