X-Git-Url: http://www.dolda2000.com/gitweb/?p=ashd.git;a=blobdiff_plain;f=src%2Fdirplex%2Fconf.c;fp=src%2Fdirplex.c;h=96a7704b6fc11516ec5c0387229fd0f3019fda02;hp=de9ecf28c2146aeb15ef9544c034dedd223436c4;hb=600a1ce79471493f8cad5fcf118dc9797331d5aa;hpb=7f5a46defa51aef52a9b2aca958d90c01b8804ed diff --git a/src/dirplex.c b/src/dirplex/conf.c similarity index 53% rename from src/dirplex.c rename to src/dirplex/conf.c index de9ecf2..96a7704 100644 --- a/src/dirplex.c +++ b/src/dirplex/conf.c @@ -18,59 +18,23 @@ #include #include -#include #include +#include #include -#include -#include -#include #include -#include +#include #ifdef HAVE_CONFIG_H #include #endif #include -#include #include -#include -#include -#include #include -#define PAT_BASENAME 0 -#define PAT_PATHNAME 1 -#define PAT_ALL 2 -#define PAT_DEFAULT 3 - -#define PT_FILE 0 -#define PT_DIR 1 - -struct config { - struct config *next, *prev; - char *path; - time_t mtime, lastck; - struct child *children; - struct pattern *patterns; - char **index; -}; - -struct rule { - int type; - char **patterns; -}; - -struct pattern { - struct pattern *next; - int type; - char *childnm; - char **fchild; - struct rule **rules; -}; +#include "dirplex.h" static struct config *cflist; -static struct config *gconfig, *lconfig; -static time_t now; +struct config *gconfig, *lconfig; static void freerule(struct rule *rule) { @@ -115,7 +79,7 @@ static void freeconfig(struct config *cf) free(cf); } -static struct child *getchild(struct config *cf, char *name) +struct child *getchild(struct config *cf, char *name) { struct child *ch; @@ -236,7 +200,7 @@ static struct config *emptyconfig(void) return(cf); } -static struct config *readconfig(char *file) +struct config *readconfig(char *file) { struct cfstate *s; FILE *in; @@ -276,7 +240,7 @@ static struct config *readconfig(char *file) return(cf); } -static struct config *getconfig(char *path) +struct config *getconfig(char *path) { struct config *cf; struct stat sb; @@ -315,7 +279,7 @@ static struct config *getconfig(char *path) return(cf); } -static struct config **getconfigs(char *file) +struct config **getconfigs(char *file) { static struct config **ret = NULL; struct { @@ -347,7 +311,7 @@ static struct config **getconfigs(char *file) return(ret = buf.b); } -static struct child *findchild(char *file, char *name) +struct child *findchild(char *file, char *name) { int i; struct config **cfs; @@ -361,7 +325,7 @@ static struct child *findchild(char *file, char *name) return(ch); } -static struct pattern *findmatch(char *file, int trydefault, int dir) +struct pattern *findmatch(char *file, int trydefault, int dir) { int i, o, c; char *bn; @@ -409,276 +373,3 @@ static struct pattern *findmatch(char *file, int trydefault, int dir) return(findmatch(file, 1, dir)); return(NULL); } - -static void handle(struct hthead *req, int fd, char *path, struct pattern *pat) -{ - struct child *ch; - - headappheader(req, "X-Ash-File", path); - if(pat->fchild) { - stdforkserve(pat->fchild, req, fd); - } else { - if((ch = findchild(path, pat->childnm)) == NULL) { - flog(LOG_ERR, "child %s requested, but was not declared", pat->childnm); - simpleerror(fd, 500, "Configuration Error", "The server is erroneously configured. Handler %s was requested, but not declared.", pat->childnm); - return; - } - if(childhandle(ch, req, fd)) - simpleerror(fd, 500, "Server Error", "The request handler crashed."); - } -} - -static void handlefile(struct hthead *req, int fd, char *path) -{ - struct pattern *pat; - - if((pat = findmatch(path, 0, 0)) == NULL) { - simpleerror(fd, 404, "Not Found", "The requested URL has no corresponding resource."); - return; - } - handle(req, fd, path, pat); -} - -static char *findfile(char *path, char *name, struct stat *sb) -{ - DIR *dir; - struct stat sbuf; - struct dirent *dent; - char *p, *fp, *ret; - - if(sb == NULL) - sb = &sbuf; - if((dir = opendir(path)) == NULL) - return(NULL); - ret = NULL; - while((dent = readdir(dir)) != NULL) { - /* Ignore backup files. - * XXX: There is probably a better and more extensible way to - * do this. */ - if(dent->d_name[strlen(dent->d_name) - 1] == '~') - continue; - if((p = strchr(dent->d_name, '.')) == NULL) - continue; - if(p - dent->d_name != strlen(name)) - continue; - if(strncmp(dent->d_name, name, strlen(name))) - continue; - fp = sprintf3("%s/%s", path, dent->d_name); - if(stat(fp, sb)) - continue; - if(!S_ISREG(sb->st_mode)) - continue; - ret = sstrdup(fp); - break; - } - closedir(dir); - return(ret); -} - -static void handledir(struct hthead *req, int fd, char *path) -{ - struct config **cfs; - int i, o; - struct stat sb; - char *inm, *ipath, *cpath; - struct pattern *pat; - - cpath = sprintf2("%s/", path); - cfs = getconfigs(cpath); - for(i = 0; cfs[i] != NULL; i++) { - if(cfs[i]->index != NULL) { - for(o = 0; cfs[i]->index[o] != NULL; o++) { - inm = cfs[i]->index[o]; - ipath = sprintf2("%s/%s", path, inm); - if(!stat(ipath, &sb) && S_ISREG(sb.st_mode)) { - handlefile(req, fd, ipath); - free(ipath); - goto out; - } - free(ipath); - - if(!strchr(inm, '.') && ((ipath = findfile(path, inm, NULL)) != NULL)) { - handlefile(req, fd, ipath); - free(ipath); - goto out; - } - } - break; - } - } - if((pat = findmatch(cpath, 0, 1)) != NULL) { - handle(req, fd, cpath, pat); - goto out; - } - simpleerror(fd, 403, "Not Authorized", "Will not send listings for this directory."); - -out: - free(cpath); -} - -static int checkpath(struct hthead *req, int fd, char *path, char *rest); - -static int checkentry(struct hthead *req, int fd, char *path, char *rest, char *el) -{ - struct stat sb; - char *newpath; - int rv; - - if(!el == '.') { - simpleerror(fd, 404, "Not Found", "The requested URL has no corresponding resource."); - return(1); - } - if(!stat(sprintf3("%s/%s", path, el), &sb)) { - if(S_ISDIR(sb.st_mode)) { - if(!*rest) { - stdredir(req, fd, 301, sprintf3("%s/", el)); - return(1); - } - newpath = sprintf2("%s/%s", path, el); - rv = checkpath(req, fd, newpath, rest + 1); - free(newpath); - return(rv); - } else if(S_ISREG(sb.st_mode)) { - newpath = sprintf2("%s/%s", path, el); - replrest(req, rest); - handlefile(req, fd, newpath); - free(newpath); - return(1); - } - simpleerror(fd, 404, "Not Found", "The requested URL has no corresponding resource."); - return(1); - } - if(!strchr(el, '.') && ((newpath = findfile(path, el, NULL)) != NULL)) { - replrest(req, rest); - handlefile(req, fd, newpath); - free(newpath); - return(1); - } - return(0); -} - -static int checkpath(struct hthead *req, int fd, char *path, char *rest) -{ - struct config *cf; - char *p, *el; - int rv; - - el = NULL; - rv = 0; - - if(!strncmp(path, "./", 2)) - path += 2; - cf = getconfig(path); - - if((p = strchr(rest, '/')) == NULL) { - el = unquoteurl(rest); - rest = ""; - } else { - char buf[p - rest + 1]; - memcpy(buf, rest, p - rest); - buf[p - rest] = 0; - el = unquoteurl(buf); - rest = p; - } - if(el == NULL) { - simpleerror(fd, 400, "Bad Request", "The requested URL contains an invalid escape sequence."); - rv = 1; - goto out; - } - if(strchr(el, '/') || (!*el && *rest)) { - simpleerror(fd, 404, "Not Found", "The requested URL has no corresponding resource."); - rv = 1; - goto out; - } - if(!*el) { - replrest(req, rest); - handledir(req, fd, path); - return(1); - } - rv = checkentry(req, fd, path, rest, el); - -out: - if(el != NULL) - free(el); - return(rv); -} - -static void serve(struct hthead *req, int fd) -{ - now = time(NULL); - if(!checkpath(req, fd, ".", req->rest)) - simpleerror(fd, 404, "Not Found", "The requested URL has no corresponding resource."); -} - -static void usage(FILE *out) -{ - fprintf(out, "usage: dirplex [-hN] [-c CONFIG] DIR\n"); -} - -int main(int argc, char **argv) -{ - int c; - int nodef; - char *gcf, *lcf, *clcf; - struct hthead *req; - int fd; - - nodef = 0; - lcf = NULL; - while((c = getopt(argc, argv, "hNc:")) >= 0) { - switch(c) { - case 'h': - usage(stdout); - exit(0); - case 'N': - nodef = 1; - break; - case 'c': - lcf = optarg; - break; - default: - usage(stderr); - exit(1); - } - } - if(argc - optind < 1) { - usage(stderr); - exit(1); - } - if(!nodef) { - if((gcf = findstdconf("ashd/dirplex.rc")) != NULL) { - gconfig = readconfig(gcf); - free(gcf); - } - } - if(lcf != NULL) { - if(strchr(lcf, '/') == NULL) { - if((clcf = findstdconf(sprintf3("ashd/%s", lcf))) == NULL) { - flog(LOG_ERR, "could not find requested configuration `%s'", lcf); - exit(1); - } - if((lconfig = readconfig(clcf)) == NULL) - exit(1); - free(clcf); - } else { - if((lconfig = readconfig(lcf)) == NULL) - exit(1); - } - } - if(chdir(argv[optind])) { - flog(LOG_ERR, "could not change directory to %s: %s", argv[optind], strerror(errno)); - exit(1); - } - signal(SIGCHLD, SIG_IGN); - while(1) { - if((fd = recvreq(0, &req)) < 0) { - if(errno != 0) - flog(LOG_ERR, "recvreq: %s", strerror(errno)); - break; - } - serve(req, fd); - freehthead(req); - close(fd); - } - return(0); -}