git.sophuwu.com > manhttpd
added some config stuff
sophuwu sophie@sophuwu.com
Sat, 12 Jul 2025 22:20:37 +0200
commit

a134b32c433275c9df1266d260939e521b71f783

parent

2fb2c8272d5b4f258f98a26dcee4af4a42318296

M .gitignore.gitignore

@@ -1,5 +1,3 @@

.idea build/ -man2htmlsrc/.idea -man2htmlsrc/m2h -man2htmlsrc/mh+testdb
M CFG/CFG.goCFG/CFG.go

@@ -1,7 +1,7 @@

package CFG import ( - "net/http" + "fmt" "os" "os/exec" "sophuwu.site/manhttpd/neterr"

@@ -9,14 +9,18 @@ "strings"

) var ( + Mandoc string = "mandoc" + DbCmd string = "apropos" // or "whatis" + ManCmd string = "man" + Hostname string - Port string - Mandoc string - DbCmd string - ManCmd string - Server http.Server - Addr string ) + +func which(s string) (string, error) { + c := exec.Command("which", s) + b, e := c.CombinedOutput() + return strings.TrimSpace(string(b)), e +} func init() { var e error

@@ -33,46 +37,29 @@ if Hostname == "" {

Hostname = "Unresolved" } - if b, e = exec.Command("which", func() string { - if s = os.Getenv("MANDOCPATH"); s != "" { - return s - } - return "mandoc" - }()).Output(); e != nil || len(b) == 0 { + var err error + Mandoc, err = which("mandoc") + fmt.Println(Mandoc, err) + if err != nil || len(Mandoc) == 0 { neterr.Fatal("dependency `mandoc` not found in $PATH, is it installed?\n") - } else { - Mandoc = strings.TrimSpace(string(b)) + } + ManCmd, err = which("man") + if err != nil { + neterr.Fatal("dependency `man` not found in $PATH, is it installed?\n") } - f := func(s string) string { - if b, e = exec.Command("which", s).Output(); e != nil || len(b) == 0 { - return "" + DbCmd, err = which("apropos") + if err != nil || len(DbCmd) == 0 { + DbCmd, err = which("whatis") + if err != nil || len(DbCmd) == 0 { + neterr.Fatal("dependency `apropos` or `whatis` not found in $PATH, is it installed?\n") } - return strings.TrimSpace(string(b)) } - if s = f("man"); s == "" { - neterr.Fatal("dependency `man` not found. `man` and its libraries are required for manhttpd to function.") - } else { - ManCmd = s + if len(os.Args) > 1 && strings.HasSuffix(os.Args[1], ".conf") { + ConfFile = os.Args[1] } - - if s = f("apropos"); s == "" { - neterr.Fatal("dependency `apropos` not found. `apropos` is required for search functionality.") - } else { - DbCmd = s - } - - Port = os.Getenv("ListenPort") - if Port == "" { - Port = "8082" - } - Addr = os.Getenv("ListenAddr") - if Addr == "" { - Addr = "0.0.0.0" - } - - Server = http.Server{ - Addr: Addr + ":" + Port, - Handler: nil, + DefaultConf, err = ParseEtcConf() + if err != nil { + neterr.Fatal("Failed to parse configuration file:", err) } }
A CFG/etc.conf.go

@@ -0,0 +1,99 @@

+package CFG + +import ( + "fmt" + "net/http" + "os" + "strings" +) + +var ConfFile = "/etc/manhttpd/manhttpd.conf" + +type EtcConf struct { + Hostname string + Port string + Addr string + RequireAuth bool + PasswdFile string + TldrPages bool + EnableStats bool + StatisticDB string +} + +var DefaultConf = EtcConf{ + Hostname: "", + Port: "8082", + Addr: "0.0.0.0", + RequireAuth: false, + PasswdFile: "/etc/manhttpd/passwd", + TldrPages: false, + EnableStats: false, + StatisticDB: "/var/lib/manhttpd/stats.db", +} + +func (c *EtcConf) Parse() error { + var mp = map[string]any{ + "hostname": &(c.Hostname), + "port": &(c.Port), + "addr": &(c.Addr), + "require_auth": &(c.RequireAuth), + "passwd_file": &(c.PasswdFile), + "tldr_pages": &(c.TldrPages), + "enable_stats": &(c.EnableStats), + "statistic_db": &(c.StatisticDB), + } + b, err := os.ReadFile(ConfFile) + if err != nil { + return err + } + var j, k string + var kv []string + for _, v := range strings.Split(string(b), "\n") { + if len(v) == 0 || v[0] == '#' { + continue // skip empty lines and comments + } + kv = strings.SplitN(v, " ", 2) + if len(kv) != 2 { + return fmt.Errorf("invalid line in %s: %s", ConfFile, v) + } + k = strings.TrimSpace(kv[0]) + j = strings.TrimSpace(kv[1]) + if val, ok := mp[k]; ok { + switch v := val.(type) { + case *string: + *v = j + case *bool: + *v = j == "yes" + default: + return fmt.Errorf("unsupported type for key %s in %s", k, ConfFile) + } + } else { + return fmt.Errorf("unknown key %s in %s", k, ConfFile) + } + } + return nil +} + +func ParseEtcConf() (EtcConf, error) { + c := DefaultConf + if err := c.Parse(); err != nil { + return c, fmt.Errorf("failed to parse %s: %w", ConfFile, err) + } + if c.Port == "" { + c.Port = "8082" + } + if c.Addr == "" { + c.Addr = "0.0.0.0" + } + if c.Hostname != "" { + Hostname = c.Hostname + } + return c, nil +} + +func (c *EtcConf) Server(h http.Handler) *http.Server { + return &http.Server{ + Addr: c.Addr + ":" + c.Port, + Handler: h, + } +}
M extra/nfpm.yamlextra/nfpm.yaml

@@ -33,9 +33,10 @@ contents:

- src: ../build/manhttpd dst: /usr/bin/manhttpd - src: ./manhttpd.service - dst: /etc/manhttpd.service + dst: /etc/manhttpd/manhttpd.service type: config overrides: deb: scripts: postinstall: ./postinstall.sh + preinstall: ./preinst.sh
M extra/postinstall.shextra/postinstall.sh

@@ -1,8 +1,16 @@

#!/bin/bash if [[ -f /etc/manhttpd.service ]]; then - ln -s /etc/manhttpd.service /etc/systemd/system/manhttpd.service + mv /etc/manhttpd.service /etc/manhttpd/manhttpd.service +fi +if [[ -f /etc/manhttpd/manhttpd.service ]]; then + ln -s /etc/manhttpd/manhttpd.service /etc/systemd/system/manhttpd.service fi +if [[ ! -d /var/lib/manhttpd ]]; then + mkdir -p /var/lib/manhttpd +fi +chown manhttpd:manhttpd /var/lib/manhttpd + systemctl daemon-reload systemctl enable manhttpd systemctl start manhttpd
A extra/preinst.sh

@@ -0,0 +1,24 @@

+#!/bin/bash + +getent group manhttpd > /dev/null +if [[ $? -ne 0 ]]; then + addgroup --system manhttpd +fi + +getent passwd manhttpd > /dev/null +if [[ $? -ne 0 ]]; then + adduser --system --disabled-password --home /var/lib/manhttpd --no-create-home --group manhttpd manhttpd +fi + + + +if [[ ! -d /var/lib/manhttpd ]]; then + mkdir -p /var/lib/manhttpd + chown manhttpd:manhttpd /var/lib/manhttpd + chmod 755 /var/lib/manhttpd +fi + +# Create the configuration directory for manhttpd +if [[ ! -d /etc/manhttpd ]]; then + mkdir -p /etc/manhttpd +fi
M go.modgo.mod

@@ -1,3 +1,5 @@

module sophuwu.site/manhttpd go 1.21.5 + +require gopkg.in/yaml.v3 v3.0.1
M go.sumgo.sum

@@ -0,0 +1,4 @@

+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
M main.gomain.go

@@ -13,8 +13,8 @@ "strings"

) func main() { - CFG.Server.Handler = ManHandler{} - err := CFG.Server.ListenAndServe() + s := CFG.DefaultConf.Server(ManHandler{}) + err := s.ListenAndServe() if err != nil { fmt.Println("Error starting server:", err) }
M manpage/manpage.gomanpage/manpage.go

@@ -24,7 +24,7 @@ var arg = []string{"-w", m.Name}

if m.Section != "" { arg = []string{"-w", "-s" + m.Section, m.Name} } - b, err := exec.Command("man", arg...).Output() + b, err := exec.Command(CFG.ManCmd, arg...).Output() m.Path = strings.TrimSpace(string(b)) return err }