#include <errno.h>
#include <ctype.h>
#include <regex.h>
+#include <sys/wait.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
char *restpat;
};
-static struct config *config;
+static struct config *gconfig, *lconfig;
+static volatile int reload = 0;
static void freepattern(struct pattern *pat)
{
free(pat);
}
+static void freeconfig(struct config *cf)
+{
+ struct child *ch, *nch;
+ struct pattern *pat, *npat;
+
+ for(ch = cf->children; ch != NULL; ch = nch) {
+ nch = ch->next;
+ freechild(ch);
+ }
+ for(pat = cf->patterns; pat != NULL; pat = npat) {
+ npat = pat->next;
+ freepattern(pat);
+ }
+ free(cf);
+}
+
static struct child *getchild(struct config *cf, char *name)
{
struct child *ch;
char *chnm;
struct child *ch;
- if(((chnm = findmatch(config, req, 0)) == NULL) && ((chnm = findmatch(config, req, 1)) == NULL)) {
+ chnm = NULL;
+ if(chnm == NULL)
+ chnm = findmatch(lconfig, req, 0);
+ if(chnm == NULL)
+ chnm = findmatch(lconfig, req, 1);
+ if(gconfig != NULL) {
+ if(chnm == NULL)
+ chnm = findmatch(gconfig, req, 0);
+ if(chnm == NULL)
+ chnm = findmatch(gconfig, req, 1);
+ }
+ if(chnm == NULL) {
simpleerror(fd, 404, "Not Found", "The requested resource could not be found on this server.");
return;
}
- if((ch = getchild(config, chnm)) == NULL) {
+ ch = NULL;
+ if(ch == NULL)
+ ch = getchild(lconfig, chnm);
+ if(gconfig != NULL) {
+ if(ch == NULL)
+ ch = getchild(gconfig, chnm);
+ }
+ if(ch == NULL) {
flog(LOG_ERR, "child %s requested, but was not declared", chnm);
simpleerror(fd, 500, "Configuration Error", "The server is erroneously configured. Handler %s was requested, but not declared.", chnm);
return;
}
- if(childhandle(ch, req, fd))
+ if(childhandle(ch, req, fd, NULL, NULL))
simpleerror(fd, 500, "Server Error", "The request handler crashed.");
}
+static void reloadconf(char *nm)
+{
+ struct config *cf;
+
+ if((cf = readconfig(nm)) == NULL) {
+ flog(LOG_WARNING, "could not reload configuration file `%s'", nm);
+ return;
+ }
+ mergechildren(cf->children, lconfig->children);
+ freeconfig(lconfig);
+ lconfig = cf;
+}
+
+static void chldhandler(int sig)
+{
+ pid_t pid;
+
+ do {
+ pid = waitpid(-1, NULL, WNOHANG);
+ } while(pid > 0);
+}
+
+static void sighandler(int sig)
+{
+ if(sig == SIGHUP)
+ reload = 1;
+}
+
+static void usage(FILE *out)
+{
+ fprintf(out, "usage: patplex [-hN] CONFIGFILE\n");
+}
+
int main(int argc, char **argv)
{
+ int c;
+ int nodef;
+ char *gcf;
struct hthead *req;
int fd;
-
- if(argc < 2) {
- flog(LOG_ERR, "usage: patplex CONFIGFILE");
+
+ nodef = 0;
+ while((c = getopt(argc, argv, "hN")) >= 0) {
+ switch(c) {
+ case 'h':
+ usage(stdout);
+ exit(0);
+ case 'N':
+ nodef = 1;
+ break;
+ default:
+ usage(stderr);
+ exit(1);
+ }
+ }
+ if(argc - optind < 1) {
+ usage(stderr);
exit(1);
}
- config = readconfig(argv[1]);
- signal(SIGCHLD, SIG_IGN);
+ if(!nodef) {
+ if((gcf = findstdconf("ashd/patplex.rc")) != NULL) {
+ gconfig = readconfig(gcf);
+ free(gcf);
+ }
+ }
+ if((lconfig = readconfig(argv[optind])) == NULL) {
+ flog(LOG_ERR, "could not read `%s'", argv[optind]);
+ exit(1);
+ }
+ signal(SIGCHLD, chldhandler);
+ signal(SIGHUP, sighandler);
+ signal(SIGPIPE, sighandler);
while(1) {
+ if(reload) {
+ reloadconf(argv[optind]);
+ reload = 0;
+ }
if((fd = recvreq(0, &req)) < 0) {
+ if(errno == EINTR)
+ continue;
if(errno != 0)
flog(LOG_ERR, "recvreq: %s", strerror(errno));
break;