Add display
to shell script.
This commit is contained in:
parent
e552f97db1
commit
16c0c476cd
4 changed files with 143 additions and 82 deletions
10
lib/decodedos.js
Normal file
10
lib/decodedos.js
Normal file
|
@ -0,0 +1,10 @@
|
|||
process.stdout.write(decodeDOS(process.argv[2] /*text*/ || ''),
|
||||
process.env.RLS_ENCODING || 'binary', function() {
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
function decodeDOS(arg) {
|
||||
return arg.replace(/#(\d+);/g, function(str, charCode) {
|
||||
return String.fromCharCode(+charCode);
|
||||
});
|
||||
}
|
110
lib/read.bat
110
lib/read.bat
|
@ -1,42 +1,68 @@
|
|||
@echo off
|
||||
setlocal
|
||||
setlocal ENABLEDELAYEDEXPANSION
|
||||
|
||||
if "%~1"=="noechoback" (
|
||||
call :read_s
|
||||
if ERRORLEVEL 1 exit /b 1
|
||||
) else (
|
||||
set /p INPUT=<CON >CON
|
||||
)
|
||||
set /p ="'%INPUT%'"<NUL
|
||||
endlocal
|
||||
exit /b 0
|
||||
|
||||
:: Silent Read
|
||||
:read_s
|
||||
|
||||
:: where /q powershell
|
||||
:: Win <Vista and <Server2008 don't have `where`.
|
||||
powershell /? >NUL 2>&1
|
||||
:: Win <7 and <Server2008R2 don't have PowerShell as default.
|
||||
:: Win XP and Server2003 have `ScriptPW` (`scriptpw.dll`).
|
||||
:: In the systems that don't have both, an error is thrown.
|
||||
if ERRORLEVEL 1 (
|
||||
set "EXECOMMAND=cscript //nologo "%~dp0read.cs.js""
|
||||
) else (
|
||||
set "EXECOMMAND=powershell -Command "$text = read-host -AsSecureString; ^
|
||||
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR^($text^); ^
|
||||
[System.Runtime.InteropServices.Marshal]::PtrToStringAuto^($BSTR^)""
|
||||
)
|
||||
|
||||
:: Can't get `ERRORLEVEL` from sub-shell (`for`).
|
||||
:: 2 `%ERRCODE%` lines are returned if an error is thrown.
|
||||
set ERRCODE=ERR
|
||||
set "EXECOMMAND=%EXECOMMAND% ^& if ERRORLEVEL 1 ^(echo %ERRCODE%^& echo %ERRCODE%^)"
|
||||
:: echo %EXECOMMAND%
|
||||
|
||||
for /f "usebackq delims=" %%i in (`%EXECOMMAND%`) do (
|
||||
if "%%i"=="%ERRCODE%" if "!INPUT!"=="%ERRCODE%" exit /b 1
|
||||
set "INPUT=%%i"
|
||||
)
|
||||
exit /b 0
|
||||
@echo off
|
||||
setlocal ENABLEDELAYEDEXPANSION
|
||||
|
||||
:args_loop
|
||||
if "%~1"=="" (
|
||||
goto args_end
|
||||
|
||||
) else if "%~1"=="--noechoback" (
|
||||
set noechoback=1
|
||||
|
||||
) else if "%~1"=="--keyin" (
|
||||
set keyin=1
|
||||
|
||||
) else if "%~1"=="--display" (
|
||||
set "display=%~2"
|
||||
shift /1
|
||||
|
||||
)
|
||||
shift /1
|
||||
goto args_loop
|
||||
:args_end
|
||||
|
||||
:: type tmpfile.txt >CON
|
||||
if "%display%" NEQ "" if "%NODE_EXEC_PATH%" NEQ "" (
|
||||
"%NODE_EXEC_PATH%" "%~dp0decodedos.js" "%display%" >CON
|
||||
if ERRORLEVEL 1 exit /b 1
|
||||
)
|
||||
|
||||
if "%noechoback%"=="1" (
|
||||
call :read_s
|
||||
if ERRORLEVEL 1 exit /b 1
|
||||
) else (
|
||||
set /p input=<CON >CON
|
||||
)
|
||||
set /p ="'%input%'"<NUL
|
||||
|
||||
endlocal
|
||||
exit /b 0
|
||||
|
||||
:: Silent Read
|
||||
:read_s
|
||||
|
||||
:: where /q powershell
|
||||
:: Win <Vista and <Server2008 don't have `where`.
|
||||
powershell /? >NUL 2>&1
|
||||
:: Win <7 and <Server2008R2 don't have PowerShell as default.
|
||||
:: Win XP and Server2003 have `ScriptPW` (`scriptpw.dll`).
|
||||
:: In the systems that don't have both, an error is thrown.
|
||||
if ERRORLEVEL 1 (
|
||||
set "exec_line=cscript //nologo "%~dp0read.cs.js""
|
||||
) else (
|
||||
set "exec_line=powershell -Command "$text = read-host -AsSecureString; ^
|
||||
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR^($text^); ^
|
||||
[System.Runtime.InteropServices.Marshal]::PtrToStringAuto^($BSTR^)""
|
||||
)
|
||||
|
||||
:: Can't get `ERRORLEVEL` from sub-shell.
|
||||
:: 2 `%ERRCODE%` lines are returned if an error is thrown.
|
||||
set ERRCODE=ERR
|
||||
set "exec_line=%exec_line% ^& if ERRORLEVEL 1 ^(echo %ERRCODE%^& echo %ERRCODE%^)"
|
||||
:: echo %exec_line%
|
||||
|
||||
for /f "usebackq delims=" %%i in (`%exec_line%`) do (
|
||||
if "%%i"=="%ERRCODE%" if "!input!"=="%ERRCODE%" exit /b 1
|
||||
set "input=%%i"
|
||||
)
|
||||
|
||||
exit /b 0
|
||||
|
|
25
lib/read.sh
25
lib/read.sh
|
@ -3,21 +3,36 @@ read_s() {
|
|||
stty --file=/dev/tty -echo echonl 2>/dev/null || \
|
||||
stty -F /dev/tty -echo echonl 2>/dev/null || \
|
||||
stty -f /dev/tty -echo echonl || exit 1
|
||||
IFS= read -r INPUT </dev/tty || exit 1
|
||||
IFS= read -r input </dev/tty || exit 1
|
||||
stty --file=/dev/tty echo -echonl 2>/dev/null || \
|
||||
stty -F /dev/tty echo -echonl 2>/dev/null || \
|
||||
stty -f /dev/tty echo -echonl || exit 1
|
||||
}
|
||||
|
||||
if [ "$1" = "noechoback" ]; then
|
||||
# getopt(s)
|
||||
while [ $# -ge 1 ]; do
|
||||
case "$1" in
|
||||
"--noechoback") noechoback=1;;
|
||||
"--keyin") keyin=1;;
|
||||
"--display") shift; display=$1;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [ -n "$display" ]; then
|
||||
printf '%s' "$display" >/dev/tty
|
||||
fi
|
||||
|
||||
if [ "$noechoback" = "1" ]; then
|
||||
# Try `-s` option. *ksh have it that not `--silent`. Therefore, don't try it.
|
||||
if [ -n "$BASH_VERSION" ] || [ -n "$ZSH_VERSION" ]; then
|
||||
IFS= read -rs INPUT </dev/tty 2>/dev/null && printf '\n' >/dev/tty || read_s
|
||||
IFS= read -rs input </dev/tty 2>/dev/null && printf '\n' >/dev/tty || read_s
|
||||
else
|
||||
read_s
|
||||
fi
|
||||
else
|
||||
IFS= read -r INPUT </dev/tty || exit 1
|
||||
IFS= read -r input </dev/tty || exit 1
|
||||
fi
|
||||
printf '%s' "'$INPUT'"
|
||||
printf '%s' "'$input'"
|
||||
|
||||
exit 0
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
var
|
||||
IS_WIN = process.platform === 'win32',
|
||||
SHELL_PATH = IS_WIN ? process.env.comspec || 'cmd.exe' : '/bin/sh',
|
||||
SHELL_PATH = IS_WIN ? process.env.ComSpec || 'cmd.exe' : '/bin/sh',
|
||||
SHELL_CMD = __dirname + (IS_WIN ? '\\read.bat' : '/read.sh'),
|
||||
ALGORITHM_CIPHER = 'aes-256-cbc',
|
||||
ALGORITHM_HASH = 'sha256',
|
||||
|
@ -39,8 +39,6 @@ function _readlineSync(options) { // options.display is string
|
|||
|
||||
if (IS_WIN) { // r/w mode not supported
|
||||
if (process.stdin.isTTY && process.stdout.isTTY) {
|
||||
|
||||
console.warn('STD TRY');
|
||||
if (options.display !== '') {
|
||||
// process.stdout.write(options.display, encoding);
|
||||
fs.writeSync(process.stdout.fd, options.display);
|
||||
|
@ -48,12 +46,9 @@ function _readlineSync(options) { // options.display is string
|
|||
}
|
||||
fd = process.stdin.fd;
|
||||
isOpened = true;
|
||||
console.warn('STD OK');
|
||||
|
||||
} else {
|
||||
|
||||
try {
|
||||
console.warn('CON TRY');
|
||||
if (options.display !== '') {
|
||||
fd = fs.openSync('\\\\.\\CON', 'w');
|
||||
fs.writeSync(fd, options.display);
|
||||
|
@ -62,13 +57,10 @@ function _readlineSync(options) { // options.display is string
|
|||
}
|
||||
fd = fs.openSync('\\\\.\\CON', 'rs');
|
||||
isOpened = true;
|
||||
console.warn('CON OK');
|
||||
} catch (e) {}
|
||||
|
||||
if (!isOpened || options.display !== '') { // Retry
|
||||
|
||||
try {
|
||||
console.warn('CONINOUT TRY');
|
||||
// For raw device path
|
||||
// On XP, 2000, 7 (x86), it might fail.
|
||||
// And, process.binding('fs') might be no good.
|
||||
|
@ -84,24 +76,19 @@ function _readlineSync(options) { // options.display is string
|
|||
fd = fsBind.open('CONIN$',
|
||||
constBind.O_RDWR | constBind.O_SYNC, parseInt('0666', 8));
|
||||
isOpened = true;
|
||||
console.warn('CONINOUT OK');
|
||||
} catch (e) {}
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
} else {
|
||||
try {
|
||||
console.warn('/dev/tty TRY');
|
||||
fd = fs.openSync('/dev/tty', 'rs+');
|
||||
isOpened = true;
|
||||
if (options.display !== '') {
|
||||
fs.writeSync(fd, options.display);
|
||||
options.display = '';
|
||||
}
|
||||
console.warn('/dev/tty OK');
|
||||
} catch (e) {}
|
||||
|
||||
}
|
||||
|
||||
if (isOpened && options.display === '') {
|
||||
|
@ -148,12 +135,26 @@ function _readlineShell(options) {
|
|||
encoding: encoding
|
||||
};
|
||||
|
||||
if (options.noEchoBack) {
|
||||
cmdArgs.push('noechoback');
|
||||
// To send any text to crazy Windows shell safely.
|
||||
function encodeDOS(arg) {
|
||||
return arg.replace(/[^\w\u0080-\uFFFF]/g, function(chr) {
|
||||
return '#' + chr.charCodeAt(0) + ';';
|
||||
});
|
||||
}
|
||||
|
||||
if (options.keyIn) { cmdArgs.push('--keyin'); }
|
||||
else if (options.noEchoBack) { cmdArgs.push('--noechoback'); }
|
||||
if (options.display !== '') {
|
||||
if (IS_WIN) {
|
||||
cmdArgs.push('--display', encodeDOS(options.display));
|
||||
process.env.NODE_EXEC_PATH = process.execPath;
|
||||
process.env.RLS_ENCODING = encoding;
|
||||
} else {
|
||||
cmdArgs.push('--display', options.display);
|
||||
}
|
||||
}
|
||||
|
||||
if (childProc.execFileSync) {
|
||||
console.warn('execFileSync');
|
||||
if (IS_WIN) {
|
||||
process.env.Q = '"'; // The quote (") that isn't escaped.
|
||||
execArgs = ['/V:ON', '/S', '/C',
|
||||
|
@ -173,10 +174,10 @@ function _readlineShell(options) {
|
|||
res.error.shellMessage = e.stderr.trim();
|
||||
}
|
||||
} else {
|
||||
console.warn('_execSyncByFile');
|
||||
res = _execSyncByFile(cmdArgs, execOptions);
|
||||
}
|
||||
if (!res.error) { res.input = res.input.replace(/^'|'$/g, ''); }
|
||||
options.display = '';
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -222,7 +223,7 @@ function _execSyncByFile(cmdArgs, execOptions) {
|
|||
process.env.Q = '"'; // The quote (") that isn't escaped.
|
||||
// `()` for ignore space by echo
|
||||
execArgs = ['/V:ON', '/S', '/C',
|
||||
'(' + SHELL_PATH + ' /V:ON /S /C %Q%%Q%' + SHELL_CMD + '%Q%' +
|
||||
'(%Q%' + SHELL_PATH + '%Q% /V:ON /S /C %Q%%Q%' + SHELL_CMD + '%Q%' +
|
||||
cmdArgs.map(function(arg) { return ' %Q%' + arg + '%Q%'; }).join('') +
|
||||
' & (echo !ERRORLEVEL!)>%Q%' + pathStatus + '%Q%%Q%) 2>%Q%' + pathStderr + '%Q%' +
|
||||
' |%Q%' + process.execPath + '%Q% %Q%' + __dirname + '\\encrypt.js%Q%' +
|
||||
|
@ -232,8 +233,9 @@ function _execSyncByFile(cmdArgs, execOptions) {
|
|||
} else {
|
||||
execArgs = ['-c',
|
||||
// Use `()`, not `{}` for `-c` (text param)
|
||||
'(' + SHELL_PATH + ' "' + SHELL_CMD + '"' +
|
||||
cmdArgs.map(function(arg) { return ' "' + arg + '"'; }).join('') +
|
||||
'("' + SHELL_PATH + '" "' + SHELL_CMD + '"' +
|
||||
cmdArgs.map(function(arg)
|
||||
{ return ' "' + arg.replace(/[\\"`]/g, '\\\$&') + '"'; }).join('') +
|
||||
'; echo $?>"' + pathStatus + '") 2>"' + pathStderr + '"' +
|
||||
' |"' + process.execPath + '" "' + __dirname + '/encrypt.js"' +
|
||||
' "' + ALGORITHM_CIPHER + '" "' + password + '"' +
|
||||
|
@ -292,27 +294,35 @@ exports.setBufferSize = function(newBufSize) {
|
|||
};
|
||||
|
||||
exports.prompt = function(options) {
|
||||
options = options || {};
|
||||
options.display = promptText + '';
|
||||
options.keyIn = false;
|
||||
return _readlineSync(options);
|
||||
var readOptions = {
|
||||
display: promptText + '',
|
||||
noEchoBack: options.noEchoBack,
|
||||
keyIn: false,
|
||||
noTrim: options.noTrim
|
||||
};
|
||||
return _readlineSync(readOptions);
|
||||
};
|
||||
|
||||
exports.question = function(query, options) {
|
||||
options = options || {};
|
||||
var readOptions = {
|
||||
/* jshint eqnull:true */
|
||||
options.display = query != null ? query + '' : '';
|
||||
display: query != null ? query + '' : '',
|
||||
/* jshint eqnull:false */
|
||||
options.keyIn = false;
|
||||
return _readlineSync(options);
|
||||
noEchoBack: options.noEchoBack,
|
||||
keyIn: false,
|
||||
noTrim: options.noTrim
|
||||
};
|
||||
return _readlineSync(readOptions);
|
||||
};
|
||||
|
||||
exports.keyIn = function(query, options) {
|
||||
options = options || {};
|
||||
var readOptions = {
|
||||
/* jshint eqnull:true */
|
||||
options.display = query != null ? query + '' : '';
|
||||
display: query != null ? query + '' : '',
|
||||
/* jshint eqnull:false */
|
||||
options.keyIn = true;
|
||||
options.noEchoBack = false;
|
||||
return _readlineSync(options);
|
||||
noEchoBack: false,
|
||||
keyIn: true,
|
||||
noTrim: true
|
||||
};
|
||||
return _readlineSync(readOptions);
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue