func loadConfig() (*config, []string, error) {
	cfg := config{
		HomeDir:    defaultHomeDir,
		ActiveNet:  defaultActiveNet,
		ConfigFile: defaultConfigFile,
		DebugLevel: defaultLogLevel,
		LogDir:     defaultLogDir,
		UserAgent:  defaultUserAgent,
		User:       "",
		Address:    "",
	}
	serviceOpts := serviceOptions{}
	preCfg := cfg
	preParser, err := newConfigParser(&preCfg, &serviceOpts, flags.HelpFlag)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	_, err = preParser.Parse()
	if err != nil {
		var e *flags.Error
		if errors.As(err, &e) {
			if e.Type != flags.ErrHelp {
				fmt.Fprintln(os.Stderr, err)
				os.Exit(1)
			} else {
				fmt.Fprintln(os.Stdout, err)
				os.Exit(0)
			}
		}
	}
	appName := filepath.Base(os.Args[0])
	appName = strings.TrimSuffix(appName, filepath.Ext(appName))
	usageMessage := fmt.Sprintf("Use %s -h to show usage", appName)
	if serviceOpts.ServiceCommand != "" && runServiceCommand != nil {
		err := runServiceCommand(serviceOpts.ServiceCommand)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
		}
		os.Exit(0)
	}
	if preCfg.HomeDir != "" {
		cfg.HomeDir, _ = filepath.Abs(preCfg.HomeDir)
		if preCfg.ConfigFile == defaultConfigFile {
			defaultConfigFile = filepath.Join(cfg.HomeDir,
				defaultConfigFilename)
			preCfg.ConfigFile = defaultConfigFile
			cfg.ConfigFile = defaultConfigFile
		} else {
			cfg.ConfigFile = preCfg.ConfigFile
		}
		if preCfg.ConfigFile == defaultConfigFile {
			defaultConfigFile = filepath.Join(cfg.HomeDir,
				defaultConfigFilename)
			preCfg.ConfigFile = defaultConfigFile
			cfg.ConfigFile = defaultConfigFile
		} else {
			cfg.ConfigFile = preCfg.ConfigFile
		}
		if preCfg.LogDir == defaultLogDir {
			cfg.LogDir = filepath.Join(cfg.HomeDir, defaultLogDirname)
		} else {
			cfg.LogDir = preCfg.LogDir
		}
	}
	if !fileExists(preCfg.ConfigFile) {
		preIni := flags.NewIniParser(preParser)
		err = preIni.WriteFile(preCfg.ConfigFile, flags.IniDefault)
		if err != nil {
			return nil, nil, fmt.Errorf("error creating a default "+
				"config file: %v", err)
		}
	}
	var configFileError error
	parser, err := newConfigParser(&cfg, &serviceOpts, flags.Default)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return nil, nil, err
	}
	if preCfg.ConfigFile != defaultConfigFile {
		err = flags.NewIniParser(parser).ParseFile(preCfg.ConfigFile)
		if err != nil {
			var e *os.PathError
			if !errors.As(err, &e) {
				fmt.Fprintf(os.Stderr, "Error parsing config "+
					"file: %v\n", err)
				fmt.Fprintln(os.Stderr, usageMessage)
				return nil, nil, err
			}
			configFileError = err
		}
	}
	remainingArgs, err := parser.Parse()
	if err != nil {
		var e *flags.Error
		if !errors.As(err, &e) || e.Type != flags.ErrHelp {
			fmt.Fprintln(os.Stderr, usageMessage)
		}
		return nil, nil, err
	}
	const funcName = "loadConfig"
	err = os.MkdirAll(cfg.HomeDir, 0700)
	if err != nil {
		var e *os.PathError
		if errors.As(err, &e) && os.IsExist(err) {
			if link, lerr := os.Readlink(e.Path); lerr == nil {
				str := "is symlink %s -> %s mounted?"
				err = fmt.Errorf(str, e.Path, link)
			}
		}
		str := "%s: failed to create home directory: %v"
		err := fmt.Errorf(str, funcName, err)
		fmt.Fprintln(os.Stderr, err)
		return nil, nil, err
	}
	cfg.LogDir = cleanAndExpandPath(cfg.LogDir)
	logRotator = nil
	initLogRotator(filepath.Join(cfg.LogDir, defaultLogFilename))
	if cfg.DebugLevel == "show" {
		fmt.Println("Supported subsystems", supportedSubsystems())
		os.Exit(0)
	}
	if err := parseAndSetDebugLevels(cfg.DebugLevel); err != nil {
		err := fmt.Errorf("%s: %v", funcName, err.Error())
		fmt.Fprintln(os.Stderr, err)
		fmt.Fprintln(os.Stderr, usageMessage)
		return nil, nil, err
	}
	switch cfg.ActiveNet {
	case chaincfg.SimNetParams().Name:
		cfg.net = chaincfg.SimNetParams()
	case chaincfg.TestNet3Params().Name:
		cfg.net = chaincfg.TestNet3Params()
	case chaincfg.MainNetParams().Name:
		cfg.net = chaincfg.MainNetParams()
	default:
		return nil, nil, fmt.Errorf("unknown network provided %v",
			cfg.ActiveNet)
	}
	if cfg.Profile != "" {
		if _, err := strconv.Atoi(cfg.Profile); err == nil {
			cfg.Profile = net.JoinHostPort("127.0.0.1", cfg.Profile)
		}
		_, portStr, err := net.SplitHostPort(cfg.Profile)
		if err != nil {
			str := "%s: profile: %s"
			err := fmt.Errorf(str, funcName, err)
			fmt.Fprintln(os.Stderr, err)
			fmt.Fprintln(os.Stderr, usageMessage)
			return nil, nil, err
		}
		if port, _ := strconv.Atoi(portStr); port < 1024 || port > 65535 {
			str := "%s: profile: address %s: port must be between 1024 and 65535"
			err := fmt.Errorf(str, funcName, cfg.Profile)
			fmt.Fprintln(os.Stderr, err)
			fmt.Fprintln(os.Stderr, usageMessage)
			return nil, nil, err
		}
	}
	if cfg.Pool == "" {
		str := "%s: the pool address cannot be an empty string"
		err := fmt.Errorf(str, funcName)
		fmt.Fprintln(os.Stderr, err)
		fmt.Fprintln(os.Stderr, usageMessage)
		return nil, nil, err
	}
	cfg.Pool = strings.Replace(cfg.Pool, "stratum+tcp://", "", 1)
	_, poolPort, err := net.SplitHostPort(cfg.Pool)
	if err != nil {
		str := "%s: invalid pool address, %s"
		err := fmt.Errorf(str, funcName, err)
		fmt.Fprintln(os.Stderr, err)
		fmt.Fprintln(os.Stderr, usageMessage)
		return nil, nil, err
	}
	if port, _ := strconv.Atoi(poolPort); port < 1024 || port > 65535 {
		str := "%s: profile: address %s: port must be between 1024 and 65535"
		err := fmt.Errorf(str, funcName, cfg.Profile)
		fmt.Fprintln(os.Stderr, err)
		fmt.Fprintln(os.Stderr, usageMessage)
		return nil, nil, err
	}
	availableCPUs := runtime.NumCPU()
	if cfg.MaxProcs < 1 || cfg.MaxProcs > availableCPUs {
		log.Warnf("%d is not a valid value for MaxProcs. Defaulting to %d.", cfg.MaxProcs, availableCPUs)
		cfg.MaxProcs = availableCPUs
	}
	if configFileError != nil {
		log.Warnf("%v", configFileError)
	}
	return &cfg, remainingArgs, nil
}
loadConfig initializes and parses the config using a config file and command
line options.

