और खोल भागने समस्या के लिए एक पूर्ण समाधान है:
यहां एक नमूना कार्य है। हालांकि यह शैल के लिए स्ट्रिंग से बचने के सटीक प्रश्न का उत्तर नहीं देता है। यह कार्यक्रम के लिए तर्क पारित करने की समस्या हल करता है। यह समाधान आदेशों को निष्पादित करने के लिए आदेशों को निष्पादित करने के लिए आदेशों को निष्पादित करने के लिए एक पॉज़िक्स पोर्टेबल तरीका है जो उन्हें बचने की आवश्यकता के बारे में चिंता किए बिना कमांड में पास किया गया है।
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <string>
#include <sys/stat.h>
#include <vector>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
std::vector<std::string> split(std::string delimiter, std::string str){
std::size_t nextPos = 0;
std::size_t delimiterSize = delimiter.size();
std::vector<std::string> list;
while(true){
std::size_t pos = str.find(delimiter, nextPos);
std::string subStr;
if(pos == std::string::npos){
list.push_back(str.substr(nextPos));
break;
}
subStr = str.substr(nextPos, pos - nextPos);
list.push_back(subStr);
nextPos = pos + delimiterSize;
}
return list;
}
bool isFileExecutable(const std::string &file)
{
struct stat st;
if (stat(file.c_str(), &st) < 0)
return false;
if ((st.st_mode & S_IEXEC) != 0)
return true;
return false;
}
std::string ensureEndsWithSlash(std::string path){
if(path[path.length()-1] != '/'){
path += "/";
}
return path;
}
std::string findProgram(std::string name){
// check if it's relative
if(name.size() > 2){
if(name[0] == '.' && name[1] == '/'){
if(isFileExecutable(name)){
return name;
}
return std::string();
}
}
std::vector<std::string> pathEnv = split(":", getenv("PATH"));
for(std::string path : pathEnv){
path = ensureEndsWithSlash(path);
path += name;
if(isFileExecutable(path)){
return path;
}
}
return std::string();
}
// terminal condition
void toVector(std::vector<std::string> &vector, const std::string &str){
vector.push_back(str);
}
template<typename ...Args>
void toVector(std::vector<std::string> &vector, const std::string &str, Args ...args){
vector.push_back(str);
toVector(vector, args...);
}
int waitForProcess(pid_t processId){
if(processId == 0){
return 0;
}
int status = 0;
int exitCode = -1;
while(waitpid(processId, &status, 0) != processId){
// wait for it
}
if (WIFEXITED(status)) {
exitCode = WEXITSTATUS(status);
}
return exitCode;
}
/**
Runs the process and returns the exit code.
You should change it so you can detect process failure
vs this function actually failing as a process can return -1 too
@return -1 on failure, or exit code of process.
*/
template<typename ...Args>
int mySystem(Args ...args){
std::vector<std::string> command;
toVector(command, args...);
command[0] = findProgram(command[0]);
if(command[0].empty()){
// handle this case by returning error or something
// maybe std::abort() with error message
return -1;
}
pid_t pid = fork();
if(pid) {
// parent wait for child
return waitForProcess(pid);
}
// we are child make a C friendly array
// this process will be replaced so we don't care about memory
// leaks at this point.
std::vector<char*> c_command;
for(int i = 0; i < command.size(); ++i){
c_command.push_back(strdup(command[i].c_str()));
}
// null terminate the sequence
c_command.push_back(nullptr);
execvp(c_command[0], &c_command[0]);
// just incase
std::abort();
return 0;
}
int main(int argc, char**argv){
// example usage
mySystem("echo", "hello", "world");
}
स्रोत
2016-07-23 21:10:53
आप सही हैं। यह न केवल है '' लेकिन ' "'" ': पी –
यह एक विशिष्ट खोल के लिए एक सुरक्षित समाधान बनाने के लिए संभव है, लेकिन मैं जवाब प्रश्न पूछा, स्वीकार किया कि यह इसके बारे में जाने के लिए सबसे अच्छा तरीका नहीं था, और एक सुरक्षित प्रदान की वैकल्पिक। मुझे नहीं लगता कि यह एक कम वोट के लायक है। –