Add the -l option (aka -o login): be a login shell. Meaningful only on

the command line (with both - and + forms) - overrides the presence (or
otherwise) of a '-' as argv[0][0].

Since this allows any shell to be a login shell (which simply means that
it runs /etc/profile and ~/.profile at shell startup - there are no other
side effects) add a new, always set at startup, variable NBSH_INVOCATION
which has a char string as its value, where each char has a meaning,
more or less related to how the shell was started.   See sh(1).
This is intended to allow those startup scripts to tailor their behaviour
to the nature of this particular login shell (it is possible to detect
whether a shell is a login shell merely because of -l, or whether it would
have been anyway, before the -l option was added - and more).   The
var could also be used to set different values for $ENV for different
uses of the shell.
This commit is contained in:
kre 2022-09-18 06:03:19 +00:00
parent 4f7a59ca7b
commit e7b0505e69
6 changed files with 224 additions and 15 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: main.c,v 1.88 2021/10/26 10:07:20 kre Exp $ */
/* $NetBSD: main.c,v 1.89 2022/09/18 06:03:19 kre Exp $ */
/*-
* Copyright (c) 1991, 1993
@ -42,7 +42,7 @@ __COPYRIGHT("@(#) Copyright (c) 1991, 1993\
#if 0
static char sccsid[] = "@(#)main.c 8.7 (Berkeley) 7/19/95";
#else
__RCSID("$NetBSD: main.c,v 1.88 2021/10/26 10:07:20 kre Exp $");
__RCSID("$NetBSD: main.c,v 1.89 2022/09/18 06:03:19 kre Exp $");
#endif
#endif /* not lint */
@ -212,6 +212,7 @@ main(int argc, char **argv)
initpwd();
setstackmark(&smark);
procargs(argc, argv);
setvar_invocation(argc, argv);
#if 0 /* This now happens (indirectly) in the procargs() just above */
/*
@ -229,7 +230,7 @@ main(int argc, char **argv)
choose_ps1();
#endif
if (argv[0] && argv[0][0] == '-') {
if (loginsh) {
state = 1;
read_profile("/etc/profile");
state1:

View File

@ -1,4 +1,4 @@
/* $NetBSD: option.list,v 1.9 2018/11/23 20:40:06 kre Exp $ */
/* $NetBSD: option.list,v 1.10 2022/09/18 06:03:19 kre Exp $ */
/*
* define the shell's settable options
@ -58,6 +58,7 @@ sflag stdin s # read from standard input
// non-standard options -- 'i' is just a state, not an option in standard.
iflag interactive i # interactive shell
loginsh login l # a login shell
cdprint cdprint # always print result of a cd
usefork fork F # use fork(2) instead of vfork(2)
pflag nopriv p # preserve privs if set[ug]id

View File

@ -1,4 +1,4 @@
/* $NetBSD: options.c,v 1.57 2022/04/16 14:20:45 kre Exp $ */
/* $NetBSD: options.c,v 1.58 2022/09/18 06:03:19 kre Exp $ */
/*-
* Copyright (c) 1991, 1993
@ -37,7 +37,7 @@
#if 0
static char sccsid[] = "@(#)options.c 8.2 (Berkeley) 5/4/95";
#else
__RCSID("$NetBSD: options.c,v 1.57 2022/04/16 14:20:45 kre Exp $");
__RCSID("$NetBSD: options.c,v 1.58 2022/09/18 06:03:19 kre Exp $");
#endif
#endif /* not lint */
@ -122,6 +122,10 @@ procargs(int argc, char **argv)
if (debug == 2)
debug = 1;
#endif
arg0 = argv[0];
if (loginsh == 2 && arg0 != NULL && arg0[0] == '-')
loginsh = 1;
/*
* Any options not dealt with as special cases just above,
* and which were not set on the command line, are set to
@ -136,7 +140,6 @@ procargs(int argc, char **argv)
optlist[i].dflt = optlist[i].val;
}
arg0 = argv[0];
if (sflag == 0 && minusc == NULL) {
commandname = argv[0];
arg0 = *argptr++;

View File

@ -1,4 +1,4 @@
.\" $NetBSD: sh.1,v 1.249 2022/09/16 19:25:09 kre Exp $
.\" $NetBSD: sh.1,v 1.250 2022/09/18 06:03:19 kre Exp $
.\" Copyright (c) 1991, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
@ -31,10 +31,11 @@
.\"
.\" @(#)sh.1 8.6 (Berkeley) 5/4/95
.\"
.Dd January 7, 2022
.\" RIP Noi, October 6, 1959 --
.Dd August 26, 2022
.Dt SH 1
.\" everything except c o and s (keep them ordered)
.ds flags abCEeFfhIiLmnpquVvXx
.ds flags abCEeFfhIiLlmnpquVvXx
.Os
.Sh NAME
.Nm sh
@ -119,11 +120,20 @@ option is not present, the shell is considered an interactive shell.
An interactive shell generally prompts before each command and handles
programming and command errors differently (as described below).
When first starting,
if neither the
.Fl l
nor
.Cm \+l
options were given on the command line,
the shell inspects argument 0, and if it begins with a dash
.Sq - ,
.Sq \- ,
or if the
.Fl l
option was given,
the shell is also considered
a login shell.
This is normally done automatically by the system
Beginning argument 0 with a dash is normally done
automatically by the system
when the user first logs in.
A login shell first reads commands
(as if by using the
@ -409,6 +419,23 @@ in this shell.
For more details see the section
.Sx LINENO
below.
.It Fl l Em login
When set on the command line, the shell will be considered
a login shell.
When reset on the command line
.Po Cm \&+l
or
.Cm Cm \&+o Em login Pc ,
the shell will not be
considered a login shell, even if the command name parameter
.Po Va argv[0] Pc
begins with a dash
.Pq Sq \- .
See
.Sx Invocation
for the effects of this.
Changing the value of this option while the shell is
running has no effect.
.It Fl m Em monitor
Turn on job control (set automatically at shell startup,
if not mentioned on the command line, when interactive).
@ -4660,6 +4687,144 @@ This environment setting overrides the
.Ev MAIL
setting.
There is a maximum of 10 mailboxes that can be monitored at once.
.It Ev NBSH_INVOCATION
When
.Nm
starts, after it has processed its arguments,
and imported variables from the environment,
this variable is set to a string of one or more
characters which indicate the way the command line
was processed.
This is intended to be used in the startup
scripts
.Pq see Sx Invocation
to allow them to determine what actions are
appropriate to take.
.Ev NBSH_INVOCATION
is marked
.Dq not to be exported .
Apart from the way it is initialized,
and that it overrides any value that may
have been set in the environment,
there is nothing special about it.
It can be unset, or altered,
with no ramifications,
other than whatever effect this might have
on its use in the startup scripts.
.Pp
When the value of this variable remains as set at startup by
.Nm
the following characters may appear in the value,
in the circumstances described.
Any present will always appear in ASCII lexical
order, as they appear below (to make testing the value easier to code).
.Pp
.Bl -compact -tag -width M__ -offset indent
.It \&!
Always present when set by
.Nm ,
and is always first.
No specific meaning is attributed to this character.
.It \&\-
Set when the first character of
.Va argv[0]
as set when the shell was invoked was a dash
.Pq Sq \&\- .
.It \&0
Set when at startup, the special parameter
.Dv \&$#
has the value 0.
That is, no arguments were given to the script
in the case that there is a script.
.It \&c
The
.Fl c
option was given on the command line.
.It \&f
Neither the
.Fl c
nor
.Fl s
options were present on the command line,
but there is at least one non-option argument,
which will then be interpreted as the name of the
.Ar command_file
to process.
.It \&i
The shell is interactive.
At startup this indicates that
.Sq i
will appear in the value of the
special parameter
.Va \&$\- .
However, the special parameter will
alter as the
.Fl i
option is manipulated by the
.Ic set
built-in command, but
.Ev NBSH_INVOCATION
is never subsequently altered by the shell itself
(unless manipulated by a regular variable operations).
.It \&l
The shell is a login shell.
As with
.Sq i
(the same operational conditions apply)
this character will be present if the
.Sq l
is present in
.Va \&$-
when the shell is starting.
Note that if
.Sq l
is present, and
.Sq \&\-
is not, then the shell was invoked
with the
.Fl l
option on the command line (or the
equivalent
.Fl o Em login ) .
On the other hand, if
.Sq \&\-
appears, and
.Sq l
does not,
then the shell was invoked with the
.Cm +l
option (or its equivalent) on the command line.
If both
.Sq \&\-
and
.Sq l
appear, then the shell is a normal login
shell, the
.Fl l
option might have been given, but had no effect.
If neither
.Sq \&\-
nor
.Sq l
appear, then the shell is not a login shell,
and was never intended to be.
The
.Cm +l
option might have been given, but had no effect.
.It \&p
The shell was started as a privileged
(set user id) process.
This indicates that the
.Fl p
option must have been given on the command
line, or privileges would have been dropped.
.It \&s
The shell will read commands from standard input.
The
.Fl s
option was given, or implied.
This does not imply that the shell is interactive.
.El
.It Ev PATH
The default search path for executables.
See the

View File

@ -1,4 +1,4 @@
/* $NetBSD: var.c,v 1.80 2021/08/09 11:29:30 kre Exp $ */
/* $NetBSD: var.c,v 1.81 2022/09/18 06:03:19 kre Exp $ */
/*-
* Copyright (c) 1991, 1993
@ -37,7 +37,7 @@
#if 0
static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 5/4/95";
#else
__RCSID("$NetBSD: var.c,v 1.80 2021/08/09 11:29:30 kre Exp $");
__RCSID("$NetBSD: var.c,v 1.81 2022/09/18 06:03:19 kre Exp $");
#endif
#endif /* not lint */
@ -527,7 +527,45 @@ setvareq(char *s, int flags)
VTRACE(DBG_VARS, ("new [%s] (%d) %#x\n", s, nlen, vp->flags));
}
void
setvar_invocation(int argc, char **argv)
{
char value[32]; /* if we ever get 30, HELP */
char *v;
/*
* Keep the following in ascii lexical order ( ie: Z before a )
*/
v = value;
*v++ = '@'; /* never empty, and the '-' is not first */
if (argc > 0 && argv[0] != NULL && argv[0][0] == '-')
*v++ = '-';
if (shellparam.nparam == 0)
*v++ = '0';
if (minusc)
*v++ = 'c';
if (commandname)
*v++ = 'f';
if (iflag)
*v++ = 'i';
if (loginsh)
*v++ = 'l';
if (privileged)
*v++ = 'p';
if (sflag)
*v++ = 's';
*v++ = '\0';
/*
* this cannot fail, the var name is OK,
* there cannot be any (non special) read only
* variables at this point, ...
*/
setvar("NBSH_INVOCATION", value, VNOEXPORT);
}
/*
* Process a linked list of variable assignments.

View File

@ -1,4 +1,4 @@
/* $NetBSD: var.h,v 1.38 2018/12/04 14:03:30 kre Exp $ */
/* $NetBSD: var.h,v 1.39 2022/09/18 06:03:19 kre Exp $ */
/*-
* Copyright (c) 1991, 1993
@ -144,6 +144,7 @@ void listmklocal(struct strlist *, int);
void poplocalvars(void);
int unsetvar(const char *, int);
void choose_ps1(void);
void setvar_invocation(int, char **);
int setvarsafe(const char *, const char *, int);
void print_quoted(const char *);
int validname(const char *, int, int *);