maccatcher-2.1.5/0000755000000000000000000000000011650712003011772 5ustar0000000000000000maccatcher-2.1.5/Setup.hs0000644000000000000000000000011211650712003013420 0ustar0000000000000000 import Distribution.Simple main = defaultMain maccatcher-2.1.5/samples0000644000000000000000000000465311650712003013371 0ustar0000000000000000 --------------------------------------------------------------- BSD `ifconfig` lo0: flags=8049 mtu 16384 inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1 inet 127.0.0.1 netmask 0xff000000 inet6 ::1 prefixlen 128 gif0: flags=8010 mtu 1280 stf0: flags=0<> mtu 1280 en0: flags=8863 mtu 1500 inet6 fe80::21f:5bff:fed7:1e5%en0 prefixlen 64 scopeid 0x4 inet 192.168.1.134 netmask 0xffffff00 broadcast 192.168.1.255 ether 00:1f:5b:d7:01:e5 media: autoselect status: active supported media: autoselect -------------------------------------------------------------- Linux `ifconfig` eth0 Link encap:Ethernet HWaddr 12:31:38:01:B9:E7 inet addr:10.253.190.21 Bcast:10.253.191.255 Mask:255.255.254.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:8020401 errors:0 dropped:0 overruns:0 frame:0 TX packets:7752826 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:814600921 (776.8 Mb) TX bytes:1696982847 (1618.3 Mb) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:23120 errors:0 dropped:0 overruns:0 frame:0 TX packets:23120 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:1234078 (1.1 Mb) TX bytes:1234078 (1.1 Mb) ----------------------------------------------------------- Windows `ipconfig` Windows IP Configuration Host Name . . . . . . . . . . . . : ixl Primary Dns Suffix . . . . . . . : Node Type . . . . . . . . . . . . : Hybrid IP Routing Enabled. . . . . . . . : No WINS Proxy Enabled. . . . . . . . : No Ethernet adapter Local Area Connection 2: Connection-specific DNS Suffix . : Description . . . . . . . . . . . : 3Com PCI Ethernet Adapter Physical Address. . . . . . . . . : 00-04-76-4E-75-3F Dhcp Enabled. . . . . . . . . . . : Yes Autoconfiguration Enabled . . . . : Yes IP Address. . . . . . . . . . . . : 148.64.133.73 Subnet Mask . . . . . . . . . . . : 255.255.192.0 Default Gateway . . . . . . . . . : 148.64.128.1 DHCP Server . . . . . . . . . . . : 148.64.128.1 DNS Servers . . . . . . . . . . . : 148.78.249.200 148.78.249.201 Lease Obtained. . . . . . . . . . : April 19, 2003 11:51:37 AM Lease Expires . . . . . . . . . . : April 19, 2003 12:21:37 PM maccatcher-2.1.5/MACCatcher.hs0000644000000000000000000000036611650712003014225 0ustar0000000000000000#!/usr/bin/env runhaskell import System.Info.MAC main = do macs <- macs case macs of _:_ -> mapM_ print macs [ ] -> putStrLn "Failed to obtain MAC address." maccatcher-2.1.5/CONTRIBUTORS0000644000000000000000000000027511650712003013656 0ustar0000000000000000 Jason Dusek Martin Grabmueller Joachim Breitner Nathan Howell maccatcher-2.1.5/README0000644000000000000000000000020611650712003012650 0ustar0000000000000000 Utilities for scraping the MAC address via the command line, on *NIX and Windows. The MAC address is cached after the first run. maccatcher-2.1.5/maccatcher.cabal0000644000000000000000000000207511650712003015054 0ustar0000000000000000name: maccatcher version: 2.1.5 category: Text license: BSD3 license-file: LICENSE author: Jason Dusek maintainer: oss@solidsnack.be synopsis: Obtain the host MAC address on *NIX and Windows. description: Obtain the host MAC address on *NIX and Windows. cabal-version: >= 1.6 build-type: Simple extra-source-files: README , CONTRIBUTORS , samples source-repository head type: git location: http://github.com/solidsnack/maccatcher.git flag split-base flag cli description: Enable command line tool. default: False library build-depends: base >= 3 && < 5 , binary , process , parsec exposed-modules: Data.MAC System.Info.MAC System.Info.MAC.Fetch executable maccatcher main-is: MACCatcher.hs if flag(cli) buildable: True else buildable: False maccatcher-2.1.5/LICENSE0000644000000000000000000000314011650712003012775 0ustar0000000000000000 © 1970-2038, persons listed in the CONTRIBUTORS file (hereafter "contributors"). The list of contributors shall be understood as an integral component of this copyright notice. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: . Redistributions of source code must retain the above copyright notice, this list of conditions, the list of contributors and the following disclaimer. . Redistributions in binary form must reproduce the above copyright notice, this list of conditions, the list of contributors and the following disclaimer in the documentation and/or other materials provided with the distribution. . Names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission. This software is provided by the contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed. In no event shall the contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage. maccatcher-2.1.5/Data/0000755000000000000000000000000011650712003012643 5ustar0000000000000000maccatcher-2.1.5/Data/MAC.hs0000644000000000000000000000444711650712003013610 0ustar0000000000000000 {-| A MAC address datatype, representing the six bytes of a MAC address, also known as an OID, IAB or \"...Vendor Address, Vendor ID, NIC Address, Ethernet Address and others.\", see -} module Data.MAC where import Numeric import Data.Word import Data.List import Data.Bits import Foreign.Ptr import Foreign.Storable import Data.Binary import Data.Binary.Put import Data.Binary.Get import Text.Printf import Text.Read import qualified Text.Read.Lex as Rex import qualified Text.ParserCombinators.ReadPrec as Rex import qualified Text.ParserCombinators.ReadP as Rex data MAC = MAC {-# UNPACK #-} !Word8 {-# UNPACK #-} !Word8 {-# UNPACK #-} !Word8 {-# UNPACK #-} !Word8 {-# UNPACK #-} !Word8 {-# UNPACK #-} !Word8 deriving (Eq, Ord, Bounded) instance Show MAC where show (MAC a b c d e f) = printf "%02x:%02x:%02x:%02x:%02x:%02x" a b c d e f instance Read MAC where readPrec = Rex.lift $ do a <- Rex.readHexP [b, c, d, e, f] <- Rex.many $ Rex.char ':' >> Rex.readHexP return $ MAC a b c d e f instance Binary MAC where -- Thanks to aslatter@gmail.com for this instance. put (MAC a b c d e f) = do putWord8 a putWord8 b putWord8 c putWord8 d putWord8 e putWord8 f get = do a <- getWord8 b <- getWord8 c <- getWord8 d <- getWord8 e <- getWord8 f <- getWord8 return $ MAC a b c d e f instance Storable MAC where -- Thanks to aslatter@gmail.com for this instance. sizeOf _ = 6 alignment _ = 1 peek p = do a <- peek $ castPtr p b <- peekByteOff p 1 c <- peekByteOff p 2 d <- peekByteOff p 3 e <- peekByteOff p 4 f <- peekByteOff p 5 return $ MAC a b c d e f poke p (MAC a b c d e f) = do poke (castPtr p) a pokeByteOff p 1 b pokeByteOff p 2 c pokeByteOff p 3 d pokeByteOff p 4 e pokeByteOff p 5 f maccatcher-2.1.5/System/0000755000000000000000000000000011650712003013256 5ustar0000000000000000maccatcher-2.1.5/System/Info/0000755000000000000000000000000011650712003014151 5ustar0000000000000000maccatcher-2.1.5/System/Info/MAC.hs0000644000000000000000000000265611650712003015116 0ustar0000000000000000{-# OPTIONS_GHC -fno-cse #-} {-| Obtain a MAC address for the host system, on *NIX and Windows. -} module System.Info.MAC ( mac , macs , nic , nics , refresh ) where import Data.MAC import System.Info.MAC.Fetch import Data.IORef import System.IO import System.IO.Unsafe import Data.Maybe import Control.Applicative {-| Fetch MAC address, using a cached value if it is available. -} mac :: IO (Maybe MAC) mac = listToMaybe <$> macs {-| Fetch MAC addresses, using a cached value if it is available. -} macs :: IO [MAC] macs = map snd <$> nics {-| Fetch a name-MAC pair, using a cached value if it is available. -} nic :: IO (Maybe (String, MAC)) nic = listToMaybe <$> nics {-| Fetch name-MAC pairs, using a cached value if it is available. -} nics :: IO [(String, MAC)] nics = do val <- readIORef fetched case val of [ ] -> refresh _:_ -> return val {-| Explicitly re-run the MAC reading operation. -} refresh :: IO [(String, MAC)] refresh = do res <- fetchNICs writeIORef fetched res return res {-# NOINLINE fetched #-} fetched = unsafePerformIO $ newIORef [] maccatcher-2.1.5/System/Info/MAC/0000755000000000000000000000000011650712003014551 5ustar0000000000000000maccatcher-2.1.5/System/Info/MAC/Fetch.hs0000644000000000000000000000675211650712003016150 0ustar0000000000000000{-# LANGUAGE TupleSections #-} {-| System specific routines for determing the MAC address and macros to help sort things out at compile time. -} module System.Info.MAC.Fetch where import Data.MAC import Control.Monad import Control.Applicative ((<$>)) import Data.List import Data.Maybe import System.Process import System.Info import System.IO import Text.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 :: IO String i_config = do (_, o, _, h) <- runInteractiveCommand cmd outputs <- hGetContents o seq (length outputs) (return ()) waitForProcess h return outputs where cmd | 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 = parseNICs parseNIC_ifconfig {-| Parses the output of Windows @ipconfig@. -} ipconfig :: Parser [(String, MAC)] ipconfig = parseNICs parseNIC_ipconfig parseNIC_ifconfig :: Parser (Maybe (String, MAC)) parseNIC_ifconfig = do name <- many1 alphaNum skipManyTill (satisfy (/= '\n')) markers char ' ' ((name,) <$>) <$> parseMAC ':' where markers = choice $ map (try . string) [ "ether", "HWaddr" ] parseNIC_ipconfig :: Parser (Maybe (String, MAC)) parseNIC_ipconfig = do name <- do string "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)] parseNICs p = catMaybes <$> parseNICs' where parseNICs' = (skipManyAnyTill . choice) [ eof >> return [] , do try (nl >> nl) nic <- p (nic:) <$> parseNICs' ] parseMAC sepChar = maybeMAC . intercalate ":" <$> sepHex (char sepChar) parse' :: String -> Parser [t] -> String -> [t] parse' source parser = either (const []) id . parse parser source maybeMAC :: String -> Maybe MAC maybeMAC s = case reads s of [(mac, _)] -> Just mac _ -> Nothing sepHex = sepBy (sequence [hexDigit, hexDigit]) manyAnyTill :: Parser Char -> Parser String manyAnyTill = manyTill anyChar skipManyTill :: Parser a -> Parser b -> Parser b skipManyTill p end = choice [try end, p >> skipManyTill p end] skipManyAnyTill :: Parser a -> Parser a skipManyAnyTill = skipManyTill anyChar nl = many (char '\r') >> char '\n'