package main import ( "bufio" "fmt" "os" "mcquay.me/pm/keyring" ) const usage = `pm: simple, cross-platform system package manager subcommands: environ (env) -- print environment information keyring (key) -- interact with pm's OpenPGP keyring ` const keyUsage = `pm keyring: interact with pm's OpenPGP keyring subcommands: create (c) -- create a fresh keypair export (e) -- export a public key to stdout import (i) -- import a public key from stdin list (ls) -- list configured key info remove (rm) -- remove a key from the keyring sign (s) -- sign a file verify (v) -- verify a detached signature ` func main() { if len(os.Args) < 2 { fatalf("pm: missing subcommand\n\n%v", usage) } cmd := os.Args[1] root := os.Getenv("PM_ROOT") if root == "" { root = "/usr/local" } signID := os.Getenv("PM_PGP_ID") switch cmd { case "env", "environ": fmt.Printf("PM_ROOT=%q\n", root) fmt.Printf("PM_PGP_ID=%q\n", signID) case "key", "keyring": if len(os.Args[1:]) < 2 { fatalf("pm keyring: insufficient args\n\nusage: %v", keyUsage) } sub, args := os.Args[2], os.Args[3:] switch sub { case "ls", "list": if err := keyring.ListKeys(root, os.Stdout); err != nil { fatalf("listing keypair: %v\n", err) } case "c", "create": var name, email string s := bufio.NewScanner(os.Stdin) fmt.Printf("name: ") s.Scan() if err := s.Err(); err != nil { fatalf("reading name: %v\n", err) } name = s.Text() fmt.Printf("email: ") s.Scan() if err := s.Err(); err != nil { fatalf("reading email: %v\n", err) } email = s.Text() if err := os.Stdin.Close(); err != nil { fatalf("%v\n", err) } if err := keyring.NewKeyPair(root, name, email); err != nil { fatalf("creating keypair: %v\n", err) } case "export", "e": if len(args) != 1 { fatalf("missing email argument\n") } email := args[0] if err := keyring.Export(root, os.Stdout, email); err != nil { fatalf("exporting public key for %q: %v\n", email, err) } case "sign", "s": if signID == "" { fatalf("must set PM_PGP_ID\n") } if err := keyring.Sign(root, signID, os.Stdin, os.Stdout); err != nil { fatalf("signing: %v\n", err) } case "verify", "v": if len(args) != 2 { fatalf("usage: pm key verify \n") } fn, sn := args[0], args[1] ff, err := os.Open(fn) if err != nil { fatalf("opening %q: %v\n", fn, err) } defer ff.Close() sf, err := os.Open(sn) if err != nil { fatalf("opening %q: %v\n", fn, err) } defer sf.Close() if err := keyring.Verify(root, ff, sf); err != nil { fatalf("detached sig verify: %v\n", err) } case "i", "import": if err := keyring.Import(root, os.Stdin); err != nil { fatalf("importing key: %v\n", err) } case "remove", "rm": if len(args) != 1 { fatalf("missing key id\n\nusage: pm key remove \n") } id := args[0] if err := keyring.Remove(root, id); err != nil { fatalf("removing key for %q: %v\n", id, err) } default: fatalf("unknown keyring subcommand: %q\n\nusage: %v", sub, keyUsage) } default: fatalf("uknown subcommand %q\n\nusage: %v", cmd, usage) } } func fatalf(f string, args ...interface{}) { fmt.Fprintf(os.Stderr, f, args...) os.Exit(1) }