Proposal unix. Change to `IO (Maybe String)`: getLoginName, getUserEntry* and getGroupEntry*

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Proposal unix. Change to `IO (Maybe String)`: getLoginName, getUserEntry* and getGroupEntry*

Thomas Miedema
In the unix package, in System.Posix.User, we have the following functions [1]:

* getLoginName (getlogin)
* getUserEntryForID (getpwuid_r)
* getGroupEntryForID (getgrgid_r)
* getUserEntryForName (getpwnam_r)
* getGroupEntryForName (getgrnam_r)

They have signature `IO String`, and use `throwErrnoIfNull` to call the c functions listed in parenthesis.


## Proposal
Change the signature of the functions listed above to `IO (Maybe String)`.

The new semantics would be:
* If the c function returns a NULL pointer with errno set to ENOENT, meaning the given user or group could not be found, the result is Nothing.
* If another error occured, an error is thrown (no change).
* Otherwise the result is Just "result".


## Motivation
At least `getlogin` and `getgrgid` are unreliable on Linux. It is possible for them to return NULL pointers [2] even when the user is logged in and has an associated user entry in /etc/passwd and group entry in /etc/group.

Examples:
* when `getLoginName` is called using a terminal emulator that doesn't write login records to /var/run/utmp, or inside screen/tmux, `getlogin` tends to return NULL pointers [3].
* `getGroupEntryForID` can throw a NULL pointer exception inside chroots or other environments where the information in /etc/groups is not to be considered reliable [4].

Since we can, let's give the above Haskell functions a type safe(r) api.

If the proposal gets rejected, I will just add a warning message to the docstrings of the functions in question and permanently disable their tests from the unix testsuite, since this is currently causing problems [5,6].

Discussion period: 2 weeks.


## Links


## Details
* Another function in the same module that needs to change is `getEffectiveUserName`, because it calls the function `getUserEntryForID` mentioned before. 

* The following functions don't need to change, since they return the empty list if no entries are found:
  - getGroups (getgroups)
  - getAllGroupEntries (getgrent)
  - getAllUserEntries (getpwent)

* The rest of the functions in the module don't need to change either, since they are not expected to return NULL pointers, according to their respective man pages:
  - getRealUserID (getuid)
  - getRealGroupID (getgid)
  - getEffectiveUserID (geteuid)
  - getEffectiveGroupID (getegid)

_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal unix. Change to `IO (Maybe String)`: getLoginName, getUserEntry* and getGroupEntry*

Johan Tibell-2
I think we should add the saner versions (that return Maybe) under new names to avoid unnecessarily breaking backwards compatibility.

On Fri, Sep 26, 2014 at 6:23 PM, Thomas Miedema <[hidden email]> wrote:
In the unix package, in System.Posix.User, we have the following functions [1]:

* getLoginName (getlogin)
* getUserEntryForID (getpwuid_r)
* getGroupEntryForID (getgrgid_r)
* getUserEntryForName (getpwnam_r)
* getGroupEntryForName (getgrnam_r)

They have signature `IO String`, and use `throwErrnoIfNull` to call the c functions listed in parenthesis.


## Proposal
Change the signature of the functions listed above to `IO (Maybe String)`.

The new semantics would be:
* If the c function returns a NULL pointer with errno set to ENOENT, meaning the given user or group could not be found, the result is Nothing.
* If another error occured, an error is thrown (no change).
* Otherwise the result is Just "result".


## Motivation
At least `getlogin` and `getgrgid` are unreliable on Linux. It is possible for them to return NULL pointers [2] even when the user is logged in and has an associated user entry in /etc/passwd and group entry in /etc/group.

Examples:
* when `getLoginName` is called using a terminal emulator that doesn't write login records to /var/run/utmp, or inside screen/tmux, `getlogin` tends to return NULL pointers [3].
* `getGroupEntryForID` can throw a NULL pointer exception inside chroots or other environments where the information in /etc/groups is not to be considered reliable [4].

Since we can, let's give the above Haskell functions a type safe(r) api.

If the proposal gets rejected, I will just add a warning message to the docstrings of the functions in question and permanently disable their tests from the unix testsuite, since this is currently causing problems [5,6].

Discussion period: 2 weeks.


## Links


