Merge "veyron/security: Update documentation for ACL formatting."
diff --git a/lib/cmdline/cmdline.go b/lib/cmdline/cmdline.go
index d6705e6..dcc5aee 100644
--- a/lib/cmdline/cmdline.go
+++ b/lib/cmdline/cmdline.go
@@ -15,7 +15,6 @@
 package cmdline
 
 import (
-	"errors"
 	"flag"
 	"fmt"
 	"io"
@@ -23,9 +22,17 @@
 	"strings"
 )
 
+// ErrExitCode may be returned by the Run function of a Command to cause the
+// program to exit with a specific error code.
+type ErrExitCode int
+
+func (x ErrExitCode) Error() string {
+	return fmt.Sprintf("exit code %d", x)
+}
+
 // ErrUsage is returned to indicate an error in command usage; e.g. unknown
-// flags, subcommands or args.
-var ErrUsage = errors.New("usage error")
+// flags, subcommands or args.  It corresponds to exit code 1.
+const ErrUsage = ErrExitCode(1)
 
 // Command represents a single command in a command-line program.  A program
 // with subcommands is represented as a root Command with children representing
@@ -46,7 +53,8 @@
 
 	// Run is a function that runs cmd with args.  If both Children and Run are
 	// specified, Run will only be called if none of the children match.  It is an
-	// error if neither is specified.
+	// error if neither is specified.  The special ErrExitCode error may be
+	// returned to indicate the command should exit with a specific exit code.
 	Run func(cmd *Command, args []string) error
 
 	// parent holds the parent of this Command, or nil if this is the root.
@@ -107,8 +115,10 @@
 	return cmd.stderr
 }
 
-// Errorf should be called to signal an invalid usage of the command.
-func (cmd *Command) Errorf(format string, v ...interface{}) error {
+// UsageErrorf prints the error message represented by the printf-style format
+// string and args, followed by the usage description of cmd.  Returns ErrUsage
+// to make it easy to use from within the cmd.Run function.
+func (cmd *Command) UsageErrorf(format string, v ...interface{}) error {
 	fmt.Fprint(cmd.stderr, "ERROR: ")
 	fmt.Fprintf(cmd.stderr, format, v...)
 	fmt.Fprint(cmd.stderr, "\n\n")
@@ -236,7 +246,7 @@
 			return runHelp(child, subArgs, style)
 		}
 	}
-	return cmd.Errorf("%s: unknown command %q", cmd.Name, subName)
+	return cmd.UsageErrorf("%s: unknown command %q", cmd.Name, subName)
 }
 
 // recursiveHelp prints help recursively via DFS from this cmd onward.
@@ -328,20 +338,20 @@
 	if cmd.Run != nil {
 		if cmd.ArgsName == "" && len(args) > 0 {
 			if len(cmd.Children) > 0 {
-				return cmd.Errorf("%s: unknown command %q", cmd.Name, args[0])
+				return cmd.UsageErrorf("%s: unknown command %q", cmd.Name, args[0])
 			} else {
-				return cmd.Errorf("%s doesn't take any arguments", cmd.Name)
+				return cmd.UsageErrorf("%s doesn't take any arguments", cmd.Name)
 			}
 		}
 		return cmd.Run(cmd, args)
 	}
 	switch {
 	case len(cmd.Children) == 0:
-		return cmd.Errorf("%s: neither Children nor Run is specified", cmd.Name)
+		return cmd.UsageErrorf("%s: neither Children nor Run is specified", cmd.Name)
 	case len(args) > 0:
-		return cmd.Errorf("%s: unknown command %q", cmd.Name, args[0])
+		return cmd.UsageErrorf("%s: unknown command %q", cmd.Name, args[0])
 	default:
-		return cmd.Errorf("%s: no command specified", cmd.Name)
+		return cmd.UsageErrorf("%s: no command specified", cmd.Name)
 	}
 }
 
