zsh-workers
 help / color / mirror / code / Atom feed
* PATCH: exit after 10 EOF's
@ 2004-09-13 11:18 Peter Stephenson
  2004-09-13 17:51 ` Bart Schaefer
  2004-09-19  6:50 ` Bart Schaefer
  0 siblings, 2 replies; 22+ messages in thread
From: Peter Stephenson @ 2004-09-13 11:18 UTC (permalink / raw)
  To: Zsh hackers list

The shell is supposed to exit after 10 EOFs if ignore_eof is set.
When zle is in use this appears to have been broken for a long time.
(It's not affected by my recent patch for aborting a list causing the
shell to exit, even though that touched the same code.)

I think the following patch is OK.  It duplicates the usual test from
the top-level loop inside zle, but if we're going to continue with the
feature that the "use 'exit' to exit" message is handled as a zle
message (which doesn't cause a new command line to be output) that seems
to be inevitable.

This ought to be part of the test suite, but with zle it needs zpty and
I don't understand the tests with zpty.

Index: Src/init.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/init.c,v
retrieving revision 1.42
diff -u -r1.42 init.c
--- Src/init.c	11 Jul 2004 22:53:03 -0000	1.42
+++ Src/init.c	13 Sep 2004 11:12:47 -0000
@@ -37,7 +37,7 @@
 #include "version.h"
 
 /**/
-int noexitct = 0;
+mod_export int noexitct = 0;
 
 /* buffer for $_ and its length */
 
Index: Src/Zle/zle_main.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_main.c,v
retrieving revision 1.50
diff -u -r1.50 zle_main.c
--- Src/Zle/zle_main.c	2 Sep 2004 09:20:39 -0000	1.50
+++ Src/Zle/zle_main.c	13 Sep 2004 11:12:48 -0000
@@ -688,17 +688,27 @@
 	selectlocalmap(NULL);
 	bindk = getkeycmd();
 	if (bindk) {
-	    if (!ll && isfirstln && !(zlereadflags & ZLRF_IGNOREEOF) &&
-		lastchar == eofchar) {
+	    if (!ll && isfirstln && lastchar == eofchar) {
 		/*
 		 * Slight hack: this relies on getkeycmd returning
 		 * a value for the EOF character.  However,
 		 * undefined-key is fine.  That's necessary because
 		 * otherwise we can't distinguish this case from
 		 * a ^C.
+		 *
+		 * The noxitct test is done in the top-level loop
+		 * if zle is not running.  As we trap EOFs at this
+		 * level inside zle we need to mimic it here.
+		 * If we break, the top-level loop will actually increment
+		 * noexitct an extra time; that doesn't cause any
+		 * problems.
 		 */
-		eofsent = 1;
-		break;
+		if (!(zlereadflags & ZLRF_IGNOREEOF) ||
+		    ++noexitct >= 10)
+		{
+		    eofsent = 1;
+		    break;
+		}
 	    }
 	    if (execzlefunc(bindk, zlenoargs))
 		handlefeep(zlenoargs);

-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
CSR Ltd., Science Park, Milton Road,
Cambridge, CB4 0WH, UK                          Tel: +44 (0)1223 692070


**********************************************************************
This email and any files transmitted with it are confidential and
intended solely for the use of the individual or entity to whom they
are addressed. If you have received this email in error please notify
the system manager.

This footnote also confirms that this email message has been swept by
MIMEsweeper for the presence of computer viruses.

www.mimesweeper.com
**********************************************************************


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: PATCH: exit after 10 EOF's
  2004-09-13 11:18 PATCH: exit after 10 EOF's Peter Stephenson
@ 2004-09-13 17:51 ` Bart Schaefer
  2004-09-15  9:46   ` Peter Stephenson
  2004-09-19  6:50 ` Bart Schaefer
  1 sibling, 1 reply; 22+ messages in thread
From: Bart Schaefer @ 2004-09-13 17:51 UTC (permalink / raw)
  To: Zsh hackers list

On Mon, 13 Sep 2004, Peter Stephenson wrote:

> The shell is supposed to exit after 10 EOFs if ignore_eof is set.
> When zle is in use this appears to have been broken for a long time.

Actually I think that was intentional.  ZLE is able to distinguish a real
end-of-file from a press of the EOF key, so it doesn't need the failsafe
to prevent it from going into an infinite loop when the SHIN descriptor
is closed.

In other words, the shell is supposed to exit after 10 real end-of-files,
not after 10 keyboard-initiated end-of-files.

Unless I've missed or forgotten something ...


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: PATCH: exit after 10 EOF's
  2004-09-13 17:51 ` Bart Schaefer
@ 2004-09-15  9:46   ` Peter Stephenson
  2004-09-15 15:43     ` Bart Schaefer
  0 siblings, 1 reply; 22+ messages in thread
From: Peter Stephenson @ 2004-09-15  9:46 UTC (permalink / raw)
  To: zsh-workers

Bart Schaefer wrote:
> On Mon, 13 Sep 2004, Peter Stephenson wrote:
> 
> > The shell is supposed to exit after 10 EOFs if ignore_eof is set.
> > When zle is in use this appears to have been broken for a long time.
> 
> Actually I think that was intentional.  ZLE is able to distinguish a real
> end-of-file from a press of the EOF key, so it doesn't need the failsafe
> to prevent it from going into an infinite loop when the SHIN descriptor
> is closed.

You mean, because canonical input is turned off.

> In other words, the shell is supposed to exit after 10 real end-of-files,
> not after 10 keyboard-initiated end-of-files.
> 
> Unless I've missed or forgotten something ...

Hmm... the documentation for ignore_eof says:

  However, ten consecutive EOFs will cause the shell to exit anyway,
  to avoid the shell hanging if its tty goes away.

  Also, if this option is set and the Zsh Line Editor is used, widgets
  implemented by shell functions can be bound to EOF (normally
  Control-D) without printing the normal warning message.  This works
  only for normal widgets, not for completion widgets.

This implies there's not even an error message, which isn't right.  The
error message implies it *is* being treated as EOF, which is what really
made me change it.  I would suggest either followng the documentation or
the standard 10-character practice.

The documentation could imply that if you bound ^D to something other
than the default, you wouldn't get the message, but there doesn't appear
to be any support for that, and I don't think it's useful.

-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
CSR Ltd., Science Park, Milton Road,
Cambridge, CB4 0WH, UK                          Tel: +44 (0)1223 692070


**********************************************************************
This email and any files transmitted with it are confidential and
intended solely for the use of the individual or entity to whom they
are addressed. If you have received this email in error please notify
the system manager.

This footnote also confirms that this email message has been swept by
MIMEsweeper for the presence of computer viruses.

www.mimesweeper.com
**********************************************************************


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: PATCH: exit after 10 EOF's
  2004-09-15  9:46   ` Peter Stephenson
@ 2004-09-15 15:43     ` Bart Schaefer
  2004-09-15 16:02       ` Bart Schaefer
  0 siblings, 1 reply; 22+ messages in thread
From: Bart Schaefer @ 2004-09-15 15:43 UTC (permalink / raw)
  To: Peter Stephenson; +Cc: zsh-workers

On Wed, 15 Sep 2004, Peter Stephenson wrote:

> Hmm... the documentation for ignore_eof says:
> 
>   However, ten consecutive EOFs will cause the shell to exit anyway,
>   to avoid the shell hanging if its tty goes away.
> 
>   Also, if this option is set and the Zsh Line Editor is used, widgets
>   implemented by shell functions can be bound to EOF (normally
>   Control-D) without printing the normal warning message.  This works
>   only for normal widgets, not for completion widgets.
> 
> This implies there's not even an error message, which isn't right.

It implies that _widgets implemented by shell functions_ don't print an
error.  Which they don't -- try this:

 foo() { LBUFFER='Where is my error?' }
 zle -N foo
 setopt ignoreeof
 bindkey \^D foo
 <Ctrl-D>

The reason there's no error in that case is because of the way eofsent 
because of the test

    } else if((w = func->widget)->flags & (WIDGET_INT|WIDGET_NCOMP)) {

at approximately line 904 of zle_main.c.  User-defined widgets don't have
such flags (see the discussion about how maybe they should, as per auto-
suffix removal) so they can't possibly take that code branch.

> The error message implies it *is* being treated as EOF

No, it's not being treated as EOF.  It's being treated as a key bound to 
the EOF character (and not explicitly bound to anything else).  Because
it is bound to the EOF character, zsh assumes the user meant to send an
EOF and warns about why it didn't exit.  That has nothing whatsoever to
do with whether or not it exits after 10 of them.

> The documentation could imply that if you bound ^D to something other
> than the default, you wouldn't get the message, but there doesn't appear
> to be any support for that

See above.

> and I don't think it's useful.

I disagree.

See also the heavily-commented (for a change) code in getkey() at around 
line 617, where it explains about zle exiting on 20 consecutive (real) 
EOFs.


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: PATCH: exit after 10 EOF's
  2004-09-15 15:43     ` Bart Schaefer
@ 2004-09-15 16:02       ` Bart Schaefer
  2004-09-15 16:14         ` Peter Stephenson
  0 siblings, 1 reply; 22+ messages in thread
From: Bart Schaefer @ 2004-09-15 16:02 UTC (permalink / raw)
  To: zsh-workers

On Wed, 15 Sep 2004, Bart Schaefer wrote:

> No, it's not being treated as EOF.  It's being treated as a key bound to 
> the EOF character (and not explicitly bound to anything else).

I'll clarify that by noting that "explicitly bound" is important, as it's 
*implicitly* bound to delete-char-or-list.

> > and I don't think it's useful.
> 
> I disagree.

Here's an example of why.

  count-ctrl-D() { zle -M $((++ctrlD)) }
  zle -N count-ctrl-D
  bindkey \^D count-ctrl-D
  setopt ignoreeof

Now start typing ctrl-D at the beginning of an empty line.  With the patch 
you introduced, the shell will exit before displaying "10".  Without the 
patch, you can go on counting forever.

I haven't searched the archives, but I'm pretty sure someone (maybe me) 
made similar arguments the last time something about ignoreeof behavior
came up (which would have been several years ago).


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: PATCH: exit after 10 EOF's
  2004-09-15 16:02       ` Bart Schaefer
@ 2004-09-15 16:14         ` Peter Stephenson
  2004-09-16 14:57           ` Peter Stephenson
  0 siblings, 1 reply; 22+ messages in thread
From: Peter Stephenson @ 2004-09-15 16:14 UTC (permalink / raw)
  To: zsh-workers

Hmm, this is a nasty mess.  I still don't like the compromise.

I'd settle for removing the message and the count and documenting that
with ignore_eof set zle treats ^D like any other character.

-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
CSR Ltd., Science Park, Milton Road,
Cambridge, CB4 0WH, UK                          Tel: +44 (0)1223 692070


**********************************************************************
The information transmitted is intended only for the person or
entity to which it is addressed and may contain confidential 
and/or privileged material. 
Any review, retransmission, dissemination or other use of, or
taking of any action in reliance upon, this information by 
persons or entities other than the intended recipient is 
prohibited. 
If you received this in error, please contact the sender and 
delete the material from any computer.
**********************************************************************


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: PATCH: exit after 10 EOF's
  2004-09-15 16:14         ` Peter Stephenson
@ 2004-09-16 14:57           ` Peter Stephenson
  2004-09-16 16:12             ` Bart Schaefer
  0 siblings, 1 reply; 22+ messages in thread
From: Peter Stephenson @ 2004-09-16 14:57 UTC (permalink / raw)
  To: zsh-workers

Here is a simplification to replace the previous broken ignore_eof
behaviour (sometimes you get EOF after 10 ^D's and a message, sometimes
[in the editor] you get the same message but it doesn't exit and doesn't
call the bound widget, some [non-completion] widgets suppress the
message and work normally, some [completion] widgets don't suppress the
message and don't run...  I may have got some of that wrong, and I don't
particularly care.)  It backs off the previous patch which removed one
of the four behaviours but modified one of the others.

This should cover all bases.  The basic rule is that in ZLE ignore_eof
means the EOF character is always treated as a normal key.  If you want
any other behaviour you can use a widget.  I've supplied one which
should cover the most likely desired outcomes (though I suspect I've
made the documentation confusing).

I hope this makes fluffy bunnies gambol in the field.

If I commit it, I will remove the "#if 0" chunks properly.

Index: Doc/Zsh/contrib.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/contrib.yo,v
retrieving revision 1.36
diff -u -r1.36 contrib.yo
--- Doc/Zsh/contrib.yo	29 Jul 2004 14:22:21 -0000	1.36
+++ Doc/Zsh/contrib.yo	16 Sep 2004 14:43:20 -0000
@@ -561,6 +561,44 @@
 spots.  It can be invoked repeatedly to cycle between all positions
 reported by the completion system.
 )
+tindex(delete-char-or-list replacement)
+item(tt(delete-char-or-list))(
+This is a drop-in replacement for the builtin zle widget of the same name.
+The only difference appears when it is executed on an empty line;
+otherwise, it is indistinguishable from tt(delete-char-or-list).  It
+mimics the use of the default binding tt(\C-d) as an end-of-file character,
+but in a more configurable way.
+
+Assuming the binding is to the configured end-of-file character, the
+function is only useful if the option tt(IGNORE_EOF) is set; otherwise
+the shell will exit before the widget is called.  However, it is
+possible to disable the character with `tt(stty eof "^-")'.  In that case,
+the option tt(IGNORE_EOF) is respected.
+
+If tt(IGNORE_EOF) is set, or the style tt(ignore-eof-count) is set to an
+integer, the function prints a message and does not exit the shell.  If
+neither is set, the function exits the shell.
+
+If the style tt(ignore-eof-count) is set to an integer greater than zero,
+this gives a count of times the widget must be executed consecutively
+before the shell will be executed.
+
+The message to be printed may be customized by setting the style
+tt(ignore-eof-msg) for the context tt(:zle:)var(widget).  The value may
+contain tt(%s), which will be replaced by tt(logout) for a login shell,
+otherwise tt(exit); tt(%m), which will be replaced by the value of
+tt(ignore-eof-count); and tt(%c), which will be replaced by the count of
+consecutive times the widget has been executed.  The default message
+is `tt(zsh: use '%s' to %s.)'.
+
+The name of the widget is significant as this widget tries to invoke
+tt(.)var(widget) to implement the standard (non-EOF) behavior.  Hence this
+widget may be used to replace other bindings for tt(\C-d) (or, indeed, any
+other key used as an end-of-file character).
+
+The styles are looked up in the context tt(:zle:)var(widget), where
+var(widget) is the name of the widget.
+)
 tindex(edit-command-line)
 item(tt(edit-command-line))(
 Edit the command line using your visual editor, as in tt(ksh).
Index: Doc/Zsh/options.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/options.yo,v
retrieving revision 1.35
diff -u -r1.35 options.yo
--- Doc/Zsh/options.yo	3 Sep 2004 09:47:48 -0000	1.35
+++ Doc/Zsh/options.yo	16 Sep 2004 14:43:21 -0000
@@ -698,13 +698,16 @@
 item(tt(IGNORE_EOF) (tt(-7)))(
 Do not exit on end-of-file.  Require the use
 of tt(exit) or tt(logout) instead.
-However, ten consecutive EOFs will cause the shell to exit anyway,
+However, unless the Zsh Line Editor is active,
+ten consecutive EOFs will cause the shell to exit anyway,
 to avoid the shell hanging if its tty goes away.
 
-Also, if this option is set and the Zsh Line Editor is used, widgets
-implemented by shell functions can be bound to EOF (normally
-Control-D) without printing the normal warning message.  This works
-only for normal widgets, not for completion widgets.
+In the line editor, if the option is set end-of-file characters are
+always handled as ordinary characters.  (The line editor detects
+genuine end-of-file conditions separately.)  It is possible to implement
+a widget to handle this is some other way.  See
+the example widget tt(delete-char-or-list) in ifzman(zmanref(zshcontrib))\
+ifnzman(noderef(ZLE Functions))
 )
 pindex(INTERACTIVE_COMMENTS)
 cindex(comments, in interactive shells)
Index: Functions/Zle/delete-char-or-list
===================================================================
RCS file: Functions/Zle/delete-char-or-list
diff -N Functions/Zle/delete-char-or-list
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Functions/Zle/delete-char-or-list	16 Sep 2004 14:43:21 -0000
@@ -0,0 +1,39 @@
+# A drop-in replacement for delete-char-or-list with a more
+# configurable ignore-eof behaviour.  See zshcontrib.
+
+if [[ -z $BUFFER ]]; then
+  integer eofmax ignoreeof
+  if zstyle -s ":zle:$WIDGET" ignore-eof-count eofmax; then
+    ignoreeof=1
+  else
+    [[ -o ignore_eof ]] && ignoreof=1
+  fi
+  if [[ -n $ignoreeof ]]; then
+    integer -g __eof_count
+
+    if [[ eofmax -le 0 ]]; then
+      __eof_count=0
+    elif [[ $LASTWIDGET = $WIDGET ]]; then
+      if (( ++__eof_count == eofmax )); then
+	exit
+      fi
+    else
+      __eof_count=1
+    fi
+
+    zmodload -i zsh/zutil
+
+    local fmt msg what=exit
+    zstyle -s ":zle:$WIDGET" ignore-eof-msg fmt ||
+    fmt="zsh: use '%s' to %s."
+    [[ -o login ]] && what=logout
+    zformat -f msg $fmt s:$what m:$eofmax c:$__eof_count
+    zle -M $msg
+
+    return 1
+  else
+    exit
+  fi
+fi
+
+zle .$WIDGET
Index: Src/builtin.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/builtin.c,v
retrieving revision 1.126
diff -u -r1.126 builtin.c
--- Src/builtin.c	9 Sep 2004 10:12:47 -0000	1.126
+++ Src/builtin.c	16 Sep 2004 14:43:23 -0000
@@ -3976,7 +3976,7 @@
 
 /* Flag that we should exit the shell as soon as all functions return. */
 /**/
-int
+mod_export int
 exit_pending;
 
 /* break, bye, continue, exit, logout, return -- most of these take   *
Index: Src/init.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/init.c,v
retrieving revision 1.43
diff -u -r1.43 init.c
--- Src/init.c	13 Sep 2004 13:04:55 -0000	1.43
+++ Src/init.c	16 Sep 2004 14:43:24 -0000
@@ -37,7 +37,7 @@
 #include "version.h"
 
 /**/
-mod_export int noexitct = 0;
+int noexitct = 0;
 
 /* buffer for $_ and its length */
 
Index: Src/Zle/zle_main.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_main.c,v
retrieving revision 1.51
diff -u -r1.51 zle_main.c
--- Src/Zle/zle_main.c	13 Sep 2004 13:04:55 -0000	1.51
+++ Src/Zle/zle_main.c	16 Sep 2004 14:43:25 -0000
@@ -680,7 +680,13 @@
     FD_ZERO(&foofd);
 #endif
 
-    while (!done && !errflag) {
+    /*
+     * A widget function may decide to exit the shell.
+     * We never exit directly from functions, to allow
+     * the shell to tidy up, so we have to test for
+     * that explicitly.
+     */
+    while (!done && !errflag && !exit_pending) {
 
 	statusline = NULL;
 	vilinerange = 0;
@@ -688,27 +694,17 @@
 	selectlocalmap(NULL);
 	bindk = getkeycmd();
 	if (bindk) {
-	    if (!ll && isfirstln && lastchar == eofchar) {
+	    if (!ll && isfirstln && !(zlereadflags & ZLRF_IGNOREEOF) &&
+		lastchar == eofchar) {
 		/*
 		 * Slight hack: this relies on getkeycmd returning
 		 * a value for the EOF character.  However,
 		 * undefined-key is fine.  That's necessary because
 		 * otherwise we can't distinguish this case from
 		 * a ^C.
-		 *
-		 * The noxitct test is done in the top-level loop
-		 * if zle is not running.  As we trap EOFs at this
-		 * level inside zle we need to mimic it here.
-		 * If we break, the top-level loop will actually increment
-		 * noexitct an extra time; that doesn't cause any
-		 * problems.
 		 */
-		if (!(zlereadflags & ZLRF_IGNOREEOF) ||
-		    ++noexitct >= 10)
-		{
-		    eofsent = 1;
-		    break;
-		}
+		eofsent = 1;
+		break;
 	    }
 	    if (execzlefunc(bindk, zlenoargs))
 		handlefeep(zlenoargs);
@@ -904,12 +900,14 @@
     } else if((w = func->widget)->flags & (WIDGET_INT|WIDGET_NCOMP)) {
 	int wflags = w->flags;
 
+#if 0
 	if (keybuf[0] == eofchar && !keybuf[1] &&
 	    !ll && isfirstln && (zlereadflags & ZLRF_IGNOREEOF)) {
 	    showmsg((!islogin) ? "zsh: use 'exit' to exit." :
 		    "zsh: use 'logout' to logout.");
 	    ret = 1;
 	} else {
+#endif
 	    if(!(wflags & ZLE_KEEPSUFFIX))
 		removesuffix();
 	    if(!(wflags & ZLE_MENUCMP)) {
@@ -933,7 +931,9 @@
 	    }
 	    if (!(wflags & ZLE_NOTCOMMAND))
 		lastcmd = wflags;
+#if 0
 	}
+#endif
 	r = 1;
     } else {
 	Shfunc shf = (Shfunc) shfunctab->getnode(shfunctab, w->u.fnnam);


-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
CSR Ltd., Science Park, Milton Road,
Cambridge, CB4 0WH, UK                          Tel: +44 (0)1223 692070


**********************************************************************
This email and any files transmitted with it are confidential and
intended solely for the use of the individual or entity to whom they
are addressed. If you have received this email in error please notify
the system manager.

This footnote also confirms that this email message has been swept by
MIMEsweeper for the presence of computer viruses.

www.mimesweeper.com
**********************************************************************


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: PATCH: exit after 10 EOF's
  2004-09-16 14:57           ` Peter Stephenson
@ 2004-09-16 16:12             ` Bart Schaefer
  2004-09-16 16:28               ` Peter Stephenson
  0 siblings, 1 reply; 22+ messages in thread
From: Bart Schaefer @ 2004-09-16 16:12 UTC (permalink / raw)
  To: Peter Stephenson; +Cc: zsh-workers

On Thu, 16 Sep 2004, Peter Stephenson wrote:

> This should cover all bases.  The basic rule is that in ZLE ignore_eof
> means the EOF character is always treated as a normal key.

> I hope this makes fluffy bunnies gambol in the field.

Sorry, my bunnies are not gamboling, they're sharpening pitchforks and 
looking for torches.  This is a backwards-incompatible change, and I 
object to it.  The default behavior of ZLE on receiving an EOF character 
is supposed to be identical to the default behavior of 4.3BSD csh upon 
receiving an EOF character.  That is, either exit (when not ignoreeof) or 
print a warning (when ignoreeof) if the character is received at the start 
of an empty buffer.

Note that you CANNOT handle this with widgets, because "stty eof" is not
dependent on widget bindings.  The above behavior has to occur on receipt
of the tty eof character, even if that has been changed, without changing
(or requiring the user to change) the underlying keybindings.

> If you want any other behaviour you can use a widget.

No, you can't, see above.


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: PATCH: exit after 10 EOF's
  2004-09-16 16:12             ` Bart Schaefer
@ 2004-09-16 16:28               ` Peter Stephenson
  0 siblings, 0 replies; 22+ messages in thread
From: Peter Stephenson @ 2004-09-16 16:28 UTC (permalink / raw)
  To: zsh-workers

Bart Schaefer wrote:
> This is a backwards-incompatible change, and I 
> object to it.  The default behavior of ZLE on receiving an EOF character 
> is supposed to be identical to the default behavior of 4.3BSD csh upon 
> receiving an EOF character.  That is, either exit (when not ignoreeof) or 
> print a warning (when ignoreeof) if the character is received at the start 
> of an empty buffer.

Well, hence the exit after 10 characters, which was what made the
behaviour actually compatible... I still consider the behaviour before
my previous patch confusing well past the point of unusability.

I'm prepared to consider another option, such as zle_ignore_eof (meaning
that ignore_eof really did what csh used to, and zle_ignore_eof would be
my current proposal, or something such), or anything other than what was
there just before...

-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
CSR Ltd., Science Park, Milton Road,
Cambridge, CB4 0WH, UK                          Tel: +44 (0)1223 692070


**********************************************************************
This email and any files transmitted with it are confidential and
intended solely for the use of the individual or entity to whom they
are addressed. If you have received this email in error please notify
the system manager.

This footnote also confirms that this email message has been swept by
MIMEsweeper for the presence of computer viruses.

www.mimesweeper.com
**********************************************************************


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: PATCH: exit after 10 EOF's
  2004-09-13 11:18 PATCH: exit after 10 EOF's Peter Stephenson
  2004-09-13 17:51 ` Bart Schaefer
@ 2004-09-19  6:50 ` Bart Schaefer
  2004-09-19  7:45   ` Duncan Sinclair
  2004-09-19 11:53   ` Peter Stephenson
  1 sibling, 2 replies; 22+ messages in thread
From: Bart Schaefer @ 2004-09-19  6:50 UTC (permalink / raw)
  To: Zsh hackers list

On Mon, 13 Sep 2004, Peter Stephenson wrote:

> This ought to be part of the test suite, but with zle it needs zpty and 
> I don't understand the tests with zpty.

I meant to reply to this before and got distracted by later developments
in the thread.

The idea behind the zpty-based tests isn't much different from the way the 
"nslookup" wrapper function is implemented.  You start a shell as pristine 
as possible on the pty; initialize it by feeding it some commands to set 
the environment, and to change the prompts to something distinctive so 
that it can be recognized later; and then start alternately scanning for
your special prompt and sending more commands, checking to see that the 
stuff that gets output between prompts is what you expected.

The completion tests use the same idea but in a considerably more complex 
manner, e.g., arranging to have every item in a completion listing emit 
markers before and after each actual list entry, so that all the entries
can be parsed out and verified.

On Thu, 16 Sep 2004, Peter Stephenson wrote:
> 
> [...] the previous broken ignore_eof behaviour (sometimes you get EOF 
> after 10 ^D's and a message, sometimes [in the editor] you get the same 
> message but it doesn't exit and doesn't call the bound widget, some 
> [non-completion] widgets suppress the message and work normally, some 
> [completion] widgets don't suppress the message and don't run...  I may 
> have got some of that wrong, and I don't particularly care.)

I'm going to try to get it right anyway, because unless we know what it 
does we don't know what to "fix."  (I confess to slight bafflement over 
why this suddenly needs to be changed, when it has been the way it is for 
at least five and possibly as many as ten years without causing any flood 
of complaints, but ...)  So here I go.  This is divided into two parts, 
"HOW THE WORLD GOT THIS WAY" and "THE WAY OF THE WORLD WE GOT".  You can 
search forward for the second part if you'd prefer to avoid a historical 
reenactment.

Part One: HOW THE WORLD GOT THIS WAY

There are two base cases, which ultimately resolve to: (1) it is possible 
to differentiate the typing of the TTY driver EOF character from the true 
closing of the TTY file descriptor, and (2) it's not possible.  It turns 
out that (1) occurs only when ZLE is active and (2) occurs only when ZLE 
is not active.

Now, a detour into history.  I wasn't actually at University of California
Berkeley during the three years or so when the following would have taken
place, but I've seen the csh source code and was puttering around USENET 
at the time, encountering writings from the personalities involved, so I 
think this is a fair approximation of reality.

When csh introduced completion, there was no such thing as a line editor.  
The TTY driver was all there was.  So the writers of csh hijacked some of 
the TTY driver behaviors and abused them to implement completion.  One of 
the behaviors they hijacked is that it's possible to partly fill the 
driver input buffer, then type the EOF character to force that buffer to 
be flushed (written to the shell).  The shell would see some characters of 
input followed by an EOF (but without a newline), interpret that as a 
request for a completion listing, output one, and then go back to reading 
from the TTY.  If the TTY descriptor was not closed -- i.e., if the driver 
was only "pretending" it had been closed, because of the EOF character -- 
then the new read would block, awaiting more input from the user.  Bunnies
were gamboling.

However, some characters of input followed by an EOF is also what the 
shell would see in the event that the TTY descriptor really was closed.  
So the csh authors had a dilemma -- they had to come up with a heuristic 
to "guess" when an EOF really was an EOF, despite lack of direct evidence 
one way or another.  So the first heuristic they tried was "an EOF on an 
empty buffer is a real EOF."  All well and good, except that users got 
used to typing the EOF character for completion listings and would 
sometimes accidentally do so when the buffer was empty, and got really 
upset when this logged them off (this was before windowing systems, too). 
So the csh authors introduced "set ignoreeof", but then they needed a new 
heuristic to stop the shell from going into an infinite loop when the TTY 
line dropped.  So they picked "10 EOFs in a row is a real EOF."  Nobody 
who set ignoreeof ever really hammered the EOF key 10 times, as a way to 
exit the shell or otherwise, so the bunnies gamboled some more.

Unfortunately, some sysadmins put "set ignoreeof" in /etc/cshrc, and a few 
power users who _never_ made the mistake of typing EOF in an empty buffer, 
except when they wanted to log off, got confused when their shell would 
not exit.  Nobody can bully a shell author like an annoyed power user 
(recall those bunnies with pitchforks), so a warning message was added to 
explain that the shell really had seen the EOF, it just wasn't paying any 
attention to it.  The power users would mutter under their breath about 
sysadmins catering to newbie lusers and fix their own ~/.cshrc to unset 
ignoreeof, and then go quietly back to typing the EOF character when they 
wanted to exit from the shell.  The bunnies didn't exactly gambol, but
the didn't storm the castle.

Now we return to the present day.  Keep in mind, though, that an EOF, 
whether from a "pretending" TTY driver or from a real closed descriptor, 
is a read() that returns zero bytes.  Nothing.  Nada.  It's not a 
keystroke, so in spite of the perception of the user that he pressed some 
keys, the shell can't use what it read to look up a keybinding.

There is, in addition to the aforementioned two base cases, an assumption 
that the _default_ behavior of the shell upon receipt of a TTY driver EOF 
character should be the same whether or not ZLE is active.  Nearly all the 
early users of zsh were converting from csh, so both the default behavior 
and the heuristic for telling when an EOF really is an EOF were copied 
from csh.  Except that zsh can, when ZLE is active, do something that csh 
never could: really know when it has an EOF _character_ as opposed to a 
closed descriptor.  Exactly what zsh can do with this knowledge is limited
in two ways:

a. In any situation where csh would have read zero bytes, zsh has to 
behave (by _default_ only; not necessarily after it's been reconfigured) 
as if it read zero bytes.  That means no widgets are called on the EOF 
character unless csh would have treated it as a completion request.

b. In any situation where csh would have printed a warning, zsh has to
print a warning.  This applies only when ignoreeof is set, so for the
following discussion I'll subdivide base cases 1 and 2 into 1, 1i, 2, and
2i, where the "i" designates ignoreeof being set.

However, because no one ever intended for 10 consecutive EOF _characters_ 
to be treated as a real EOF -- rather, they intended 10 consecutive zero- 
byte reads to be treated as _not_ an EOF character, and nobody ever typed 
10 EOF characters on purpose -- zsh does _not_ have to play dumb and exit
on 10 EOF characters.

Another historical detour:  At about the same time this decision was put 
into effect, somebody introduced a terminal emulator bug (probably having 
to do with switching from BSD descriptor handling to STREAMS) such that on 
at least one popular operating system, zsh could not tell whether a zero- 
byte read meant the terminal window had been closed.  So the old heuristic 
was revived, although at a different place in the code, and with a larger 
count (for no good reason that I recall), to prevent an infinite loop when 
such a terminal emulator was, in fact, closed.  However, this has nothing
to do with how zsh behaves on normal input, so we can set it aside.

So we now have cases 1, 1i, 2, and 2i, and we further subdivide those into 
two more categories: (A) default behavior, and (B) behavior after zsh has 
been reconfigured.  However, zsh can't be reconfigured in any way that is 
interesting for terminal input when ZLE is not active, so cases 1A and 1B 
collapse to the same, as do 1Ai and 1Bi.  Leaving us with cases:

(1) Zsh must silently exit on a zero-byte read.

(1i) Zsh must print a warning on a zero-byte read, and must exit after 10 
     zero-byte reads.

(2A) ZLE must cause zsh to silently exit on reading the EOF character in 
     an empty buffer or upon a true EOF.

(2Ai) ZLE must print a warning on reading the EOF character in an empty 
      buffer.  It may not call any widget instead or as well.  It must 
      cause zsh to silently exit on a true EOF.

(2B) ZLE need not cause zsh to exit on reading the EOF character, and may 
     call a widget.  It must cause zsh to silently exit on a true EOF.

(2Bi) ZLE need not print a warning on the EOF character, and may call a 
      widget.  It must cause zsh to silently exit on a true EOF.

This brings us at last to the crucial bits:  How does zsh know when it has 
been reconfigured, and what reconfigurations change the behavior?

Part Two: THE WAY OF THE WORLD WE GOT

The choice was made to assume that:

- zsh has been reconfigured if the keystroke that corresponds to the EOF 
character is bound to a widget that is not an internal widget;

- the behavior should only change if in fact the aforementioned not- 
internal widget is also not a completion widget, because replacing "old" 
completion with "new" completion should be otherwise transparent.

Hence the following should, presently, be true statements:

* Zsh exits on 10 EOF characters only when ZLE is not active, and only 
  because 10 EOF characters are indistinguishable from 10 zero-byte reads,
  which is what really causes it to exit.

* When the binding for the key corresponding to the EOF character is a
  binding to _any_ internal widget, pressing the EOF character in an empty
  buffer _either_ exits _or_ prints a warning, and does _not_ call that
  widget.

* When the binding for the key corresponding to the EOF character is a
  binding to _any_ completion widget, pressing the EOF character in an 
  empty buffer _either_ exits _or_ prints a warning, and does _not_ call 
  the widget.  (This happens to overlap with the foregoing statement for 
  internal completion widgets.)

* When the binding for the key corresponding to the EOF character is any
  _other_ widget, the EOF character _either_ exits _or_ calls the widget
  (which implies not printing the warning).  "Other" happens at this time
  to be limited to widgets created with "zle -N".

* In each "either" choice above, the setting of the ignoreeof option is
  used to determine whether to exit (option unset) or to do whatever it
  is that happens when the shell does not exit (option set).

One could argue, then, that a better name for the option would have been 
"no_exit_on_tty_eof_character" -- but historical precedent was "ignoreeof" 
and, prior to this thread, nobody ever expressed serious concern over the 
naming inaccuracy.

In any case, if you can find a situation that violates any of those five
statements, I'd agree that said situation is a bug.

Returning to your excerpt far above, you appear to object to the fact that 
the conditions of "not internal" and "not completion" are simultaneously 
required in order for a widget binding to override the default behavior of 
setopt ignoreeof.  Is that an accurate summation?

You also feel that there shouldn't be a distinction on the behavior of 10 
EOF characters, but my assertion is that 10 EOF characters was never 
intended to have any semantics of its own and shouldn't be given any now.
It's nothing but an unfortunate side-effect, and one that ZLE correctly
avoided before, which is why I think 20363 should be backed out.

On Thu, 16 Sep 2004, Peter Stephenson wrote:
> 
> I'm prepared to consider another option, such as zle_ignore_eof (meaning
> that ignore_eof really did what csh used to, and zle_ignore_eof would be
> my current proposal, or something such), or anything other than what was
> there just before...

Given all that I just explained, do you still feel that we have arrived in
a bad place?  Every decision along the way was made for a clear reason, at
the time.  Do you still think that bifurcating yet _again_, with another
option, would truly improve matters?

My own preference would be that we _do_ have exactly what was there just 
before, except perhaps to include in the documentation some (hopefully 
small) portion of what I have exposited in this message, in order that we
don't ever have to go through this again.

Whew.  Bunnies look around uncertainly, wondering if it's OK to gambol.


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: PATCH: exit after 10 EOF's
  2004-09-19  6:50 ` Bart Schaefer
@ 2004-09-19  7:45   ` Duncan Sinclair
  2004-09-19 16:41     ` Bart Schaefer
  2004-09-19 11:53   ` Peter Stephenson
  1 sibling, 1 reply; 22+ messages in thread
From: Duncan Sinclair @ 2004-09-19  7:45 UTC (permalink / raw)
  To: zsh-workers

Hi Guys,

My own feelings are that this...

> However, because no one ever intended for 10 consecutive EOF 
> _characters_
> to be treated as a real EOF -- rather, they intended 10 consecutive 
> zero-
> byte reads to be treated as _not_ an EOF character, and nobody ever 
> typed
> 10 EOF characters on purpose -- zsh does _not_ have to play dumb and 
> exit
> on 10 EOF characters.

... while it may have been historically true, isn't any more.  I quite 
often have to use a shared account where the shell is set to tcsh, and 
ignoreeof is turned on.  It annoys me greatly, but as it is a shared 
account I have limited power to change things.  I have held down 
control-D on purpose and watched a whole stream of warnings scroll up 
the screen rather than give in and type "exit" or "logout" - tcsh 
eventually gets the message and exits.

This is why I feel that Peter's patch isn't a bad thing.  As for 
default vs configured behaviour wrt widgets and such, I'd agree that if 
you've set ignoreeof and you've got a special binding on <whatever EOF 
is set to>, then you probably want to be able to hit it 10 times in a 
row without the shell exiting.

But in the absence of any special binding I don't see what's wrong with 
giving in and exiting after <some number> of the standard ignoreeof 
warnings have been printed.

I believe that tcsh (30 warnings?), bash (10) and ksh (10) all do this, 
and they all have the same ability to detect an EOF character 
separately from an EOF condition.

Cheers,


Duncan.



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: PATCH: exit after 10 EOF's
  2004-09-19  6:50 ` Bart Schaefer
  2004-09-19  7:45   ` Duncan Sinclair
@ 2004-09-19 11:53   ` Peter Stephenson
  2004-09-19 17:00     ` Bart Schaefer
  1 sibling, 1 reply; 22+ messages in thread
From: Peter Stephenson @ 2004-09-19 11:53 UTC (permalink / raw)
  To: zsh-workers

Bart Schaefer wrote:
>... a lot ...

Thanks for the long explanation.  The reason I started suggesting a
change now is that I didn't realise how confused the implementation was.

I think the key bits that need discussing are...

> Returning to your excerpt far above, you appear to object to the fact that 
> the conditions of "not internal" and "not completion" are simultaneously 
> required in order for a widget binding to override the default behavior of 
> setopt ignoreeof.  Is that an accurate summation?

Yes, particularly since even calling a builtin widget from a zle -N
widget doesn't override the behaviour.  I have for a long time had a
widget which calls delete-char-or-list and is bound as a replacement to
^D and you still get the message.  Consequently, for most zsh users,
the additional feature is nothing more than a confusion.  I would have
thought an explicit option to make it so ('so' means that either you
have 'standard' ignore_eof behaviour in zle, or you have no special response
to the EOF character at all) would be an advantage.

My guess is that because of this problem very few people are relying on
(nor possibly even aware of, despite the documentation) the
suppress-message behaviour of widget binding, so the inconvenience is
minimal.

> You also feel that there shouldn't be a distinction on the behavior of 10 
> EOF characters, but my assertion is that 10 EOF characters was never 
> intended to have any semantics of its own and shouldn't be given any now.
> It's nothing but an unfortunate side-effect, and one that ZLE correctly
> avoided before, which is why I think 20363 should be backed out.

I have absolutely no disagreement with your detailed technical
description.

My feeling, however, is that to most users who've heard of it "shell
exits after 10 EOFs" is part of the feature.  I don't want shell users to
have to know about the distinction between canonical input and what the
line editor does.  I want it just to work.  It seems to me consistency
in the user interface is considerably preferable to a low-level
technical consistency that users won't notice.

Indeed, although this isn't an important point, we're not strictly being
technically consistent, since as you say the character isn't a real EOF
in zle anyway, so printing a message as if it was is already a confusion.

(I have been known in the past to hit ^Ds until the shell exits, but
probably I'm weird.  Obviously I haven't done it in zsh for a long time.)

I would be delighted if there was a strong body of opinion one way or
the other to resolve the issue.  Maybe some prodding on zsh-users is
appropriate.

I find it unfortunate that the message in zle (when it isn't going to
exit) is the same as from the base shell (when it eventually will).  If
there's no enthusiasm for a new option, maybe simply fixing the message
to indicate the shell isn't going to exit is useful.

-- 
Peter Stephenson <pws@pwstephenson.fsnet.co.uk>
Work: pws@csr.com
Web: http://www.pwstephenson.fsnet.co.uk


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: PATCH: exit after 10 EOF's
  2004-09-19  7:45   ` Duncan Sinclair
@ 2004-09-19 16:41     ` Bart Schaefer
  2004-09-19 17:52       ` Peter Stephenson
  0 siblings, 1 reply; 22+ messages in thread
From: Bart Schaefer @ 2004-09-19 16:41 UTC (permalink / raw)
  To: zsh-workers

On Sun, 19 Sep 2004, Duncan Sinclair wrote:

> But in the absence of any special binding I don't see what's wrong with 
> giving in and exiting after <some number> of the standard ignoreeof 
> warnings have been printed.

You may have hit on the solution.  Rather than counting the number of EOF 
key presses, count the number of warnings printed.  Thus suppressing the 
warning is the same as suppressing the exit behavior (which is not true of 
the code as patched by 20363).  I'd settle for that, I think.


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: PATCH: exit after 10 EOF's
  2004-09-19 11:53   ` Peter Stephenson
@ 2004-09-19 17:00     ` Bart Schaefer
  0 siblings, 0 replies; 22+ messages in thread
From: Bart Schaefer @ 2004-09-19 17:00 UTC (permalink / raw)
  To: zsh-workers

On Sun, 19 Sep 2004, Peter Stephenson wrote:

> I think the key bits that need discussing are...
> 
> > Returning to your excerpt far above, you appear to object to the fact that 
> > the conditions of "not internal" and "not completion" are simultaneously 
> > required in order for a widget binding to override the default behavior of 
> > setopt ignoreeof.  Is that an accurate summation?
> 
> Yes, particularly since even calling a builtin widget from a zle -N
> widget doesn't override the behaviour.

That actually has to do with the implementation of "zle name-of-widget". 
It passes back through the code that tests for whether to emit the warning 
(though not back through the code that exits).  I suppose one could argue 
that this is also intentional, so that one can create transparent wrappers 
around internal widgets, but in this case I doubt anyone thought that far
ahead.

Of course there _is_ a workaround:  "setopt localoptions noignoreeof" in 
widgets that use "zle name-of-widget".  However, I agree this is not the 
ideal solution.

> My guess is that because of this problem very few people are relying on 
> (nor possibly even aware of, despite the documentation) the suppress- 
> message behaviour of widget binding, so the inconvenience is minimal.

I don't disagree -- in fact, I think it's more likely that people are
unknowingly relying on the unintentional transparency behavior.  Certainly
a lot of people are unknowingly relying on the "not a completion widget"
behavior.  Either way, though, it makes changing it problematic.

I'm going to drop the discussion of "10 EOF characters" at this point 
because I'm increasingly of the opinion that counting 10 warnings instead 
is an agreeable solution, leaving us only with the question of how best to 
allow suppression of the warning.


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: PATCH: exit after 10 EOF's
  2004-09-19 16:41     ` Bart Schaefer
@ 2004-09-19 17:52       ` Peter Stephenson
  2004-09-19 18:26         ` Bart Schaefer
  2004-09-19 19:11         ` Bart Schaefer
  0 siblings, 2 replies; 22+ messages in thread
From: Peter Stephenson @ 2004-09-19 17:52 UTC (permalink / raw)
  To: zsh-workers

Bart Schaefer wrote:
> On Sun, 19 Sep 2004, Duncan Sinclair wrote:
> 
> > But in the absence of any special binding I don't see what's wrong with 
> > giving in and exiting after <some number> of the standard ignoreeof 
> > warnings have been printed.
> 
> You may have hit on the solution.  Rather than counting the number of EOF 
> key presses, count the number of warnings printed.  Thus suppressing the 
> warning is the same as suppressing the exit behavior (which is not true of 
> the code as patched by 20363).  I'd settle for that, I think.

Yes, that sounds OK.  If we could somehow make it (without too much
tortuous code) that any zle -N widget, no matter what it contains,
suppresses the warning and the EOF behaviour, I would be fairly happy.

My main remaining unhappiness is with the structure of the code, which
is why the message and the exiting are separate as patched; the same
test occurs in two places (not counting the main loop in the main
shell).  However, maybe that can be fixed, too.

pws


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: PATCH: exit after 10 EOF's
  2004-09-19 17:52       ` Peter Stephenson
@ 2004-09-19 18:26         ` Bart Schaefer
  2004-09-19 19:25           ` Bart Schaefer
  2004-09-19 19:11         ` Bart Schaefer
  1 sibling, 1 reply; 22+ messages in thread
From: Bart Schaefer @ 2004-09-19 18:26 UTC (permalink / raw)
  To: zsh-workers

On Sun, 19 Sep 2004, Peter Stephenson wrote:

> Bart Schaefer wrote:
> > 
> > You may have hit on the solution.  Rather than counting the number of EOF 
> > key presses, count the number of warnings printed.
> 
> Yes, that sounds OK.  If we could somehow make it (without too much
> tortuous code) that any zle -N widget, no matter what it contains,
> suppresses the warning and the EOF behaviour, I would be fairly happy.

I haven't gotten to the latter part yet, but here's a patch that (a) backs 
out 20363 and (b) causes the count to apply to printing of the warning. 
The actual implementation is that, with ignoreeof set, ZLE pretends it 
received an EOF only when it also prints a warning about it.  The counter 
in the toplevel loop then suffices and we don't have to count warnings.

> My main remaining unhappiness is with the structure of the code, which
> is why the message and the exiting are separate as patched; the same
> test occurs in two places (not counting the main loop in the main
> shell).  However, maybe that can be fixed, too.

Well, sort of.  See what you think.

Index: Src/init.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/init.c,v
retrieving revision 1.43
diff -u -r1.43 init.c
--- Src/init.c	13 Sep 2004 13:04:55 -0000	1.43
+++ Src/init.c	19 Sep 2004 18:24:52 -0000
@@ -37,7 +37,7 @@
 #include "version.h"
 
 /**/
-mod_export int noexitct = 0;
+int noexitct = 0;
 
 /* buffer for $_ and its length */
 
Index: Src/Zle/zle_main.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_main.c,v
retrieving revision 1.51
diff -u -r1.51 zle_main.c
--- Src/Zle/zle_main.c	13 Sep 2004 13:04:55 -0000	1.51
+++ Src/Zle/zle_main.c	19 Sep 2004 18:24:52 -0000
@@ -688,30 +688,23 @@
 	selectlocalmap(NULL);
 	bindk = getkeycmd();
 	if (bindk) {
-	    if (!ll && isfirstln && lastchar == eofchar) {
+	    if (!ll && isfirstln && !(zlereadflags & ZLRF_IGNOREEOF) &&
+		lastchar == eofchar) {
 		/*
 		 * Slight hack: this relies on getkeycmd returning
 		 * a value for the EOF character.  However,
 		 * undefined-key is fine.  That's necessary because
 		 * otherwise we can't distinguish this case from
 		 * a ^C.
-		 *
-		 * The noxitct test is done in the top-level loop
-		 * if zle is not running.  As we trap EOFs at this
-		 * level inside zle we need to mimic it here.
-		 * If we break, the top-level loop will actually increment
-		 * noexitct an extra time; that doesn't cause any
-		 * problems.
 		 */
-		if (!(zlereadflags & ZLRF_IGNOREEOF) ||
-		    ++noexitct >= 10)
-		{
-		    eofsent = 1;
-		    break;
-		}
+		eofsent = 1;
+		break;
 	    }
-	    if (execzlefunc(bindk, zlenoargs))
+	    if (execzlefunc(bindk, zlenoargs)) {
 		handlefeep(zlenoargs);
+		if (eofsent)
+		    break;
+	    }
 	    handleprefixes();
 	    /* for vi mode, make sure the cursor isn't somewhere illegal */
 	    if (invicmdmode() && cs > findbol() &&
@@ -908,6 +901,7 @@
 	    !ll && isfirstln && (zlereadflags & ZLRF_IGNOREEOF)) {
 	    showmsg((!islogin) ? "zsh: use 'exit' to exit." :
 		    "zsh: use 'logout' to logout.");
+	    eofsent = 1;
 	    ret = 1;
 	} else {
 	    if(!(wflags & ZLE_KEEPSUFFIX))


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: PATCH: exit after 10 EOF's
  2004-09-19 17:52       ` Peter Stephenson
  2004-09-19 18:26         ` Bart Schaefer
@ 2004-09-19 19:11         ` Bart Schaefer
  1 sibling, 0 replies; 22+ messages in thread
From: Bart Schaefer @ 2004-09-19 19:11 UTC (permalink / raw)
  To: zsh-workers

On Sun, 19 Sep 2004, Peter Stephenson wrote:

> If we could somehow make it (without too much tortuous code) that any 
> zle -N widget, no matter what it contains, suppresses the warning and 
> the EOF behaviour, I would be fairly happy.

Here's the hunk for that.  Line numbers are off because I haven't 
committed 20387 yet, so this is not directly applicable via "patch".

@@ -887,10 +897,17 @@
     } else if((w = func->widget)->flags & (WIDGET_INT|WIDGET_NCOMP)) {
 	int wflags = w->flags;
 
-	if (keybuf[0] == eofchar && !keybuf[1] &&
+	/*
+	 * The rule is that "zle -N" widgets suppress EOF warnings.  When
+	 * a "zle -N" widget invokes "zle another-widget" we pass through
+	 * this code again, but with actual arguments rather than with the
+	 * zlenoargs placeholder.
+	 */
+	if (keybuf[0] == eofchar && !keybuf[1] && args == zlenoargs &&
 	    !ll && isfirstln && (zlereadflags & ZLRF_IGNOREEOF)) {
 	    showmsg((!islogin) ? "zsh: use 'exit' to exit." :
 		    "zsh: use 'logout' to logout.");


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: PATCH: exit after 10 EOF's
  2004-09-19 18:26         ` Bart Schaefer
@ 2004-09-19 19:25           ` Bart Schaefer
  2004-09-20 10:15             ` Peter Stephenson
  2004-09-20 13:59             ` Peter Stephenson
  0 siblings, 2 replies; 22+ messages in thread
From: Bart Schaefer @ 2004-09-19 19:25 UTC (permalink / raw)
  To: zsh-workers

On Sun, 19 Sep 2004, Bart Schaefer wrote:

> I haven't gotten to the latter part yet, but here's a patch that (a) backs 
> out 20363 and (b) causes the count to apply to printing of the warning.

Actually I just noticed that it doesn't _completely_ back out 20363.  This
part of 20363 is still there:

 	bindk = getkeycmd();
-	if (!ll && isfirstln && !(zlereadflags & ZLRF_IGNOREEOF) &&
-	    lastchar == eofchar) {
-	    eofsent = 1;
-	    break;
-	}
 	if (bindk) {
-	    if (execzlefunc(bindk, zlenoargs))
+	    if (!ll && isfirstln && !(zlereadflags & ZLRF_IGNOREEOF) &&
+		lastchar == eofchar) {
+		/*
+		 * Slight hack: this relies on getkeycmd returning
+		 * a value for the EOF character.  However,
+		 * undefined-key is fine.  That's necessary because
+		 * otherwise we can't distinguish this case from
+		 * a ^C.
+		 */
+		eofsent = 1;
+		break;
+	    }
+	    if (execzlefunc(bindk, zlenoargs)) {


However, I can't figure out when getkeycmd() might fail to return a value 
for the EOF character, so I can't decide whether this makes a difference.


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: PATCH: exit after 10 EOF's
  2004-09-19 19:25           ` Bart Schaefer
@ 2004-09-20 10:15             ` Peter Stephenson
  2004-09-20 13:59             ` Peter Stephenson
  1 sibling, 0 replies; 22+ messages in thread
From: Peter Stephenson @ 2004-09-20 10:15 UTC (permalink / raw)
  To: zsh-workers

Bart Schaefer wrote:
> On Sun, 19 Sep 2004, Bart Schaefer wrote:
> 
> > I haven't gotten to the latter part yet, but here's a patch that (a) backs 
> > out 20363 and (b) causes the count to apply to printing of the warning.
> 
> Actually I just noticed that it doesn't _completely_ back out 20363.  This
> part of 20363 is still there:

That's the chunk from 20300.  It's the change that fixes the problem
that after a ^D and two ^C's (without ignore_eof) the shell exits.
There's no reason to remove that.

-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
CSR Ltd., Science Park, Milton Road,
Cambridge, CB4 0WH, UK                          Tel: +44 (0)1223 692070


**********************************************************************
This email and any files transmitted with it are confidential and
intended solely for the use of the individual or entity to whom they
are addressed. If you have received this email in error please notify
the system manager.

This footnote also confirms that this email message has been swept by
MIMEsweeper for the presence of computer viruses.

www.mimesweeper.com
**********************************************************************


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: PATCH: exit after 10 EOF's
  2004-09-19 19:25           ` Bart Schaefer
  2004-09-20 10:15             ` Peter Stephenson
@ 2004-09-20 13:59             ` Peter Stephenson
  2004-09-20 14:43               ` Bart Schaefer
  1 sibling, 1 reply; 22+ messages in thread
From: Peter Stephenson @ 2004-09-20 13:59 UTC (permalink / raw)
  To: zsh-workers

I've applied these two patches and now I get the message from within zle
(no reprinting of command line) when I have a zle -N widget bound to ^D,
but the shell doesn't exit.  If I use a completion widget I get the
message and the prompt is reprinted from the main shell.

The following is what I have applied.

Index: Src/init.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/init.c,v
retrieving revision 1.43
diff -u -r1.43 init.c
--- Src/init.c	13 Sep 2004 13:04:55 -0000	1.43
+++ Src/init.c	20 Sep 2004 13:58:02 -0000
@@ -37,7 +37,7 @@
 #include "version.h"
 
 /**/
-mod_export int noexitct = 0;
+int noexitct = 0;
 
 /* buffer for $_ and its length */
 
Index: Src/Zle/zle_main.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_main.c,v
retrieving revision 1.51
diff -u -r1.51 zle_main.c
--- Src/Zle/zle_main.c	13 Sep 2004 13:04:55 -0000	1.51
+++ Src/Zle/zle_main.c	20 Sep 2004 13:58:07 -0000
@@ -688,30 +688,23 @@
 	selectlocalmap(NULL);
 	bindk = getkeycmd();
 	if (bindk) {
-	    if (!ll && isfirstln && lastchar == eofchar) {
+	    if (!ll && isfirstln && !(zlereadflags & ZLRF_IGNOREEOF) &&
+		lastchar == eofchar) {
 		/*
 		 * Slight hack: this relies on getkeycmd returning
 		 * a value for the EOF character.  However,
 		 * undefined-key is fine.  That's necessary because
 		 * otherwise we can't distinguish this case from
 		 * a ^C.
-		 *
-		 * The noxitct test is done in the top-level loop
-		 * if zle is not running.  As we trap EOFs at this
-		 * level inside zle we need to mimic it here.
-		 * If we break, the top-level loop will actually increment
-		 * noexitct an extra time; that doesn't cause any
-		 * problems.
 		 */
-		if (!(zlereadflags & ZLRF_IGNOREEOF) ||
-		    ++noexitct >= 10)
-		{
-		    eofsent = 1;
-		    break;
-		}
+		eofsent = 1;
+		break;
 	    }
-	    if (execzlefunc(bindk, zlenoargs))
+	    if (execzlefunc(bindk, zlenoargs)) {
 		handlefeep(zlenoargs);
+		if (eofsent)
+		    break;
+	    }
 	    handleprefixes();
 	    /* for vi mode, make sure the cursor isn't somewhere illegal */
 	    if (invicmdmode() && cs > findbol() &&
@@ -904,10 +897,17 @@
     } else if((w = func->widget)->flags & (WIDGET_INT|WIDGET_NCOMP)) {
 	int wflags = w->flags;
 
-	if (keybuf[0] == eofchar && !keybuf[1] &&
+	/*
+	 * The rule is that "zle -N" widgets suppress EOF warnings.  When
+	 * a "zle -N" widget invokes "zle another-widget" we pass through
+	 * this code again, but with actual arguments rather than with the
+	 * zlenoargs placeholder.
+	 */
+	if (keybuf[0] == eofchar && !keybuf[1] && args == zlenoargs &&
 	    !ll && isfirstln && (zlereadflags & ZLRF_IGNOREEOF)) {
 	    showmsg((!islogin) ? "zsh: use 'exit' to exit." :
 		    "zsh: use 'logout' to logout.");
+	    eofsent = 1;
 	    ret = 1;
 	} else {
 	    if(!(wflags & ZLE_KEEPSUFFIX))

-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
CSR Ltd., Science Park, Milton Road,
Cambridge, CB4 0WH, UK                          Tel: +44 (0)1223 692070


**********************************************************************
This email and any files transmitted with it are confidential and
intended solely for the use of the individual or entity to whom they
are addressed. If you have received this email in error please notify
the system manager.

This footnote also confirms that this email message has been swept by
MIMEsweeper for the presence of computer viruses.

www.mimesweeper.com
**********************************************************************


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: PATCH: exit after 10 EOF's
  2004-09-20 13:59             ` Peter Stephenson
@ 2004-09-20 14:43               ` Bart Schaefer
  2004-09-20 14:53                 ` Peter Stephenson
  0 siblings, 1 reply; 22+ messages in thread
From: Bart Schaefer @ 2004-09-20 14:43 UTC (permalink / raw)
  To: Peter Stephenson; +Cc: zsh-workers

On Mon, 20 Sep 2004, Peter Stephenson wrote:

> I've applied these two patches and now I get the message from within zle
> (no reprinting of command line) when I have a zle -N widget bound to ^D,

I can't reproduce this.  I tried:

zagzig% widget() { : }
zagzig% zle -N widget
zagzig% bindkey \^D widget
zagzig% setopt ignoreeof
zagzig% 

(typing ctrl-D several times does nothing).

I then did:

zagzig% widget() { LBUFFER+=$KEYS }
zagzig% ^D^D^D^D^D^D^D

I next did:

zagzig% widget() { zle self-insert }
zagzig% ^D^D^D^D^D^D^D

Can you give me the exact command sequence you used?

> but the shell doesn't exit.

That part I can reproduce, but then, it's not supposed to exit.

> If I use a completion widget I get the message and the prompt is 
> reprinted from the main shell.

Hmm, yes, I hadn't noticed that difference.  There's no other way to keep
the noexitct increment limited to the top-level loop, though.  Is this
really a problem?

For reference, what I have is:

Index: Src/init.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/init.c,v
retrieving revision 1.43
retrieving revision 1.44
diff -u -r1.43 -r1.44
--- Src/init.c	13 Sep 2004 13:04:55 -0000	1.43
+++ Src/init.c	20 Sep 2004 13:37:41 -0000	1.44
@@ -37,7 +37,7 @@
 #include "version.h"
 
 /**/
-mod_export int noexitct = 0;
+int noexitct = 0;
 
 /* buffer for $_ and its length */
 
Index: Src/Zle/zle_main.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_main.c,v
retrieving revision 1.51
retrieving revision 1.53
diff -u -r1.51 -r1.53
--- Src/Zle/zle_main.c	13 Sep 2004 13:04:55 -0000	1.51
+++ Src/Zle/zle_main.c	20 Sep 2004 14:04:03 -0000	1.53
@@ -688,30 +688,23 @@
 	selectlocalmap(NULL);
 	bindk = getkeycmd();
 	if (bindk) {
-	    if (!ll && isfirstln && lastchar == eofchar) {
+	    if (!ll && isfirstln && !(zlereadflags & ZLRF_IGNOREEOF) &&
+		lastchar == eofchar) {
 		/*
 		 * Slight hack: this relies on getkeycmd returning
 		 * a value for the EOF character.  However,
 		 * undefined-key is fine.  That's necessary because
 		 * otherwise we can't distinguish this case from
 		 * a ^C.
-		 *
-		 * The noxitct test is done in the top-level loop
-		 * if zle is not running.  As we trap EOFs at this
-		 * level inside zle we need to mimic it here.
-		 * If we break, the top-level loop will actually increment
-		 * noexitct an extra time; that doesn't cause any
-		 * problems.
 		 */
-		if (!(zlereadflags & ZLRF_IGNOREEOF) ||
-		    ++noexitct >= 10)
-		{
-		    eofsent = 1;
-		    break;
-		}
+		eofsent = 1;
+		break;
 	    }
-	    if (execzlefunc(bindk, zlenoargs))
+	    if (execzlefunc(bindk, zlenoargs)) {
 		handlefeep(zlenoargs);
+		if (eofsent)
+		    break;
+	    }
 	    handleprefixes();
 	    /* for vi mode, make sure the cursor isn't somewhere illegal */
 	    if (invicmdmode() && cs > findbol() &&
@@ -904,10 +897,17 @@
     } else if((w = func->widget)->flags & (WIDGET_INT|WIDGET_NCOMP)) {
 	int wflags = w->flags;
 
-	if (keybuf[0] == eofchar && !keybuf[1] &&
+	/*
+	 * The rule is that "zle -N" widgets suppress EOF warnings.  When
+	 * a "zle -N" widget invokes "zle another-widget" we pass through
+	 * this code again, but with actual arguments rather than with the
+	 * zlenoargs placeholder.
+	 */
+	if (keybuf[0] == eofchar && !keybuf[1] && args == zlenoargs &&
 	    !ll && isfirstln && (zlereadflags & ZLRF_IGNOREEOF)) {
 	    showmsg((!islogin) ? "zsh: use 'exit' to exit." :
 		    "zsh: use 'logout' to logout.");
+	    eofsent = 1;
 	    ret = 1;
 	} else {
 	    if(!(wflags & ZLE_KEEPSUFFIX))


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: PATCH: exit after 10 EOF's
  2004-09-20 14:43               ` Bart Schaefer
@ 2004-09-20 14:53                 ` Peter Stephenson
  0 siblings, 0 replies; 22+ messages in thread
From: Peter Stephenson @ 2004-09-20 14:53 UTC (permalink / raw)
  To: zsh-workers

Bart Schaefer wrote:
> On Mon, 20 Sep 2004, Peter Stephenson wrote:
> 
> > I've applied these two patches and now I get the message from within zle
> > (no reprinting of command line) when I have a zle -N widget bound to ^D,
> 
> I can't reproduce this.

It was because I had a widget that explicitly output the message.  The
widget I was originally using now works as expected.  So it looks OK.

-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
CSR Ltd., Science Park, Milton Road,
Cambridge, CB4 0WH, UK                          Tel: +44 (0)1223 692070


**********************************************************************
This email and any files transmitted with it are confidential and
intended solely for the use of the individual or entity to whom they
are addressed. If you have received this email in error please notify
the system manager.

This footnote also confirms that this email message has been swept by
MIMEsweeper for the presence of computer viruses.

www.mimesweeper.com
**********************************************************************


^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2004-09-20 14:54 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-09-13 11:18 PATCH: exit after 10 EOF's Peter Stephenson
2004-09-13 17:51 ` Bart Schaefer
2004-09-15  9:46   ` Peter Stephenson
2004-09-15 15:43     ` Bart Schaefer
2004-09-15 16:02       ` Bart Schaefer
2004-09-15 16:14         ` Peter Stephenson
2004-09-16 14:57           ` Peter Stephenson
2004-09-16 16:12             ` Bart Schaefer
2004-09-16 16:28               ` Peter Stephenson
2004-09-19  6:50 ` Bart Schaefer
2004-09-19  7:45   ` Duncan Sinclair
2004-09-19 16:41     ` Bart Schaefer
2004-09-19 17:52       ` Peter Stephenson
2004-09-19 18:26         ` Bart Schaefer
2004-09-19 19:25           ` Bart Schaefer
2004-09-20 10:15             ` Peter Stephenson
2004-09-20 13:59             ` Peter Stephenson
2004-09-20 14:43               ` Bart Schaefer
2004-09-20 14:53                 ` Peter Stephenson
2004-09-19 19:11         ` Bart Schaefer
2004-09-19 11:53   ` Peter Stephenson
2004-09-19 17:00     ` Bart Schaefer

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).