Commit: 96cb82a6a478ff62ad2559ad12243be22e7f9b26
Parent: e786a1955194a065984aa34575491764893073bc
Author: Randy Palamar
Date: Sun, 15 Aug 2021 16:57:38 -0600
import oboeruhttp
Diffstat:
3 files changed, 152 insertions(+), 2 deletions(-)
diff --git a/Makefile b/Makefile
@@ -4,7 +4,7 @@ include config.mk
OBOERU_SRC = oboeru.c util.c
OBOERU_OBJ = $(OBOERU_SRC:.c=.o)
-default: oboeru
+default: oboeru oboeruhttp
config.h:
cp config.def.h $@
@@ -17,13 +17,19 @@ $(OBOERU_OBJ): config.h
oboeru: $(OBOERU_OBJ)
$(CC) -o $@ $(OBOERU_OBJ) $(LDFLAGS)
+oboeruhttp:
+ go build -ldflags "$(GOLDFLAGS)" $@.go
+
install: oboeru
mkdir -p $(PREFIX)/bin
cp oboeru $(PREFIX)/bin
chmod 755 $(PREFIX)/bin/oboeru
+ cp oboeruhttp $(PREFIX)/bin
+ chmod 755 $(PREFIX)/bin/oboeruhttp
uninstall:
rm $(PREFIX)/bin/oboeru
+ rm $(PREFIX)/bin/oboeruhttp
clean:
- rm *.o oboeru
+ rm *.o oboeru oboeruhttp
diff --git a/config.mk b/config.mk
@@ -2,3 +2,6 @@ PREFIX = /usr/local
CPPFLAGS = -D_BSD_SOURCE
CFLAGS = -O2 -std=c99 -Wall -pedantic $(CPPFLAGS) $(INCS)
+LDFLAGS = -s -static
+
+GOLDFLAGS = -s
diff --git a/oboeruhttp.go b/oboeruhttp.go
@@ -0,0 +1,141 @@
+package main
+
+import (
+ "bufio"
+ "context"
+ "flag"
+ "fmt"
+ "net/http"
+ "os"
+ "strings"
+)
+
+var ctx context.Context
+var cancel context.CancelFunc
+
+var front, back string
+var cardlock = false
+
+var html_midf, html_midb, html_quit string
+const html_head = "<!DOCTYPE html><html><head><meta charset='utf-8' />" +
+ "<link rel='stylesheet' type='text/css' href='/_/style.css'>" +
+ "<title>oboeru</title></head><body><div>"
+const html_foot = "</div></body></html>"
+
+func usage() {
+ fmt.Fprintf(os.Stderr, "usage: %s [-p port] [-FPQS label]\n", os.Args[0])
+ flag.PrintDefaults()
+}
+
+func create_req_map() map[string]string {
+ return map[string]string {
+ "/fail": "fail",
+ "/pass": "pass",
+ "/quit": "quit",
+ "/show": "show",
+ }
+}
+
+func format_page(head string, body string, mid string, foot string) string {
+ return strings.Join([]string{head, body, mid, foot}, "")
+}
+
+func get_next_card() []string {
+ stdin := bufio.NewScanner(os.Stdin)
+ stdin.Scan()
+ return strings.Split(stdin.Text(), "\t")
+}
+
+func show_card(w http.ResponseWriter, card string, mid string) {
+ html := format_page(html_head, card, mid, html_foot)
+ w.Header().Set("Content-Type", "text/html; charset=utf-8")
+ fmt.Fprint(w, html)
+}
+
+func quit(w http.ResponseWriter) {
+ show_card(w, html_quit, "")
+ fmt.Fprintln(os.Stdout, "quit")
+ cancel() /* send signal to shutdown srv */
+}
+
+func response(w http.ResponseWriter, r *http.Request) {
+ req_map := create_req_map()
+
+ /* won't err since all invalid reqs have been rerouted to "/" */
+ str, _ := req_map[r.RequestURI]
+
+ switch str {
+ case "show":
+ show_card(w, back, html_midb)
+ case "quit":
+ quit(w)
+ case "fail":
+ fallthrough
+ case "pass":
+ cardlock = false
+ fmt.Fprintln(os.Stdout, str)
+ http.Redirect(w, r, "/", http.StatusSeeOther)
+ }
+}
+
+func serve(w http.ResponseWriter, r *http.Request) {
+ var card []string
+ if cardlock == false {
+ card = get_next_card()
+ if len(card) != 2 {
+ quit(w)
+ }
+
+ cardlock = true
+ front = card[0]
+ back = card[1]
+ }
+
+ show_card(w, front, html_midf)
+}
+
+func main() {
+ var (
+ port = flag.Uint("p", 6969, "port number")
+ fail = flag.String("F", "fail", "fail label")
+ pass = flag.String("P", "pass", "pass label")
+ show = flag.String("S", "show", "show label")
+ quit = flag.String("Q", "quit", "quit label")
+ bye = flag.String("q", "Goodbye!", "text to display before quitting")
+ )
+
+ flag.Usage = usage
+ flag.Parse()
+
+ html_midf = strings.Join([]string{"<a href='/quit'>", *quit,
+ "</a> · <a href='/show'>", *show, "</a>"}, "")
+ html_midb = strings.Join([]string{"<a href='/fail'>", *fail,
+ "</a> · <a href='/quit'>", *quit,
+ "</a> · <a href='/pass'>", *pass, "</a>"}, "")
+ html_quit = *bye
+
+ ctx, cancel = context.WithCancel(context.Background())
+
+ wd, _ := os.Getwd()
+ fs := http.FileServer(http.Dir(wd))
+
+ http.HandleFunc("/", serve)
+
+ /* pretend requested files are in wd/_/ so that they can
+ * be accessed on the fly */
+ http.Handle("/_/", http.StripPrefix("/_/", fs))
+
+ /* map allowed reqs to the handler fn response() */
+ for k, _ := range create_req_map() {
+ http.HandleFunc(k, response)
+ }
+
+ server := fmt.Sprintf(":%d", *port)
+ srv := &http.Server{Addr: server}
+ go func() {
+ srv.ListenAndServe()
+ }()
+ <- ctx.Done() /* wait for signal to shutdown */
+
+ srv.Shutdown(ctx)
+}