Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
[PATCH] disown: add -a option
- X-seq: zsh-workers 54585
- From: dana <dana@xxxxxxx>
- To: zsh-workers@xxxxxxx
- Subject: [PATCH] disown: add -a option
- Date: Wed, 20 May 2026 14:00:29 -0500
- Archived-at: <https://zsh.org/workers/54585>
- Feedback-id: i9be146f9:Fastmail
- List-id: <zsh-workers.zsh.org>
this is a bash feature that's been brought up on the ml once or twice,
and i think on irc. it's easier than `disown %${(k)^jobstates}`
doesn't depend on the actual curjob change from w/54584 but the diff is
based on it
dana
diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo
index 095bc5783..dbd96c6c0 100644
--- a/Doc/Zsh/builtins.yo
+++ b/Doc/Zsh/builtins.yo
@@ -464,13 +464,14 @@ enditem()
)
findex(disown)
cindex(jobs, disowning)
-xitem(tt(disown) [ var(job) ... ])
+xitem(tt(disown) [ tt(-a) | var(job) ... ])
xitem(var(job) ... tt(&|))
item(var(job) ... tt(&!))(
Remove the specified var(job)s from the job table; the shell will
no longer report their status, and will not complain if you
try to exit an interactive shell with them running or stopped.
If no var(job) is specified, disown the current job.
+With tt(-a), disown all jobs.
If the var(job)s are currently stopped and the tt(AUTO_CONTINUE) option
is not set, a warning is printed containing information about how to
diff --git a/Src/builtin.c b/Src/builtin.c
index 706191832..864b9d70f 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -58,7 +58,7 @@ static struct builtin builtins[] =
BUILTIN("declare", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL | BINF_ASSIGN, (HandlerFunc)bin_typeset, 0, -1, 0, "AE:%F:%HL:%R:%TUZ:%afghi:%klmnp:%rtuxz", NULL),
BUILTIN("dirs", 0, bin_dirs, 0, -1, 0, "clpv", NULL),
BUILTIN("disable", 0, bin_enable, 0, -1, BIN_DISABLE, "afmprs", NULL),
- BUILTIN("disown", 0, bin_fg, 0, -1, BIN_DISOWN, NULL, NULL),
+ BUILTIN("disown", 0, bin_fg, 0, -1, BIN_DISOWN, "a", NULL),
BUILTIN("echo", BINF_SKIPINVALID, bin_print, 0, -1, BIN_ECHO, "neE", "-"),
BUILTIN("emulate", 0, bin_emulate, 0, -1, 0, "lLR", NULL),
BUILTIN("enable", 0, bin_enable, 0, -1, BIN_ENABLE, "afmprs", NULL),
diff --git a/Src/jobs.c b/Src/jobs.c
index 2661ea0c1..03987d436 100644
--- a/Src/jobs.c
+++ b/Src/jobs.c
@@ -2419,6 +2419,12 @@ int
bin_fg(char *name, char **argv, Options ops, int func)
{
int job, lng, firstjob = -1, retval = 0, ofunc = func;
+ int disown_all = (func == BIN_DISOWN && OPT_ISSET(ops, 'a'));
+
+ if (disown_all && *argv) {
+ zwarnnam(name, "argument not meaningful with -a: %s", *argv);
+ return 1;
+ }
if (OPT_ISSET(ops,'Z')) {
int len;
@@ -2483,10 +2489,12 @@ bin_fg(char *name, char **argv, Options ops, int func)
* will prevent zexit from complaining about stopped jobs */
stopmsg = 2;
if (!*argv) {
+ if (disown_all) {
+ firstjob = 0;
/* This block handles all of the default cases (no arguments). bg,
fg and disown act on the current job, and jobs and wait act on all the
jobs. */
- if (func == BIN_FG || func == BIN_BG || func == BIN_DISOWN) {
+ } else if (func == BIN_FG || func == BIN_BG || func == BIN_DISOWN) {
/* W.r.t. the above comment, we'd better have a current job at this
point or else. */
if (curjob == -1 || (jobtab[curjob].stat & STAT_NOPRINT)) {
@@ -2574,7 +2582,7 @@ bin_fg(char *name, char **argv, Options ops, int func)
}
/* The only type of argument allowed now is a job spec. Check it. */
job = (*argv) ? getjob(*argv, name) : firstjob;
- firstjob = -1;
+ firstjob = (disown_all && job <= maxjob) ? job + 1 : -1;
if (job == -1) {
retval = 127;
break;
@@ -2582,6 +2590,8 @@ bin_fg(char *name, char **argv, Options ops, int func)
jstat = oldjobtab ? oldjobtab[job].stat : jobtab[job].stat;
if (!(jstat & STAT_INUSE) ||
(jstat & STAT_NOPRINT)) {
+ if (disown_all)
+ continue;
if (!isset(POSIXBUILTINS))
zwarnnam(name, "%s: no such job", *argv);
unqueue_signals();
diff --git a/Test/W02jobs.ztst b/Test/W02jobs.ztst
index 135869d81..f38e90dcd 100644
--- a/Test/W02jobs.ztst
+++ b/Test/W02jobs.ztst
@@ -273,6 +273,19 @@
#*>\[1] * suspended * sleep 3
#*>disown: warning: job is suspended*
+ zpty_start
+ zpty_input 'sleep 2 &; sleep 3 &; sleep 4 &; disown -a; jobs'
+ zpty_stop
+0:disown -a
+*>\[1] <->
+*>\[2] <->
+*>\[3] <->
+
+ zpty_start
+ zpty_input '( sleep 2 &; sleep 3 &; sleep 4 &; disown -a; jobs ); :'
+ zpty_stop
+0:disown -a in sub-shell
+
zpty_start
zpty_input 'sleep 2 &; sleep 3 &|; jobs; disown'
zpty_input 'sleep 2 &; sleep 3 &!; jobs; disown'
Messages sorted by:
Reverse Date,
Date,
Thread,
Author