int win_makedir(char *path, char **emsg) { if (!CreateDirectory(path, NULL)) { int ret, ecode = GetLastError(); *emsg = get_error_msg(ecode); switch (ecode) { case ERROR_FILE_NOT_FOUND: case ERROR_PATH_NOT_FOUND: ret = FX_NO_SUCH_FILE; break; case ERROR_ACCESS_DENIED: ret = FX_PERMISSION_DENIED; break; case ERROR_ALREADY_EXISTS: ret = FX_FAILURE; break; default: ret = FX_FAILURE; } return ret; } *emsg = NULL; return FX_OK; }
int win_createfile(char *path, unsigned int flags, void **handle, char **emsg) { DWORD access = 0, shared = 0, dispo = 0; HANDLE fd; int len = (int)strlen(path); if (flags & FXF_READ) { access |= GENERIC_READ; } if (flags & FXF_WRITE) { access |= GENERIC_WRITE; } if (flags & FXF_APPEND) { access |= FILE_APPEND_DATA; } if (flags & FXF_CREAT) { dispo |= CREATE_ALWAYS; } if (!(flags & FXF_CREAT) && (flags & FXF_TRUNC)) { dispo |= TRUNCATE_EXISTING; } if (flags & FXF_EXCL) { shared = 0; } else { shared = FILE_SHARE_READ | FILE_SHARE_WRITE; } fd = CreateFile(path, access, shared, NULL, dispo, FILE_ATTRIBUTE_NORMAL, NULL); if (fd == INVALID_HANDLE_VALUE) { int ret, ecode = GetLastError(); *emsg = get_error_msg(ecode); switch (ecode) { case ERROR_FILE_NOT_FOUND: case ERROR_PATH_NOT_FOUND: ret = FX_NO_SUCH_FILE; break; case ERROR_ACCESS_DENIED: ret = FX_PERMISSION_DENIED; break; case ERROR_ALREADY_EXISTS: ret = FX_FAILURE; break; default: ret = FX_FAILURE; } return ret; } *handle = fd; return FX_OK; }
void WatchWin32::watch(const std::string &dir, uint32_t filters, const Callback &callback){ auto fnd = watchers.find(dir); if (fnd != watchers.end() && fnd->second.filter != filters){ fnd->second.filter = filters; fnd->second.callback = callback; register_watch(fnd->second); return; } HANDLE handle = CreateFile(dir.c_str(), FILE_LIST_DIRECTORY, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, nullptr); if (handle == INVALID_HANDLE_VALUE){ std::cerr << "lfw Error: failed to create handle for " << dir << ": " << get_error_msg(GetLastError()) << std::endl; return; } auto it = watchers.emplace(std::make_pair(dir, WatchData{handle, dir, filters, callback})); register_watch(it.first->second); }
// python function stop(channel) static PyObject *py_stop_channel(PyObject *self, PyObject *args, PyObject *kwargs) { char key[8]; char *channel; int gpio; int allowed = -1; clear_error_msg(); if (!PyArg_ParseTuple(args, "s", &channel)) return NULL; if (!get_key(channel, key)) { PyErr_SetString(PyExc_ValueError, "Invalid PWM key or name."); return NULL; } // check to ensure gpio is one of the allowed pins // Not protecting the call as if the get_key() fails, we won't make it here get_gpio_number(channel, &gpio); // Check to see if GPIO is allowed on the hardware // A 1 means we're good to go allowed = gpio_allowed(gpio); if (allowed == -1) { char err[2000]; snprintf(err, sizeof(err), "Error determining hardware. (%s)", get_error_msg()); PyErr_SetString(PyExc_ValueError, err); return NULL; } else if (allowed == 0) { char err[2000]; snprintf(err, sizeof(err), "GPIO %d not available on current Hardware", gpio); PyErr_SetString(PyExc_ValueError, err); return NULL; } softpwm_disable(key); Py_RETURN_NONE; }
void display_db_error_msg(void) { Errors::display_error_msg(db_error); db_error = get_error_msg(Errors::error_no_error); }
void update_last_error(void) { last_error = db_error; db_error = get_error_msg(Errors::error_no_error); }
namespace DBase { // TODO(Garcia): CONTINUE WORKING ON THIS DATABASE FILE. static Errors::err_info db_error = get_error_msg(Errors::error_no_error); static Errors::err_info last_error = get_error_msg(Errors::error_no_error); void update_last_error(void) { last_error = db_error; db_error = get_error_msg(Errors::error_no_error); } // Table map used to store information of each database table. std::unordered_map<std::string, Table&> table_map; // Still needing to update this thing. Table* add_table(Database& database, std::string password) { std::pair<std::string, Table&> stored_pair(password, database); table_map.insert(stored_pair); return NULL; // for now... } Database::Database(void) : containers() , table_name("no name") , directory_path(default_path + table_name) { } Database::Database(std::string table_name) : Database() { this->table_name = table_name; directory_path = default_path + table_name; } Database::~Database(void) { } // Merges database to this one. bool Database::merge(Database* database) { if(database == NULL) { db_error = last_error = Errors::get_error_msg(Errors::error_null_value); return false; } for(size_t i = 0; i < database->get_number_of_containers(); ++i) { _iter iter = std::find(containers.begin(), containers.end(), (*database)[i]); if(iter == containers.end()) { containers.push_back((*database)[i]); } } return true; } // Checks if database is a subset of this one. bool Database::is_subset(Database* database) { return true; } /** * Saves the database into its own folder. * Still working on this!!!! */ bool Database::save_table(std::string name) { folder_create(); if(db_error.code_number == Errors::error_path_not_found) { return false; } if(!containers.empty()) { std::ofstream file; serialization::ObjectStream temp_stream; for(int i = 0; i < containers.size(); ++i) { Container* container = &containers.at(i); file.open(directory_path + "/" + container->get_container_name() + ".txt" , std::fstream::in | std::fstream::out | std::fstream::trunc); if(file.is_open()) { container->serialize(temp_stream); temp_stream.write_to_file(file); file.close(); } } } update_last_error(); return true; } // Load up a database to this one. Will override everything on this database object. bool Database::load_table(std::string name) { return true; } bool Database::folder_create(void) { _BOOL_ success = create_folder(directory_path.c_str(), NULL); if(success == 0) { _ERR_ err = _OBTAIN_LAST_ERROR; // These are windows api macros that must be changed later on for compatibility reasons. if(err == ERROR_ALREADY_EXISTS) { db_error = get_error_msg(Errors::error_folder_already_exists); } else if(err == ERROR_PATH_NOT_FOUND) { db_error = get_error_msg(Errors::error_path_not_found); } } return bool(success); } bool Database::change_database_name(std::string new_name) { if(table_name.compare(new_name) == STR_MATCH) { return false; } table_name = new_name; return true; } bool Database::add_container(Container* container) { bool is_unique = true; _iter iter = std::find(containers.begin(), containers.end(), *container); if(iter == containers.end()) { containers.push_back(*container); } else { is_unique = false; } return is_unique; } bool Database::remove_container(std::string container_name) { bool removed = false; Container temp(container_name); _iter iter = std::find(containers.begin(), containers.end(), temp); if(iter != containers.end()) { containers.erase(iter); removed = true; } return removed; } Container* Database::get_container(std::string container_name) { Container* container_ptr = NULL; for(size_t i = 0; i < containers.size(); ++i) { Container* cont = &containers.at(i); if(cont->get_container_name().compare(container_name) == STR_MATCH) { container_ptr = cont; break; } } return container_ptr; } Database Database::intersection(Database* database) { Database new_database; return new_database; } Database Database::clone(void) { return *this; } Column* Database::find_column(std::string column_name) { Column* container_ptr = new Column(column_name); for(size_t i = 0; i < containers.size(); ++i) { Container* container = &containers[i]; for(size_t j = 0; j < container->get_size(); ++j) { Element* element = &(*container)[j]; if(element->get_column_name().compare(column_name) == STR_MATCH) { container_ptr->insert_element(*element); break; } } } return container_ptr; } Column* Database::find_column(Column column) { return find_column(column.get_column_name()); } std::string Database::display_all_containers() { std::string result = ""; return result; } int Database::compare_to(const Database& _right) { if(containers.size() == _right.containers.size()) { return (_EQUAL); } else if(containers.size() > _right.containers.size()) { return (_GREATER); } else { return (_LESSER); } } bool Database::equals(const Database& _right) { bool is_equal = false; if(table_name.compare(_right.table_name) == STR_MATCH) { if(directory_path.compare(_right.directory_path) == STR_MATCH) { if(containers.size() == _right.containers.size()) { bool result = true; for(size_t i = 0; i < containers.size(); ++i) { Container& container = containers.at(i); std::vector<Container>& vec_containers = (std::vector<Container>)_right.containers; _iter iter = std::find(vec_containers.begin(), vec_containers.end(), container); if(iter == vec_containers.end()) { result = false; break; } } if(result) { is_equal = true; } } } } return is_equal; } const Database& Database::operator=(const Database& _right) { this->table_name = _right.table_name; this->directory_path = _right.directory_path; this->containers = _right.containers; return (*this); } void display_db_error_msg(void) { Errors::display_error_msg(db_error); db_error = get_error_msg(Errors::error_no_error); } void display_last_error(void) { Errors::display_error_msg(last_error); } } // Database nameapace
void printDebug(int errorcode) { char *msg; msg = get_error_msg(errorcode); printf("D: %s, SYM: %s, Lahead: %s, LINENR: %d \n",msg, get_token_name(symbol), get_token_name(lookahead), lineNR); }
void printError(int errorcode) { char *msg; msg = get_error_msg(errorcode); printf("Syntax error at: %d %s \n", lineNR, msg); }
static VALUE oci8_make_exc(dvoid *errhp, sword status, ub4 type, OCIStmt *stmthp, const char *file, int line) { VALUE exc; char errmsg[128]; sb4 errcode = -1; VALUE msg; VALUE parse_error_offset = Qnil; VALUE sql = Qnil; int rv; int numarg = 1; switch (status) { case OCI_ERROR: exc = eOCIError; msg = get_error_msg(errhp, type, "Error", &errcode); numarg = 4; break; case OCI_SUCCESS_WITH_INFO: exc = eOCISuccessWithInfo; msg = get_error_msg(errhp, type, "Error", &errcode); numarg = 4; break; case OCI_NO_DATA: exc = eOCINoData; msg = get_error_msg(errhp, type, "No Data", &errcode); numarg = 4; break; case OCI_INVALID_HANDLE: exc = eOCIInvalidHandle; msg = rb_usascii_str_new_cstr("Invalid Handle"); break; case OCI_NEED_DATA: exc = eOCINeedData; msg = rb_usascii_str_new_cstr("Need Data"); break; case OCI_STILL_EXECUTING: exc = eOCIStillExecuting; msg = rb_usascii_str_new_cstr("Still Executing"); break; case OCI_CONTINUE: exc = eOCIContinue; msg = rb_usascii_str_new_cstr("Continue"); break; default: sprintf(errmsg, "Unknown error (%d)", status); exc = eOCIException; msg = rb_usascii_str_new_cstr(errmsg); } if (stmthp != NULL) { ub2 offset; text *text; ub4 size; rv = OCIAttrGet(stmthp, OCI_HTYPE_STMT, &offset, 0, OCI_ATTR_PARSE_ERROR_OFFSET, errhp); if (rv == OCI_SUCCESS) { parse_error_offset = INT2FIX(offset); } rv = OCIAttrGet(stmthp, OCI_HTYPE_STMT, &text, &size, OCI_ATTR_STATEMENT, errhp); if (rv == OCI_SUCCESS) { sql = rb_external_str_new_with_enc(TO_CHARPTR(text), size, oci8_encoding); } } exc = rb_funcall(exc, oci8_id_new, numarg, msg, INT2FIX(errcode), sql, parse_error_offset); return set_backtrace(exc, file, line); }
// python function start(channel, duty_cycle, freq, polarity) static PyObject *py_start_channel(PyObject *self, PyObject *args, PyObject *kwargs) { char key[8]; char *channel = NULL; float frequency = 2000.0; float duty_cycle = 0.0; int polarity = 0; int gpio; int allowed = -1; static char *kwlist[] = {"channel", "duty_cycle", "frequency", "polarity", NULL}; clear_error_msg(); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|ffi", kwlist, &channel, &duty_cycle, &frequency, &polarity)) { return NULL; } ASSRT(channel != NULL); if (!module_setup) { init_module(); } if (!get_key(channel, key)) { PyErr_SetString(PyExc_ValueError, "Invalid SOFTPWM key or name."); return NULL; } // check to ensure gpio is one of the allowed pins // Not protecting the call as if the get_key() fails, we won't make it here get_gpio_number(channel, &gpio); // Check to see if GPIO is allowed on the hardware // A 1 means we're good to go allowed = gpio_allowed(gpio); if (allowed == -1) { char err[2000]; snprintf(err, sizeof(err), "Error determining hardware. (%s)", get_error_msg()); PyErr_SetString(PyExc_ValueError, err); return NULL; } else if (allowed == 0) { char err[2000]; snprintf(err, sizeof(err), "GPIO %d not available on current Hardware", gpio); PyErr_SetString(PyExc_ValueError, err); return NULL; } if (duty_cycle < 0.0 || duty_cycle > 100.0) { PyErr_SetString(PyExc_ValueError, "duty_cycle must have a value from 0.0 to 100.0"); return NULL; } if (frequency <= 0.0) { PyErr_SetString(PyExc_ValueError, "frequency must be greater than 0.0"); return NULL; } if (polarity < 0 || polarity > 1) { PyErr_SetString(PyExc_ValueError, "polarity must be either 0 or 1"); return NULL; } if (softpwm_start(key, duty_cycle, frequency, polarity) < 0) { printf("softpwm_start failed"); char err[2000]; snprintf(err, sizeof(err), "Error starting softpwm on pin %s (%s)", key, get_error_msg()); PyErr_SetString(PyExc_RuntimeError, err); return NULL; } Py_RETURN_NONE; }
/** stat a file on winnt - this is *very* painful **/ int win_filestat(stat_b *st, char *path, unsigned int want, unsigned int *give, char **err) { WIN32_FILE_ATTRIBUTE_DATA stat; SID_IDENTIFIER_AUTHORITY world_auth = SECURITY_WORLD_SID_AUTHORITY; PSID owner, group, world = NULL; PACL dacl; PSECURITY_DESCRIPTOR pdesc; int have_sec = 0; *give = 0; if (!GetFileAttributesEx(path, GetFileExInfoStandard, &stat)) { int ret, ecode = GetLastError(); *err = get_error_msg(ecode); switch (ecode) { case ERROR_FILE_NOT_FOUND: case ERROR_PATH_NOT_FOUND: ret = FX_NO_SUCH_FILE; break; case ERROR_ACCESS_DENIED: ret = FX_PERMISSION_DENIED; break; default: ret = FX_FAILURE; } return ret; } /* create a PSID for well known group "world" - this is equivalent to "others" on POSIX */ if (!AllocateAndInitializeSid(&world_auth, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &world)) world = NULL; memset(st, 0x0, sizeof(*st)); *give |= ATTR_SIZE; if (!(stat.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) st->size = ((unsigned __int64)stat.nFileSizeHigh << 32) + (unsigned __int64)stat.nFileSizeLow; else st->size = 0; if (GetNamedSecurityInfo(path, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, &owner, &group, &dacl, NULL, &pdesc) != ERROR_SUCCESS) { ERR(have_sec, "Could not retrieve security info"); have_sec = 0; } else have_sec = 1; if (have_sec) { /* fake unix style uid & gid. We will do this by getting the string representations of the owner & group PIDS and converting them to numbers (hopefully unique) char *temp; ConvertSidToStringSid(owner, &temp); st->uid = st->gid = atol(temp); printf("(%s) sid = %l , %l\n", temp, st->uid, st->gid); LocalFree(temp); */ st->uid = st->gid = 42; *give |= ATTR_UIDGID; } /* not applicable for v3 - the commented code is for v6 if ((want & ATTR_UIDGID) & have_sec){ wchar_t uname[UNLEN + 1], dname[DNLEN + 1], gname[1000], gname2[1000]; DWORD unlen = UNLEN, dnlen = DNLEN, gnlen = 1000, gnlen2 = 1000; SID_NAME_USE stype; st->owner = malloc(UNLEN + DNLEN + 2); if (!LookupAccountSidW(NULL, owner, uname, &unlen, dname, &dnlen, &stype)) { ERR(GetLastError(), "Could not lookup ownername"); free(st->owner); st->owner = NULL; } else swprintf(st->owner, UNLEN + DNLEN + 2, L"%s@%s", uname, dname); st->group = malloc(UNLEN + DNLEN + 2 + 2000); if (!LookupAccountSidW(NULL, group, gname, &gnlen, gname2, &gnlen2, &stype)) { ERR(GetLastError(), "Could not lookup group name"); if (st->owner) swprintf(st->group, UNLEN + DNLEN + 2 + 2000, L"None@%", dname); else { free(st->group); st->group = NULL; } } else swprintf(st->group, UNLEN + DNLEN + 2 + 2000, L"%s@%s", gname, gname2); *give |= ATTR_OWNERGROUP; } */ st->perms = 0; st->perms |= stat.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ? FX_S_IFDIR : FX_S_IFREG; if (have_sec) { TRUSTEE_W ident = {NULL, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID}; ACCESS_MASK acc; ident.TrusteeType = TRUSTEE_IS_USER; ident.ptstrName = owner; if (GetEffectiveRightsFromAclW(dacl, &ident, &acc) == ERROR_SUCCESS) { if (acc & FILE_EXECUTE) st->perms |= FX_S_IXUSR; if (acc & FILE_WRITE_DATA) st->perms |= FX_S_IWUSR; if (acc & FILE_READ_DATA) st->perms |= FX_S_IRUSR; } ident.TrusteeType = TRUSTEE_IS_GROUP; ident.ptstrName = group; if (GetEffectiveRightsFromAclW(dacl, &ident, &acc) == ERROR_SUCCESS) { if (acc & FILE_EXECUTE) st->perms |= FX_S_IXGRP; if (acc & FILE_WRITE_DATA) st->perms |= FX_S_IWGRP; if (acc & FILE_READ_DATA) st->perms |= FX_S_IRGRP; } if (world) { ident.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; ident.ptstrName = world; if (GetEffectiveRightsFromAclW(dacl, &ident, &acc) == ERROR_SUCCESS) { if (acc & FILE_EXECUTE) st->perms |= FX_S_IROTH; if (acc & FILE_WRITE_DATA) st->perms |= FX_S_IWOTH; if (acc & FILE_READ_DATA) st->perms |= FX_S_IROTH; } } /* we can't do shit about the S_ISUID, S_ISGUID & S_ISVTX flags */ *give |= ATTR_PERMISSIONS; } win_to_unix_time(stat.ftLastAccessTime, &st->atime); win_to_unix_time(stat.ftLastWriteTime, &st->mtime); *give |= ATTR_ACMODTIME; /* st->acl = NULL; if (want & ATTR_BITS) { st->attrib_bits_valid = ATTR_ARCHIVE | ATTR_COMPRESSED | ATTR_READONLY | ATTR_SYSTEM | ATTR_SPARSE | ATTR_HIDDEN | ATTR_ENCRYPTED; st->attrib_bits = (stat.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) | (stat.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED) | (stat.dwFileAttributes & FILE_ATTRIBUTE_READONLY) | (stat.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) | (stat.dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) | (stat.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) | (stat.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED); *give |= ATTR_BITS; } */ if (world) FreeSid(world); if (pdesc) LocalFree(pdesc); return FX_OK; }
/* Execute a command as a "user". The command is run as cmd.exe /c <command> The command is executed from the user's HOME (as determined by the user profile) Input, Output & Err streams are redirected. */ void *win_execute_command(wchar_t *shell, wchar_t *command, wchar_t *user, wchar_t *password, wchar_t *domain, wchar_t *root, int pty_mode) { SECURITY_ATTRIBUTES sa; STARTUPINFOW si; HANDLE out_rd_tmp, in_wr_tmp, out_wr, in_rd, in_wr, err_wr; exec_ctx *ctx; HANDLE ttok, ntok; int ret; ZeroMemory(&sa, sizeof(sa)); sa.nLength = sizeof(sa); sa.bInheritHandle = TRUE; ctx = malloc(sizeof(*ctx)); ZeroMemory(ctx, sizeof(*ctx)); ctx->pty_mode = pty_mode; /* setup the parent child plumbing */ if (!CreatePipe(&in_rd, &in_wr_tmp, &sa, 0)) { printf("Couldn't set up in pipe to child %s", get_error_msg(GetLastError())); free(ctx); return NULL; } if (!CreatePipe(&out_rd_tmp, &out_wr, &sa, 0)) { printf("Couldn't set up stdout pipe to child %s", get_error_msg(GetLastError())); free(ctx); return NULL; } if (!DuplicateHandle(GetCurrentProcess(), out_wr, GetCurrentProcess(), &err_wr, 0, TRUE, DUPLICATE_SAME_ACCESS)) { printf("Couldn't set up stderr pipe to child %s", get_error_msg(GetLastError())); free(ctx); return NULL; } if (!DuplicateHandle(GetCurrentProcess(), out_rd_tmp, GetCurrentProcess(), &ctx->out_rd, 0, FALSE, DUPLICATE_SAME_ACCESS)) { return NULL; } if (!DuplicateHandle(GetCurrentProcess(), in_wr_tmp, GetCurrentProcess(), &in_wr, 0, FALSE, DUPLICATE_SAME_ACCESS)) { return NULL; } CloseHandle(out_rd_tmp); CloseHandle(in_wr_tmp); ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; si.wShowWindow = SW_HIDE; si.hStdInput = in_rd; si.hStdOutput = out_wr; si.hStdError = err_wr; /* if (!CreateProcessWithLogonW(user, domain, password, LOGON_WITH_PROFILE, shell, command, 0, NULL, root, &si, &ctx->pi)) { */ ret = LogonUserW(user, domain, password, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &ttok); if (!ret) { CloseHandle(ttok); INFO(GetLastError(), "Login failed for user"); return NULL; } ret = DuplicateTokenEx(ttok, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenPrimary, &ntok); if (!ret) { CloseHandle(ttok); INFO(GetLastError(), "Can't impersonate user"); return NULL; } CloseHandle(ttok); if (!CreateProcessAsUserW(ntok, shell, command, NULL, NULL, TRUE, 0, NULL, root, &si, &ctx->pi)) { int ecode = GetLastError(); INFO(GetLastError(), "CreateProcess failed"); free(ctx); CloseHandle(ntok); return NULL; } CloseHandle(ntok); CloseHandle(out_wr); CloseHandle(err_wr); CloseHandle(in_rd); return ctx; }
bool CmdexSync::execute() { set_error_msg(""); // clear old error if present bool slot_connected = !(signal_execute_tick.slots().begin() == signal_execute_tick.slots().end()); if (slot_connected && !signal_execute_tick.emit(status_starting)) return false; if (!cmdex_.execute()) { // try to execute debug_out_error("app", DBG_FUNC_MSG << "cmdex_.execute() failed.\n"); import_error(); // get error from cmdex and display warnings if needed // emit this for execution loggers cmdex_sync_signal_execute_finish()->emit(CmdexSyncCommandInfo(get_command_name(), get_command_args(), get_stdout_str(), get_stderr_str(), get_error_msg())); if (slot_connected) signal_execute_tick.emit(status_failed); return false; } bool stop_requested = false; // stop requested from tick function bool signals_sent = false; // stop signals sent while(!cmdex_.stopped_cleanup_needed()) { if (!stop_requested) { // running and no stop requested yet // call the tick function with "running" periodically. // if it returns false, try to stop. if (slot_connected && !signal_execute_tick.emit(status_running)) { debug_out_info("app", DBG_FUNC_MSG << "execute_tick slot returned false, trying to stop the program.\n"); stop_requested = true; } } if (stop_requested && !signals_sent) { // stop request received // send the stop request to the command if (!cmdex_.try_stop()) { // try sigterm. this returns false if it can't be done (no permissions, zombie) debug_out_warn("app", DBG_FUNC_MSG << "cmdex_.try_stop() returned false.\n"); } // set sigkill timeout to 3 sec (in case sigterm fails); won't do anything if already exited. cmdex_.set_stop_timeouts(0, forced_kill_timeout_msec); // import_error(); // don't need errors here - they will be available later anyway. signals_sent = true; } // alert the tick function if (stop_requested && slot_connected) { signal_execute_tick.emit(status_stopping); // ignore returned value here } // without this, no event sources will be processed and the program will // hang waiting for the child to exit (the watch handler won't be called). while(g_main_context_pending(NULL)) { g_main_context_iteration(NULL, false); } Glib::usleep(50*1000); // 50 msec. avoids 100% CPU usage. } // command exited, do a cleanup. cmdex_.stopped_cleanup(); import_error(); // get error from cmdex and display warnings if needed // emit this for execution loggers cmdex_sync_signal_execute_finish()->emit(CmdexSyncCommandInfo(get_command_name(), get_command_args(), get_stdout_str(), get_stderr_str(), get_error_msg())); if (slot_connected) signal_execute_tick.emit(status_stopped); // last call return true; }