From beb885811f30183db102b016d2ee570b596b4674 Mon Sep 17 00:00:00 2001
From: Ranjeet Kumar Ranjan <ranjeetr@composewell.com>
Date: Wed, 6 Jul 2022 15:58:19 +0530
Subject: [PATCH 1/2] Add Id module

---
 src/Streamly/Coreutils/Id.hs | 56 ++++++++++++++++++++++++++++++++++++
 streamly-coreutils.cabal     |  1 +
 2 files changed, 57 insertions(+)
 create mode 100644 src/Streamly/Coreutils/Id.hs

diff --git a/src/Streamly/Coreutils/Id.hs b/src/Streamly/Coreutils/Id.hs
new file mode 100644
index 00000000..80c5bff2
--- /dev/null
+++ b/src/Streamly/Coreutils/Id.hs
@@ -0,0 +1,56 @@
+-- |
+-- Module      : Streamly.Coreutils.Id
+-- Copyright   : (c) 2022 Composewell Technologies
+-- License     : BSD-3-Clause
+-- Maintainer  : streamly@composewell.com
+-- Stability   : experimental
+-- Portability : GHC
+--
+-- Get real and effective user and group IDs.
+
+module Streamly.Coreutils.Id
+    (
+      getRealUserID
+    , getRealGroupID
+    , getEffectiveUserID
+    , getEffectiveGroupID
+    , getGroups
+    , getLoginName
+    , getEffectiveUserName
+    )
+where
+
+import Data.Word (Word32)
+import System.Posix.Types (CGid(CGid), CUid(CUid))
+
+import qualified System.Posix.User as Posix
+
+getRealUserID :: IO Word32
+getRealUserID = do
+    CUid x <- Posix.getRealUserID
+    return x
+
+getRealGroupID :: IO Word32
+getRealGroupID = do
+    CGid x <- Posix.getRealGroupID
+    return x
+
+getEffectiveUserID :: IO Word32
+getEffectiveUserID =  do
+    CUid x <- Posix.getEffectiveUserID
+    return x
+
+getEffectiveGroupID :: IO Word32
+getEffectiveGroupID = do
+    CGid x <- Posix.getEffectiveGroupID
+    return x
+
+getGroups :: IO [Word32]
+getGroups =
+    map (\(CGid x) -> x) <$> Posix.getGroups
+
+getLoginName :: IO String
+getLoginName = Posix.getLoginName
+
+getEffectiveUserName :: IO String
+getEffectiveUserName = Posix.getEffectiveUserName
diff --git a/streamly-coreutils.cabal b/streamly-coreutils.cabal
index fa31b395..42e5101e 100644
--- a/streamly-coreutils.cabal
+++ b/streamly-coreutils.cabal
@@ -98,6 +98,7 @@ library
     , Streamly.Coreutils.Common
     , Streamly.Coreutils.Cp
     , Streamly.Coreutils.FileTest
+    , Streamly.Coreutils.Id
     , Streamly.Coreutils.ShellWords
     , Streamly.Coreutils.Uniq
     , Streamly.Coreutils.Which

From 8028918ddff8fcb0716fdd52b328aeee6dd2650b Mon Sep 17 00:00:00 2001
From: Ranjeet Kumar Ranjan <ranjeetr@composewell.com>
Date: Tue, 12 Jul 2022 12:22:22 +0530
Subject: [PATCH 2/2] Fix review comments

---
 src/Streamly/Coreutils/Id.hs | 71 ++++++++++++++++++++++++++++++------
 1 file changed, 59 insertions(+), 12 deletions(-)

diff --git a/src/Streamly/Coreutils/Id.hs b/src/Streamly/Coreutils/Id.hs
index 80c5bff2..1a0f1614 100644
--- a/src/Streamly/Coreutils/Id.hs
+++ b/src/Streamly/Coreutils/Id.hs
@@ -10,13 +10,18 @@
 
 module Streamly.Coreutils.Id
     (
-      getRealUserID
-    , getRealGroupID
-    , getEffectiveUserID
-    , getEffectiveGroupID
-    , getGroups
-    , getLoginName
-    , getEffectiveUserName
+      id
+      
+    -- * Options
+    , IdOptions
+    , effectiveGroupId
+    , groups
+    , realGroupId
+    , realUserId
+    , effectiveUserId
+    , effectiveUserName
+    , realUserName
+    , IdResult(..)
     )
 where
 
@@ -25,6 +30,44 @@ import System.Posix.Types (CGid(CGid), CUid(CUid))
 
 import qualified System.Posix.User as Posix
 
+import Prelude hiding (id)
+
+data IdOptions =
+      RealGroupId
+    | EffectiveGroupId
+    | Groups
+    | RealUserName
+    | EffectiveUserName
+    | RealUserId
+    | EffectiveUserId
+
+realGroupId :: IdOptions
+realGroupId = RealGroupId
+
+effectiveGroupId :: IdOptions
+effectiveGroupId = EffectiveGroupId
+
+groups :: IdOptions
+groups = Groups
+
+realUserName :: IdOptions
+realUserName = RealUserName
+
+effectiveUserName :: IdOptions
+effectiveUserName = EffectiveUserName
+
+realUserId :: IdOptions
+realUserId = RealUserId
+
+effectiveUserId :: IdOptions
+effectiveUserId = EffectiveUserId
+
+data IdResult =
+      Id Word32
+    | Ids [Word32]
+    | Name String
+        deriving Show
+
 getRealUserID :: IO Word32
 getRealUserID = do
     CUid x <- Posix.getRealUserID
@@ -49,8 +92,12 @@ getGroups :: IO [Word32]
 getGroups =
     map (\(CGid x) -> x) <$> Posix.getGroups
 
-getLoginName :: IO String
-getLoginName = Posix.getLoginName
-
-getEffectiveUserName :: IO String
-getEffectiveUserName = Posix.getEffectiveUserName
+id :: IdOptions -> IO IdResult
+id opt = case opt of
+    RealGroupId -> Id <$> getRealGroupID
+    EffectiveGroupId -> Id <$> getEffectiveGroupID
+    Groups -> Ids <$> getGroups
+    RealUserName -> Name <$> Posix.getLoginName
+    EffectiveUserName -> Name <$> Posix.getEffectiveUserName
+    RealUserId -> Id <$> getRealUserID
+    EffectiveUserId -> Id <$> getEffectiveUserID