package main import ( "errors" "fmt" "os" "os/signal" "path/filepath" "runtime" "syscall" "github.com/safing/portbase/info" "github.com/safing/portbase/log" "github.com/safing/portmaster/updates" "github.com/spf13/cobra" ) const ( logPrefix = "[control]" ) var ( updateStoragePath string databaseRootDir *string rootCmd = &cobra.Command{ Use: "portmaster-control", Short: "contoller for all portmaster components", PersistentPreRunE: initPmCtl, RunE: func(cmd *cobra.Command, args []string) error { return cmd.Help() }, } ) func init() { // Let cobra ignore if we are running as "GUI" or not cobra.MousetrapHelpText = "" databaseRootDir = rootCmd.PersistentFlags().String("db", "", "set database directory") err := rootCmd.MarkPersistentFlagRequired("db") if err != nil { panic(err) } } func main() { var err error // check if we are running in a console (try to attach to parent console if available) runningInConsole, err = attachToParentConsole() if err != nil { fmt.Printf("failed to attach to parent console: %s\n", err) os.Exit(1) } // set meta info info.Set("Portmaster Control", "0.2.5", "AGPLv3", true) // check if meta info is ok err = info.CheckVersion() if err != nil { fmt.Printf("%s compile error: please compile using the provided build script\n", logPrefix) os.Exit(1) } // react to version flag if info.PrintVersion() { os.Exit(0) } // warn about CTRL-C on windows if runningInConsole && runtime.GOOS == "windows" { fmt.Printf("%s WARNING: portmaster-control is marked as a GUI application in order to get rid of the console window.\n", logPrefix) fmt.Printf("%s WARNING: CTRL-C will immediately kill without clean shutdown.\n", logPrefix) } // not using portbase logger log.SetLogLevel(log.CriticalLevel) // for debugging // log.Start() // log.SetLogLevel(log.TraceLevel) // go func() { // time.Sleep(3 * time.Second) // pprof.Lookup("goroutine").WriteTo(os.Stdout, 2) // os.Exit(1) // }() // catch interrupt for clean shutdown signalCh := make(chan os.Signal) signal.Notify( signalCh, os.Interrupt, os.Kill, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, ) // start root command go func() { if err = rootCmd.Execute(); err != nil { os.Exit(1) } os.Exit(0) }() // wait for signals for sig := range signalCh { if childIsRunning.IsSet() { fmt.Printf("%s got %s signal (ignoring), waiting for child to exit...\n", logPrefix, sig) } else { fmt.Printf("%s got %s signal, exiting... (not executing anything)\n", logPrefix, sig) os.Exit(0) } } } func initPmCtl(cmd *cobra.Command, args []string) (err error) { // transform from db base path to updates path if *databaseRootDir != "" { updates.SetDatabaseRoot(*databaseRootDir) updateStoragePath = filepath.Join(*databaseRootDir, "updates") } else { return errors.New("please supply the database directory using the --db flag") } return nil }