github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/libcmdline/cmdline.go (about) 1 // Copyright 2015 Keybase, Inc. All rights reserved. Use of 2 // this source code is governed by the included BSD license. 3 4 package libcmdline 5 6 import ( 7 "fmt" 8 "io" 9 "strings" 10 "time" 11 12 "github.com/keybase/cli" 13 "github.com/keybase/client/go/libkb" 14 ) 15 16 type Command interface { 17 libkb.Command 18 ParseArgv(*cli.Context) error // A command-specific parse-args 19 Run() error // Run in client mode 20 } 21 22 type ForkCmd int 23 type LogForward int 24 25 const ( 26 NormalFork ForkCmd = iota 27 NoFork 28 ForceFork 29 ) 30 31 const ( 32 LogForwardNormal LogForward = iota 33 LogForwardNone 34 ) 35 36 type CommandLine struct { 37 app *cli.App 38 ctx *cli.Context 39 cmd Command 40 name string // the name of the chosen command 41 service bool // The server is a special command 42 fork ForkCmd // If the command is to stop (then don't start the server) 43 noStandalone bool // On if this command can't run in standalone mode 44 logForward LogForward // What do to about log forwarding 45 skipOutOfDateCheck bool // don't try to check for service being out of date 46 skipAccountResetCheck bool // don't check if our account is scheduled for rest 47 defaultCmd string 48 } 49 50 func (p CommandLine) IsService() bool { return p.service } 51 func (p CommandLine) SkipOutOfDateCheck() bool { return p.skipOutOfDateCheck } 52 func (p CommandLine) SkipAccountResetCheck() bool { return p.skipAccountResetCheck } 53 func (p *CommandLine) SetService() { p.service = true } 54 func (p CommandLine) GetForkCmd() ForkCmd { return p.fork } 55 func (p *CommandLine) SetForkCmd(v ForkCmd) { p.fork = v } 56 func (p *CommandLine) SetNoStandalone() { p.noStandalone = true } 57 func (p CommandLine) IsNoStandalone() bool { return p.noStandalone } 58 func (p *CommandLine) SetLogForward(f LogForward) { p.logForward = f } 59 func (p *CommandLine) GetLogForward() LogForward { return p.logForward } 60 func (p *CommandLine) SetSkipOutOfDateCheck() { p.skipOutOfDateCheck = true } 61 func (p *CommandLine) SetSkipAccountResetCheck() { p.skipAccountResetCheck = true } 62 63 func (p CommandLine) GetNoAutoFork() (bool, bool) { 64 return p.GetBool("no-auto-fork", true) 65 } 66 func (p CommandLine) GetAutoFork() (bool, bool) { 67 return p.GetBool("auto-fork", true) 68 } 69 func (p CommandLine) GetHome() string { 70 return p.GetGString("home") 71 } 72 func (p CommandLine) GetMobileSharedHome() string { 73 return p.GetGString("mobile-shared-home") 74 } 75 func (p CommandLine) GetServerURI() (string, error) { 76 return p.GetGString("server"), nil 77 } 78 func (p CommandLine) GetConfigFilename() string { 79 return p.GetGString("config-file") 80 } 81 func (p CommandLine) GetGUIConfigFilename() string { 82 return p.GetGString("gui-config-file") 83 } 84 func (p CommandLine) GetUpdaterConfigFilename() string { 85 return p.GetGString("updater-config-file") 86 } 87 func (p CommandLine) GetDeviceCloneStateFilename() string { 88 return p.GetGString("device-clone-state-file") 89 } 90 func (p CommandLine) GetSessionFilename() string { 91 return p.GetGString("session-file") 92 } 93 func (p CommandLine) GetDbFilename() string { 94 return p.GetGString("db") 95 } 96 func (p CommandLine) GetChatDbFilename() string { 97 return p.GetGString("chat-db") 98 } 99 func (p CommandLine) GetPvlKitFilename() string { 100 return p.GetGString("pvl-kit") 101 } 102 func (p CommandLine) GetParamProofKitFilename() string { 103 return p.GetGString("paramproof-kit") 104 } 105 func (p CommandLine) GetExternalURLKitFilename() string { 106 return p.GetGString("externalurl-kit") 107 } 108 func (p CommandLine) GetProveBypass() (bool, bool) { 109 return p.GetBool("prove-bypass", true) 110 } 111 func (p CommandLine) GetDebug() (bool, bool) { 112 // --no-debug suppresses --debug. Note that although we don't define a 113 // separate GetNoDebug() accessor, fork_server.go still looks for 114 // --no-debug by name, to pass it along to an autoforked daemon. 115 if noDebug, _ := p.GetBool("no-debug", true); noDebug { 116 return false /* val */, true /* isSet */ 117 } 118 return p.GetBool("debug", true) 119 } 120 func (p CommandLine) GetDebugJourneycard() (bool, bool) { 121 return p.GetBool("debug-journeycard", true) 122 } 123 func (p CommandLine) GetDisplayRawUntrustedOutput() (bool, bool) { 124 return p.GetBool("display-raw-untrusted-output", true) 125 } 126 func (p CommandLine) GetVDebugSetting() string { 127 return p.GetGString("vdebug") 128 } 129 func (p CommandLine) GetPGPFingerprint() *libkb.PGPFingerprint { 130 return libkb.PGPFingerprintFromHexNoError(p.GetGString("fingerprint")) 131 } 132 func (p CommandLine) GetProxy() string { 133 return p.GetGString("proxy") 134 } 135 func (p CommandLine) GetLogFile() string { 136 return p.GetGString("log-file") 137 } 138 func (p CommandLine) GetEKLogFile() string { 139 return p.GetGString("ek-log-file") 140 } 141 func (p CommandLine) GetPerfLogFile() string { 142 return p.GetGString("perf-log-file") 143 } 144 func (p CommandLine) GetGUILogFile() string { 145 return p.GetGString("gui-log-file") 146 } 147 func (p CommandLine) GetUseDefaultLogFile() (bool, bool) { 148 return p.GetBool("use-default-log-file", true) 149 } 150 func (p CommandLine) GetUseRootConfigFile() (bool, bool) { 151 return p.GetBool("use-root-config-file", true) 152 } 153 func (p CommandLine) GetLogPrefix() string { 154 return p.GetGString("log-prefix") 155 } 156 157 func (p CommandLine) GetLogFormat() string { 158 return p.GetGString("log-format") 159 } 160 func (p CommandLine) GetGpgHome() string { 161 return p.GetGString("gpg-home") 162 } 163 func (p CommandLine) GetAPIDump() (bool, bool) { 164 return p.GetBool("api-dump-unsafe", true) 165 } 166 func (p CommandLine) GetGregorSaveInterval() (time.Duration, bool) { 167 ret, err := p.GetGDuration("push-save-interval") 168 if err != nil { 169 return 0, false 170 } 171 return ret, true 172 } 173 func (p CommandLine) GetGregorDisabled() (bool, bool) { 174 return p.GetBool("push-disabled", true) 175 } 176 func (p CommandLine) GetSecretStorePrimingDisabled() (bool, bool) { 177 // SecretStorePrimingDisabled is only for tests 178 return false, false 179 } 180 func (p CommandLine) GetBGIdentifierDisabled() (bool, bool) { 181 return p.GetBool("bg-identifier-disabled", true) 182 } 183 184 func (p CommandLine) GetGregorURI() string { 185 return p.GetGString("push-server-uri") 186 } 187 func (p CommandLine) GetGregorPingInterval() (time.Duration, bool) { 188 ret, err := p.GetGDuration("push-ping-interval") 189 if err != nil { 190 return 0, false 191 } 192 return ret, true 193 } 194 func (p CommandLine) GetGregorPingTimeout() (time.Duration, bool) { 195 ret, err := p.GetGDuration("push-ping-timeout") 196 if err != nil { 197 return 0, false 198 } 199 return ret, true 200 } 201 202 func (p CommandLine) GetChatDelivererInterval() (time.Duration, bool) { 203 ret, err := p.GetGDuration("chat-deliverer-interval") 204 if err != nil { 205 return 0, false 206 } 207 return ret, true 208 } 209 210 func (p CommandLine) GetRunMode() (libkb.RunMode, error) { 211 return libkb.StringToRunMode(p.GetGString("run-mode")) 212 } 213 func (p CommandLine) GetFeatureFlags() (libkb.FeatureFlags, error) { 214 return libkb.StringToFeatureFlags(p.GetGString("features")), nil 215 } 216 func (p CommandLine) GetPinentry() string { 217 return p.GetGString("pinentry") 218 } 219 func (p CommandLine) GetAppType() libkb.AppType { 220 return libkb.DesktopAppType 221 } 222 func (p CommandLine) IsMobileExtension() (bool, bool) { 223 return false, false 224 } 225 func (p CommandLine) GetSlowGregorConn() (bool, bool) { 226 return p.GetBool("slow-gregor-conn", true) 227 } 228 func (p CommandLine) GetReadDeletedSigChain() (bool, bool) { 229 return p.GetBool("read-deleted-sigchain", true) 230 } 231 func (p CommandLine) GetGString(s string) string { 232 return p.ctx.GlobalString(s) 233 } 234 func (p CommandLine) GetString(s string) string { 235 return p.ctx.String(s) 236 } 237 func (p CommandLine) GetGInt(s string) int { 238 return p.ctx.GlobalInt(s) 239 } 240 func (p CommandLine) GetGDuration(s string) (time.Duration, error) { 241 return time.ParseDuration(p.GetGString(s)) 242 } 243 func (p CommandLine) GetGpg() string { 244 return p.GetGString("gpg") 245 } 246 func (p CommandLine) GetSecretKeyringTemplate() string { 247 return p.GetGString("secret-keyring") 248 } 249 func (p CommandLine) GetSocketFile() string { 250 return p.GetGString("socket-file") 251 } 252 func (p CommandLine) GetPidFile() string { 253 return p.GetGString("pid-file") 254 } 255 func (p CommandLine) GetScraperTimeout() (time.Duration, bool) { 256 ret, err := p.GetGDuration("scraper-timeout") 257 if err != nil { 258 return 0, false 259 } 260 return ret, true 261 } 262 func (p CommandLine) GetAPITimeout() (time.Duration, bool) { 263 ret, err := p.GetGDuration("api-timeout") 264 if err != nil { 265 return 0, false 266 } 267 return ret, true 268 } 269 func (p CommandLine) GetGpgOptions() []string { 270 var ret []string 271 s := p.GetGString("gpg-options") 272 if len(s) > 0 { 273 ret = strings.Fields(s) 274 } 275 return ret 276 } 277 278 func (p CommandLine) getKIDs(name string) []string { 279 s := p.GetGString(name) 280 if len(s) == 0 { 281 return nil 282 } 283 return strings.Split(s, ":") 284 } 285 286 func (p CommandLine) GetMerkleKIDs() []string { 287 return p.getKIDs("merkle-kids") 288 } 289 290 func (p CommandLine) GetCodeSigningKIDs() []string { 291 return p.getKIDs("code-signing-kids") 292 } 293 294 func (p CommandLine) GetUserCacheMaxAge() (time.Duration, bool) { 295 ret, err := p.GetGDuration("user-cache-maxage") 296 if err != nil { 297 return 0, false 298 } 299 return ret, true 300 } 301 302 func (p CommandLine) GetProofCacheSize() (int, bool) { 303 ret := p.GetGInt("proof-cache-size") 304 if ret != 0 { 305 return ret, true 306 } 307 return 0, false 308 } 309 310 func (p CommandLine) GetLevelDBNumFiles() (int, bool) { 311 ret := p.GetGInt("leveldb-num-files") 312 if ret != 0 { 313 return ret, true 314 } 315 return 0, false 316 } 317 318 func (p CommandLine) GetLevelDBWriteBufferMB() (int, bool) { 319 ret := p.GetGInt("leveldb-write-buffer-mb") 320 if ret != 0 { 321 return ret, true 322 } 323 return 0, false 324 } 325 326 func (p CommandLine) GetChatInboxSourceLocalizeThreads() (int, bool) { 327 ret := p.GetGInt("chat-inboxsource-localizethreads") 328 if ret != 0 { 329 return ret, true 330 } 331 return 0, false 332 } 333 334 func (p CommandLine) GetLinkCacheSize() (int, bool) { 335 ret := p.GetGInt("link-cache-size") 336 if ret != 0 { 337 return ret, true 338 } 339 return 0, false 340 } 341 342 func (p CommandLine) GetUPAKCacheSize() (int, bool) { 343 ret := p.GetGInt("upak-cache-size") 344 if ret != 0 { 345 return ret, true 346 } 347 return 0, false 348 } 349 350 func (p CommandLine) GetUIDMapFullNameCacheSize() (int, bool) { 351 ret := p.GetGInt("uid-map-full-name-cache-size") 352 if ret != 0 { 353 return ret, true 354 } 355 return 0, false 356 } 357 358 func (p CommandLine) GetPayloadCacheSize() (int, bool) { 359 ret := p.GetGInt("payload-cache-size") 360 if ret != 0 { 361 return ret, true 362 } 363 return 0, false 364 } 365 366 func (p CommandLine) GetLocalTrackMaxAge() (time.Duration, bool) { 367 ret, err := p.GetGDuration("local-track-maxage") 368 if err != nil { 369 return 0, false 370 } 371 return ret, true 372 } 373 374 func (p CommandLine) GetStandalone() (bool, bool) { 375 return p.GetBool("standalone", true) 376 } 377 378 func (p CommandLine) GetLocalRPCDebug() string { 379 return p.GetGString("local-rpc-debug-unsafe") 380 } 381 382 func (p CommandLine) GetTimers() string { 383 return p.GetGString("timers") 384 } 385 386 func (p CommandLine) GetTorMode() (ret libkb.TorMode, err error) { 387 if s := p.GetGString("tor-mode"); s != "" { 388 ret, err = libkb.StringToTorMode(s) 389 } 390 return ret, err 391 } 392 393 func (p CommandLine) GetTorHiddenAddress() string { 394 return p.GetGString("tor-hidden-address") 395 } 396 func (p CommandLine) GetTorProxy() string { 397 return p.GetGString("tor-proxy") 398 } 399 400 func (p CommandLine) GetProxyType() string { 401 return p.GetGString("proxy-type") 402 } 403 404 func (p CommandLine) IsCertPinningEnabled() bool { 405 r1, _ := p.GetBool("disable-cert-pinning", true) 406 // Defaults to false since it is a boolean flag, so just invert it 407 return !r1 408 } 409 410 func (p CommandLine) GetMountDir() string { 411 return p.GetGString("mountdir") 412 } 413 414 func (p CommandLine) GetMountDirDefault() string { 415 return p.GetGString("mountdirdefault") 416 } 417 418 func (p CommandLine) GetRememberPassphrase(libkb.NormalizedUsername) (bool, bool) { 419 return p.GetBool("remember-passphrase", true) 420 } 421 422 func (p CommandLine) GetAttachmentDisableMulti() (bool, bool) { 423 return p.GetBool("attachment-disable-multi", true) 424 } 425 426 func (p CommandLine) GetDisableTeamAuditor() (bool, bool) { 427 return p.GetBool("disable-team-auditor", true) 428 } 429 430 func (p CommandLine) GetDisableTeamBoxAuditor() (bool, bool) { 431 return p.GetBool("disable-team-box-auditor", true) 432 } 433 434 func (p CommandLine) GetDisableEKBackgroundKeygen() (bool, bool) { 435 return p.GetBool("disable-ek-backgorund-keygen", true) 436 } 437 438 func (p CommandLine) GetDisableMerkleAuditor() (bool, bool) { 439 return p.GetBool("disable-merkle-auditor", true) 440 } 441 442 func (p CommandLine) GetDisableSearchIndexer() (bool, bool) { 443 return p.GetBool("disable-search-indexer", true) 444 } 445 446 func (p CommandLine) GetDisableBgConvLoader() (bool, bool) { 447 return p.GetBool("disable-bg-conv-loader", true) 448 } 449 450 func (p CommandLine) GetEnableBotLiteMode() (bool, bool) { 451 return p.GetBool("enable-bot-lite-mode", true) 452 } 453 454 func (p CommandLine) GetExtraNetLogging() (bool, bool) { 455 return p.GetBool("extra-net-logging", true) 456 } 457 458 func (p CommandLine) GetForceLinuxKeyring() (bool, bool) { 459 return p.GetBool("force-linux-keyring", true) 460 } 461 462 func (p CommandLine) GetForceSecretStoreFile() (bool, bool) { 463 return false, false // not configurable via command line flags 464 } 465 466 func (p CommandLine) GetRuntimeStatsEnabled() (bool, bool) { 467 return false, false 468 } 469 470 func (p CommandLine) GetAttachmentHTTPStartPort() (int, bool) { 471 ret := p.GetGInt("attachment-httpsrv-port") 472 if ret != 0 { 473 return ret, true 474 } 475 return 0, false 476 } 477 478 func (p CommandLine) GetBool(s string, glbl bool) (bool, bool) { 479 var v bool 480 if glbl { 481 v = p.ctx.GlobalBool(s) 482 } else { 483 v = p.ctx.Bool(s) 484 } 485 return v, v 486 } 487 488 type CmdBaseHelp struct { 489 ctx *cli.Context 490 } 491 492 func (c *CmdBaseHelp) GetUsage() libkb.Usage { 493 return libkb.Usage{} 494 } 495 func (c *CmdBaseHelp) ParseArgv(*cli.Context) error { return nil } 496 497 type CmdGeneralHelp struct { 498 CmdBaseHelp 499 } 500 501 func (c *CmdBaseHelp) RunClient() error { return c.Run() } 502 503 func (c *CmdBaseHelp) Run() error { 504 cli.ShowAppHelp(c.ctx) 505 return nil 506 } 507 508 type CmdSpecificHelp struct { 509 CmdBaseHelp 510 name string 511 } 512 513 func (c CmdSpecificHelp) Run() error { 514 cli.ShowCommandHelp(c.ctx, c.name) 515 return nil 516 } 517 518 func NewCommandLine(addHelp bool, extraFlags []cli.Flag) *CommandLine { 519 app := cli.NewApp() 520 ret := &CommandLine{app: app, fork: NormalFork} 521 ret.PopulateApp(addHelp, extraFlags) 522 return ret 523 } 524 525 func (p *CommandLine) PopulateApp(addHelp bool, extraFlags []cli.Flag) { 526 app := p.app 527 app.Name = "keybase" 528 app.EnableBashCompletion = true 529 app.Version = libkb.VersionString() 530 app.Usage = "Keybase command line client." 531 532 app.Flags = []cli.Flag{ 533 cli.BoolFlag{ 534 Name: "api-dump-unsafe", 535 Usage: "Dump API call internals (may leak secrets).", 536 }, 537 cli.StringFlag{ 538 Name: "api-timeout", 539 Usage: "set the HTTP timeout for API calls to the keybase API server", 540 }, 541 cli.StringFlag{ 542 Name: "api-uri-path-prefix", 543 Usage: "Specify an alternate API URI path prefix.", 544 }, 545 cli.StringFlag{ 546 Name: "app-start-mode", 547 Usage: "Specify 'service' to auto-start UI app, or anything else to disable", 548 }, 549 cli.BoolFlag{ 550 Name: "bg-identifier-disabled", 551 Usage: "supply to disable the BG identifier loop", 552 }, 553 cli.StringFlag{ 554 Name: "chat-db", 555 Usage: "Specify an alternate local Chat DB location.", 556 }, 557 cli.StringFlag{ 558 Name: "code-signing-kids", 559 Usage: "Set of code signing key IDs (colon-separated).", 560 }, 561 cli.StringFlag{ 562 Name: "config-file, c", 563 Usage: "Specify an (alternate) master config file.", 564 }, 565 cli.BoolFlag{ 566 Name: "use-root-config-file", 567 Usage: "Use the default root config on Linux only.", 568 }, 569 cli.StringFlag{ 570 Name: "db", 571 Usage: "Specify an alternate local DB location.", 572 }, 573 cli.BoolFlag{ 574 Name: "debug, d", 575 Usage: "Enable debugging mode.", 576 }, 577 cli.BoolFlag{ 578 Name: "disable-cert-pinning", 579 Usage: "Disable certificate pinning within the app. WARNING: This reduces the security of the app. Do not use " + 580 "unless necessary! This should only be used if you are running keybase behind a proxy that does TLS interception.", 581 }, 582 cli.BoolFlag{ 583 Name: "display-raw-untrusted-output", 584 Usage: "Display output from users (messages, chats, ...) in the terminal without escaping terminal codes. WARNING: maliciously crafted unescaped outputs can overwrite anything you see on the terminal.", 585 }, 586 cli.StringFlag{ 587 Name: "features", 588 Usage: "specify experimental feature flags", 589 }, 590 cli.StringFlag{ 591 Name: "gpg", 592 Usage: "Path to GPG client (optional for exporting keys).", 593 }, 594 cli.StringFlag{ 595 Name: "gpg-options", 596 Usage: "Options to use when calling GPG.", 597 }, 598 cli.StringFlag{ 599 Name: "home, H", 600 Usage: "Specify an (alternate) home directory.", 601 }, 602 cli.IntFlag{ 603 Name: "leveldb-num-files", 604 Usage: "Specify the max number of files LevelDB may open", 605 }, 606 cli.StringFlag{ 607 Name: "local-rpc-debug-unsafe", 608 Usage: "Use to debug local RPC (may leak secrets).", 609 }, 610 cli.StringFlag{ 611 Name: "log-file", 612 Usage: "Specify a log file for the keybase service.", 613 }, 614 cli.StringFlag{ 615 Name: "ek-log-file", 616 Usage: "Specify a log file for the keybase ephemeral key log.", 617 }, 618 cli.StringFlag{ 619 Name: "log-format", 620 Usage: "Log format (default, plain, file, fancy).", 621 }, 622 cli.StringFlag{ 623 Name: "log-prefix", 624 Usage: "Specify a prefix for a unique log file name.", 625 }, 626 cli.StringFlag{ 627 Name: "merkle-kids", 628 Usage: "Set of admissible Merkle Tree fingerprints (colon-separated).", 629 }, 630 cli.BoolFlag{ 631 Name: "no-debug", 632 Usage: "Suppress debugging mode; takes precedence over --debug.", 633 }, 634 cli.StringFlag{ 635 Name: "pgpdir, gpgdir", 636 Usage: "Specify a PGP directory (default is ~/.gnupg).", 637 }, 638 cli.StringFlag{ 639 Name: "pid-file", 640 Usage: "Location of the keybased pid-file (to ensure only one running daemon).", 641 }, 642 cli.StringFlag{ 643 Name: "pinentry", 644 Usage: "Specify a path to find a pinentry program.", 645 }, 646 cli.IntFlag{ 647 Name: "proof-cache-size", 648 Usage: "Number of proof entries to cache.", 649 }, 650 cli.StringFlag{ 651 Name: "proxy", 652 Usage: "Specify a proxy to ship all Web requests over; Must be used with --proxy-type; Example: localhost:8080", 653 }, 654 cli.StringFlag{ 655 Name: "proxy-type", 656 Usage: fmt.Sprintf("set the proxy type; One of: %s", libkb.GetCommaSeparatedListOfProxyTypes()), 657 }, 658 cli.BoolFlag{ 659 Name: "push-disabled", 660 Usage: "Disable push server connection (which is on by default)", 661 }, 662 cli.IntFlag{ 663 Name: "push-save-interval", 664 Usage: "Set the interval between saves of the push cache (in seconds)", 665 }, 666 cli.StringFlag{ 667 Name: "push-server-uri", 668 Usage: "Specify a URI for contacting the Keybase push server", 669 }, 670 cli.StringFlag{ 671 Name: "pvl-kit", 672 Usage: "Specify an alternate local PVL kit file location.", 673 }, 674 cli.StringFlag{ 675 Name: "paramproof-kit", 676 Usage: "Specify an alternate local parameterized proof kit file location.", 677 }, 678 cli.BoolFlag{ 679 Name: "prove-bypass", 680 Usage: "Prove even disabled proof services", 681 }, 682 cli.BoolFlag{ 683 Name: "remember-passphrase", 684 Usage: "Remember keybase passphrase", 685 }, 686 cli.StringFlag{ 687 Name: "run-mode", 688 Usage: "Run mode (devel, staging, prod).", // These are defined in libkb/constants.go 689 }, 690 cli.StringFlag{ 691 Name: "scraper-timeout", 692 Usage: "set the HTTP timeout for external proof scrapers", 693 }, 694 cli.StringFlag{ 695 Name: "secret-keyring", 696 Usage: "Location of the Keybase secret-keyring (P3SKB-encoded).", 697 }, 698 cli.StringFlag{ 699 Name: "server, s", 700 Usage: "Specify server API.", 701 }, 702 cli.StringFlag{ 703 Name: "session-file", 704 Usage: "Specify an alternate session data file.", 705 }, 706 cli.BoolFlag{ 707 Name: "slow-gregor-conn", 708 Usage: "Slow responses from gregor for testing", 709 }, 710 cli.BoolFlag{ 711 Name: "read-deleted-sigchain", 712 Usage: "Allow admins to read deleted sigchains for debugging.", 713 }, 714 cli.StringFlag{ 715 Name: "socket-file", 716 Usage: "Location of the keybased socket-file.", 717 }, 718 cli.BoolFlag{ 719 Name: "standalone", 720 Usage: "Use the client without any daemon support.", 721 }, 722 cli.StringFlag{ 723 Name: "timers", 724 Usage: "Specify 'a' for API; 'r' for RPCs; and 'x' for eXternal API calls", 725 }, 726 cli.StringFlag{ 727 Name: "tor-hidden-address", 728 Usage: fmt.Sprintf("set TOR address of keybase server; defaults to %s", libkb.TorServerURI), 729 }, 730 cli.StringFlag{ 731 Name: "tor-mode", 732 Usage: "set TOR mode to be 'leaky', 'none', or 'strict'. 'none' by default. See 'help tor' for more details.", 733 }, 734 cli.StringFlag{ 735 Name: "tor-proxy", 736 Usage: fmt.Sprintf("set TOR proxy; when Tor mode is on; defaults to %s when TOR is enabled", libkb.TorProxy), 737 }, 738 cli.StringFlag{ 739 Name: "updater-config-file", 740 Usage: "Specify a path to the updater config file", 741 }, 742 cli.StringFlag{ 743 Name: "gui-config-file", 744 Usage: "Specify a path to the GUI config file", 745 }, 746 cli.BoolFlag{ 747 Name: "use-default-log-file", 748 Usage: "Log to the default log file in $XDG_CACHE_HOME, or ~/.cache if unset.", 749 }, 750 cli.IntFlag{ 751 Name: "user-cache-size", 752 Usage: "Number of User entries to cache.", 753 }, 754 cli.StringFlag{ 755 Name: "vdebug", 756 Usage: "Verbose debugging; takes a comma-joined list of levels and tags", 757 }, 758 cli.BoolFlag{ 759 Name: "debug-journeycard", 760 Usage: "Enable experimental journey cards", 761 }, 762 cli.BoolFlag{ 763 Name: "disable-team-auditor", 764 Usage: "Disable auditing of teams", 765 }, 766 cli.BoolFlag{ 767 Name: "disable-team-box-auditor", 768 Usage: "Disable box auditing of teams", 769 }, 770 cli.BoolFlag{ 771 Name: "disable-merkle-auditor", 772 Usage: "Disable background probabilistic merkle audit", 773 }, 774 cli.BoolFlag{ 775 Name: "disable-search-indexer", 776 Usage: "Disable chat search background indexer", 777 }, 778 cli.BoolFlag{ 779 Name: "disable-bg-conv-loader", 780 Usage: "Disable background conversation loading", 781 }, 782 cli.BoolFlag{ 783 Name: "enable-bot-lite-mode", 784 Usage: "Enable bot lite mode. Disables non-critical background services for bot performance.", 785 }, 786 cli.BoolFlag{ 787 Name: "force-linux-keyring", 788 Usage: "Require the use of the OS keyring (Gnome Keyring or KWallet) and fail if not available rather than falling back to file-based secret store.", 789 }, 790 cli.BoolFlag{ 791 Name: "extra-net-logging", 792 Usage: "Do additional debug logging during network requests.", 793 }, 794 } 795 if extraFlags != nil { 796 app.Flags = append(app.Flags, extraFlags...) 797 } 798 799 app.Commands = []cli.Command{} 800 } 801 802 func filter(cmds []cli.Command, fn func(cli.Command) bool) []cli.Command { 803 var filter []cli.Command 804 for _, cmd := range cmds { 805 if fn(cmd) { 806 filter = append(filter, cmd) 807 } 808 } 809 return filter 810 } 811 812 func (p *CommandLine) AddCommands(cmds []cli.Command) { 813 cmds = filter(cmds, func(c cli.Command) bool { 814 return c.Name != "" 815 }) 816 p.app.Commands = append(p.app.Commands, cmds...) 817 } 818 819 func (p *CommandLine) SetDefaultCommand(name string, cmd Command) { 820 p.defaultCmd = name 821 p.app.Action = func(c *cli.Context) { 822 p.cmd = cmd 823 p.ctx = c 824 p.name = name 825 } 826 } 827 828 // Called back from inside our subcommands, when they're picked... 829 func (p *CommandLine) ChooseCommand(cmd Command, name string, ctx *cli.Context) { 830 p.cmd = cmd 831 p.name = name 832 p.ctx = ctx 833 } 834 835 func (p *CommandLine) Parse(args []string) (cmd Command, err error) { 836 // This is suboptimal, but the default help action when there are 837 // no args crashes. 838 // (cli sets HelpPrinter to nil when p.app.Run(...) returns.) 839 if len(args) == 1 && p.defaultCmd == "help" { 840 args = append(args, p.defaultCmd) 841 } 842 843 // Actually pick a command 844 err = p.app.Run(args) 845 846 // Should not be populated 847 cmd = p.cmd 848 849 if err != nil || cmd == nil { 850 return 851 } 852 853 // cli.HelpPrinter is nil here...anything that needs it will panic. 854 855 // If we failed to parse arguments properly, switch to the help command 856 if err = p.cmd.ParseArgv(p.ctx); err == nil { 857 _, err = p.GetRunMode() 858 } 859 if err != nil { 860 cmd = &CmdSpecificHelp{CmdBaseHelp{p.ctx}, p.name} 861 } 862 863 return 864 } 865 866 func (p *CommandLine) SetOutputWriter(w io.Writer) { 867 p.app.Writer = w 868 } 869 870 // AddHelpTopics appends topics to the list of help topics for 871 // this app. 872 func (p *CommandLine) AddHelpTopics(topics []cli.HelpTopic) { 873 p.app.HelpTopics = append(p.app.HelpTopics, topics...) 874 }