git.sophuwu.com > manhttpd   
              152
            
             package CFG

import (
	"context"
	"errors"
	"fmt"
	"git.sophuwu.com/gophuwu/flags"
	"git.sophuwu.com/manhttpd/neterr"
	"golang.org/x/sys/unix"
	"net/http"
	"os"
	"os/exec"
	"os/signal"
	"strings"
)

var (
	Mandoc      string = "mandoc"
	DbCmd       string = "apropos" // or "whatis"
	ManCmd      string = "man"
	Hostname    string = ""
	Port        string = "8082"
	Addr        string = "0.0.0.0"
	RequireAuth bool   = false
	PasswdFile  string = "/var/lib/manhttpd/authuwu"
	TldrPages   bool   = false
	TldrDir     string = "/var/lib/manhttpd/tldr"
	EnableStats bool   = false
	StatisticDB string = "/var/lib/manhttpd/manhttpd.db"
	UseTLS      bool   = false
	TLSCertFile string = ""
	TLSKeyFile  string = ""
)

func which(s string) (string, error) {
	c := exec.Command("which", s)
	b, e := c.CombinedOutput()
	return strings.TrimSpace(string(b)), e
}

func checkCmds() {
	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")
	}
	ManCmd, err = which("man")
	if err != nil {
		neterr.Fatal("dependency `man` not found in $PATH, is it installed?\n")
	}
	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")
		}
	}
}

func getHostname() {
	var e error
	var b []byte
	var s string
	if s = os.Getenv("HOSTNAME"); s != "" {
		Hostname = s
	} else if s, e = os.Hostname(); e == nil {
		Hostname = s
	} else if b, e = os.ReadFile("/etc/hostname"); e == nil {
		Hostname = strings.TrimSpace(string(b))
	}
}

func getEnvs() {
	var s string
	s = os.Getenv("ListenPort")
	if s != "" {
		Port = s
	}
	s = os.Getenv("ListenAddr")
	if s != "" {
		Addr = s
	}
}

func ParseConfig() {
	checkCmds()

	s, err := flags.GetStringFlag("conf")
	if err != nil {
		neterr.Fatal("Failed to get configuration file flag:", err)
	}
	if s != "" {
		ConfFile = s
	}

	err = parse()
	if err != nil {
		if !errors.Is(err, NoConfError) {
			neterr.Fatal("Failed to parse configuration file:", err)
		}
		getEnvs()
	}

	if Hostname == "" {
		getHostname()
	}
}

func HttpHostname(r *http.Request) string {
	if Hostname != "" {
		return Hostname
	}
	if r.Host != "" {
		return r.Host
	}
	if r.URL != nil && r.URL.Host != "" {
		return r.URL.Host
	}
	if r.TLS != nil && r.TLS.ServerName != "" {
		return r.TLS.ServerName
	}
	return ""
}

func ListenAndServe(h http.Handler) {
	var err error
	server := http.Server{
		Addr:    Addr + ":" + Port,
		Handler: h,
	}
	sigchan := make(chan os.Signal)
	go func() {
		signal.Notify(sigchan, unix.SIGINT, unix.SIGTERM, unix.SIGQUIT, unix.SIGKILL, unix.SIGSTOP)
		<-sigchan
		fmt.Println("Stopping server...")
		err = server.Shutdown(context.Background())
		if err != nil {
			fmt.Println("Error stopping server: %v", err)
		}
	}()
	fmt.Println("Starting server on", server.Addr)
	if UseTLS && TLSCertFile != "" && TLSKeyFile != "" {
		err = server.ListenAndServeTLS(TLSCertFile, TLSKeyFile)
	} else {
		err = server.ListenAndServe()
	}
	if err != nil && !errors.Is(err, http.ErrServerClosed) {
		fmt.Println("Error starting server:", err)
	}
	fmt.Println("Server stopped.")
}