@@ -352,8 +362,8 @@
 func (cmd *Command) Main() {
 	cmd.Init(nil, os.Stdout, os.Stderr)
 	if err := cmd.Execute(os.Args[1:]); err != nil {
-		if err == ErrUsage {
-			os.Exit(1)
+		if code, ok := err.(ErrExitCode); ok {
+			os.Exit(int(code))
 		} else {
 			fmt.Fprintf(os.Stderr, "ERROR: %v\n", err)
 			os.Exit(2)
diff --git a/lib/cmdline/cmdline_test.go b/lib/cmdline/cmdline_test.go
index 6fdf3c5..e9c471b 100644
--- a/lib/cmdline/cmdline_test.go
+++ b/lib/cmdline/cmdline_test.go
@@ -25,7 +25,7 @@
 		if args[0] == "error" {
 			return errEcho
 		} else if args[0] == "bad_arg" {
-			return cmd.Errorf("Invalid argument %v", args[0])
+			return cmd.UsageErrorf("Invalid argument %v", args[0])
 		}
 	}
 	if flagExtra {
diff --git a/profiles/platform_darwin.go b/profiles/platform_darwin.go
index 933b589..e6b2af3 100644
--- a/profiles/platform_darwin.go
+++ b/profiles/platform_darwin.go
@@ -10,7 +10,6 @@
 	"fmt"
 
 	"veyron.io/veyron/veyron2"
-	"veyron.io/veyron/veyron2/security"
 )
 
 // Platform returns the description of the Platform this process is running on.
@@ -30,6 +29,5 @@
 		Machine: C.GoString(&t.machine[0]),
 		Node:    C.GoString(&t.nodename[0]),
 	}
-	d.Identity = security.FakePublicID(fmt.Sprintf("%s/%s/%s", d.Vendor, d.Model, d.Node))
 	return d, nil
 }
diff --git a/runtimes/google/ipc/full_test.go b/runtimes/google/ipc/full_test.go
index be1655c..10e2baf 100644
--- a/runtimes/google/ipc/full_test.go
+++ b/runtimes/google/ipc/full_test.go
@@ -134,6 +134,9 @@
 	}
 	// Add a fakeTimeCaveat to allow the discharge to expire
 	expiry := fakeTimeCaveat(clock.Now())
+	if err := c.Dischargeable(ctx); err != nil {
+		return nil, fmt.Errorf("third-party caveat %v cannot be discharged for this context: %v", c, err)
+	}
 	return serverID.MintDischarge(c, ctx, time.Hour, []security.Caveat{newCaveat(expiry)})
 }
 
diff --git a/security/audit/id_test.go b/security/audit/id_test.go
index 5a58432..8d01746 100644
--- a/security/audit/id_test.go
+++ b/security/audit/id_test.go
@@ -245,6 +245,7 @@
 func (thirdPartyCaveat) Requirements() security.ThirdPartyRequirements {
 	return security.ThirdPartyRequirements{}
 }
+func (thirdPartyCaveat) Dischargeable(security.Context) error { return nil }
 
 // context implements security.Context
 type context struct{}
diff --git a/security/util_test.go b/security/util_test.go
index 1da3c31..0e32e1d 100644
--- a/security/util_test.go
+++ b/security/util_test.go
@@ -87,6 +87,7 @@
 func (tpCaveat) ID() (id string)                                   { return }
 func (tpCaveat) Location() (loc string)                            { return }
 func (tpCaveat) Requirements() (r security.ThirdPartyRequirements) { return }
+func (tpCaveat) Dischargeable(security.Context) (err error)        { return }
 
 func TestCaveatUtil(t *testing.T) {
 	type C []security.Caveat
diff --git a/services/security/discharger/discharger.go b/services/security/discharger/discharger.go
index 5e701d1..b110866 100644
--- a/services/security/discharger/discharger.go
+++ b/services/security/discharger/discharger.go
@@ -23,6 +23,9 @@
 	if !ok {
 		return nil, fmt.Errorf("type %T does not implement security.ThirdPartyCaveat", caveatAny)
 	}
+	if err := caveat.Dischargeable(ctx); err != nil {
+		return nil, fmt.Errorf("third-party caveat %v cannot be discharged for this context: %v", caveat, err)
+	}
 	return d.id.MintDischarge(caveat, ctx, time.Minute, nil)
 }
 
