void write(const nstr& in){ if(ifd_ < 0){ NERROR("command was not started with input mode"); } int n = ::write(ifd_, in.c_str(), in.length()); if(n < 0){ NERROR("error while writing"); } }
nvar run_(const nstr& fs, const nvec& v){ nvar f = nvar(fs, nvar::Func); f.append(v); stringstream sstr; generator_.generate(sstr, f); NCommand* cmd = _commandPool.acquire(); cmd->write(sstr.str()); nvec m; if(!cmd->matchOutput(_outputRegex, m, 10.0)){ delete cmd; _commandPool.release(0); NERROR("failed to run: " + v); } _commandPool.release(cmd); //cout << "out: " << m[1] << endl; return parser_.parse(m[1]); }
void init(){ _mutex.lock(); if(!_initialized){ NProgram::use(); if(_mathKernelPath.empty()){ NERROR("unspecified _mathKernelPath"); } if(!NSys::exists(_mathKernelPath)){ NERROR("invalid _mathKernelPath: " + _mathKernelPath); } _initialized = true; } _mutex.unlock(); }
bool connect(const nstr& host, int port){ if(socket_){ NERROR("socket exists"); } socket_ = new NSocket; if(!socket_->connect(host, port)){ delete socket_; socket_ = 0; return false; } init(); return true; }
NRegex_(NRegex* o, const nstr& pattern, uint32_t flags) : o_(o){ try{ #ifdef __APPLE__ regex_ = new regex(pattern.c_str()); #else nstr normPattern = pattern; normPattern.findReplace("[^]", "."); regex_ = new regex(normPattern.c_str()); #endif } catch(std::exception& e){ NERROR("invalid pattern: " + pattern); } }
bool readError(nstr& err, double timeout){ if(efd_ < 0){ NERROR("command was not started with error mode"); } char buf[2049]; fd_set fds; FD_ZERO(&fds); FD_SET(efd_, &fds); double sec = floor(timeout); double fsec = timeout - sec; timeval tv; tv.tv_sec = sec; tv.tv_usec = fsec*1e6; if(select(efd_ + 1, &fds, NULL, NULL, &tv)){ for(;;){ int n = ::read(efd_, buf, 2048); if(n == -1){ timeval tv2; tv2.tv_sec = 0; tv2.tv_usec = 50000; if(!select(ofd_ + 1, &fds, NULL, NULL, &tv2)){ break; } } else if(n == 0){ return true; } buf[n] = '\0'; err += buf; } return true; } else{ return false; } }
bool matchError(const NRegex& regex, nvec& m, double timeout){ if(efd_ < 0){ NERROR("command was not started with output mode"); } char buf[2049]; fd_set fds; FD_ZERO(&fds); FD_SET(ofd_, &fds); nstr err; for(;;){ double sec = floor(timeout); double fsec = timeout - sec; timeval tv; tv.tv_sec = sec; tv.tv_usec = fsec*1e6; if(select(efd_ + 1, &fds, NULL, NULL, &tv)){ int n = ::read(efd_, buf, 2048); if(n > 0){ buf[n] = '\0'; err += buf; if(regex.match(err, m)){ return true; } } } else{ return false; } } }
void validate(const nvar& v){ if(!NConcept::isNumeric(v, false)){ NERROR("invalid value: " + v.toStr()); } }
NCommand_(NCommand* o, const nstr& command, int mode) : o_(o), command_(command), closeSignal_(15), ifd_(-1), ofd_(-1), efd_(-1), mode_(mode){ int ip[2]; int op[2]; int ep[2]; if(mode_ & NCommand::OutputWithError && (mode_ & NCommand::Output || mode_ & NCommand::Error)){ NERROR("OutputWithError mode cannot be combined with Output or " "Error modes"); } if(mode_ & NCommand::Input){ pipe(ip); } if(mode_ & NCommand::Output){ pipe(op); } if(mode_ & NCommand::Error){ pipe(ep); } if(mode_ & NCommand::OutputWithError){ pipe(op); } if(!isPersistent()){ _resourceManager->add(o_); } pid_ = fork(); if(pid_ < 0){ NERROR("failed to execute command: " + command); } if(pid_ == 0){ if(mode_ & NCommand::Input){ ::close(ip[1]); dup2(ip[0], 0); ::close(ip[0]); } if(mode_ & NCommand::Output){ ::close(op[0]); dup2(op[1], 1); ::close(op[1]); } if(mode_ & NCommand::Error){ ::close(ep[0]); dup2(ep[1], 2); ::close(ep[1]); } if(mode_ & NCommand::OutputWithError){ ::close(op[0]); dup2(op[1], 1); dup2(op[1], 2); ::close(op[1]); } if(execl("/bin/bash", "bash", "-c", command.c_str(), NULL) < 0){ NERROR("failed to execute command: " + command); } } else{ if(mode_ & NCommand::Input){ ::close(ip[0]); ifd_ = ip[1]; } if(mode_ & NCommand::Output){ ::close(op[1]); ofd_ = op[0]; fcntl(ofd_, F_SETFL, O_NONBLOCK); } if(mode_ & NCommand::Error){ ::close(ep[1]); efd_ = ep[0]; fcntl(efd_, F_SETFL, O_NONBLOCK); } if(mode_ & NCommand::OutputWithError){ ::close(op[1]); ofd_ = op[0]; efd_ = op[0]; fcntl(ofd_, F_SETFL, O_NONBLOCK); } } }