func (rc *ResolvConf) parse(reader *libio.Reader) {
	for {
		c := reader.SkipSpaces()
		if c == 0 {
			break
		}
		if c == ';' || c == '#' {
			reader.SkipUntil(newLineTerms)
			continue
		}
		tok, isTerm, _ := reader.ReadUntil(ascii.Spaces, newLineTerms)
		if isTerm {
			continue
		}
		tok = ascii.ToLower(tok)
		v := string(tok)
		switch v {
		case "domain":
			rc.parseValue(reader, &rc.Domain)
		case "search":
			rc.parseSearch(reader)
		case "nameserver":
			v = ""
			rc.parseValue(reader, &v)
			if len(rc.NameServers) < 3 && len(v) > 0 {
				rc.NameServers = append(rc.NameServers, v)
			}
		case "options":
			rc.parseOptions(reader)
		default:
			reader.SkipUntil(newLineTerms)
		}
	}
	rc.sanitize()
}
parse open and parse the resolv.conf file.

Lines that contain a semicolon (;) or hash character (#) in the first
column are treated as comments.

The keyword and value must appear on a single line, and the keyword (e.g.,
nameserver) must start the line.  The value follows the keyword, separated
by white space.

See `man resolv.conf`
package net
import (
	"os"
	"strconv"
	"strings"
	"github.com/shuLhan/share/lib/ascii"
	libio "github.com/shuLhan/share/lib/io"
)
const (
	envLocaldomain = "LOCALDOMAIN"
)
var (
	newLineTerms = []byte{'\n'}
	getHostname = os.Hostname
)
type ResolvConf struct {
	Domain string
	Search []string
	NameServers []string
	NDots int
	Timeout int
	Attempts int
	OptMisc map[string]bool
}
func NewResolvConf(path string) (*ResolvConf, error) {
	rc := &ResolvConf{
		OptMisc: make(map[string]bool),
	}
	reader, err := libio.NewReader(path)
	if err != nil {
		return nil, err
	}
	rc.parse(reader)
	return rc, nil
}
func (rc *ResolvConf) Init(src string) {
	reader := new(libio.Reader)
	reader.Init([]byte(src))
	rc.reset()
	rc.parse(reader)
}
func (rc *ResolvConf) reset() {
	rc.Domain = ""
	rc.Search = nil
	rc.NameServers = nil
	rc.OptMisc = make(map[string]bool)
}