extract arg quoting for iwndows

This commit is contained in:
Tim Felgentreff 2022-04-28 21:01:27 +02:00
parent cca28d94a6
commit e4c4b29805
3 changed files with 49 additions and 31 deletions
src

View file

@ -146,6 +146,8 @@ extern bool CanAccessFile(const char *filename);
/// Read the contents of a directory
extern int ReadDataDirectory(const char *dirname, std::vector<FileList> &flp);
extern std::vector<std::string> QuoteArguments(std::vector<std::string> args);
//@}
#endif // !__IOLIB_H__

View file

@ -837,4 +837,46 @@ FileWriter *CreateFileWriter(const std::string &filename)
}
}
/**
* Quote arguments for usage in calls to system(), popen() and similar.
* Really only needed on Windows, where all these calls just concatenate
* all arguments with a space and pass the full string to the next process.
*/
std::vector<std::string> QuoteArguments(std::vector<std::string> args)
{
std::vector<std::string> outArgs;
for (auto arg : args) {
#ifdef WIN32
if (!arg.empty() && arg.find_first_of(" \t\n\v\"") == std::string::npos) {
outArgs.push_back(arg);
} else {
// Windows always needs argument quoting around arguments with spaces
std::string ss = "\"";
for (auto ch = arg.begin(); ; ch++) {
int backslashes = 0;
while (ch != arg.end() && *ch == '\\') {
ch++;
backslashes++;
}
if (ch == arg.end()) {
ss.append(backslashes * 2, '\\');
break;
} else if (*ch == '"') {
ss.append(backslashes * 2 + 1, '\\');
ss.push_back(*ch);
} else {
ss.append(backslashes, '\\');
ss.push_back(*ch);
}
}
ss.push_back('"');
outArgs.push_back(ss);
}
#else
outArgs.push_back(arg);
#endif
}
return outArgs;
}
//@}

View file

@ -2158,38 +2158,12 @@ static int CclRestartStratagus(lua_State *l)
break;
}
}
int newArgc = OriginalArgv.size() + (insertRestartArgument ? 2 : 1);
std::vector<std::string> quotedArgs = QuoteArguments(OriginalArgv);
int newArgc = quotedArgs.size() + (insertRestartArgument ? 2 : 1);
char **argv = new char*[newArgc];
for (unsigned int i = 0; i < OriginalArgv.size(); i++) {
#ifdef WIN32
if (!OriginalArgv[i].empty() && OriginalArgv[i].find_first_of(" \t\n\v\"") == std::string::npos) {
argv[i] = const_cast<char*>(OriginalArgv[i].c_str());
} else {
// Windows always needs argument quoting around arguments with spaces
std::string ss = "\"";
for (auto ch = OriginalArgv[i].begin(); ; ch++) {
int backslashes = 0;
while (ch != OriginalArgv[i].end() && *ch == '\\') {
ch++;
backslashes++;
}
if (ch == OriginalArgv[i].end()) {
ss.append(backslashes * 2, '\\');
break;
} else if (*ch == '"') {
ss.append(backslashes * 2 + 1, '\\');
ss.push_back(*ch);
} else {
ss.append(backslashes, '\\');
ss.push_back(*ch);
}
}
ss.push_back('"');
argv[i] = strdup(ss.c_str());
}
#else
argv[i] = const_cast<char*>(OriginalArgv[i].c_str());
#endif
for (unsigned int i = 0; i < quotedArgs.size(); i++) {
argv[i] = const_cast<char*>(quotedArgs[i].c_str());
}
if (insertRestartArgument) {
argv[newArgc - 2] = (char*)"-r";