Checke Console::lineedit error return values

Console::lineedit can return -1 to indicate input error and -2 to
indicate the program is closing. But most users don't check possible
unusual return values which can lead to exit hang.
develop
Pauli 2018-06-21 16:57:36 +03:00
parent 84b1361387
commit 1fc37f8ddc
6 changed files with 51 additions and 35 deletions

@ -283,9 +283,6 @@ static int lua_dfhack_is_interactive(lua_State *S)
static int dfhack_lineedit_sync(lua_State *S, Console *pstream) static int dfhack_lineedit_sync(lua_State *S, Console *pstream)
{ {
if (!pstream)
return 2;
const char *prompt = luaL_optstring(S, 1, ">> "); const char *prompt = luaL_optstring(S, 1, ">> ");
const char *hfile = luaL_optstring(S, 2, NULL); const char *hfile = luaL_optstring(S, 2, NULL);
@ -299,7 +296,10 @@ static int dfhack_lineedit_sync(lua_State *S, Console *pstream)
if (rv < 0) if (rv < 0)
{ {
lua_pushnil(S); lua_pushnil(S);
lua_pushstring(S, "input error"); if (rv == -2)
lua_pushstring(S, "shutdown requested");
else
lua_pushstring(S, "input error");
return 2; return 2;
} }
else else
@ -333,8 +333,11 @@ static int dfhack_lineedit(lua_State *S)
lua_settop(S, 2); lua_settop(S, 2);
Console *pstream = get_console(S); Console *pstream = get_console(S);
if (!pstream) if (!pstream) {
lua_pushnil(S);
lua_pushstring(S, "no console");
return 2; return 2;
}
lua_rawgetp(S, LUA_REGISTRYINDEX, &DFHACK_QUERY_COROTABLE_TOKEN); lua_rawgetp(S, LUA_REGISTRYINDEX, &DFHACK_QUERY_COROTABLE_TOKEN);
lua_rawgetp(S, -1, S); lua_rawgetp(S, -1, S);
@ -1058,7 +1061,11 @@ bool DFHack::Lua::RunCoreQueryLoop(color_ostream &out, lua_State *state,
prompt = ">> "; prompt = ">> ";
std::string curline; std::string curline;
con.lineedit(prompt,curline,hist); rv = con.lineedit(prompt,curline,hist);
if (rv < 0) {
rv = rv == -2 ? LUA_OK : LUA_ERRRUN;
break;
}
hist.add(curline); hist.add(curline);
{ {

@ -505,17 +505,17 @@ function prompt_yes_no(msg,default)
prompt = prompt..' (y/n)[n]: ' prompt = prompt..' (y/n)[n]: '
end end
while true do while true do
local rv = dfhack.lineedit(prompt) local rv,err = dfhack.lineedit(prompt)
if rv then if not rv then
if string.match(rv,'^[Yy]') then qerror(err);
return true elseif string.match(rv,'^[Yy]') then
elseif string.match(rv,'^[Nn]') then return true
return false elseif string.match(rv,'^[Nn]') then
elseif rv == 'abort' then return false
qerror('User abort') elseif rv == 'abort' then
elseif rv == '' and default ~= nil then qerror('User abort')
return default elseif rv == '' and default ~= nil then
end return default
end end
end end
end end
@ -524,7 +524,10 @@ end
function prompt_input(prompt,check,quit_str) function prompt_input(prompt,check,quit_str)
quit_str = quit_str or '~~~' quit_str = quit_str or '~~~'
while true do while true do
local rv = dfhack.lineedit(prompt) local rv,err = dfhack.lineedit(prompt)
if not rv then
qerror(err);
end
if rv == quit_str then if rv == quit_str then
qerror('User abort') qerror('User abort')
end end

@ -214,7 +214,7 @@ DFHack::command_result parseRectangle(DFHack::color_ostream & out,
bool hasConsole = true) bool hasConsole = true)
{ {
using namespace DFHack; using namespace DFHack;
int newWidth = 0, newHeight = 0, newZLevels = 0; int newWidth = 0, newHeight = 0, newZLevels = 0, rv = 0;
if (end > start + 1) if (end > start + 1)
{ {
@ -237,7 +237,8 @@ DFHack::command_result parseRectangle(DFHack::color_ostream & out,
str.str(""); str.str("");
str << "Set range width <" << width << "> "; str << "Set range width <" << width << "> ";
con.lineedit(str.str(), command, hist); if ((rv = con.lineedit(str.str(), command, hist)) < 0)
return rv == -2 ? CR_OK : CR_FAILURE;
hist.add(command); hist.add(command);
newWidth = command.empty() ? width : atoi(command.c_str()); newWidth = command.empty() ? width : atoi(command.c_str());
} else { } else {
@ -251,7 +252,8 @@ DFHack::command_result parseRectangle(DFHack::color_ostream & out,
str.str(""); str.str("");
str << "Set range height <" << height << "> "; str << "Set range height <" << height << "> ";
con.lineedit(str.str(), command, hist); if ((rv = con.lineedit(str.str(), command, hist)) < 0)
return rv == -2 ? CR_OK : CR_FAILURE;
hist.add(command); hist.add(command);
newHeight = command.empty() ? height : atoi(command.c_str()); newHeight = command.empty() ? height : atoi(command.c_str());
} else { } else {
@ -265,7 +267,8 @@ DFHack::command_result parseRectangle(DFHack::color_ostream & out,
str.str(""); str.str("");
str << "Set range z-levels <" << zLevels << "> "; str << "Set range z-levels <" << zLevels << "> ";
con.lineedit(str.str(), command, hist); if ((rv = con.lineedit(str.str(), command, hist)) < 0)
return rv == -2 ? CR_OK : CR_FAILURE;
hist.add(command); hist.add(command);
newZLevels = command.empty() ? zLevels : atoi(command.c_str()); newZLevels = command.empty() ? zLevels : atoi(command.c_str());
} else { } else {

@ -188,8 +188,9 @@ command_result df_liquids (color_ostream &out_, vector <string> & parameters)
std::stringstream str; std::stringstream str;
print_prompt(str, cur_mode); print_prompt(str, cur_mode);
str << "# "; str << "# ";
if(out.lineedit(str.str(),input,liquids_hist) == -1) int rv;
return CR_FAILURE; if((rv = out.lineedit(str.str(),input,liquids_hist)) < 0)
return rv == -2 ? CR_OK : CR_FAILURE;
liquids_hist.add(input); liquids_hist.add(input);
commands.clear(); commands.clear();

@ -96,6 +96,7 @@ command_result mode (color_ostream &out_, vector <string> & parameters)
string command = ""; string command = "";
bool set = false; bool set = false;
bool abuse = false; bool abuse = false;
int rv = 0;
t_gamemodes gm; t_gamemodes gm;
for(auto iter = parameters.begin(); iter != parameters.end(); iter++) for(auto iter = parameters.begin(); iter != parameters.end(); iter++)
{ {
@ -139,9 +140,9 @@ command_result mode (color_ostream &out_, vector <string> & parameters)
string selected; string selected;
input_again: input_again:
CommandHistory hist; CommandHistory hist;
out.lineedit("Enter new mode: ",selected, hist); rv = out.lineedit("Enter new mode: ",selected, hist);
if(selected == "c") if(rv < 0 || selected == "c")
return CR_OK; return rv == -2 ? CR_OK : CR_FAILURE;
const char * start = selected.c_str(); const char * start = selected.c_str();
char * end = 0; char * end = 0;
select = strtol(start, &end, 10); select = strtol(start, &end, 10);
@ -178,14 +179,14 @@ command_result mode (color_ostream &out_, vector <string> & parameters)
{ {
CommandHistory hist; CommandHistory hist;
string selected; string selected;
out.lineedit("Enter new game mode number (c for exit): ",selected, hist); rv = out.lineedit("Enter new game mode number (c for exit): ",selected, hist);
if(selected == "c") if(rv < 0 || selected == "c")
return CR_OK; return rv == -2 ? CR_OK : CR_FAILURE;
const char * start = selected.c_str(); const char * start = selected.c_str();
gm.g_mode = (GameMode) strtol(start, 0, 10); gm.g_mode = (GameMode) strtol(start, 0, 10);
out.lineedit("Enter new game type number (c for exit): ",selected, hist); rv = out.lineedit("Enter new game type number (c for exit): ",selected, hist);
if(selected == "c") if(rv < 0 || selected == "c")
return CR_OK; return rv == -2 ? CR_OK : CR_FAILURE;
start = selected.c_str(); start = selected.c_str();
gm.g_type = (GameType) strtol(start, 0, 10); gm.g_type = (GameType) strtol(start, 0, 10);
} }

@ -984,9 +984,10 @@ command_result df_tiletypes (color_ostream &out_, vector <string> & parameters)
printState(out); printState(out);
std::string input = ""; std::string input = "";
int rv = 0;
if (out.lineedit("tiletypes> ",input,tiletypes_hist) == -1) if ((rv = out.lineedit("tiletypes> ",input,tiletypes_hist)) < 0)
return CR_FAILURE; return rv == -2 ? CR_OK : CR_FAILURE;
tiletypes_hist.add(input); tiletypes_hist.add(input);
commands.clear(); commands.clear();