From 37c866e1e16a6d2dded11ba93c2e04af3764a139 Mon Sep 17 00:00:00 2001 From: "Joe Richey joerichey@google.com" Date: Wed, 21 Jun 2017 10:21:21 -0700 Subject: cmd/fscrypt: setup, encrypt, unlock commands This commit adds in the framework for adding commands and subcommands to the fscrypt tool. This commit adds in the "setup", "encrypt", and "unlock" commands. Additional information can be found by running: fscrypt --help. This commit defines how flags are parsed and errors are handled. It also creates an extensible framework for prompting the user for information. Change-Id: I159d7f44ee2b2bbc5e072f0802850e082d9a13ce --- cmd/fscrypt/fscrypt.go | 117 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 113 insertions(+), 4 deletions(-) (limited to 'cmd/fscrypt/fscrypt.go') diff --git a/cmd/fscrypt/fscrypt.go b/cmd/fscrypt/fscrypt.go index 191d4fb..d3185fa 100644 --- a/cmd/fscrypt/fscrypt.go +++ b/cmd/fscrypt/fscrypt.go @@ -1,5 +1,6 @@ /* - * fscrypt.go - Stub file which currently just prints out the time + * fscrypt.go - File which starts up and runs the application. Initializes + * information about the application like the name, version, author, etc... * * Copyright 2017 Google Inc. * Author: Joe Richey (joerichey@google.com) @@ -19,16 +20,124 @@ /* fscrypt is a comprehensive command line tool for managing filesystem encryption. - -It currently just tells the time. */ package main import ( "fmt" + "io/ioutil" + "log" + "os" "time" + + "github.com/urfave/cli" +) + +var ( + // Current version of the program (set by Makefile) + version string + // Formatted build time (set by Makefile) + buildTime string + // Authors to display in the info command + Authors = []cli.Author{{ + Name: "Joe Richey", + Email: "joerichey@google.com", + }} ) func main() { - fmt.Printf("The time is now: %v\n", time.Now()) + cli.AppHelpTemplate = appHelpTemplate + cli.CommandHelpTemplate = commandHelpTemplate + cli.SubcommandHelpTemplate = subcommandHelpTemplate + + // Create our command line application + app := cli.NewApp() + app.Usage = shortUsage + app.Authors = Authors + app.Copyright = apache2GoogleCopyright + + // Grab the version and compilation time passed in from the Makefile. + app.Version = version + app.Compiled, _ = time.Parse(time.UnixDate, buildTime) + app.OnUsageError = onUsageError + + // Setup global flags + cli.HelpFlag = helpFlag + cli.VersionFlag = versionFlag + cli.VersionPrinter = func(c *cli.Context) { + cli.HelpPrinter(c.App.Writer, versionInfoTemplate, c.App) + } + app.Flags = universalFlags + + // We hide the help subcommand so that "fscrypt --help" works + // and "fscrypt help" does not. + app.HideHelp = true + + // Initialize command list and setup all of the commands. + app.Action = defaultAction + app.Commands = []cli.Command{Setup, Encrypt, Unlock} + for i := range app.Commands { + setupCommand(&app.Commands[i]) + } + + app.Run(os.Args) +} + +// setupCommand performs some common setup for each command. This includes +// hiding the help, formating the description, adding in the necessary +// flags, setting up error handlers, etc... Note that the command is modified +// in place and its subcommands are also setup. +func setupCommand(command *cli.Command) { + command.Description = wrapText(command.Description, indentLength) + command.HideHelp = true + command.Flags = append(command.Flags, universalFlags...) + + if command.Action == nil { + command.Action = defaultAction + } + + // Setup function handlers + command.OnUsageError = onUsageError + if len(command.Subcommands) == 0 { + command.Before = setupOutputs + } else { + // Cleanup subcommands (if applicable) + for i := range command.Subcommands { + setupCommand(&command.Subcommands[i]) + } + } +} + +// setupOutputs makes sure our logs, errors, and output are going to the correct +// io.Writers and that we haven't over-specified our flags. We only print the +// logs when using verbose, and only print normal stuff when not using quiet. +func setupOutputs(c *cli.Context) error { + log.SetOutput(ioutil.Discard) + c.App.Writer = ioutil.Discard + + if verboseFlag.Value { + log.SetOutput(os.Stdout) + } + if !quietFlag.Value { + c.App.Writer = os.Stdout + } + return nil +} + +// defaultAction will be run when no command is specified. +func defaultAction(c *cli.Context) error { + // Always default to showing the help + if helpFlag.Value { + cli.ShowAppHelp(c) + return nil + } + + // Only exit when not calling with the help command + var message string + if args := c.Args(); args.Present() { + message = fmt.Sprintf("command \"%s\" not found", args.First()) + } else { + message = "no command was specified" + } + return &usageError{c, message} } -- cgit v1.2.3