## Details
* Another function in the same module that needs to change is `getEffectiveUserName`, because it calls the function `getUserEntryForID` mentioned before. 

* The following functions don't need to change, since they return the empty list if no entries are found:
  - getGroups (getgroups)
  - getAllGroupEntries (getgrent)
  - getAllUserEntries (getpwent)

* The rest of the functions in the module don't need to change either, since they are not expected to return NULL pointers, according to their respective man pages:
  - getRealUserID (getuid)
  - getRealGroupID (getgid)
  - getEffectiveUserID (geteuid)
  - getEffectiveGroupID (getegid)

_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries



_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal unix. Change to `IO (Maybe String)`: getLoginName, getUserEntry* and getGroupEntry*

Greg Weber
Agreed with Johan. If there are meaningful error messages that get produced, Either is better than Maybe.

On Fri, Sep 26, 2014 at 9:47 AM, Johan Tibell <[hidden email]> wrote:
I think we should add the saner versions (that return Maybe) under new names to avoid unnecessarily breaking backwards compatibility.

On Fri, Sep 26, 2014 at 6:23 PM, Thomas Miedema <[hidden email]> wrote:
In the unix package, in System.Posix.User, we have the following functions [1]:

* getLoginName (getlogin)
* getUserEntryForID (getpwuid_r)
* getGroupEntryForID (getgrgid_r)
* getUserEntryForName (getpwnam_r)
* getGroupEntryForName (getgrnam_r)

They have signature `IO String`, and use `throwErrnoIfNull` to call the c functions listed in parenthesis.


## Proposal
Change the signature of the functions listed above to `IO (Maybe String)`.

The new semantics would be:
* If the c function returns a NULL pointer with errno set to ENOENT, meaning the given user or group could not be found, the result is Nothing.
* If another error occured, an error is thrown (no change).
* Otherwise the result is Just "result".


## Motivation
At least `getlogin` and `getgrgid` are unreliable on Linux. It is possible for them to return NULL pointers [2] even when the user is logged in and has an associated user entry in /etc/passwd and group entry in /etc/group.

Examples:
* when `getLoginName` is called using a terminal emulator that doesn't write login records to /var/run/utmp, or inside screen/tmux, `getlogin` tends to return NULL pointers [3].
* `getGroupEntryForID` can throw a NULL pointer exception inside chroots or other environments where the information in /etc/groups is not to be considered reliable [4].

Since we can, let's give the above Haskell functions a type safe(r) api.

If the proposal gets rejected, I will just add a warning message to the docstrings of the functions in question and permanently disable their tests from the unix testsuite, since this is currently causing problems [5,6].

Discussion period: 2 weeks.


## Links


## Details
* Another function in the same module that needs to change is `getEffectiveUserName`, because it calls the function `getUserEntryForID` mentioned before. 

* The following functions don't need to change, since they return the empty list if no entries are found:
  - getGroups (getgroups)
  - getAllGroupEntries (getgrent)
  - getAllUserEntries (getpwent)

* The rest of the functions in the module don't need to change either, since they are not expected to return NULL pointers, according to their respective man pages:
  - getRealUserID (getuid)
  - getRealGroupID (getgid)
  - getEffectiveUserID (geteuid)
  - getEffectiveGroupID (getegid)

_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries



_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries



_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal unix. Change to `IO (Maybe String)`: getLoginName, getUserEntry* and getGroupEntry*

Brandon Allbery
On Fri, Sep 26, 2014 at 1:33 PM, Greg Weber <[hidden email]> wrote:
Agreed with Johan. If there are meaningful error messages that get produced, Either is better than Maybe.

"Meaningful" is open to question; what you get back is a NULL pointer amd an errno, both of which can be annoyingly non-specific.

--
brandon s allbery kf8nh                               sine nomine associates
[hidden email]                                  [hidden email]
unix, openafs, kerberos, infrastructure, xmonad        http://sinenomine.net

_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal unix. Change to `IO (Maybe String)`: getLoginName, getUserEntry* and getGroupEntry*

Henning Thielemann-4
In reply to this post by Johan Tibell-2
Am 26.09.2014 um 18:47 schrieb Johan Tibell:

> I think we should add the saner versions (that return Maybe) under new
> names to avoid unnecessarily breaking backwards compatibility.

Alternatively, you could start a new module and re-use the existing
function names.

_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries