using read -p from in script launched by execute_process

Hi,

related to: execute_process buffers and doesn't print question when process is waiting on user input.

My goal is to add a path to user PATH environment variable during installation process but I want to request his permission first.

A workaround would be to set an option for cmake command line but it’s not user friendly as he must allow (or disallow) at configuration step for the manipulation, which is disconnect from installation time.

Regards
A.

1 Like

For my specific use case, I add a bit of context that may be significant to solve the issue.

In my project CMakeLists.txt:

INSTALL(SCRIPT ".../MyInstallScript.cmake")

In MyInstallScript.cmake

execute_process(".../PromptUser.sh" OUTPUT_VARIABLE FOO RESULT_VARIABLE FOOR ERROR_VARIABLE FOO_ER)

In PromptUser.sh

#/usr/bin/env bash

while true; do
read -p "Do you want to go on? (yn) " yn
case $yn in 
[yY] ) echo "go on";
exit 0;;
[nN] ) echo "stop";
exit 1;;
* ) echo "invalid response";;
esac
done

read prompt is not displayed and echo command are buffered into FOO but not displayed.
besides in this case all echo are buffered, whereas I would be interested only in the last echo (for instance: “stop” instead of “invalid response invalid response invalid response invalid response stop”)

Thanks.

I don’t know that stdin is forwarded properly for this kind of stuff. I have no idea what this means for cmake-gui or ccmake (in a full CMake run). Script mode might be able to support it, but it sounds new to me.

Try this keyboard input function, it works with bash, sh, powershell and cmd.
When enter is pressed, a variable containing the keyboard input string is returned.

##############################################################################
# dk_keyboardInput(RETURN_VAR)
# 
#
function(dk_keyboardInput RETURN_VAR) 
	
	###### BASH ######
	execute_process(COMMAND bash -c "command -v 'bash'" OUTPUT_VARIABLE BASH_EXE OUTPUT_STRIP_TRAILING_WHITESPACE)
	if(EXISTS "${BASH_EXE}")
		set(cmnd ${BASH_EXE} -c "read -p '' stdin&& echo $stdin")
		#message("${cmnd}")
		execute_process(COMMAND ${cmnd} OUTPUT_VARIABLE stdin OUTPUT_STRIP_TRAILING_WHITESPACE)
		if("${stdin}" STREQUAL "$stdin")
			set(stdin "")
		endif()
		set(${ARGV0} "${stdin}" PARENT_SCOPE)
		return()
	endif()
	
	
	###### SH ######
	execute_process(COMMAND sh -c "command -v 'sh'" OUTPUT_VARIABLE SH_EXE OUTPUT_STRIP_TRAILING_WHITESPACE)	
	if(EXISTS "${SH_EXE}")
		set(cmnd ${SH_EXE} -c "read -p '' stdin&& echo $stdin")
		#message("${cmnd}")
		execute_process(COMMAND ${cmnd} OUTPUT_VARIABLE stdin OUTPUT_STRIP_TRAILING_WHITESPACE)
		if("${stdin}" STREQUAL "$stdin")
			set(stdin "")
		endif()
		set(${ARGV0} "${stdin}" PARENT_SCOPE)
		return()
	endif()
	
	
	###### POWERSHELL ######
	find_program(POWERSHELL_EXE powershell.exe)
	if(EXISTS "${POWERSHELL_EXE}")
		set(cmnd ${POWERSHELL_EXE} Read-Host)
		#message("${cmnd}")
		execute_process(COMMAND ${cmnd} OUTPUT_VARIABLE stdin OUTPUT_STRIP_TRAILING_WHITESPACE)
		if("${stdin}" STREQUAL "$stdin")
			set(stdin "")
		endif()
		set(${ARGV0} "${stdin}" PARENT_SCOPE)		
		return()
	endif()
	
	
	###### CMD ######
	if(EXISTS "$ENV{COMSPEC}")
		string(REPLACE "/" "\\" CMD_EXE "$ENV{COMSPEC}")  # convert to windows path delimiters
		set(cmnd "${CMD_EXE}" /V:ON /c "set /p stdin=& echo !stdin!")
		#message("${cmnd}")
		execute_process(COMMAND ${cmnd} OUTPUT_VARIABLE stdin OUTPUT_STRIP_TRAILING_WHITESPACE)		
		if("${stdin}" STREQUAL "!stdin!")
			set(stdin "")
		endif()
		set(${ARGV0} "${stdin}" PARENT_SCOPE)
		return()
	endif()
	
	message(FATAL_ERROR "Could not locate bash, sh, cmd or powershell")
endfunction()
1 Like

Thanks for proposing a solution. I actually already implemented a workaround based on a “per shell” basis, with a fallback, which is quite unsatisfactory. I didn’t reported it because I expected some more general solution. You’re covering two cases I didn’t need so far so I’m keeping your proposal in some corner if they become relevant.
btw my approach is slightly different, instead of giving the command through cmake, I’m calling a sub-script in the given shell langage. I don’t know the pro and cons of both ways to go.

regards
A.