package  netimport  (	"errors" 	"internal/bytealg" 	"os" 	"sync" 	"time" )const  (	nssConfigPath  = "/etc/nsswitch.conf" )var  nssConfig  nsswitchConfig type  nsswitchConfig  struct  {	initOnce  sync .Once  		ch           chan  struct {} 	lastChecked  time .Time      	mu       sync .Mutex  	nssConf  *nssConf }func  getSystemNSS nssConf  {	nssConfig .tryUpdate ()	nssConfig .mu .Lock ()	conf  := nssConfig .nssConf 	nssConfig .mu .Unlock ()	return  conf }func  (conf  *nsswitchConfig ) init 	conf .nssConf  = parseNSSConfFile ("/etc/nsswitch.conf" )	conf .lastChecked  = time .Now ()	conf .ch  = make (chan  struct {}, 1 )}func  (conf  *nsswitchConfig ) tryUpdate 	conf .initOnce .Do (conf .init )		if  !conf .tryAcquireSema () {		return 	}	defer  conf .releaseSema ()	now  := time .Now ()	if  conf .lastChecked .After (now .Add (-5  * time .Second )) {		return 	}	conf .lastChecked  = now 	var  mtime  time .Time 	if  fi , err  := os .Stat (nssConfigPath ); err  == nil  {		mtime  = fi .ModTime ()	}	if  mtime .Equal (conf .nssConf .mtime ) {		return 	}	nssConf  := parseNSSConfFile (nssConfigPath )	conf .mu .Lock ()	conf .nssConf  = nssConf 	conf .mu .Unlock ()}func  (conf  *nsswitchConfig ) acquireSema 	conf .ch  <- struct {}{}}func  (conf  *nsswitchConfig ) tryAcquireSema bool  {	select 	case  conf .ch  <-  struct {}{}:		return  true 	default :		return  false 	}}func  (conf  *nsswitchConfig ) releaseSema 	<-conf .ch }type  nssConf  struct  {	mtime    time .Time               	err      error                   	sources  map [string ][]nssSource  }type  nssSource  struct  {	source    string  	criteria  []nssCriterion }func  (s  nssSource ) standardCriteria bool  {	for  i , crit  := range  s .criteria  {		if  !crit .standardStatusAction (i  == len (s .criteria )-1 ) {			return  false 		}	}	return  true }type  nssCriterion  struct  {	negate  bool    	status  string  	action  string  }func  (c  nssCriterion ) standardStatusAction last  bool ) bool  {	if  c .negate  {		return  false 	}	var  def  string 	switch  c .status  {	case  "success" :		def  = "return" 	case  "notfound" , "unavail" , "tryagain" :		def  = "continue" 	default :				return  false 	}	if  last  && c .action  == "return"  {		return  true 	}	return  c .action  == def }func  parseNSSConfFile file  string ) *nssConf  {	f , err  := open (file )	if  err  != nil  {		return  &nssConf {err : err }	}	defer  f .close ()	mtime , _ , err  := f .stat ()	if  err  != nil  {		return  &nssConf {err : err }	}	conf  := parseNSSConf (f )	conf .mtime  = mtime 	return  conf }func  parseNSSConf f  *file ) *nssConf  {	conf  := new (nssConf )	for  line , ok  := f .readLine (); ok ; line , ok  = f .readLine () {		line  = trimSpace (removeComment (line ))		if  len (line ) == 0  {			continue 		}		colon  := bytealg .IndexByteString (line , ':' )		if  colon  == -1  {			conf .err  = errors .New ("no colon on line" )			return  conf 		}		db  := trimSpace (line [:colon ])		srcs  := line [colon +1 :]		for  {			srcs  = trimSpace (srcs )			if  len (srcs ) == 0  {				break 			}			sp  := bytealg .IndexByteString (srcs , ' ' )			var  src  string 			if  sp  == -1  {				src  = srcs 				srcs  = ""  			} else  {				src  = srcs [:sp ]				srcs  = trimSpace (srcs [sp +1 :])			}			var  criteria  []nssCriterion 						if  len (srcs ) > 0  && srcs [0 ] == '['  {				bclose  := bytealg .IndexByteString (srcs , ']' )				if  bclose  == -1  {					conf .err  = errors .New ("unclosed criterion bracket" )					return  conf 				}				var  err  error 				criteria , err  = parseCriteria (srcs [1 :bclose ])				if  err  != nil  {					conf .err  = errors .New ("invalid criteria: "  + srcs [1 :bclose ])					return  conf 				}				srcs  = srcs [bclose +1 :]			}			if  conf .sources  == nil  {				conf .sources  = make (map [string ][]nssSource )			}			conf .sources [db ] = append (conf .sources [db ], nssSource {				source :   src ,				criteria : criteria ,			})		}	}	return  conf }func  parseCriteria x  string ) (c  []nssCriterion , err  error ) {	err  = foreachField (x , func (f  string ) error  {		not  := false 		if  len (f ) > 0  && f [0 ] == '!'  {			not  = true 			f  = f [1 :]		}		if  len (f ) < 3  {			return  errors .New ("criterion too short" )		}		eq  := bytealg .IndexByteString (f , '=' )		if  eq  == -1  {			return  errors .New ("criterion lacks equal sign" )		}		if  hasUpperCase (f ) {			lower  := []byte (f )			lowerASCIIBytes (lower )			f  = string (lower )		}		c  = append (c , nssCriterion {			negate : not ,			status : f [:eq ],			action : f [eq +1 :],		})		return  nil 	})	return } The pages are generated with Golds v0.7.6 . (GOOS=linux GOARCH=amd64)
Golds  is a Go 101  project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101  (reachable from the left QR code) to get the latest news of Golds .