Index | Thread | Search

From:
Stuart Henderson <stu@spacehopper.org>
Subject:
Re: Fix for vi editing mode in sftp(1) (PING)
To:
Walter Alejandro Iglesias <wai@roquesor.com>
Cc:
tech@openbsd.org
Date:
Mon, 19 Jan 2026 20:16:28 +0000

Download raw body.

Thread
On 2026/01/19 20:26, Walter Alejandro Iglesias wrote:
> On Mon, Jan 19, 2026 at 05:12:14PM +0000, Stuart Henderson wrote:
> > On 2026/01/19 11:09, Walter Alejandro Iglesias wrote:
> > > On Sun, Dec 21, 2025 at 11:49:36AM +0100, Walter Alejandro Iglesias wrote:
> > > > Currently vi editing mode doesn't work in sftp(1), only emacs.  Since
> > > > editline(3) support is already included in sftp, it doesn't hurt to make
> > > > it fully work, right?
> > > > 
> > > > To test it you need this:
> > > > 
> > > >   $ cat ~/.editrc
> > > >   sftp:bind -v
> > > > 
> > > 
> > > 
> > > Index: sftp.c
> > > ===================================================================
> > > RCS file: /cvs/src/usr.bin/ssh/sftp.c,v
> > > diff -u -p -u -p -r1.247 sftp.c
> > > --- sftp.c	13 Oct 2025 00:54:29 -0000	1.247
> > > +++ sftp.c	19 Dec 2025 15:21:45 -0000
> > > @@ -2210,6 +2210,7 @@ interactive_loop(struct sftp_conn *conn,
> > >  	HistEvent hev;
> > >  	extern char *__progname;
> > >  	struct complete_ctx complete_ctx;
> > > +	const char *editor;
> > >  
> > >  	if (!batchmode && isatty(STDIN_FILENO)) {
> > >  		if ((el = el_init(__progname, stdin, stdout, stderr)) == NULL)
> > > @@ -2239,6 +2240,11 @@ interactive_loop(struct sftp_conn *conn,
> > >  		el_set(el, EL_BIND, "\\e\\e[D", "ed-prev-word", NULL);
> > >  		/* make ^w match ksh behaviour */
> > >  		el_set(el, EL_BIND, "^w", "ed-delete-prev-word", NULL);
> > > +
> > > +		/* Vi command mode */
> > > +		el_get(el, EL_EDITOR, &editor);
> > > +		if (editor[0] == 'v')
> > > +			el_set(el, EL_BIND, "^[", "vi-command-mode", NULL);
> > >  	}
> > >  
> > >  	if ((remote_path = sftp_realpath(conn, ".")) == NULL)
> > 
> > works as advertised, but I think it would probably be a good idea to
> > check el_get()'s return code before dereferencing editor.
> 
> It's already hard coded to "emacs" a few lines above my change (see line
> 2224 of sftp.c):
> 
> 		el_set(el, EL_EDITOR, "emacs");
> 
> 
> But it doesn't hurt another check to be sure. ;-)

well, &editor is obviously not set directly by that el_set.

if el_get() returns failure before it sets &editor (for whatever
reason), editor contains garbage, so dereferencing that won't do
anything good.

> 
> 
> > 
> > ok?
> > 
> > Index: sftp.c
> > ===================================================================
> > RCS file: /cvs/src/usr.bin/ssh/sftp.c,v
> > diff -u -p -r1.247 sftp.c
> > --- sftp.c	13 Oct 2025 00:54:29 -0000	1.247
> > +++ sftp.c	19 Jan 2026 17:11:38 -0000
> > @@ -2204,6 +2204,7 @@ interactive_loop(struct sftp_conn *conn,
> >  	char *remote_path;
> >  	char *dir = NULL, *startdir = NULL;
> >  	char cmd[2048];
> > +	const char *editor;
> >  	int err, interactive;
> >  	EditLine *el = NULL;
> >  	History *hl = NULL;
> > @@ -2239,6 +2240,10 @@ interactive_loop(struct sftp_conn *conn,
> >  		el_set(el, EL_BIND, "\\e\\e[D", "ed-prev-word", NULL);
> >  		/* make ^w match ksh behaviour */
> >  		el_set(el, EL_BIND, "^w", "ed-delete-prev-word", NULL);
> > +
> > +		/* Vi command mode */
> > +		if (el_get(el, EL_EDITOR, &editor) == 0 && editor[0] == 'v')
> > +			el_set(el, EL_BIND, "^[", "vi-command-mode", NULL);
> >  	}
> > 
> >  	if ((remote_path = sftp_realpath(conn, ".")) == NULL)
> > 
> 
> -- 
> Walter
>