Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upon new shell or TERM change, command completion fails outside of the default path #642

Closed
pghvlaans opened this issue May 26, 2023 · 6 comments
Labels
bug Something is not working

Comments

@pghvlaans
Copy link

pghvlaans commented May 26, 2023

This bug appears to have been introduced in f8faa2a.

In both line editor modes, immediately after starting the shell or after changing the $TERM variable, command completion fails for executables in places other than the default path (/bin:/usr/bin). This effect lasts until a new prompt is reached by carriage return executing a command or ctrl+C.

@McDutchie McDutchie added the bug Something is not working label May 27, 2023
@McDutchie
Copy link

Thanks for the report.

Using a normal command substitution instead of a shared-state command substitution to invoke tput seems to be an effective workaround for the bug. So there must still be some bug involving command -p and/or shared-state command substitutions somewhere, but about an hour of searching got me nowhere so far.

diff --git a/src/cmd/ksh93/edit/edit.c b/src/cmd/ksh93/edit/edit.c
index ce21a8f07..1dac5391b 100644
--- a/src/cmd/ksh93/edit/edit.c
+++ b/src/cmd/ksh93/edit/edit.c
@@ -413,7 +413,7 @@ static void get_tput(char *tp, char **cpp)
 	sh_offoption(SH_RESTRICTED);
 	sh_offoption(SH_VERBOSE);
 	sh_offoption(SH_XTRACE);
-	sfprintf(sh.strbuf,".sh.value=${ \\command -p tput %s 2>/dev/null;}",tp);
+	sfprintf(sh.strbuf,".sh.value=$(\\command -p tput %s 2>/dev/null)",tp);
 	sh_trap(sfstruse(sh.strbuf),0);
 	if((cp = nv_getval(SH_VALNOD)) && (!*cpp || strcmp(cp,*cpp)!=0))
 	{

@McDutchie
Copy link

Another workaround: execute a dummy command (:) after the shared-state comsub.

diff --git a/src/cmd/ksh93/edit/edit.c b/src/cmd/ksh93/edit/edit.c
index ce21a8f07..9aed564ac 100644
--- a/src/cmd/ksh93/edit/edit.c
+++ b/src/cmd/ksh93/edit/edit.c
@@ -413,7 +413,7 @@ static void get_tput(char *tp, char **cpp)
 	sh_offoption(SH_RESTRICTED);
 	sh_offoption(SH_VERBOSE);
 	sh_offoption(SH_XTRACE);
-	sfprintf(sh.strbuf,".sh.value=${ \\command -p tput %s 2>/dev/null;}",tp);
+	sfprintf(sh.strbuf,".sh.value=${ \\command -p tput %s 2>/dev/null;};:",tp);
 	sh_trap(sfstruse(sh.strbuf),0);
 	if((cp = nv_getval(SH_VALNOD)) && (!*cpp || strcmp(cp,*cpp)!=0))
 	{

@pghvlaans
Copy link
Author

pghvlaans commented May 27, 2023

I found a third workaround: add sh_offstate(SH_DEFPATH) after restoring the shell options.

diff --git a/src/cmd/ksh93/edit/edit.c b/src/cmd/ksh93/edit/edit.c
index ce21a8f0..cb07c670 100644
--- a/src/cmd/ksh93/edit/edit.c
+++ b/src/cmd/ksh93/edit/edit.c
@@ -429,6 +429,7 @@ static void get_tput(char *tp, char **cpp)
        }
        nv_unset(SH_VALNOD);
        sh.options = o;
+       sh_offstate(SH_DEFPATH);
        sigrelease(SIGINT);
 }

EDIT: Is this something that should be handled in whence.c?

@pghvlaans
Copy link
Author

I suppose that means a command -p bug per se can be ruled out, since the SH_DEFPATH state doesn't do any damage with ordinary command substitution.

@McDutchie
Copy link

Of course SH_DEFPATH is the problem. I need more caffeine...

EDIT: Is this something that should be handled in whence.c?

No, the actual running of commands via command is handled in sh_exec(); whence.c handles command -v and command -V.

I tried this patch (click triangle) that turns off SH_DEFPATH at the end of every sh_exec() invocation and in sh_exit() instead of at the beginning of sh_exec(), but that causes a few regression test failures as sh_exec() heavily uses recursion.
diff --git a/src/cmd/ksh93/sh/fault.c b/src/cmd/ksh93/sh/fault.c
index f024f6520..b26b9c11f 100644
--- a/src/cmd/ksh93/sh/fault.c
+++ b/src/cmd/ksh93/sh/fault.c
@@ -564,6 +564,7 @@ void sh_exit(int xno)
 	struct checkpt	*pp = (struct checkpt*)sh.jmplist;
 	int		sig=0;
 	Sfio_t		*pool;
+	sh_offstate(SH_DEFPATH);
 	/* POSIX requires exit status >= 2 for error in 'test'/'[' */
 	if(xno==1 && sh.bltinfun==b_test)
 		sh.exitval = 2;
diff --git a/src/cmd/ksh93/sh/xec.c b/src/cmd/ksh93/sh/xec.c
index 6fb0b9371..b8f474853 100644
--- a/src/cmd/ksh93/sh/xec.c
+++ b/src/cmd/ksh93/sh/xec.c
@@ -893,7 +893,6 @@ int sh_exec(const Shnode_t *t, int flags)
 			job.curjobid = 0;
 			flags &= ~sh_state(SH_INTERACTIVE);
 		}
-		sh_offstate(SH_DEFPATH);
 		if(!(flags & sh_state(SH_ERREXIT)))
 			sh_offstate(SH_ERREXIT);
 		sh.exitval=0;
@@ -1443,6 +1442,7 @@ int sh_exec(const Shnode_t *t, int flags)
 #endif
 				if(sh.topfd > topfd && !(sh.subshell && (np==SYSEXEC || np==SYSREDIR)))
 					sh_iorestore(topfd,jmpval);  /* avoid leaking unused file descriptors */
+				sh_offstate(SH_DEFPATH);
 				exitset();
 				break;
 			}

So I think the following is probably the best we can do: when turning on the command completion state (SH_COMPLETE), make sure SH_DEFPATH is off.

diff --git a/src/cmd/ksh93/edit/completion.c b/src/cmd/ksh93/edit/completion.c
index bc6ae9c4c..ffb898793 100644
--- a/src/cmd/ksh93/edit/completion.c
+++ b/src/cmd/ksh93/edit/completion.c
@@ -385,6 +385,7 @@ int ed_expand(Edit_t *ep, char outbuff[],int *cur,int *eol,int mode, int count)
 		{
 			cmd_completion=1;
 			sh_onstate(SH_COMPLETE);
+			sh_offstate(SH_DEFPATH);
 		}
 		if(ep->e_nlist)
 		{

@pghvlaans
Copy link
Author

Cool, that seems to work. Thank you!

FWIW: Adding the two sh_offstate in the first patch but not removing the one at the beginning of sh_exec() doesn't fail the path tests.

McDutchie added a commit that referenced this issue May 27, 2023
The referenced commit makes ksh invoke tput(1) with `command -p` on
init and when TERM changes, which turns on the SH_DEFPATH shell
state. It is turned off again in sh_exec() before running a new
command, however, command completion can occur before that. So the
first command completion operation only searched the default path.

src/cmd/ksh93/edit/completion.c: ed_expand():
- When turning on SH_COMPLETE to activate command completion, also
  turn off SH_DEFPATH.

Thanks to @pghvlaans for the report.
Resolves: #642
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something is not working
Projects
None yet
Development

No branches or pull requests

2 participants