{-# LANGUAGE TupleSections
#-}{-| System specific routines for determing the MAC address and macros to help
sort things out at compile time.
-}moduleSystem.Info.MAC.FetchwhereimportData.MACimportControl.MonadimportControl.Applicative((<$>))importData.ListimportData.MaybeimportSystem.ProcessimportSystem.InfoimportSystem.IOimportText.ParserCombinators.Parsec{-| Obtain a list containing the name and MAC of all NICs.
-}fetchNICs::IO[(String,MAC)]fetchNICs=parser<$>i_config{-| Run @ifconfig@ or @ipconfig@, as appropriate, capturing its output.
-}i_config::IOStringi_config=do(_,o,_,h)<-runInteractiveCommandcmdoutputs<-hGetContentsoseq(lengthoutputs)(return())waitForProcesshreturnoutputswherecmd|os=="mingw32"="ipconfig /all"|otherwise="LANG=C ifconfig"parser|os=="mingw32"=parse'"ipconfig"ipconfig|otherwise=parse'"ifconfig"ifconfig.("\n\n"++){-| Parses the output of Linux or BSD @ifconfig@.
-}ifconfig::Parser[(String,MAC)]ifconfig=parseNICsparseNIC_ifconfig{-| Parses the output of Windows @ipconfig@.
-}ipconfig::Parser[(String,MAC)]ipconfig=parseNICsparseNIC_ipconfigparseNIC_ifconfig::Parser(Maybe(String,MAC))parseNIC_ifconfig=doname<-many1alphaNumskipManyTill(satisfy(/='\n'))markerschar' '((name,)<$>)<$>parseMAC':'wheremarkers=choice$map(try.string)["ether","HWaddr"]parseNIC_ipconfig::Parser(Maybe(String,MAC))parseNIC_ipconfig=doname<-dostring"Ethernet adapter "manyTill(satisfy(/='\n'))(char':')(skipManyAnyTill.choice)[try(nl>>nl)>>unexpected"\\r\\n\\r\\n",(try.string)"Physical Address"]manyTill(satisfy(/='\n'))(char':')char' '((name,)<$>)<$>parseMAC'-'parseNICs::Parser(Maybe(String,MAC))->Parser[(String,MAC)]parseNICsp=catMaybes<$>parseNICs'whereparseNICs'=(skipManyAnyTill.choice)[eof>>return[],dotry(nl>>nl)nic<-p(nic:)<$>parseNICs']parseMACsepChar=maybeMAC.intercalate":"<$>sepHex(charsepChar)parse'::String->Parser[t]->String->[t]parse'sourceparser=either(const[])id.parseparsersourcemaybeMAC::String->MaybeMACmaybeMACs=casereadssof[(mac,_)]->Justmac_->NothingsepHex=sepBy(sequence[hexDigit,hexDigit])manyAnyTill::ParserChar->ParserStringmanyAnyTill=manyTillanyCharskipManyTill::Parsera->Parserb->ParserbskipManyTillpend=choice[tryend,p>>skipManyTillpend]skipManyAnyTill::Parsera->ParseraskipManyAnyTill=skipManyTillanyCharnl=many(char'\r')>>char'\n'