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:
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");