|
| 1 | +-- | |
| 2 | +-- Module : Streamly.Coreutils.Id |
| 3 | +-- Copyright : (c) 2022 Composewell Technologies |
| 4 | +-- License : BSD-3-Clause |
| 5 | +-- Maintainer : streamly@composewell.com |
| 6 | +-- Stability : experimental |
| 7 | +-- Portability : GHC |
| 8 | +-- |
| 9 | +-- Experimental alternative wrapper API over System.Posix.User. |
| 10 | +-- |
| 11 | +-- Shorter names, closer to shell commands. |
| 12 | +-- Int for user-id/group-id for covnenience. |
| 13 | +-- Adds one missing function |
| 14 | +-- |
| 15 | +-- Functions to get and set the user and group id of the current process. |
| 16 | +-- |
| 17 | +-- Substitutes the functionality of the @id@ and @whoami@ coreutils commands. |
| 18 | +-- |
| 19 | +-- This is a Posix only module. |
| 20 | + |
| 21 | +-- TODO: create a portable module with "idNum" and "idName" commands to print |
| 22 | +-- the current user id, name. |
| 23 | +-- |
| 24 | +-- Can separate process API and the user DB API. |
| 25 | + |
| 26 | +module Streamly.Coreutils.Id |
| 27 | + ( |
| 28 | + uid |
| 29 | + , euid |
| 30 | + , gid |
| 31 | + , egid |
| 32 | + , uid2name |
| 33 | + , gid2name |
| 34 | + -- , groups |
| 35 | + ) |
| 36 | +where |
| 37 | + |
| 38 | +import System.Posix (getGroupEntryForID) |
| 39 | +import Prelude hiding (id) |
| 40 | +import qualified System.Posix.User as Posix |
| 41 | + |
| 42 | +------------------------------------------------------ |
| 43 | +-- Current process settings |
| 44 | +------------------------------------------------------ |
| 45 | + |
| 46 | +-- | Return current process real user id. |
| 47 | +-- |
| 48 | +-- id -ru |
| 49 | +uid :: IO Int |
| 50 | +uid = fromIntegral <$> Posix.getRealUserID |
| 51 | + |
| 52 | +-- | Return current process real group id. |
| 53 | +-- |
| 54 | +-- id -rg |
| 55 | +gid :: IO Int |
| 56 | +gid = fromIntegral <$> Posix.getRealGroupID |
| 57 | + |
| 58 | +-- | Return current process effective user id. |
| 59 | +-- |
| 60 | +-- id -u |
| 61 | +euid :: IO Int |
| 62 | +euid = fromIntegral <$> Posix.getEffectiveUserID |
| 63 | + |
| 64 | +-- | Return current process effective group id. |
| 65 | +-- |
| 66 | +-- id -g |
| 67 | +egid :: IO Int |
| 68 | +egid = fromIntegral <$> Posix.getEffectiveGroupID |
| 69 | + |
| 70 | +-- | Get groups associated with the current process. |
| 71 | +-- |
| 72 | +-- id -G |
| 73 | +groups :: IO [Int] |
| 74 | +groups = fmap fromIntegral <$> Posix.getGroups |
| 75 | + |
| 76 | +-- | The original login name of the process. Note: the current user name may |
| 77 | +-- change by setuid but login name remains the same. |
| 78 | +logname :: IO String |
| 79 | +logname = Posix.getLoginName |
| 80 | + |
| 81 | +------------------------------------------------------ |
| 82 | +-- These should go to user database module? |
| 83 | +------------------------------------------------------ |
| 84 | + |
| 85 | +-- XXX We can parse the passwd file ourselves instead of using C code |
| 86 | +-- XXX Use an Compact Array/OsString instead? |
| 87 | + |
| 88 | +{- |
| 89 | +-- getpwuid |
| 90 | +uid2pwent = |
| 91 | +
|
| 92 | +-- getgrgid |
| 93 | +gid2grent = |
| 94 | +
|
| 95 | +-- getpwnam |
| 96 | +name2pwent = |
| 97 | +
|
| 98 | +-- getgrnam |
| 99 | +name2grent = |
| 100 | +
|
| 101 | +-- Stream the entries. |
| 102 | +getpwents = |
| 103 | +-} |
| 104 | + |
| 105 | +-- | Convert numeric user id to user name. |
| 106 | +uid2name :: Int -> IO String |
| 107 | +uid2name i = do |
| 108 | + -- XXX fromIntegral downcast |
| 109 | + pw <- Posix.getUserEntryForID (fromIntegral i) |
| 110 | + return (Posix.userName pw) |
| 111 | + |
| 112 | +-- XXX Use an Compact Array/OsString instead? |
| 113 | + |
| 114 | +-- | Convert numeric group id to group name. |
| 115 | +gid2name :: Int -> IO String |
| 116 | +gid2name i = do |
| 117 | + -- XXX fromIntegral downcast |
| 118 | + pw <- Posix.getGroupEntryForID (fromIntegral i) |
| 119 | + return (Posix.groupName pw) |
| 120 | + |
| 121 | +-- Note there is no uid2groups as anyway the groups file has the user name. We |
| 122 | +-- search by name even if uid is provided. So we can convert uid to name and |
| 123 | +-- then search. |
| 124 | + |
| 125 | +-- | List all the groups in which a uid occurs. Returns (gid, group name). |
| 126 | +-- |
| 127 | +-- id -Gn <user> |
| 128 | +user2groups :: Int -> [(Int, String)] |
| 129 | +user2groups = undefined |
| 130 | + |
| 131 | +-- | Current process user name. |
| 132 | +-- |
| 133 | +-- id -un |
| 134 | +whoami :: IO String |
| 135 | +whoami = uid >>= uid2name |
| 136 | + |
| 137 | +-- | Current process group names. |
| 138 | +-- |
| 139 | +-- id -Gn |
| 140 | +groupNames :: IO [String] |
| 141 | +groupNames = do |
| 142 | + xs <- Posix.getGroups |
| 143 | + fmap Posix.groupName <$> mapM getGroupEntryForID xs |
0 commit comments