// Copyright IBM Corp. 2020, 2026 // SPDX-License-Identifier: BUSL-1.1 package cmd import ( "path/filepath" "strings" ) // legacyBinaryName is the name of the upstream HashiCorp Boundary binary. A // "boundary" symlink to the threshold binary is shipped in packages and // container images so existing scripts keep working. const legacyBinaryName = "boundary" // envNoLegacyNameNotice, when set to a non-empty value, silences the // deprecation notice printed when the binary is invoked as "boundary". const envNoLegacyNameNotice = "THRESHOLD_NO_DEPRECATION_NOTICE" // invokedAsLegacyName reports whether argv0 refers to the legacy "boundary" // binary name. Directory components and a Windows ".exe" suffix are ignored. func invokedAsLegacyName(argv0 string) bool { // Normalize Windows separators too, since filepath.Base on unix does not // treat backslash as a separator. argv0 = strings.ReplaceAll(argv0, `\`, "/") base := strings.ToLower(filepath.Base(argv0)) base = strings.TrimSuffix(base, ".exe") return base == legacyBinaryName } // LegacyNameNotice returns the one-line deprecation notice (including a // trailing newline) to write to stderr when the binary was invoked as // "boundary", or an empty string when no notice should be shown. No notice is // shown for any other invocation name, when shell completion is running // (COMP_LINE is set, so that a notice never corrupts the user's prompt), or // when THRESHOLD_NO_DEPRECATION_NOTICE is set. The notice is only ever written // to stderr so that machine-readable stdout output is unaffected. // // getenv is typically os.Getenv. func LegacyNameNotice(argv0 string, getenv func(string) string) string { if !invokedAsLegacyName(argv0) { return "" } if getenv("COMP_LINE") != "" || getenv(envNoLegacyNameNotice) != "" { return "" } return "Note: the 'boundary' command name is deprecated; use 'threshold' instead. " + "(Set " + envNoLegacyNameNotice + "=1 to silence this notice.)\n" }