Module Name: src
Committed By: kre
Date: Wed Oct 9 13:43:33 UTC 2024
Modified Files:
src/bin/sh: builtins.def jobs.c sh.1 shell.h trap.c trap.h
Log Message:
PR bin/58687 -- implement suspend as a builtin in sh
Requested by uwe@ in PR bin/58687 without objections from
anyone except me, here is an implementation of a suspend
builtin command for /bin/sh
The sh.1 man page is updated, naturally, to describe it.
This new builtin does not exist in SMALL shells -- as used
on (some) boot media, etc.
If this turns out not to be useful, it can easily be removed.
To generate a diff of this commit:
cvs rdiff -u -r1.28 -r1.29 src/bin/sh/builtins.def
cvs rdiff -u -r1.122 -r1.123 src/bin/sh/jobs.c
cvs rdiff -u -r1.264 -r1.265 src/bin/sh/sh.1
cvs rdiff -u -r1.32 -r1.33 src/bin/sh/shell.h
cvs rdiff -u -r1.57 -r1.58 src/bin/sh/trap.c
cvs rdiff -u -r1.25 -r1.26 src/bin/sh/trap.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/bin/sh/builtins.def
diff -u src/bin/sh/builtins.def:1.28 src/bin/sh/builtins.def:1.29
--- src/bin/sh/builtins.def:1.28 Wed Oct 9 12:27:11 2024
+++ src/bin/sh/builtins.def Wed Oct 9 13:43:32 2024
@@ -1,5 +1,5 @@
#!/bin/sh -
-# $NetBSD: builtins.def,v 1.28 2024/10/09 12:27:11 kre Exp $
+# $NetBSD: builtins.def,v 1.29 2024/10/09 13:43:32 kre Exp $
#
# Copyright (c) 1991, 1993
# The Regents of the University of California. All rights reserved.
@@ -80,6 +80,7 @@ setvarcmd setvar
shiftcmd -s shift
#ifndef SMALL
specialvarcmd specialvar
+suspendcmd -j suspend
#endif
testcmd -u test -u [
timescmd -s times
Index: src/bin/sh/jobs.c
diff -u src/bin/sh/jobs.c:1.122 src/bin/sh/jobs.c:1.123
--- src/bin/sh/jobs.c:1.122 Tue Jun 18 07:21:31 2024
+++ src/bin/sh/jobs.c Wed Oct 9 13:43:32 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: jobs.c,v 1.122 2024/06/18 07:21:31 kre Exp $ */
+/* $NetBSD: jobs.c,v 1.123 2024/10/09 13:43:32 kre Exp $ */
/*-
* Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
#if 0
static char sccsid[] = "@(#)jobs.c 8.5 (Berkeley) 5/4/95";
#else
-__RCSID("$NetBSD: jobs.c,v 1.122 2024/06/18 07:21:31 kre Exp $");
+__RCSID("$NetBSD: jobs.c,v 1.123 2024/10/09 13:43:32 kre Exp $");
#endif
#endif /* not lint */
@@ -980,13 +980,124 @@ jobidcmd(int argc, char **argv)
return 0;
}
+#if JOBS
+#ifndef SMALL
+
+static int
+stop_me(int sig, int force, int pgrp, pid_t pid)
+{
+ if (force || (!loginsh && mflag && rootshell)) {
+ struct sigaction sig_dfl, sig_was;
+
+ sig_dfl.sa_handler = SIG_DFL;
+ sig_dfl.sa_flags = 0;
+ sigemptyset(&sig_dfl.sa_mask);
+
+ (void)sigaction(sig, &sig_dfl, &sig_was);
+
+ if (kill(pgrp ? 0 : pid, sig) == -1) {
+ sh_warn("suspend myself");
+ (void)sigaction(sig, &sig_was, NULL);
+ error(NULL);
+ }
+
+ (void)sigaction(sig, &sig_was, NULL);
+
+ return 0;
+ }
+
+ if (!rootshell)
+ sh_warnx("subshell environment");
+ else if (!mflag)
+ sh_warnx("job control disabled");
+ else if (loginsh)
+ sh_warnx("login shell");
+ else
+ sh_warnx("not possible??");
+
+ return 1;
+}
+
+int
+suspendcmd(int argc, char **argv)
+{
+ int sig = SIGTSTP;
+ int force = 0;
+ int pgrp = 0;
+ int status = 0;
+ char *target;
+ int c;
+
+ while ((c = nextopt("fgs:")) != 0) {
+ switch (c) {
+ case 'f':
+ force = 1;
+ break;
+ case 'g':
+ pgrp = 1;
+ break;
+ case 's':
+ sig = signame_to_signum(optionarg);
+
+ if (sig != SIGSTOP && sig != SIGTSTP &&
+ sig != SIGTTIN && sig != SIGTTOU)
+ error("bad signal '%s'", optionarg);
+ break;
+ }
+ }
+
+ if (!*argptr) /* suspend myself */
+ return stop_me(sig, force, pgrp, getpid());
+
+ while ((target = *argptr++) != NULL)
+ {
+ int pid;
+
+ if (is_number(target)) {
+ if ((pid = number(target)) == 0) {
+ sh_warnx("Cannot (yet) suspend kernel (%s)",
+ target);
+ status = 1;
+ continue;
+ }
+ } else if ((pid = getjobpgrp(target)) == 0) {
+ sh_warnx("Unknown job: %s", target);
+ status = 1;
+ continue;
+ }
+
+ if (pid == rootpid || pid == getpid()) {
+ status |= stop_me(sig, force, pgrp, pid);
+ continue;
+ }
+
+ if (pid == 1 || pid == -1) {
+ sh_warnx("Don't be funny");
+ status = 1;
+ continue;
+ }
+
+ if (pid > 0 && pgrp)
+ pid = -pid;
+
+ if (kill(pid, sig) == -1) {
+ sh_warn("failed to suspend %s", target);
+ status = 1;
+ }
+ }
+
+ return status;
+}
+#endif /* SMALL */
+#endif /* JOBS */
+
int
getjobpgrp(const char *name)
{
struct job *jp;
if (jobs_invalid)
- error("No such job: %s", name);
+ return 0;
jp = getjob(name, 1);
if (jp == 0)
return 0;
Index: src/bin/sh/sh.1
diff -u src/bin/sh/sh.1:1.264 src/bin/sh/sh.1:1.265
--- src/bin/sh/sh.1:1.264 Sat Sep 21 20:48:50 2024
+++ src/bin/sh/sh.1 Wed Oct 9 13:43:32 2024
@@ -1,4 +1,4 @@
-.\" $NetBSD: sh.1,v 1.264 2024/09/21 20:48:50 kre Exp $
+.\" $NetBSD: sh.1,v 1.265 2024/10/09 13:43:32 kre Exp $
.\" Copyright (c) 1991, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
@@ -31,7 +31,7 @@
.\"
.\" @(#)sh.1 8.6 (Berkeley) 5/4/95
.\"
-.Dd July 13, 2024
+.Dd October 6, 2024
.Dt SH 1
.\" everything except c o and s (keep them ordered)
.ds flags abCEeFfhIiLlmnpquVvXx
@@ -416,7 +416,7 @@ This option defaults to
.Dq on
in this shell.
For more details see the section
-.Sx LINENO
+.Sx Using Dv LINENO
below.
.It Fl l Em login
When set on the command line, the shell will be considered
@@ -3618,7 +3618,7 @@ Using
is an extension not implemented by most shells.
.Pp
See the section
-.Sx LINENO
+.Sx Using Dv LINENO
below for details of the effects of making the variable
.Dv LINENO
local.
@@ -4059,6 +4059,81 @@ naming the variables required,
to ensure that their special properties are available.
.\"
.Pp
+.It Ic suspend Oo Fl fg Oc Oo Fl s Ar sig Oc Oo Ar pid Ns \&| Ns Ar job ... Oc
+Causes the processes or jobs indicated to be suspended, if possible.
+If no
+.Ar pid
+or
+.Ar job
+arguments are given, or if a
+.Ar pid
+argument refers to the shell itself, and if the
+.Ic suspend
+command is issued in a shell that is not a login shell,
+has job control enabled,
+and is not executing in a subshell environment,
+then the shell will suspend itself.
+The
+.Fl f
+(force) option causes those checks to be ignored,
+the shell, when instructed to suspend itself with force,
+will always attempt to do so, which may result in a subshell
+environment becoming suspended.
+.Pp
+The
+.Fl g
+option indicates that each
+.Ar pid
+argument is to be treated as a process group identifier,
+or if no targets are given, the current process group of the shell,
+and that process group will be suspended, instead of just
+the process identified.
+This option is implied, for the one agument only, by use of a
+.Ar job
+specifier.
+Note that, unlike other built-in commands, use of a
+.Ar pid
+argument causes only that process to be suspended,
+even if that
+.Ar pid
+happens to be the process leader of a job, or another
+process in a job.
+.Pp
+The
+.Fl s Ar sig
+option cause the signal
+.Ar sig
+to be used to suspend the process, or process group.
+Only the signals that, by default, cause processes to be
+suspended
+.Pq Dv STOP Dv TSTP Dv TTIN No and Dv TTOU
+are permitted.
+The default is
+.Dv SIGTSTP .
+Note that except when
+.Dv SIGSTOP
+is sent, the target process can arrange to catch or
+ignore the signal, and perhaps not become suspended,
+if it so desires.
+Interactive processes that suport job control
+(eg: shells)
+generally ignore those signals.
+.Pp
+The
+.Ic suspend
+command exits with status 0, except if an error occurs,
+in which case it exits with a status greater than 0.
+Possible errors include usage errors;
+attempting to suspend the shell itself, when not
+permitted and without the
+.Fl f
+option;
+a target process or job not existing;
+insufficient prvileges to signal the target process or job;
+and more.
+It is not an error if the target process decides not to comply
+with a request to suspend itself.
+.Pp
.It Ic times
Prints two lines to standard output.
Each line contains two accumulated time values, expressed
@@ -4542,6 +4617,7 @@ The
.Ic jobid ,
.Ic jobs ,
.Ic kill ,
+.Ic suspend ,
and
.Ic wait
commands all accept job identifiers as arguments, in addition to
@@ -4562,7 +4638,11 @@ command.
To cause a foreground process to stop, enter the terminal's
.Ic stop
character (usually control-Z).
-To cause a background process to stop, send it a
+To cause a background process to stop,
+use the
+.Ic suspend
+built in command, or
+send it a
.Dv STOP
signal, using the kill command.
A useful function to define is
@@ -4638,9 +4718,11 @@ It's similar to
pressing the
.Aq ESC
key will throw you into vi command mode.
+Insert mode is re-entered in any of the usual vi ways,
+using the append (a) insert (i) substitute (s) (etc) commands.
Pressing the
.Aq return
-key while in command mode will pass the line to the shell.
+key in either mode will pass the line to the shell.
.Pp
The emacs-mode uses commands similar to a subset available in the
.Ic emacs
@@ -4937,7 +5019,7 @@ See
.It Dv LINENO
The current line number in the script or function.
See the section
-.Sx LINENO
+.Sx Using Dv LINENO
below for more details.
.It Ev MAIL
The name of a mail file, that will be checked for the arrival of new mail.
@@ -5317,7 +5399,7 @@ that were used when building the shell w
behaves like any other variable that has the read-only
and un-exportable attributes set.
.El
-.Ss Dv LINENO
+.Ss Using Dv LINENO
.Dv LINENO
is in many respects a normal shell variable, containing an
integer value, and can be expanded using any of the forms
Index: src/bin/sh/shell.h
diff -u src/bin/sh/shell.h:1.32 src/bin/sh/shell.h:1.33
--- src/bin/sh/shell.h:1.32 Fri Feb 9 22:08:30 2024
+++ src/bin/sh/shell.h Wed Oct 9 13:43:33 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: shell.h,v 1.32 2024/02/09 22:08:30 andvar Exp $ */
+/* $NetBSD: shell.h,v 1.33 2024/10/09 13:43:33 kre Exp $ */
/*-
* Copyright (c) 1991, 1993
@@ -56,7 +56,7 @@
#define SHELL_H
#include <sys/param.h>
-#define JOBS 1
+#define JOBS 1 /* spaces in this line are important, do not alter */
#ifndef BSD
#define BSD 1
#endif
Index: src/bin/sh/trap.c
diff -u src/bin/sh/trap.c:1.57 src/bin/sh/trap.c:1.58
--- src/bin/sh/trap.c:1.57 Sat Jul 13 13:43:58 2024
+++ src/bin/sh/trap.c Wed Oct 9 13:43:33 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: trap.c,v 1.57 2024/07/13 13:43:58 kre Exp $ */
+/* $NetBSD: trap.c,v 1.58 2024/10/09 13:43:33 kre Exp $ */
/*-
* Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
#if 0
static char sccsid[] = "@(#)trap.c 8.5 (Berkeley) 6/5/95";
#else
-__RCSID("$NetBSD: trap.c,v 1.57 2024/07/13 13:43:58 kre Exp $");
+__RCSID("$NetBSD: trap.c,v 1.58 2024/10/09 13:43:33 kre Exp $");
#endif
#endif /* not lint */
@@ -108,7 +108,7 @@ void printsignals(struct output *, int);
* or -1 if it isn't one
*/
-static int
+int
signame_to_signum(const char *p)
{
int i;
Index: src/bin/sh/trap.h
diff -u src/bin/sh/trap.h:1.25 src/bin/sh/trap.h:1.26
--- src/bin/sh/trap.h:1.25 Mon Dec 3 10:53:29 2018
+++ src/bin/sh/trap.h Wed Oct 9 13:43:33 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: trap.h,v 1.25 2018/12/03 10:53:29 martin Exp $ */
+/* $NetBSD: trap.h,v 1.26 2024/10/09 13:43:33 kre Exp $ */
/*-
* Copyright (c) 1991, 1993
@@ -50,3 +50,4 @@ void setinteractive(int);
void exitshell(int) __dead;
void exitshell_savedstatus(void) __dead;
int lastsig(void);
+int signame_to_signum(const char *);