git: 65f5dd42f11c - main - sh(1): add -l option

From: Baptiste Daroussin <bapt_at_FreeBSD.org>
Date: Wed, 20 Nov 2024 12:57:50 UTC
The branch main has been updated by bapt:

URL: https://cgit.FreeBSD.org/src/commit/?id=65f5dd42f11cdcb7716e6cdd09fac2314c144c1f

commit 65f5dd42f11cdcb7716e6cdd09fac2314c144c1f
Author:     Baptiste Daroussin <bapt@FreeBSD.org>
AuthorDate: 2024-11-20 10:48:39 +0000
Commit:     Baptiste Daroussin <bapt@FreeBSD.org>
CommitDate: 2024-11-20 12:57:18 +0000

    sh(1): add -l option
    
    -l is required by LSB for login shell, all other shells: bash, zsh,
    oksh, mksh, ... implements it.
    
    with -l sh will act as a login shell and read the profile.
    
    MFC After:      1 week
    Obtained From:  dash (3b7c8442bfe7c2fd0a6b0415df6ddf66a399fd55)
    Reviewed by:    kib, lme
    Differential Revision:  https://reviews.freebsd.org/D47681
---
 bin/sh/main.c    |  5 +++--
 bin/sh/options.c | 24 ++++++++++++++++--------
 bin/sh/options.h |  2 +-
 bin/sh/sh.1      | 10 ++++++----
 4 files changed, 26 insertions(+), 15 deletions(-)

diff --git a/bin/sh/main.c b/bin/sh/main.c
index 23147c1db0be..94e8da6b4921 100644
--- a/bin/sh/main.c
+++ b/bin/sh/main.c
@@ -95,6 +95,7 @@ main(int argc, char *argv[])
 	static struct stackmark smark, smark2;
 	volatile int state;
 	char *shinit;
+	int login;
 
 	(void) setlocale(LC_ALL, "");
 	initcharset();
@@ -128,13 +129,13 @@ main(int argc, char *argv[])
 	initvar();
 	setstackmark(&smark);
 	setstackmark(&smark2);
-	procargs(argc, argv);
+	login = procargs(argc, argv);
 	trap_init();
 	pwd_init(iflag);
 	INTON;
 	if (iflag)
 		chkmail(1);
-	if (argv[0] && argv[0][0] == '-') {
+	if (login) {
 		state = 1;
 		read_profile("/etc/profile");
 state1:
diff --git a/bin/sh/options.c b/bin/sh/options.c
index 2dab8f4ea998..54a9cb4c1c49 100644
--- a/bin/sh/options.c
+++ b/bin/sh/options.c
@@ -64,7 +64,7 @@ char *nextopt_optptr;		/* used by nextopt */
 char *minusc;			/* argument to -c option */
 
 
-static void options(int);
+static int options(int);
 static void minus_o(char *, int);
 static void setoption(int, int);
 static void setoptionbyindex(int, int);
@@ -76,19 +76,20 @@ static int getopts(char *, char *, char **, char ***, char **);
  * Process the shell command line arguments.
  */
 
-void
+int
 procargs(int argc, char **argv)
 {
-	int i;
+	int i, login;
 	char *scriptname;
 
 	argptr = argv;
+	login = argptr[0] != NULL && argptr[0][0] == '-';
 	if (argc > 0)
 		argptr++;
 	for (i = 0; i < NOPTS; i++)
 		optval[i] = 2;
 	privileged = (getuid() != geteuid() || getgid() != getegid());
-	options(1);
+	login |= options(1);
 	if (*argptr == NULL && minusc == NULL)
 		sflag = 1;
 	if (iflag != 0 && sflag == 1 && isatty(0) && isatty(1)) {
@@ -119,6 +120,8 @@ procargs(int argc, char **argv)
 		argptr++;
 	}
 	optschanged();
+
+	return (login);
 }
 
 
@@ -139,12 +142,13 @@ optschanged(void)
  * to the set special builtin.
  */
 
-static void
+static int
 options(int cmdline)
 {
 	char *kp, *p;
 	int val;
 	int c;
+	int login = 0;
 
 	if (cmdline)
 		minusc = NULL;
@@ -190,6 +194,8 @@ options(int cmdline)
 				if (q == NULL || minusc != NULL)
 					error("Bad -c option");
 				minusc = q;
+			} else if (c == 'l') {
+				login = 1;
 			} else if (c == 'o') {
 				minus_o(*argptr, val);
 				if (*argptr)
@@ -198,13 +204,13 @@ options(int cmdline)
 				setoption(c, val);
 		}
 	}
-	return;
+	return (login);
 
 	/* When processing `set', a single "-" means turn off -x and -v */
 end_options1:
 	if (!cmdline) {
 		xflag = vflag = 0;
-		return;
+		return (login);
 	}
 
 	/*
@@ -217,7 +223,7 @@ end_options2:
 	if (!cmdline) {
 		if (*argptr == NULL)
 			setparam(0, argptr);
-		return;
+		return (login);
 	}
 
 	/*
@@ -236,6 +242,8 @@ end_options2:
 		/* We need to keep the final argument */
 		argptr--;
 	}
+
+	return (login);
 }
 
 static void
diff --git a/bin/sh/options.h b/bin/sh/options.h
index 206d32c8a706..a059e19707b1 100644
--- a/bin/sh/options.h
+++ b/bin/sh/options.h
@@ -109,7 +109,7 @@ extern char **argptr;		/* argument list for builtin commands */
 extern char *shoptarg;		/* set by nextopt */
 extern char *nextopt_optptr;	/* used by nextopt */
 
-void procargs(int, char **);
+int procargs(int, char **);
 void optschanged(void);
 void freeparam(struct shparam *);
 int nextopt(const char *);
diff --git a/bin/sh/sh.1 b/bin/sh/sh.1
index 1ce26ecba328..9903508d6381 100644
--- a/bin/sh/sh.1
+++ b/bin/sh/sh.1
@@ -29,7 +29,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd December 14, 2022
+.Dd November 20, 2024
 .Dt SH 1
 .Os
 .Sh NAME
@@ -37,14 +37,14 @@
 .Nd command interpreter (shell)
 .Sh SYNOPSIS
 .Nm
-.Op Fl /+abCEefhIimnPpTuVvx
+.Op Fl /+abCEefhIilmnPpTuVvx
 .Op Fl /+o Ar longname
 .Oo
 .Ar script
 .Op Ar arg ...
 .Oc
 .Nm
-.Op Fl /+abCEefhIimnPpTuVvx
+.Op Fl /+abCEefhIilmnPpTuVvx
 .Op Fl /+o Ar longname
 .Fl c Ar string
 .Oo
@@ -52,7 +52,7 @@
 .Op Ar arg ...
 .Oc
 .Nm
-.Op Fl /+abCEefhIimnPpTuVvx
+.Op Fl /+abCEefhIilmnPpTuVvx
 .Op Fl /+o Ar longname
 .Fl s
 .Op Ar arg ...
@@ -251,6 +251,8 @@ Ignore
 from input when in interactive mode.
 .It Fl i Li interactive
 Force the shell to behave interactively.
+.It Fl l
+Force the shell to act as if it has been invoked as a login shell.
 .It Fl m Li monitor
 Turn on job control (set automatically when interactive).
 A new process group is created for each pipeline (called a job).