The configuration proceeds as follows:
1) Start with a default config with sane settings
2) Pre-parse the command line to check for an alternative config file
3) Load configuration file overwriting defaults with any specified options
4) Parse CLI options and overwrite/add any specified options

The above results in dcrpool functioning properly without any config settings
while still allowing the user to override settings with config files and
command line options.  Command line options always take precedence.
package main
import (
	"errors"
	"fmt"
	"net"
	_ "net/http/pprof"
	"os"
	"os/user"
	"path/filepath"
	"runtime"
	"sort"
	"strconv"
	"strings"
	"github.com/decred/dcrd/chaincfg/v3"
	"github.com/decred/dcrd/dcrutil/v3"
	"github.com/decred/slog"
	flags "github.com/jessevdk/go-flags"
)
const (
	defaultLogLevel       = "debug"
	defaultConfigFilename = "miner.conf"
	defaultLogDirname     = "log"
	defaultLogFilename    = "miner.log"
)
var (
	defaultActiveNet  = chaincfg.SimNetParams().Name
	defaultHomeDir    = dcrutil.AppDataDir("miner", false)
	defaultConfigFile = filepath.Join(defaultHomeDir, defaultConfigFilename)
	defaultLogDir     = filepath.Join(defaultHomeDir, defaultLogDirname)
	defaultUserAgent  = fmt.Sprintf("%s/%s", "cpuminer", minerVersion())
)
var runServiceCommand func(string) error
type config struct {
	HomeDir    string `long:"appdata" ini-name:"appdata" description:"Path to application home directory."`
	ConfigFile string `long:"configfile" ini-name:"configfile" description:"Path to configuration file."`
	ActiveNet  string `long:"activenet" ini-name:"activenet" description:"The active network being mined on. {simnet, testnet3, mainnet}"`
	User       string `long:"user" ini-name:"user" description:"The username of the mining account."`
	Address    string `long:"address" ini-name:"address" description:"The address of the mining account."`
	Pool       string `long:"pool" ini-name:"pool" description:"The stratum domain and port of the mining pool to connect to. eg. dcrpool.com:4445."`
	DebugLevel string `long:"debuglevel" ini-name:"debuglevel" description:"Logging level for all subsystems {trace, debug, info, warn, error, critical} -- You may also specify <subsystem>=<level>,<subsystem2>=<level>,... to set the log level for individual subsystems -- Use show to list available subsystems."`
	LogDir     string `long:"logdir" ini-name:"logdir" description:"The log output directory."`
	MaxProcs   int    `long:"maxprocs" ini-name:"maxprocs" description:"Number of CPU cores to use. Default is all cores."`
	Profile    string `long:"profile" ini-name:"profile" description:"Enable HTTP profiling on given [addr:]port -- NOTE port must be between 1024 and 65536."`
	Stall      bool   `long:"stall" ini-name:"stall" description:"Do not generate work submissions."`
	UserAgent  string `long:"useragent" ini-name:"useragent" description:"The user agent to identify as in a subscription message."`
	net *chaincfg.Params
}
type serviceOptions struct {
	ServiceCommand string `short:"s" long:"service" description:"Service command {install, remove, start, stop}"`
}
func validLogLevel(logLevel string) bool {
	_, ok := slog.LevelFromString(logLevel)
	return ok
}
func supportedSubsystems() []string {
	subsystems := make([]string, 0, len(subsystemLoggers))
	for subsysID := range subsystemLoggers {
		subsystems = append(subsystems, subsysID)
	}
	sort.Strings(subsystems)
	return subsystems
}
func parseAndSetDebugLevels(debugLevel string) error {
	if !strings.Contains(debugLevel, ",") && !strings.Contains(debugLevel, "=") {
		if !validLogLevel(debugLevel) {
			str := "the specified debug level [%v] is invalid"
			return fmt.Errorf(str, debugLevel)
		}
		setLogLevels(debugLevel)
		return nil
	}
	for _, logLevelPair := range strings.Split(debugLevel, ",") {
		if !strings.Contains(logLevelPair, "=") {
			str := "the specified debug level contains an invalid " +
				"subsystem/level pair [%v]"
			return fmt.Errorf(str, logLevelPair)
		}
		fields := strings.Split(logLevelPair, "=")
		subsysID, logLevel := fields[0], fields[1]
		if _, exists := subsystemLoggers[subsysID]; !exists {
			str := "the specified subsystem [%v] is invalid -- " +
				"supported subsytems %v"
			return fmt.Errorf(str, subsysID, supportedSubsystems())
		}
		if !validLogLevel(logLevel) {
			str := "the specified debug level [%v] is invalid"
			return fmt.Errorf(str, logLevel)
		}
		setLogLevel(subsysID, logLevel)
	}
	return nil
}
func fileExists(name string) bool {
	if _, err := os.Stat(name); os.IsNotExist(err) {
		return false
	}
	return true
}
func cleanAndExpandPath(path string) string {
	if path == "" {
		return path
	}
	path = os.ExpandEnv(path)
	if !strings.HasPrefix(path, "~") {
		return filepath.Clean(path)
	}
	path = path[1:]
	var pathSeparators string
	if runtime.GOOS == "windows" {
		pathSeparators = string(os.PathSeparator) + "/"
	} else {
		pathSeparators = string(os.PathSeparator)
	}
	userName := ""
	if i := strings.IndexAny(path, pathSeparators); i != -1 {
		userName = path[:i]
		path = path[i:]
	}
	homeDir := ""
	var u *user.User
	var err error
	if userName == "" {
		u, err = user.Current()
	} else {
		u, err = user.Lookup(userName)
	}
	if err == nil {
		homeDir = u.HomeDir
	}
	if homeDir == "" {
		homeDir = "."
	}
	return filepath.Join(homeDir, path)
}
func newConfigParser(cfg *config, so *serviceOptions, options flags.Options) (*flags.Parser, error) {
	parser := flags.NewParser(cfg, options)
	if runtime.GOOS == "windows" {
		_, err := parser.AddGroup("Service Options", "Service Options", so)
		if err != nil {
			return nil, err
		}
	}
	return parser, nil
}