func usageCSRFlags(w io.Writer, line int) {
	fmt.Fprintln(w, "CSR field options:")
	listOpts(w, []string{
		commonNameFlag,
		serialNumberFlag,
		organizationalUnitFlag,
		organizationFlag,
		streetAddressFlag,
		localityFlag,
		provinceFlag,
		postalCodeFlag,
		countryFlag,
		dnsNamesFlag,
		emailsFlag,
		ipsFlag,
		urisFlag,
	})
	fmt.Fprintln(w)
	outputPara(w, line, 0, usageCSRMultiPara)
}
usageCSRFlags outputs a partial usage message describing the CSR field
flags.
package main
import (
	"flag"
	"fmt"
	"io"
	"os"
	"sort"
	"strings"
	"time"
)
type option struct {
	argFmt string
	defaultLabel interface{}
	defaultValue interface{}
	desc string
}
const (
	appName        = "estclient"
	defaultTimeout = time.Second * 15
	sepChar        = ","
	versionString  = "1.0.6"
)
const (
	apsFlag                = "aps"
	certsFlag              = "certs"
	commonFlag             = "common"
	commonNameFlag         = "cn"
	configFlag             = "config"
	countryFlag            = "country"
	csrFlag                = "csr"
	dnsNamesFlag           = "dnsnames"
	ekcertsFlag            = "ekcerts"
	emailsFlag             = "emails"
	explicitAnchorFlag     = "explicit"
	headersFlag            = "headers"
	helpFlag               = "help"
	hostHeaderFlag         = "hostheader"
	hsmFlag                = "hsm"
	implicitAnchorFlag     = "implicit"
	insecureFlag           = "insecure"
	ipsFlag                = "ips"
	keyFlag                = "key"
	keyOutFlag             = "keyout"
	localityFlag           = "locality"
	organizationFlag       = "org"
	organizationalUnitFlag = "ou"
	outFlag                = "out"
	separateOutFlag        = "separate"
	passwordFlag           = "pass"
	postalCodeFlag         = "postalcode"
	provinceFlag           = "province"
	rootOutFlag            = "rootout"
	rootsOnlyFlag          = "roots"
	intermediatesOnlyFlag  = "intermediates"
	separatorFlag          = "separator"
	serialNumberFlag       = "sn"
	serverFlag             = "server"
	streetAddressFlag      = "street"
	timeoutFlag            = "timeout"
	tpmFlag                = "tpm"
	urisFlag               = "uris"
	usernameFlag           = "user"
)
const (
	durFmt    = "<duration>"
	hostFmt   = "<host:port>"
	pathFmt   = "<path>"
	stringFmt = "<string>"
)
var csrFlags = []string{
	commonNameFlag,
	countryFlag,
	dnsNamesFlag,
	emailsFlag,
	ipsFlag,
	localityFlag,
	organizationFlag,
	organizationalUnitFlag,
	postalCodeFlag,
	provinceFlag,
	serialNumberFlag,
	streetAddressFlag,
	urisFlag,
}
var optDefs = map[string]option{
	apsFlag: {
		argFmt:       stringFmt,
		defaultLabel: "none",
		defaultValue: "",
		desc:         "optional additional path segment",
	},
	certsFlag: {
		argFmt:       pathFmt,
		defaultLabel: "none",
		desc:         "TLS client certificate(s)",
		defaultValue: "",
	},
	commonFlag: {
		desc:         "show information about common options",
		defaultValue: false,
	},
	configFlag: {
		argFmt:       pathFmt,
		defaultLabel: "none",
		desc:         "configuration file",
		defaultValue: "",
	},
	csrFlag: {
		argFmt:       pathFmt,
		desc:         "PKCS#10 certificate signing request",
		defaultValue: "",
	},
	ekcertsFlag: {
		argFmt:       pathFmt,
		desc:         "endorsement key certificate(s) chain",
		defaultValue: "",
	},
	explicitAnchorFlag: {
		argFmt:       pathFmt,
		defaultLabel: "none",
		desc:         "explicit anchor file",
		defaultValue: "",
	},
	implicitAnchorFlag: {
		argFmt:       pathFmt,
		defaultLabel: "none",
		desc:         "implicit anchor file",
		defaultValue: "",
	},
	helpFlag: {
		desc:         "show this usage information",
		defaultValue: false,
	},
	headersFlag: {
		argFmt:       stringFmt,
		desc:         "optional list of additional HTTP headers",
		defaultValue: "",
	},
	hostHeaderFlag: {
		argFmt:       stringFmt,
		desc:         "override HTTP host header",
		defaultValue: "",
	},
	hsmFlag: {
		desc:         "output sample file for HSM-resident key",
		defaultValue: false,
	},
	insecureFlag: {
		desc:         "omit server TLS certificate verification",
		defaultValue: false,
	},
	keyFlag: {
		argFmt:       pathFmt,
		desc:         "private key",
		defaultValue: "",
	},
	keyOutFlag: {
		argFmt:       pathFmt,
		defaultLabel: "stdout",
		desc:         "output file for private key",
		defaultValue: "",
	},
	outFlag: {
		argFmt:       pathFmt,
		defaultLabel: "stdout",
		desc:         "output file",
		defaultValue: "",
	},
	separateOutFlag: {
		desc:         fmt.Sprintf("write every CA certificate to a separate file with optional prefix specified by -%s", outFlag),
		defaultValue: false,
	},
	passwordFlag: {
		argFmt:       stringFmt,
		defaultLabel: "none",
		desc:         "HTTP Basic Auth password",
		defaultValue: "",
	},
	rootOutFlag: {
		desc:         fmt.Sprintf("output the first root CA certificate only; this flag will be deprecated in favor of -%s, which is preferred", rootsOnlyFlag),
		defaultValue: false,
	},
	rootsOnlyFlag: {
		desc:         "only output root (self-signed) certificates",
		defaultValue: false,
	},
	intermediatesOnlyFlag: {
		desc:         "only output intermediate certificates",
		defaultValue: false,
	},
	separatorFlag: {
		argFmt:       stringFmt,
		defaultLabel: sepChar,
		desc:         "list item separator character",
		defaultValue: "",
	},
	serverFlag: {
		argFmt:       hostFmt,
		desc:         "server host and port",
		defaultValue: "",
	},
	usernameFlag: {
		argFmt:       stringFmt,
		defaultLabel: "none",
		desc:         "HTTP Basic Auth username",
		defaultValue: "",
	},
	timeoutFlag: {
		argFmt:       durFmt,
		defaultLabel: defaultTimeout,
		desc:         "request timeout",
		defaultValue: time.Duration(0),
	},
	tpmFlag: {
		desc:         "output sample file for TPM-resident key",
		defaultValue: false,
	},
	commonNameFlag: {
		argFmt:       stringFmt,
		desc:         "subject common name",
		defaultValue: "",
	},
	countryFlag: {
		argFmt:       stringFmt,
		desc:         "subject country",
		defaultValue: "",
	},
	dnsNamesFlag: {
		argFmt:       stringFmt,
		desc:         "subject alternative name DNS names",
		defaultValue: "",
	},
	emailsFlag: {
		argFmt:       stringFmt,
		desc:         "subject alternative name email addresses",
		defaultValue: "",
	},
	ipsFlag: {
		argFmt:       stringFmt,
		desc:         "subject alternative name IP addresses",
		defaultValue: "",
	},
	localityFlag: {
		argFmt:       stringFmt,
		desc:         "subject locality/city",
		defaultValue: "",
	},
	organizationalUnitFlag: {
		argFmt:       stringFmt,
		desc:         "subject organizational unit",
		defaultValue: "",
	},
	organizationFlag: {
		argFmt:       stringFmt,
		desc:         "subject organization",
		defaultValue: "",
	},
	postalCodeFlag: {
		argFmt:       stringFmt,
		desc:         "subject postal/zip code",
		defaultValue: "",
	},
	provinceFlag: {
		argFmt:       stringFmt,
		desc:         "subject province/state",
		defaultValue: "",
	},
	serialNumberFlag: {
		argFmt:       stringFmt,
		desc:         "subject serial number",
		defaultValue: "",
	},
	streetAddressFlag: {
		argFmt:       stringFmt,
		desc:         "subject street address",
		defaultValue: "",
	},
	urisFlag: {
		argFmt:       stringFmt,
		desc:         "subject alternative name URIs",
		defaultValue: "",
	},
}
func listOpts(w io.Writer, opts []string) {
	sort.Strings(opts)
	fieldWidth := 0
	for _, opt := range opts {
		def, ok := optDefs[opt]
		if !ok {
			panic(fmt.Sprintf("undefined option: %s", opt))
		}
		n := len(opt)
		if def.argFmt != "" {
			n += len(def.argFmt) + 1
		}
		if n+4 > fieldWidth {
			fieldWidth = n + 4
		}
	}
	for _, opt := range opts {
		var builder strings.Builder
		def, _ := optDefs[opt]
		argFmt := ""
		if def.argFmt != "" {
			argFmt = " " + def.argFmt
		}
		builder.WriteString(fmt.Sprintf("-%-*s%s", fieldWidth, opt+argFmt, def.desc))
		if def.defaultLabel != nil {
			builder.WriteString(fmt.Sprintf(" (default: %v)", def.defaultLabel))
		}
		fmt.Fprintf(w, "    %s\n", builder.String())
	}
}
func isFlagPassed(set *flag.FlagSet, name string) bool {
	if set == nil {
		return false
	}
	found := false
	set.Visit(func(f *flag.Flag) {
		if f.Name == name {
			found = true
		}
	})
	return found
}
func usageError(w io.Writer, line int) {
	outputPara(w, line, 0, usageShort)
	outputPara(w, line, 0, fmt.Sprintf(`Use "%s help" for a list of commands.`, appName))
	os.Exit(1)
}
func version(w io.Writer, set *flag.FlagSet) error {
	fmt.Fprintf(w, "GlobalSign EST Client %s\n", versionString)
	return nil
}
func usageMain(w io.Writer, set *flag.FlagSet) error {
	outputPara(w, usageLineLength, 0, usageShort)
	outputPara(w, usageLineLength, 0, usageMainPara)
	cmdNames := commands.Names()
	fieldWidth := 0
	for _, name := range cmdNames {
		if n := len(name); n+4 > fieldWidth {
			fieldWidth = n + 4
		}
	}
	fmt.Fprintln(w, "Commands:")
	for _, name := range cmdNames {
		cmd, _ := commands[name]
		fmt.Fprintf(w, "%s%-*s %s\n", strings.Repeat(" ", usageIndent), fieldWidth, name, cmd.shortDesc)
	}
	fmt.Fprintln(w)
	outputPara(w, usageLineLength, 0, usageCommandPara)
	if !isFlagPassed(set, commonFlag) {
		outputPara(w, usageLineLength, 0, usageCommonPara)
		return nil
	}
	fmt.Fprintln(w, "Configuration file:")
	outputPara(w, usageLineLength, usageIndent, usageConfigIntroPara)
	outputPara(w, usageLineLength, usageIndent, usageConfigLocationPara)
	outputPara(w, usageLineLength, usageIndent, usageConfigKeysPara)
	fmt.Fprintln(w, "Explicit and implicit anchors:")
	outputPara(w, usageLineLength, usageIndent, usageAnchorsIntroPara)
	outputPara(w, usageLineLength, usageIndent, usageAnchorsFormatPara)
	outputPara(w, usageLineLength, usageIndent, usageAnchorsInsecurePara)
	fmt.Fprintln(w, "Additional path segment:")
	outputPara(w, usageLineLength, usageIndent, usageAPSIntroPara)
	fmt.Fprintln(w, "TLS client certificates:")
	outputPara(w, usageLineLength, usageIndent, usageCertsIntroPara)
	outputPara(w, usageLineLength, usageIndent, usageCertsFormatPara)
	outputPara(w, usageLineLength, usageIndent, usageCertsKeyPara)
	fmt.Fprintln(w, "Additional HTTP headers:")
	outputPara(w, usageLineLength, usageIndent, usageHeadersPara)
	outputPara(w, usageLineLength, usageIndent*2, usageHeadersExample)
	fmt.Fprintln(w, "HTTP Host header:")
	outputPara(w, usageLineLength, usageIndent, usageHostHeaderPara)
	fmt.Fprintln(w, "Request timeout:")
	outputPara(w, usageLineLength, usageIndent, usageTimeoutPara)
	return nil
}