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