logname, pipes and controlling terminals
Got questions? Go ahead: Ask me anything!
A customer complained that many of his scripts would generate an error:
logname: no login name
These were scripts that had been transferred to Linux from a SCO system where they had worked without error. Upon investigation, the offense was usually due to something like:
ps -e | grep `logname`
The reason this fails on Linux is because it's supposed to. The logname command actually calls "getlogin":
/* POSIX requires using getlogin (or equivalent code). */
cp = getlogin ();
/* POSIX prohibits using a fallback technique. */
fprintf (stderr, _("%s: no login name\n"), argv);
So why doesn't getlogin work here? Because it's on the other side of a pipe and therefore isn't associated with the controlling terminal of the process that called it. The man page for getlogin says:
getlogin returns a pointer to a string containing the
name of the user logged in on the controlling terminal
of the process, or a null pointer if this information
cannot be determined.
It's deliberate: getlogin doesn't have info for the process, so logname fails.
So why does it work on SCO (and BSD and Mac OS X)? Because their getlogin is different. This is from the getlogin man page from my Mac:
In earlier versions of the system, getlogin() failed
unless the process was associated with a login terminal.
The current implementation (using setlogin()) allows
getlogin to succeed even when the process has no con-
trolling terminal. In earlier versions of the system,
the value returned by getlogin() could not be trusted
without checking the user ID. Portable programs should
probably still make this check.
So how to you fix the problem? Well, don't use logname in this way. Instead, grep for $LOGNAME or use ps -u $LOGNAME
Annoying? Sure. But "logname" shouldn't trust things like $LOGNAME, so
it probably is correct behavior.
Got something to add? Send me email.
Increase ad revenue 50-250% with Ezoic
More Articles by Tony Lawrence
Find me on Google+
© 2011-05-08 Tony Lawrence