setting current dir of remote shell

Bob Proulx bob at proulx.com
Mon Apr 30 10:25:58 EST 2007


Dave Yost wrote:
> Bob Proulx wrote:
> >For me the following works:
> >  ssh -t someserver "cd $(pwd) && exec -l \$0"
> >  $ echo $0
> >  -bash
>
> I assume you mean
> 
>   ssh -t someserver "cd $(pwd) && exec \$0 -l"

No, I really did mean 'exec -l \$0'.  Your transposition is similar
and will have similar effects but is not identical.  (Very close to
though, and the difference is quite subtle.)

  help exec
  exec: exec [-cl] [-a name] file [redirection ...]
      Exec FILE, replacing this shell with the specified program.
      If FILE is not specified, the redirections take effect in this
      shell.  If the first argument is '-l', then place a dash in the
      zeroth arg passed to FILE, as login does.  If the '-c' option
      is supplied, FILE is executed with a null environment.  The '-a'
      option means to make set argv[0] of the executed process to NAME.
      If the file cannot be executed and the shell is not interactive,
      then the shell exits, unless the shell option 'execfail' is set.

The magic part is:

  "If the first argument is '-l', then place a dash in the zeroth arg
  passed to FILE, as login does."

The classic /bin/login program has always placed a dash as the first
character of the shell when starting up login shells.  Shells inspect
their first argument, their own name, and look for a '-' in the
leading part of the name.  If the shell finds a '-' there then they
assume they were started by login and configure themselves as a login
shell.  Login shells read the defined list of environment files such
as /etc/profile and others.

The transposition of using 'exec \$0 -l' instead of 'exec -l \$0'
won't place a dash in the leading part of the shell's name.  Therefore
the shell won't think it is a login in the same way that it would if
it were really a login shell started by /bin/login.  However the shell
will by the -l option be told to behave as a login shell.  At that
point the shell will behave fully as a login shell and there is no
difference.  However if child programs want to deduce if the parent
shell is a login shell or not they usually look at $0, as I did in my
example, and look to see if the shell's name starts with a dash or
not.  This difference is probably insignificant but child processes
won't be able to tell if the parent is a login shell in that case.

The problem is that POSIX does not specify any options to exec and
therefore use of 'exec -l' is non-standard by definition.  I do not
know which shells support it and which do not.  Bash supports it and
so if it is known to be working with bash then it is fine to use.  But
if it must be completely portable to unspecified shells then of course
it would be a problem.

Meanwhile, the very reason I like it is that 'exec -l $SOMESHELL' can
spawn a random, unknown, unspecified shell as $SOMESHELL and guarantee
that it will be a login shell even if $SOMESHELL does not take the -l
option.  Because of the /bin/login interface of placing a leading dash
all shells will respect that interface.  The classic csh is an example
of a shell that does not accept a -l option to behave as a login
shell.  Therefore 'exec csh -l' would fail while 'exec -l csh' would
succeed in producing csh running as a login shell.  (I think newer csh
variants have added the -l option for compatibility.)

Bob


More information about the openssh-unix-dev mailing list