git: 07d147a7fcbf - stable/14 - sh(1): add -l option

From: Baptiste Daroussin <bapt_at_FreeBSD.org>
Date: Thu, 12 Dec 2024 15:51:27 UTC
The branch stable/14 has been updated by bapt:

URL: https://cgit.FreeBSD.org/src/commit/?id=07d147a7fcbf61125cad0470b83fe203f725dc39

commit 07d147a7fcbf61125cad0470b83fe203f725dc39
Author:     Baptiste Daroussin <bapt@FreeBSD.org>
AuthorDate: 2024-11-20 10:48:39 +0000
Commit:     Baptiste Daroussin <bapt@FreeBSD.org>
CommitDate: 2024-12-12 15:51:17 +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
    
    (cherry picked from commit 65f5dd42f11cdcb7716e6cdd09fac2314c144c1f)
---
 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 7a4dbc254f81..257f6b16162c 100644
--- a/bin/sh/main.c
+++ b/bin/sh/main.c
@@ -107,6 +107,7 @@ main(int argc, char *argv[])
 	static struct stackmark smark, smark2;
 	volatile int state;
 	char *shinit;
+	int login;
 
 	(void) setlocale(LC_ALL, "");
 	initcharset();
@@ -140,13 +141,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 87ee4ab5c658..43a8ee47411e 100644
--- a/bin/sh/options.c
+++ b/bin/sh/options.c
@@ -70,7 +70,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);
@@ -82,19 +82,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)) {
@@ -125,6 +126,8 @@ procargs(int argc, char **argv)
 		argptr++;
 	}
 	optschanged();
+
+	return (login);
 }
 
 
@@ -145,12 +148,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;
@@ -196,6 +200,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)
@@ -204,13 +210,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);
 	}
 
 	/*
@@ -223,7 +229,7 @@ end_options2:
 	if (!cmdline) {
 		if (*argptr == NULL)
 			setparam(0, argptr);
-		return;
+		return (login);
 	}
 
 	/*
@@ -242,6 +248,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 9c516b07ad23..a477f24e90ca 100644
--- a/bin/sh/options.h
+++ b/bin/sh/options.h
@@ -111,7 +111,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 03e8af70c9aa..1a0275a396ea 100644
--- a/bin/sh/sh.1
+++ b/bin/sh/sh.1
@@ -31,7 +31,7 @@
 .\"
 .\"	from: @(#)sh.1	8.6 (Berkeley) 5/4/95
 .\"
-.Dd December 14, 2022
+.Dd November 20, 2024
 .Dt SH 1
 .Os
 .Sh NAME
@@ -39,14 +39,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
@@ -54,7 +54,7 @@
 .Op Ar arg ...
 .Oc
 .Nm
-.Op Fl /+abCEefhIimnPpTuVvx
+.Op Fl /+abCEefhIilmnPpTuVvx
 .Op Fl /+o Ar longname
 .Fl s
 .Op Ar arg ...
@@ -253,6 +253,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).