bin/21089: vi silently corrupt open file on SIGINT when entering :wq in command mode

Jaakko Heinonen jh at saunalahti.fi
Thu Feb 21 13:30:03 UTC 2008


The following reply was made to PR bin/21089; it has been noted by GNATS.

From: Jaakko Heinonen <jh at saunalahti.fi>
To: Yar Tikhiy <yar at comp.chem.msu.su>
Cc: bug-followup at freebsd.org
Subject: Re: bin/21089: vi silently corrupt open file on SIGINT when
	entering :wq in command mode
Date: Thu, 21 Feb 2008 15:23:34 +0200

 --ew6BAiZeqk4r7MaW
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 
 
 Hi,
 
 On 2008-02-15, Yar Tikhiy wrote:
 > Upon a second thought, I'd rather follow the NetBSD way of dealing
 > with this issue.  Their way was hackish not for nothing: it had to
 > deal with such complex cases of nvi text input as file name completion
 > and former input replay.
 
 I have obtained a patch series from NetBSD to fix the ^C and SIGWINCH
 problems. The series contains also all other NetBSD bug fixes for v_txt.c
 excluding fixes for compile warnings. Also OpeBSD seems to use the same
 ^C fix.
 
 I have attached the patches including the original NetBSD cvs log
 messages to this mail.
 
 -- 
 Jaakko
 
 --ew6BAiZeqk4r7MaW
 Content-Type: text/x-diff; charset=us-ascii
 Content-Disposition: attachment; filename="nvi-netbsd-v_ex.c-1.diff"
 
 Obtained from:	NetBSD
 
 date: 2005/09/06 21:21:25;  author: aymeric;  state: Exp;  lines: +6 -2
 when reading an ex command within visual mode with v_tcmd(), check that
 the termination value of v_tcmd() is alright. Abort the command otherwise.
 Until the next commit in vi/v_txt.c, this is a noop.
 
 diff -u -r1.11 -r1.12
 --- v_ex.c	9 Apr 2002 01:47:35 -0000	1.11
 +++ v_ex.c	6 Sep 2005 21:21:25 -0000	1.12
 @@ -428,6 +428,10 @@ v_ex(sp, vp)
  			if (tp->term == TERM_BS)
  				break;
  
 +			/* If the user changed their mind, return. */
 +			if (tp->term != TERM_OK)
 +				break;
 +
  			/* Log the command. */
  			if (O_STR(sp, O_CEDIT) != NULL && v_ecl_log(sp, tp))
  				return (1);
 
 --ew6BAiZeqk4r7MaW
 Content-Type: text/x-diff; charset=us-ascii
 Content-Disposition: attachment; filename="nvi-netbsd-v_txt.c-1.diff"
 
 Obtained from:	NetBSD
 
 date: 2005/09/06 21:30:36;  author: aymeric;  state: Exp;  lines: +21 -10
 Finally handle ^C the correct way. This indeed requires to separate the case
 of text-recording input (usually text in insert mode) from the other cases
 (e.g. ex command input). If recording, morph to escape key so that the input
 is correctly finished for a potential replay; if not, simply bail out and
 notify that something wrong occurs. Callers will cope.
 The previous fix could make ^C sometimes produce a file completion
 or a command edition, depending on the settings of the user.
 I think this is the correct fix for since closed PR bin/11544 by pooka at . ;-)
 ----------------------------
 date: 2001/04/30 21:34:12;  author: aymeric;  state: Exp;  lines: +20 -13
 Now, ^C behaves just like <ESC> (but for the ``Interrupt'' message).
 It is consistent with what Solaris' vi and vim do.
 This addresses PR #11544 by pooka.
 
 Index: v_txt.c
 ===================================================================
 RCS file: /home/ncvs/src/contrib/nvi/vi/v_txt.c,v
 retrieving revision 1.1.1.1
 diff -p -u -r1.1.1.1 v_txt.c
 --- v_txt.c	1 Nov 1996 06:45:33 -0000	1.1.1.1
 +++ v_txt.c	18 Feb 2008 19:16:07 -0000
 @@ -510,15 +510,6 @@ next:	if (v_event_get(sp, evp, 0, ec_fla
  	case E_EOF:
  		F_SET(sp, SC_EXIT_FORCE);
  		return (1);
 -	case E_INTERRUPT:
 -		/*
 -		 * !!!
 -		 * Historically, <interrupt> exited the user from text input
 -		 * mode or cancelled a colon command, and returned to command
 -		 * mode.  It also beeped the terminal, but that seems a bit
 -		 * excessive.
 -		 */
 -		goto k_escape;
  	case E_REPAINT:
  		if (vs_repaint(sp, &ev))
  			return (1);
 @@ -526,10 +517,37 @@ next:	if (v_event_get(sp, evp, 0, ec_fla
  	case E_WRESIZE:
  		/* <resize> interrupts the input mode. */
  		v_emsg(sp, NULL, VIM_WRESIZE);
 -		goto k_escape;
 +	/* FALLTHROUGH */
  	default:
 -		v_event_err(sp, evp);
 -		goto k_escape;
 +		if (evp->e_event != E_INTERRUPT && evp->e_event != E_WRESIZE)
 +			v_event_err(sp, evp);
 +		/*
 +		 * !!!
 +		 * Historically, <interrupt> exited the user from text input
 +		 * mode or cancelled a colon command, and returned to command
 +		 * mode.  It also beeped the terminal, but that seems a bit
 +		 * excessive.
 +		 */
 +		/*
 +		 * If we are recording, morph into <escape> key so that
 +		 * we can repeat the command safely: there is no way to
 +		 * invalidate the repetition of an instance of a command,
 +		 * which would be the alternative possibility.
 +		 * If we are not recording (most likely on the command line),
 +		 * simply discard the input and return to command mode
 +		 * so that an INTERRUPT doesn't become for example a file
 +		 * completion request. -aymeric
 +		 */
 +		if (LF_ISSET(TXT_RECORD)) {
 +		    evp->e_event = E_CHARACTER;
 +		    evp->e_c = 033;
 +		    evp->e_flags = 0;
 +		    evp->e_value = K_ESCAPE;
 +		    break;
 +		} else {
 +		    tp->term = TERM_ESC;
 +		    goto k_escape;
 +		}
  	}
  
  	/*
 
 --ew6BAiZeqk4r7MaW
 Content-Type: text/x-diff; charset=us-ascii
 Content-Disposition: attachment; filename="nvi-netbsd-v_txt.c-2.diff"
 
 Obtained from: NetBSD
 
 date: 2001/08/20 21:44:57;  author: aymeric;  state: Exp;  lines: +2 -2
 Fix a bug present in nvi 1.79 where ^@ wouldn't behave as expected when
 reading an ex command from vi.
 
 diff -p -u -r1.5 -r1.6
 --- v_txt.c	1 May 2001 16:46:12 -0000	1.5
 +++ v_txt.c	20 Aug 2001 21:44:57 -0000	1.6
 @@ -557,7 +557,7 @@ next:	if (v_event_get(sp, evp, 0, ec_fla
  	 * This was not documented as far as I know, and is a great test of vi
  	 * clones.
  	 */
 -	if (rcol == 0 && !LF_ISSET(TXT_REPLAY) && evp->e_c == '\0') {
 +	if (LF_ISSET(TXT_RECORD) && rcol == 0 && evp->e_c == '\0') {
  		if (vip->rep == NULL)
  			goto done;
  
 
 --ew6BAiZeqk4r7MaW
 Content-Type: text/x-diff; charset=us-ascii
 Content-Disposition: attachment; filename="nvi-netbsd-v_txt.c-3.diff"
 
 Obtained from:	NetBSD
 
 date: 2003/06/06 08:06:47;  author: aymeric;  state: Exp;  lines: +3 -2
 branches:  1.11.4;
 When an error occurs in v_txt(), leave input mode too.
 Otherwise, (among other things) db_get() thinks it can re-use the TEXT buffers
 when it's not true, leading to a crash because that TEXT buffer will be
 released just before it is actually used to create a new one.
 This fixes PR#21797.
 
 diff -p -u -r1.10 -r1.11
 --- v_txt.c	6 Jan 2003 20:30:41 -0000	1.10
 +++ v_txt.c	6 Jun 2003 08:06:47 -0000	1.11
 @@ -1474,6 +1474,7 @@ done:	/* Leave input mode. */
  
  err:
  alloc_err:
 +	F_CLR(sp, SC_TINPUT);
  	txt_err(sp, &sp->tiq);
  	return (1);
  }
 
 --ew6BAiZeqk4r7MaW
 Content-Type: text/x-diff; charset=us-ascii
 Content-Disposition: attachment; filename="nvi-netbsd-v_txt.c-4.diff"
 
 Obtained from:	NetBSD
 
 date: 2004/11/23 14:35:45;  author: aymeric;  state: Exp;  lines: +3 -3
 branches:  1.12.2;
 Move a line of code which was "obviously" misplaced.
 This fixes a core dump when auto-completing filenames and at least one of the
 file names is larger than the screen width.
 
 Bug report and fix by Peter Bex in PR#28382
 
 diff -p -u -r1.11 -r1.12
 --- v_txt.c	6 Jun 2003 08:06:47 -0000	1.11
 +++ v_txt.c	23 Nov 2004 14:35:45 -0000	1.12
 @@ -2235,8 +2235,8 @@ txt_fc_col(sp, argc, argv)
  
  	/* If the largest file name is too large, just print them. */
  	if (colwidth > sp->cols) {
 -		p = msg_print(sp, av[0]->bp + prefix, &nf);
  		for (ac = argc, av = argv; ac > 0; --ac, ++av) {
 +			p = msg_print(sp, av[0]->bp + prefix, &nf);
  			(void)ex_printf(sp, "%s\n", p);
  			if (F_ISSET(gp, G_INTERRUPTED))
  				break;
 
 --ew6BAiZeqk4r7MaW--


More information about the freebsd-bugs mailing list