1package maddycli23import (4 "fmt"5 "os"6 "strings"78 "github.com/foxcpp/maddy/framework/log"9 "github.com/urfave/cli/v2"10)1112var app *cli.App1314func init() {15 app = cli.NewApp()16 app.Usage = "composable all-in-one mail server"17 app.Description = `Maddy is Mail Transfer agent (MTA), Mail Delivery Agent (MDA), Mail Submission18Agent (MSA), IMAP server and a set of other essential protocols/schemes19necessary to run secure email server implemented in one executable.2021This executable can be used to start the server ('run') and to manipulate22databases used by it (all other subcommands).23`24 app.Authors = []*cli.Author{25 {26 Name: "Maddy Mail Server maintainers & contributors",27 Email: "~foxcpp/maddy@lists.sr.ht",28 },29 }30 app.ExitErrHandler = func(c *cli.Context, err error) {31 cli.HandleExitCoder(err)32 }33 app.EnableBashCompletion = true34 app.Commands = []*cli.Command{35 {36 Name: "generate-man",37 Hidden: true,38 Action: func(c *cli.Context) error {39 man, err := app.ToMan()40 if err != nil {41 return err42 }43 fmt.Println(man)44 return nil45 },46 },47 {48 Name: "generate-fish-completion",49 Hidden: true,50 Action: func(c *cli.Context) error {51 cp, err := app.ToFishCompletion()52 if err != nil {53 return err54 }55 fmt.Println(cp)56 return nil57 },58 },59 }60}6162func AddGlobalFlag(f cli.Flag) {63 app.Flags = append(app.Flags, f)64}6566func AddSubcommand(cmd *cli.Command) {67 app.Commands = append(app.Commands, cmd)6869 if cmd.Name == "run" {70 // Backward compatibility hack to start the server as just ./maddy71 // Needs to be done here so we will register all known flags with72 // stdlib before Run is called.73 app.Action = func(c *cli.Context) error {74 log.Println("WARNING: Starting server not via 'maddy run' is deprecated and will stop working in the next version")75 return cmd.Action(c)76 }77 app.Flags = append(app.Flags, cmd.Flags...)78 }79}8081// RunWithoutExit is like Run but returns exit code instead of calling os.Exit82// To be used in maddy.cover.83func RunWithoutExit() int {84 code := 08586 cli.OsExiter = func(c int) { code = c }87 defer func() {88 cli.OsExiter = os.Exit89 }()9091 Run()9293 return code94}9596func Run() {97 mapStdlibFlags(app)9899 // Actual entry point is registered in maddy.go.100101 // Print help when called via maddyctl executable. To be removed102 // once backward compatibility hack for 'maddy run' is removed too.103 if strings.Contains(os.Args[0], "maddyctl") && len(os.Args) == 1 {104 if err := app.Run([]string{os.Args[0], "help"}); err != nil {105 log.DefaultLogger.Error("app.Run failed", err)106 }107 return108 }109110 if err := app.Run(os.Args); err != nil {111 log.DefaultLogger.Error("app.Run failed", err)112 }113}