package main import ( "flag" "log" "os" "os/exec" "strconv" "sync" ) var config Config const sockfile = "/tmp/gopaper.sock" const pidfilePath = "/tmp/gopaper.pid" var clog = log.New(os.Stdout, "## ", 0) var elog = log.New(os.Stdout, "ERROR: ", 3) func main() { //SETUP FLAGS var debugFlag = flag.Bool("debug", false, "help message for flag n") var dirFlag = flag.String("dir", "", "help message") flag.Parse() clog.Println("Welcome to GoPaper!") //INIT CONFIG err := config.load() if err != nil { elog.Println("unable to initialize config", err) } handleProcesses() setupLogging(*debugFlag) var waitGroup sync.WaitGroup waitGroup.Add(1) slideshowDir := make(chan string) func() { defer func() { if r := recover(); r != nil { log.Println("Panic recovered at top level", r) cleanExit(1) } }() go server(slideshowDir) go slideshow(slideshowDir) }() slideshowDir <- *dirFlag waitGroup.Wait() } func openLogfile() (*os.File, error) { //TODO: log rotation f, err := os.OpenFile(config.Cache+"logfile", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) if err != nil { return nil, err } return f, nil } func cleanExit(code int) { if code == 1 { log.Println("shutting down gracefully after errors") } else { log.Println("shutting down gracefully") } err := os.Remove(sockfile) if err != nil && !os.IsNotExist(err) { elog.Printf("unable to remove sockfile at %v. Error: %v\n", sockfile, err) } else if !os.IsNotExist(err) { log.Println("sockfile removed") } else { log.Println("no need to remove sockfile -- it doesn't exist") } err = os.Remove(pidfilePath) if err != nil && !os.IsNotExist(err) { elog.Printf("unable to remove pidfile at %v. Error: %v\n", pidfilePath, err) } else if !os.IsNotExist(err) { log.Println("pidfile removed") } else { log.Println("no need to remove pidfile -- it doesn't exist") } os.Exit(code) } func killPrevProc() error { //check if pidfile already exists if _, err := os.Stat(pidfilePath); os.IsNotExist(err) { return nil } //if it does, kill the process and delete the pidfile prexPid, err := os.ReadFile(pidfilePath) if err != nil { elog.Println("unable to read pre-existing pidfile", err) return err } //kill process err = exec.Command("kill", string(prexPid)).Run() if err != nil { elog.Printf("Error attempting to kill process %v: %v\n", string(prexPid), err) } //remove pidfile err = os.Remove(pidfilePath) if err != nil && !os.IsNotExist(err) { elog.Printf("unable to remove pidfile at %v. Error: %v\n", pidfilePath, err) } return nil } func handleProcesses() { err := killPrevProc() if err != nil { elog.Println("error attempting to kill pre-existing process: ", err) os.Exit(1) } //create new pidfile pid := strconv.FormatInt(int64(os.Getpid()), 10) pidfile, err := os.Create(pidfilePath) if err != nil { elog.Println("error trying to create pidfile:", err) os.Exit(1) } pidfile.WriteString(pid) } func setupLogging(debug bool) { clog.Printf("debug: %v", debug) //SETUP LOGGERS if debug { logfile, err := openLogfile() if err != nil { elog.Println("failed to load config", err) os.Exit(1) } clog.Printf("Logging to %v", logfile.Name()) log.SetOutput(logfile) clog.SetOutput(logfile) elog.SetOutput(logfile) } elog.SetFlags(log.LstdFlags | log.Lshortfile) log.SetFlags(log.LstdFlags) }