package main import ( "encoding/gob" "encoding/json" "flag" "fmt" "log" "os" "os/signal" "sync/atomic" "syscall" "time" "git.ophivana.moe/cat/rpcfetch" ) var ( d *rpcfetch.Client active = new(atomic.Bool) confPath string headless bool dumpConfig bool ) func init() { flag.StringVar(&confPath, "conf", "rpcfetch.conf", "path to rpcfetch configuration file") flag.BoolVar(&headless, "headless", false, "run without graphical interface") flag.BoolVar(&dumpConfig, "dump", false, "dump configuration as JSON then exit") } func main() { flag.Parse() if cf, err := os.Open(confPath); err != nil { if !os.IsNotExist(err) { log.Fatalf("error opening configuration file: %s", err) } // use defaults log.Print("configuration file does not exist, using defaults") conf = &defaultConfig } else { // decode from existing file if err = gob.NewDecoder(cf).Decode(&conf); err != nil { log.Fatalf("error reading configuration: %s", err) } if err = cf.Close(); err != nil { log.Fatalf("error closing configuration file: %s", err) } } profLast.Store(profLastCache{}) if dumpConfig { b, _ := json.Marshal(conf) fmt.Println(string(b)) os.Exit(0) } // update periodically active.Store(true) go func() { for { if active.Load() { apply() } time.Sleep(5 * time.Second) } }() // set up clean exit signal handling sig := make(chan os.Signal, 1) signal.Notify(sig, os.Interrupt, syscall.SIGTERM) go func() { log.Printf("received signal %s, exiting", (<-sig).String()) exit() }() if headless { select {} } else { // run the UI if err := ui(); err != nil { log.Fatalf("error in user interface: %s", err) } log.Print("window closed, exiting") exit() } } func exit() { active.Store(false) if err := d.Close(); err != nil { log.Printf("error closing client: %s", err) } log.Print("rpc client closed") os.Exit(0) }