| Implement some CGI variables for gopher. - geomyidae - A small C-based gopherd. | |
| git clone git://bitreich.org/geomyidae/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfri… | |
| Log | |
| Files | |
| Refs | |
| Tags | |
| README | |
| LICENSE | |
| --- | |
| commit 67eb195e1924b652b193e6332c1ce8f00fd1f2c9 | |
| parent f26ccad8ca8d0f79f7195f6871bb2ceac816ccfa | |
| Author: Christoph Lohmann <[email protected]> | |
| Date: Fri, 26 Jan 2018 13:44:53 +0100 | |
| Implement some CGI variables for gopher. | |
| I need this for having a nice IP handler on bitreich.org. | |
| Diffstat: | |
| M handlr.c | 20 +++++++++++++------- | |
| M handlr.h | 23 ++++++++++++++++++----- | |
| M ind.c | 40 +++++++++++++++++++++++++++++… | |
| M ind.h | 5 ++++- | |
| M main.c | 5 +++-- | |
| 5 files changed, 78 insertions(+), 15 deletions(-) | |
| --- | |
| diff --git a/handlr.c b/handlr.c | |
| @@ -21,7 +21,7 @@ | |
| void | |
| handledir(int sock, char *path, char *port, char *base, char *args, | |
| - char *sear, char *ohost) | |
| + char *sear, char *ohost, char *chost) | |
| { | |
| char *pa, *file, *e, *par, *b; | |
| struct dirent **dirent; | |
| @@ -78,7 +78,7 @@ handledir(int sock, char *path, char *port, char *base, char … | |
| void | |
| handlegph(int sock, char *file, char *port, char *base, char *args, | |
| - char *sear, char *ohost) | |
| + char *sear, char *ohost, char *chost) | |
| { | |
| Indexs *act; | |
| int i, ret = 0; | |
| @@ -102,7 +102,7 @@ handlegph(int sock, char *file, char *port, char *base, cha… | |
| void | |
| handlebin(int sock, char *file, char *port, char *base, char *args, | |
| - char *sear, char *ohost) | |
| + char *sear, char *ohost, char *chost) | |
| { | |
| int fd; | |
| @@ -122,7 +122,7 @@ handlebin(int sock, char *file, char *port, char *base, cha… | |
| void | |
| handlecgi(int sock, char *file, char *port, char *base, char *args, | |
| - char *sear, char *ohost) | |
| + char *sear, char *ohost, char *chost) | |
| { | |
| char *p, *path; | |
| @@ -157,7 +157,10 @@ handlecgi(int sock, char *file, char *port, char *base, ch… | |
| break; | |
| } | |
| - if (execl(file, p, sear, args, ohost, port, (char *)nil) == -1… | |
| + setcgienviron(p, file, port, base, args, sear, ohost, chost); | |
| + | |
| + if (execl(file, p, sear, args, ohost, port, | |
| + (char *)nil) == -1) { | |
| perror("execl"); | |
| _exit(1); | |
| } | |
| @@ -173,7 +176,7 @@ handlecgi(int sock, char *file, char *port, char *base, cha… | |
| void | |
| handledcgi(int sock, char *file, char *port, char *base, char *args, | |
| - char *sear, char *ohost) | |
| + char *sear, char *ohost, char *chost) | |
| { | |
| FILE *fp; | |
| char *p, *path, *ln = nil; | |
| @@ -216,7 +219,10 @@ handledcgi(int sock, char *file, char *port, char *base, c… | |
| break; | |
| } | |
| - if (execl(file, p, sear, args, ohost, port, (char *)nil) == -1… | |
| + setcgienviron(p, file, port, base, args, sear, ohost, chost); | |
| + | |
| + if (execl(file, p, sear, args, ohost, port, | |
| + (char *)nil) == -1) { | |
| perror("execl"); | |
| _exit(1); | |
| } | |
| diff --git a/handlr.h b/handlr.h | |
| @@ -6,15 +6,28 @@ | |
| #ifndef HANDLR_H | |
| #define HANDLR_H | |
| +/* | |
| + * Handler API definition | |
| + * | |
| + * path .... path to the script relative from base | |
| + * port .... port which the script should use when defining menu items | |
| + * (See -o and -p in geomyidae(8)) | |
| + * base .... base path of geomyidae ("" in case of chroot) | |
| + * args .... query string parsed after »script?query« | |
| + * sear .... search part of request (»selector\tsearch\r\n«) | |
| + * ohost ... host of geomiydae (See -h in geomyidae(8)) | |
| + * chost ... IP of the client sending a request | |
| + */ | |
| + | |
| void handledir(int sock, char *path, char *port, char *base, char *args, | |
| - char *sear, char *ohost); | |
| + char *sear, char *ohost, char *chost); | |
| void handlegph(int sock, char *file, char *port, char *base, char *args, | |
| - char *sear, char *ohost); | |
| + char *sear, char *ohost, char *chost); | |
| void handlebin(int sock, char *file, char *port, char *base, char *args, | |
| - char *sear, char *ohost); | |
| + char *sear, char *ohost, char *chost); | |
| void handlecgi(int sock, char *file, char *port, char *base, char *args, | |
| - char *sear, char *ohost); | |
| + char *sear, char *ohost, char *chost); | |
| void handledcgi(int sock, char *file, char *port, char *base, char *args, | |
| - char *sear, char *ohost); | |
| + char *sear, char *ohost, char *chost); | |
| #endif | |
| diff --git a/ind.c b/ind.c | |
| @@ -419,3 +419,43 @@ reverselookup(char *host) | |
| return rethost; | |
| } | |
| +void | |
| +setcgienviron(char *file, char *path, char *port, char *base, char *args, | |
| + char *sear, char *ohost, char *chost) | |
| +{ | |
| + char *s; | |
| + | |
| + unsetenv("AUTH_TYPE"); | |
| + unsetenv("CONTENT_LENGTH"); | |
| + unsetenv("CONTENT_TYPE"); | |
| + setenv("GATEWAY_INTERFACE", "CGI/1.1", 1); | |
| + /* TODO: Separate, if run like rest.dcgi. */ | |
| + setenv("PATH_INFO", path, 1); | |
| + | |
| + s = smprintf("%s/%s", base, path); | |
| + setenv("PATH_TRANSLATED", s, 1); | |
| + free(s); | |
| + | |
| + setenv("QUERY_STRING", args, 1); | |
| + setenv("REMOTE_ADDR", chost, 1); | |
| + /* | |
| + * Don't do a reverse lookup on every call. Only do when needed, in | |
| + * the script. The RFC allows us to set the IP to the value. | |
| + */ | |
| + setenv("REMOTE_HOST", chost, 1); | |
| + unsetenv("REMOTE_IDENT"); | |
| + unsetenv("REMOTE_USER"); | |
| + /* | |
| + * Only GET is possible in gopher. POST emulation would be really | |
| + * ugly. | |
| + */ | |
| + setenv("REQUEST_METHOD", "GET", 1); | |
| + setenv("SCRIPT_NAME", file, 1); | |
| + setenv("SERVER_NAME", ohost, 1); | |
| + setenv("SERVER_PORT", port, 1); | |
| + setenv("SERVER_PROTOCOL", "gopher/1.0", 1); | |
| + setenv("SERVER_SOFTWARE", "geomyidae", 1); | |
| + | |
| + setenv("X_GOPHER_SEARCH", sear, 1); | |
| +} | |
| + | |
| diff --git a/ind.h b/ind.h | |
| @@ -27,7 +27,8 @@ typedef struct filetype filetype; | |
| struct filetype { | |
| char *end; | |
| char *type; | |
| - void (* f)(int, char *, char *, char *, char *, char *, char *); | |
| + void (* f)(int, char *, char *, char *, char *, char *, char *, | |
| + char *); | |
| }; | |
| filetype *gettype(char *filename); | |
| @@ -47,6 +48,8 @@ int initlogging(char *logf); | |
| void stoplogging(int fd); | |
| char *smprintf(char *fmt, ...); | |
| char *reverselookup(char *host); | |
| +void setcgienviron(char *file, char *path, char *port, char *base, | |
| + char *args, char *sear, char *ohost, char *chost); | |
| #endif | |
| diff --git a/main.c b/main.c | |
| @@ -192,10 +192,11 @@ handlerequest(int sock, char *base, char *ohost, char *po… | |
| if (c == nil) | |
| c = path; | |
| type = gettype(c); | |
| - type->f(sock, path, port, base, args, sear, ohost); | |
| + type->f(sock, path, port, base, args, sear, ohost, clienth); | |
| } else { | |
| if (S_ISDIR(dir.st_mode)) { | |
| - handledir(sock, path, port, base, args, sear, ohost); | |
| + handledir(sock, path, port, base, args, sear, ohost, | |
| + clienth); | |
| if (loglvl & DIRS) { | |
| logentry(clienth, clientp, recvc, | |
| "dir listing"); |