diff --git a/tools/application/impl/impl.go b/tools/application/impl/impl.go
index fccb840..8af0a9f 100644
--- a/tools/application/impl/impl.go
+++ b/tools/application/impl/impl.go
@@ -64,7 +64,7 @@
 
 func runMatch(cmd *cmdline.Command, args []string) error {
 	if expected, got := 2, len(args); expected != got {
-		return cmd.Errorf("match: incorrect number of arguments, expected %d, got %d", expected, got)
+		return cmd.UsageErrorf("match: incorrect number of arguments, expected %d, got %d", expected, got)
 	}
 	name, profiles := args[0], args[1]
 	app, err := repository.BindApplication(name)
@@ -95,7 +95,7 @@
 
 func runPut(cmd *cmdline.Command, args []string) error {
 	if expected, got := 3, len(args); expected != got {
-		return cmd.Errorf("put: incorrect number of arguments, expected %d, got %d", expected, got)
+		return cmd.UsageErrorf("put: incorrect number of arguments, expected %d, got %d", expected, got)
 	}
 	name, profiles, envelope := args[0], args[1], args[2]
 	app, err := repository.BindApplication(name)
@@ -128,7 +128,7 @@
 
 func runRemove(cmd *cmdline.Command, args []string) error {
 	if expected, got := 2, len(args); expected != got {
-		return cmd.Errorf("remove: incorrect number of arguments, expected %d, got %d", expected, got)
+		return cmd.UsageErrorf("remove: incorrect number of arguments, expected %d, got %d", expected, got)
 	}
 	name, profile := args[0], args[1]
 	app, err := repository.BindApplication(name)
@@ -157,7 +157,7 @@
 
 func runEdit(cmd *cmdline.Command, args []string) error {
 	if expected, got := 2, len(args); expected != got {
-		return cmd.Errorf("edit: incorrect number of arguments, expected %d, got %d", expected, got)
+		return cmd.UsageErrorf("edit: incorrect number of arguments, expected %d, got %d", expected, got)
 	}
 	name, profile := args[0], args[1]
 	app, err := repository.BindApplication(name)
diff --git a/tools/binary/impl/impl.go b/tools/binary/impl/impl.go
index f690e54..b5a1cec 100644
--- a/tools/binary/impl/impl.go
+++ b/tools/binary/impl/impl.go
@@ -18,7 +18,7 @@
 
 func runDelete(cmd *cmdline.Command, args []string) error {
 	if expected, got := 1, len(args); expected != got {
-		return cmd.Errorf("delete: incorrect number of arguments, expected %d, got %d", expected, got)
+		return cmd.UsageErrorf("delete: incorrect number of arguments, expected %d, got %d", expected, got)
 	}
 	von := args[0]
 	if err := binary.Delete(von); err != nil {
@@ -45,7 +45,7 @@
 
 func runDownload(cmd *cmdline.Command, args []string) error {
 	if expected, got := 2, len(args); expected != got {
-		return cmd.Errorf("download: incorrect number of arguments, expected %d, got %d", expected, got)
+		return cmd.UsageErrorf("download: incorrect number of arguments, expected %d, got %d", expected, got)
 	}
 	von, filename := args[0], args[1]
 	if err := binary.DownloadToFile(von, filename); err != nil {
@@ -72,7 +72,7 @@
 
 func runUpload(cmd *cmdline.Command, args []string) error {
 	if expected, got := 2, len(args); expected != got {
-		return cmd.Errorf("upload: incorrect number of arguments, expected %d, got %d", expected, got)
+		return cmd.UsageErrorf("upload: incorrect number of arguments, expected %d, got %d", expected, got)
 	}
 	von, filename := args[0], args[1]
 	if err := binary.UploadFromFile(von, filename); err != nil {
diff --git a/tools/mounttable/impl/impl.go b/tools/mounttable/impl/impl.go
index 9d9a96d..5d67326 100644
--- a/tools/mounttable/impl/impl.go
+++ b/tools/mounttable/impl/impl.go
@@ -38,7 +38,7 @@
 
 func runGlob(cmd *cmdline.Command, args []string) error {
 	if expected, got := 2, len(args); expected != got {
-		return cmd.Errorf("glob: incorrect number of arguments, expected %d, got %d", expected, got)
+		return cmd.UsageErrorf("glob: incorrect number of arguments, expected %d, got %d", expected, got)
 	}
 	ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
 	defer cancel()
@@ -87,7 +87,7 @@
 
 func runMount(cmd *cmdline.Command, args []string) error {
 	if expected, got := 3, len(args); expected != got {
-		return cmd.Errorf("mount: incorrect number of arguments, expected %d, got %d", expected, got)
+		return cmd.UsageErrorf("mount: incorrect number of arguments, expected %d, got %d", expected, got)
 	}
 	ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
 	defer cancel()
@@ -122,7 +122,7 @@
 
 func runUnmount(cmd *cmdline.Command, args []string) error {
 	if expected, got := 2, len(args); expected != got {
-		return cmd.Errorf("unmount: incorrect number of arguments, expected %d, got %d", expected, got)
+		return cmd.UsageErrorf("unmount: incorrect number of arguments, expected %d, got %d", expected, got)
 	}
 	ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
 	defer cancel()
@@ -152,7 +152,7 @@
 
 func runResolveStep(cmd *cmdline.Command, args []string) error {
 	if expected, got := 1, len(args); expected != got {
-		return cmd.Errorf("mount: incorrect number of arguments, expected %d, got %d", expected, got)
+		return cmd.UsageErrorf("mount: incorrect number of arguments, expected %d, got %d", expected, got)
 	}
 	ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
 	defer cancel()
diff --git a/tools/namespace/impl/impl.go b/tools/namespace/impl/impl.go
index 2c87e49..d8fe9a9 100644
--- a/tools/namespace/impl/impl.go
+++ b/tools/namespace/impl/impl.go
@@ -24,7 +24,7 @@
 
 func runGlob(cmd *cmdline.Command, args []string) error {
 	if expected, got := 1, len(args); expected != got {
-		return cmd.Errorf("glob: incorrect number of arguments, expected %d, got %d", expected, got)
+		return cmd.UsageErrorf("glob: incorrect number of arguments, expected %d, got %d", expected, got)
 	}
 	pattern := args[0]
 	ns := rt.R().Namespace()
@@ -61,7 +61,7 @@
 
 func runMount(cmd *cmdline.Command, args []string) error {
 	if expected, got := 3, len(args); expected != got {
-		return cmd.Errorf("mount: incorrect number of arguments, expected %d, got %d", expected, got)
+		return cmd.UsageErrorf("mount: incorrect number of arguments, expected %d, got %d", expected, got)
 	}
 	name := args[0]
 	server := args[1]
@@ -96,7 +96,7 @@
 
 func runUnmount(cmd *cmdline.Command, args []string) error {
 	if expected, got := 2, len(args); expected != got {
-		return cmd.Errorf("unmount: incorrect number of arguments, expected %d, got %d", expected, got)
+		return cmd.UsageErrorf("unmount: incorrect number of arguments, expected %d, got %d", expected, got)
 	}
 	name := args[0]
 	server := args[1]
@@ -122,7 +122,7 @@
 
 func runResolve(cmd *cmdline.Command, args []string) error {
 	if expected, got := 1, len(args); expected != got {
-		return cmd.Errorf("resolve: incorrect number of arguments, expected %d, got %d", expected, got)
+		return cmd.UsageErrorf("resolve: incorrect number of arguments, expected %d, got %d", expected, got)
 	}
 	name := args[0]
 	ns := rt.R().Namespace()
@@ -150,7 +150,7 @@
 
 func runResolveToMT(cmd *cmdline.Command, args []string) error {
 	if expected, got := 1, len(args); expected != got {
-		return cmd.Errorf("resolvetomt: incorrect number of arguments, expected %d, got %d", expected, got)
+		return cmd.UsageErrorf("resolvetomt: incorrect number of arguments, expected %d, got %d", expected, got)
 	}
 	name := args[0]
 	ns := rt.R().Namespace()
@@ -178,7 +178,7 @@
 
 func runUnresolve(cmd *cmdline.Command, args []string) error {
 	if expected, got := 1, len(args); expected != got {
-		return cmd.Errorf("unresolve: incorrect number of arguments, expected %d, got %d", expected, got)
+		return cmd.UsageErrorf("unresolve: incorrect number of arguments, expected %d, got %d", expected, got)
 	}
 	name := args[0]
 	ns := rt.R().Namespace()
diff --git a/tools/profile/impl/impl.go b/tools/profile/impl/impl.go
index 1a69555..4413896 100644
--- a/tools/profile/impl/impl.go
+++ b/tools/profile/impl/impl.go
@@ -23,7 +23,7 @@
 
 func runLabel(cmd *cmdline.Command, args []string) error {
 	if expected, got := 1, len(args); expected != got {
-		return cmd.Errorf("label: incorrect number of arguments, expected %d, got %d", expected, got)
+		return cmd.UsageErrorf("label: incorrect number of arguments, expected %d, got %d", expected, got)
 	}
 	name := args[0]
 	p, err := repository.BindProfile(name)
@@ -51,7 +51,7 @@
 
 func runDescription(cmd *cmdline.Command, args []string) error {
 	if expected, got := 1, len(args); expected != got {
-		return cmd.Errorf("description: incorrect number of arguments, expected %d, got %d", expected, got)
+		return cmd.UsageErrorf("description: incorrect number of arguments, expected %d, got %d", expected, got)
 	}
 	name := args[0]
 	p, err := repository.BindProfile(name)
@@ -79,7 +79,7 @@
 
 func runSpecification(cmd *cmdline.Command, args []string) error {
 	if expected, got := 1, len(args); expected != got {
-		return cmd.Errorf("spec: incorrect number of arguments, expected %d, got %d", expected, got)
+		return cmd.UsageErrorf("spec: incorrect number of arguments, expected %d, got %d", expected, got)
 	}
 	name := args[0]
 	p, err := repository.BindProfile(name)
@@ -107,7 +107,7 @@
 
 func runPut(cmd *cmdline.Command, args []string) error {
 	if expected, got := 1, len(args); expected != got {
-		return cmd.Errorf("put: incorrect number of arguments, expected %d, got %d", expected, got)
+		return cmd.UsageErrorf("put: incorrect number of arguments, expected %d, got %d", expected, got)
 	}
 	name := args[0]
 	p, err := repository.BindProfile(name)
@@ -144,7 +144,7 @@
 
 func runRemove(cmd *cmdline.Command, args []string) error {
 	if expected, got := 1, len(args); expected != got {
-		return cmd.Errorf("remove: incorrect number of arguments, expected %d, got %d", expected, got)
+		return cmd.UsageErrorf("remove: incorrect number of arguments, expected %d, got %d", expected, got)
 	}
 	name := args[0]
 	p, err := repository.BindProfile(name)
diff --git a/tools/vrpc/impl/impl.go b/tools/vrpc/impl/impl.go
index 3851bac..05483e9 100644
--- a/tools/vrpc/impl/impl.go
+++ b/tools/vrpc/impl/impl.go
@@ -50,7 +50,7 @@
 
 func runDescribe(cmd *cmdline.Command, args []string) error {
 	if len(args) != 1 {
-		return cmd.Errorf("describe: incorrect number of arguments, expected 1, got %d", len(args))
+		return cmd.UsageErrorf("describe: incorrect number of arguments, expected 1, got %d", len(args))
 	}
 
 	runtime := rt.R()
@@ -89,7 +89,7 @@
 
 func runInvoke(cmd *cmdline.Command, args []string) error {
 	if len(args) < 2 {
-		return cmd.Errorf("invoke: incorrect number of arguments, expected at least 2, got %d", len(args))
+		return cmd.UsageErrorf("invoke: incorrect number of arguments, expected at least 2, got %d", len(args))
 	}
 	server, method, args := args[0], args[1], args[2:]
 
@@ -117,7 +117,7 @@
 	}
 
 	if len(args) != len(methodSignature.InArgs) {
-		return cmd.Errorf("invoke: incorrect number of arguments, expected %d, got %d", len(methodSignature.InArgs), len(args))
+		return cmd.UsageErrorf("invoke: incorrect number of arguments, expected %d, got %d", len(methodSignature.InArgs), len(args))
 	}
 
 	// Register all user-defined types you would like to use.
diff --git a/tools/vrpc/impl/impl_test.go b/tools/vrpc/impl/impl_test.go
index 0dd2811..2d44a19 100644
--- a/tools/vrpc/impl/impl_test.go
+++ b/tools/vrpc/impl/impl_test.go
@@ -275,8 +275,8 @@
 	}
 
 	testErrors := [][]string{
-		[]string{"EchoBool", "usage error"},
-		[]string{"DoesNotExit", "invoke: method DoesNotExit not found"},
+		[]string{"EchoBool", "exit code 1"},
+		[]string{"DoesNotExist", "invoke: method DoesNotExist not found"},
 	}
 	for _, test := range testErrors {
 		testError(t, cmd, append([]string{"invoke", name, test[0]}, test[2:]...), test[1])