geomyidae

A small C-based gopherd. (gopher://bitreich.org/1/scm/geomyidae)
git clone git://r-36.net/geomyidae
Log | Files | Refs | README | LICENSE

commit 67eb195e1924b652b193e6332c1ce8f00fd1f2c9
parent f26ccad8ca8d0f79f7195f6871bb2ceac816ccfa
Author: Christoph Lohmann <20h@r-36.net>
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:
handlr.c | 20+++++++++++++-------
handlr.h | 23++++++++++++++++++-----
ind.c | 40++++++++++++++++++++++++++++++++++++++++
ind.h | 5++++-
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 *args, 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, char *args, 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, char *args, 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, char *args, 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, char *args, 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, char *args, 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 *port, char *clienth, 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");