Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

What's the best way to determine from a ksh script if the current shell is a login shell (su - user) or not (su user).

I'm toying with:

user=$(/usr/xpg4/bin/id -un)
login=$(grep $HOME /etc/passwd | cut -d: -f1 | head -1)
if [ "$login" == "$user" ]; then
    ...
fi

or perhaps instead using the $MAIL variable based on a comment in the su man page that only su - sets MAIL:

user=$(/usr/xpg4/bin/id -un)
login=${MAIL##*/}
if [ "$login" == "$user" ]; then
    ...
fi

but neither seems strictly airtight. Is there a best-practice approach?

share|improve this question
add comment

5 Answers

case "$0" in
    -*) echo "I'm a login shell";;
esac
share|improve this answer
    
Nice! The only problem is that $0 will be the script name inside a script. Is there a way to examine shell flags, perhaps? –  David Citron Nov 16 '09 at 20:53
    
@David Citron: A script is never going to be the login shell itself, so it's not going to be able to check itself - it would have to check its parent (or parent's parent, etc), and I'm not sure how it would do that. –  Teddy Nov 17 '09 at 20:49
add comment

There is no one best practice. Anything based on recognizing variables is unreliable, and even walking up your process hierarchy requires making inferences because su executes login without forking, leaving no trace what its arguments were.

The better choice is to test directly for the settings you need. Usually, what I'm interested in when looking for login shells is that the profile was read. So, if you have free reign to modify your profile, set an indicator variable:

echo "export parsed_profile=true" >> ~/.profile

And then check that directly. Another option would be to verify you own your $HOME:

if /bin/test \! -O "$HOME"; then
    echo HOME is not set or set incorrectly.
fi

Or just directly source your profile from inside your script.

share|improve this answer
add comment

It may be, that your question is simpler than I'm making it; you might simply be asking how to tell if the user logged in as root or used su to switch to them in which case, a combination of the answers I've given would be appropriate.

Normally, a login shell is differentiated from a non-login-shell by whether various scripts got run. The reason many users start a non-login-shell is because it is a subshell of some program, or (as you note) because they use su to switch users. Those users will have $LOGNAME not equal to $USER

Unless, of course, they switch back. To detect those users, consider the following perl script:

open(P,"ps -ef|");while(<P>){m#^(\S+)\s+(\d+)\s+(\d+)#;$u{$2}=$1;$t{$2}=$3;}
$p=$$;while($t{$p}){$g{$u{$p}}=1;$p=$t{$p};}delete$g{root};$g{$u{$$}}=1;
print keys(%g),"\n";

If you want to restrict it to using su - you can use:

open(P,"ps -ef|");while(<P>){m#^(\S+)\s+(\d+)\s+(\d+).*su - #;$u{$2}=$1;$t{$2}=$3;}
$p=$$;while($t{$p}){$g{$u{$p}}=1;$p=$t{$p};}delete$g{root};$g{$u{$$}}=1;
print keys(%g),"\n";

If you want to really see login shells, note that login shells are started with argv[0] set with a leading dash, so you can use:

open(P,"ps -eo user,pid,ppid,comm|");while(<P>){m#^(\S+)\s+(\d+)\s+(\d+) -#;
  $u{$2}=$1;$t{$2}=$3;}
$p=$$;while($t{$p}){$g{$u{$p}}=1;$p=$t{$p};}delete$g{root};$g{$u{$$}}=1;
print keys(%g),"\n";

but you'll miss out on the situation where someone ran ksh --login.

share|improve this answer
add comment

On Solaris, root home directory is '/' by default, not '/root'. Some of the previous suggestions are thus unreliable.

share|improve this answer
add comment

This wouldn't be definitive, but should work most of the time

if[$HOME == "/root"] ...

share|improve this answer
1  
Well, my grep $HOME /etc/passwd option above kinda covers this in a more flexible way...no? –  David Citron Nov 16 '09 at 21:01
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.