ref: dc359256b98b9aa563e73066e2c3c3c1204c5b2a
parent: 8e7a55ce137949da45c0d63e6a7c6243f3719d25
author: Tevo <estevan.cps@gmail.com>
date: Fri Nov 6 14:18:24 EST 2020
Exec command, code cleanup
--- a/waffle.c
+++ b/waffle.c
@@ -5,13 +5,14 @@
#include <bio.h>
#include <String.h>
+char *querystr;
char *stubhost = "error.host\t1";
char *gopherhost = "localhost";
char *spacetab = " ";
char *srvroot = "./";
-char *defprog = " \n\
- info $user@$sysname:$querystr\n\
- dir 'my home!' /usr/tevo\n\
+char *defprog = "\n\
+ info you seem to be lost...\n\
+ dir 'back home' /\n\
";
enum
@@ -59,7 +60,7 @@
char *k;
int op;
} ops[] = {
- {"#", OP_COMMENT},
+ {"--", OP_COMMENT},
{"exec", OP_EXEC},
{"info", GOPHER_INFO},
@@ -91,7 +92,47 @@
return -1;
}
+char*
+readall(char *path)
+{
+ char *buf;
+ int fd, bsize = 4096;
+
+ if((fd = open(path, OREAD)) < 0)
+ sysfatal("open: %r");
+
+ buf = malloc(bsize);
+ if(buf == nil)
+ sysfatal("malloc: %r");
+
+ for(int c = 0; read(fd, buf+(c*bsize), bsize) != 0; c++)
+ {
+ buf = realloc(buf, ((c+2)*bsize));
+ if(buf == nil)
+ sysfatal("realloc: %r");
+ }
+
+ close(fd);
+ return buf;
+}
+
/*
+ * Funny bug, sometimes strings allocated on multiple invocations
+ * of the same function ends up with leftovers from previous invocations,
+ * probably getting assigned the same memory location as before (which
+ * wasn't cleaned up, so it's full of garbage), and the string "picks it up".
+ * s_terminate doesn't seem to do it's job, somehow, or I'm doing something
+ * wrong.
+ * FIXME investigate this
+ */
+void
+s_cleanup(String *str)
+{
+ for(char *c = str->base; c < str->end; c++)
+ *c = 0;
+}
+
+/*
* Like %s, but replaces tabs with spacetab
*/
#pragma varargck type "G" char*
@@ -162,6 +203,7 @@
s_putc(out, *str);
}
+ s_terminate(out);
ret = fmtprint(fmt, "%G", s_to_c(out));
s_free(scratch);
@@ -186,7 +228,7 @@
return n;
}
-#pragma varargck argpos info 1
+#pragma varargck argpos error 1
int
error(char *fmt, ...)
{
@@ -210,7 +252,8 @@
/*
* FIXME we should timeout at some point, so a user can't take us down
- * by opening connections but never sending a CRLF
+ * by opening connections but never sending a CRLF.
+ * Maybe it's not our job.
*/
String*
readrequest(void)
@@ -237,11 +280,34 @@
return strdup(req);
}
+/* FIXME disallow requests outside gopherroot */
String*
getprog(char *path)
{
- /* FIXME actually read index.waffle */
- return s_copy(defprog);
+ String *prog;
+ char *apath, buf[4096];
+ int fd, n;
+
+ apath = smprint("%s/%s", srvroot, path);
+ if(apath == nil)
+ sysfatal("smprint: %r");
+
+ if(chdir(apath) != 0)
+ {
+ free(apath);
+ return s_copy(defprog);
+ }
+ free(apath);
+
+ if((fd = open("index.waffle", OREAD)) < 0)
+ return s_copy(defprog);
+
+ prog = s_new();
+ while((n = read(fd, buf, sizeof(buf))) != 0)
+ s_memappend(prog, buf, n);
+
+ close(fd);
+ return prog;
}
String*
@@ -256,13 +322,7 @@
return nil;
comm = s_new();
- /*
- * funny bug, not sure what triggers this.
- * maybe we repeatedly get the same memory block
- * and the leftovers end up being used?
- */
- for(char *ptr = comm->base; ptr != comm->end; ptr++)
- *ptr = 0;
+ s_cleanup(comm);
for(; *prog->ptr != '\0'; prog->ptr++)
{
@@ -273,7 +333,7 @@
s_terminate(comm);
s_restart(comm);
-
+
return comm;
}
@@ -296,7 +356,7 @@
s_append(p[c], defval[c]);
else
{
- fprint(2, "incomplete command '%c'", op);
+ fprint(2, "incomplete command '%c'\n", op);
goto cleanup;
}
}
@@ -308,6 +368,33 @@
}
void
+shellexec(char *cmd)
+{
+ Waitmsg *msg;
+ char *argv[] = { "/bin/rc", "-c", cmd };
+ int rcin[2];
+ pipe(rcin);
+ switch(rfork(RFFDG|RFPROC|RFMEM|RFNAMEG|RFNOTEG|RFREND))
+ {
+ case 0:
+ close(0);
+ dup(rcin[0], 0);
+ close(rcin[0]);
+ exec("/bin/rc", argv);
+ sysfatal("exec: %r");
+ break;
+ case -1:
+ sysfatal("rfork: %r");
+ break;
+ default:
+ write(rcin[1], querystr, strlen(querystr));
+ msg = wait();
+ if(strlen(msg->msg) != 0)
+ fprint(2, "rc: %s\n", msg->msg);
+ }
+}
+
+void
interprog(String *prog)
{
int op;
@@ -318,12 +405,13 @@
while((line = nextcomm(prog)) != nil)
{
s_parse(line, curtok);
+ s_terminate(curtok);
switch(op = opforcmd(s_to_c(curtok)))
{
case OP_COMMENT:
break;
case OP_EXEC:
- error("exec not implemented (yet)");
+ shellexec(line->ptr);
break;
case GOPHER_INFO:
info("%V", line->ptr);
@@ -347,7 +435,7 @@
main(int argc, char **argv)
{
String *req, *prog;
- char *path;
+ char *path, pwd[512];
ARGBEGIN {
case 'r':
@@ -354,8 +442,10 @@
srvroot = EARGF(usage());
break;
case 'd':
- fprint(2, "defprog: not implemented\n");
- exits("noimpl");
+ defprog = readall(EARGF(usage()));
+ if(defprog == nil)
+ sysfatal("readall: %r");
+ break;
case 'h':
gopherhost = EARGF(usage());
break;
@@ -366,7 +456,14 @@
fmtinstall('G', gopherfmt);
fmtinstall('V', varfmt);
+ if(chdir(srvroot) != 0)
+ sysfatal("chdir: %r");
+
+ if(getwd(pwd, sizeof(pwd)) == 0)
+ sysfatal("getwd: %r");
+
req = readrequest();
+ querystr = s_to_c(req);
path = parsepath(s_to_c(req));
if(path == nil)
@@ -375,6 +472,7 @@
goto end;
}
+ putenv("gopherroot", pwd);
putenv("gopherhost", gopherhost);
putenv("querystr", s_to_c(req));
putenv("pathstr", path);