This post originated from an RSS feed registered with Ruby Buzz
by Daniel Berger.
Original Post: Why can't things be easy? Getting the login
Feed Title: Testing 1,2,3...
Feed URL: http://djberg96.livejournal.com/data/rss
Feed Description: A blog on Ruby and other stuff.
You would think getting the process login would be a simple matter, right? I mean, seriously, just call getlogin() and be done with it.
Oh, if only things were that simple. The first issue is that some platforms, and by "some" I mean Linux, cannot rely on getlogin() because they muck around with the utmp file. I would use cuserid() but once again Linux rears its ugly head. Here's an amusing note from the Linux man page for getlogin():
"Nobody knows precisely what cuserid() does; avoid it in portable programs. Or avoid it altogether: use getpwuid(geteuid()) instead, if that is what you meant. DO NOT USE cuserid()."
Ah, a fine bit of cargo cult programming if there ever was one. How can they not know what what it does? Actually, I think I know the answer to that, but I don't feel like starting a flame war at the moment. Let's move on.
So, what does that leave us? Probably the best solution is to just use getpwuid(getuid()). If that fails, resort to getlogin(). If that fails, Linux be damned and resort to cuserid(). If that fails resort to ENV["LOGNAME"]. If that fails resort to ENV["USER"]. If that fails...you suck.
But, there's a subtle bug with this approach. Or rather, it's possible to get different results depending on how the program is run. Consider this bit of C code:
Which means that the only reliable way to get the realy user login, and not the effective user, is to user getlogin() or cuserid(), the two functions that Linux tells you to avoid.
My temptation here is to scrap everything and use only getlogin() or cuserid(), Linux be damned. As far as I can tell, Perl just calls getlogin() and nothing else and I haven't heard any complaints.
The "satisfy everyone" solution is to allow the user to control whether or not to allow the euid to be returned like so:
Admin.get_login(euid=false)
So, if you set +euid+ to true, then the method would internally alter its strategy of getting the login, trying six different ways instead of two. It's more work, but it may be the road I take.