+package main
+
+import (
+ "flag"
+ "log"
+ "net"
+ "net/http"
+ "net/http/fcgi"
+ "os"
+ "os/signal"
+ "syscall"
+
+ "marisa.chaotic.ninja/marisa"
+)
+
+type templatedata struct {
+ Links []string
+ Size string
+ Maxsize string
+}
+
+type metadata struct {
+ Filename string
+ Size int64
+ Expiry int64
+}
+
+var conf struct {
+ user string
+ group string
+ chroot string
+ listen string
+ baseuri string
+ rootdir string
+ tmplpath string
+ filepath string
+ metapath string
+ filectx string
+ maxsize int64
+ expiry int64
+}
+
+var verbose bool
+
+func main() {
+ var err error
+ var configfile string
+ var listener net.Listener
+
+ /* default values */
+ conf.listen = "127.0.0.1:8080"
+ conf.baseuri = "http://127.0.0.1:8080"
+ conf.rootdir = "static"
+ conf.tmplpath = "templates"
+ conf.filepath = "files"
+ conf.metapath = "meta"
+ conf.filectx = "/f/"
+ conf.maxsize = 34359738368
+ conf.expiry = 86400
+
+ flag.StringVar(&configfile, "f", "", "Configuration file")
+ flag.BoolVar(&verbose, "v", false, "Verbose logging")
+ flag.Parse()
+
+ if configfile != "" {
+ if verbose {
+ log.Printf("Reading configuration %s", configfile)
+ }
+ parseconfig(configfile)
+ }
+
+ if conf.chroot != "" {
+ if verbose {
+ log.Printf("Changing root to %s", conf.chroot)
+ }
+ syscall.Chroot(conf.chroot)
+ }
+
+ if conf.listen[0] == '/' {
+ /* Remove any stale socket */
+ os.Remove(conf.listen)
+ if listener, err = net.Listen("unix", conf.listen); err != nil {
+ log.Fatal(err)
+ }
+ defer listener.Close()
+
+ /*
+ * Ensure unix socket is removed on exit.
+ * Note: this might not work when dropping privileges…
+ */
+ defer os.Remove(conf.listen)
+ sigs := make(chan os.Signal, 1)
+ signal.Notify(sigs, os.Interrupt, os.Kill, syscall.SIGTERM)
+ go func() {
+ _ = <-sigs
+ listener.Close()
+ if err = os.Remove(conf.listen); err != nil {
+ log.Fatal(err)
+ }
+ os.Exit(0)
+ }()
+ } else {
+ if listener, err = net.Listen("tcp", conf.listen); err != nil {
+ log.Fatal(err)
+ }
+ defer listener.Close()
+ }
+
+ if conf.user != "" {
+ if verbose {
+ log.Printf("Dropping privileges to %s", conf.user)
+ }
+ uid, gid, err := usergroupids(conf.user, conf.group)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ if listener.Addr().Network() == "unix" {
+ os.Chown(conf.listen, uid, gid)
+ }
+
+ syscall.Setuid(uid)
+ syscall.Setgid(gid)
+ }
+
+ http.HandleFunc("/", uploader)
+ http.Handle(conf.filectx, http.StripPrefix(conf.filectx, http.FileServer(http.Dir(conf.filepath))))
+
+ if verbose {
+ log.Printf("Starting marisa %v\n", marisa.FullVersion())
+ log.Printf("Listening on %s", conf.listen)
+ }
+
+ if listener.Addr().Network() == "unix" {
+ err = fcgi.Serve(listener, nil)
+ log.Fatal(err) /* NOTREACHED */
+ }
+
+ err = http.Serve(listener, nil)
+ log.Fatal(err) /* NOTREACHED */
+}