diff --git a/src/gui/opkg_manager.cpp b/src/gui/opkg_manager.cpp index 4826b0a44..35d9800f0 100644 --- a/src/gui/opkg_manager.cpp +++ b/src/gui/opkg_manager.cpp @@ -41,7 +41,7 @@ #include #include -#include + #include #include #include @@ -145,7 +145,7 @@ int COPKGManager::exec(CMenuTarget* parent, const string &actionKey) if (ShowMsg(LOCALE_OPKG_TITLE, loc, CMessageBox::mbrCancel, CMessageBox::mbYes | CMessageBox::mbCancel) != CMessageBox::mbrCancel) { if (parent) parent->hide(); - execCmd(pkg_types[OM_REMOVE] + pkg_vec[selected]->name, true, true); + execCmd(pkg_types[OM_REMOVE] + pkg_vec[selected]->name, CShellWindow::VERBOSE | CShellWindow::ACKNOWLEDGE_EVENT); refreshMenu(); } return res; @@ -192,7 +192,7 @@ int COPKGManager::exec(CMenuTarget* parent, const string &actionKey) if(actionKey == pkg_types[OM_UPGRADE]) { if (parent) parent->hide(); - int r = execCmd(actionKey, true, true); + int r = execCmd(actionKey, CShellWindow::VERBOSE | CShellWindow::ACKNOWLEDGE_EVENT); if (r) { showError(g_Locale->getText(LOCALE_OPKG_FAILURE_UPGRADE), strerror(errno), actionKey); } else @@ -425,9 +425,10 @@ bool COPKGManager::checkUpdates(const std::string & package_name, bool show_prog int COPKGManager::doUpdate() { - int r = execCmd(pkg_types[OM_UPDATE]); - if (r == -1) { + int r = execCmd(pkg_types[OM_UPDATE], CShellWindow::QUIET); + if (r) { string msg = string(g_Locale->getText(LOCALE_OPKG_FAILURE_UPDATE)); + msg += '\n' + tmp_str; DisplayErrorMessage(msg.c_str()); return r; } @@ -640,7 +641,7 @@ string COPKGManager::getBlankPkgName(const string& line) string COPKGManager::getPkgInfo(const string& pkg_name, const string& pkg_key, bool current_status) { - execCmd(pkg_types[current_status ? OM_STATUS : OM_INFO] + pkg_name, false, true); + execCmd(pkg_types[current_status ? OM_STATUS : OM_INFO] + pkg_name, CShellWindow::QUIET); dprintf(DEBUG_INFO, "[COPKGManager] [%s - %d] [data: %s]\n", __func__, __LINE__, tmp_str.c_str()); if (pkg_key.empty()) @@ -668,7 +669,7 @@ string COPKGManager::getKeyInfo(const string& input, const std::string& key, con return ""; } -int COPKGManager::execCmd(const char *cmdstr, bool verbose, bool acknowledge) +int COPKGManager::execCmd(const char *cmdstr, int verbose_mode) { fprintf(stderr, "execCmd(%s)\n", cmdstr); string cmd = string(cmdstr); @@ -678,7 +679,7 @@ int COPKGManager::execCmd(const char *cmdstr, bool verbose, bool acknowledge) bool ok = true; //create CShellWindow object - CShellWindow shell(cmd, (verbose ? CShellWindow::VERBOSE : 0) | (acknowledge ? CShellWindow::ACKNOWLEDGE_EVENT : 0), &res, false); + CShellWindow shell(cmd, verbose_mode, &res, false); //init slot for shell output handler with 3 args, no return value, and connect with loop handler inside of CShellWindow object sigc::slot3 sl_shell; @@ -798,7 +799,7 @@ bool COPKGManager::installPackage(const string& pkg_name, string options, bool f else{ string opts = " " + options + " "; - int r = execCmd(pkg_types[OM_INSTALL] + opts + pkg_name, true, true); + int r = execCmd(pkg_types[OM_INSTALL] + opts + pkg_name, CShellWindow::VERBOSE | CShellWindow::ACKNOWLEDGE_EVENT); if (r){ switch(r){ case OM_OUT_OF_SPACE_ERR: @@ -818,8 +819,8 @@ bool COPKGManager::installPackage(const string& pkg_name, string options, bool f } }else{ if (force_configure) - execCmd(pkg_types[OM_CONFIGURE] + getBlankPkgName(pkg_name), false, false); - installed = true; + execCmd(pkg_types[OM_CONFIGURE] + getBlankPkgName(pkg_name), 0); + installed = true; //TODO: catch real result } } diff --git a/src/gui/opkg_manager.h b/src/gui/opkg_manager.h index 0403903db..6d81e3428 100644 --- a/src/gui/opkg_manager.h +++ b/src/gui/opkg_manager.h @@ -32,6 +32,7 @@ #define __OPKG_MANAGER__ #include +#include #include #include #include @@ -97,9 +98,9 @@ class COPKGManager : public CMenuTarget }; void showErr(int* res); - int execCmd(const char* cmdstr, bool verbose = false, bool acknowledge = false); - int execCmd(std::string cmdstr, bool verbose = false, bool acknowledge = false) { - return execCmd(cmdstr.c_str(), verbose, acknowledge); + int execCmd(const char* cmdstr, int verbose_mode = 0); + int execCmd(std::string cmdstr, int verbose_mode = 0) { + return execCmd(cmdstr.c_str(), verbose_mode); }; void getPkgData(const int pkg_content_id); std::string getBlankPkgName(const std::string& line); diff --git a/src/gui/widget/shellwindow.cpp b/src/gui/widget/shellwindow.cpp index 370326e70..da1f1ed53 100644 --- a/src/gui/widget/shellwindow.cpp +++ b/src/gui/widget/shellwindow.cpp @@ -62,7 +62,7 @@ CShellWindow::CShellWindow(const std::string &Command, const int Mode, int *Res, void CShellWindow::exec() { std::string cmd; - if (!(mode & VERBOSE)){ + if (mode == 0){ cmd = "PATH=/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/usr/local/sbin ; export PATH ; " + command + " 2>/dev/null >&2"; int r = my_system(cmd.c_str()); if (res) { @@ -72,148 +72,152 @@ void CShellWindow::exec() *res = WEXITSTATUS(r); dprintf(DEBUG_NORMAL, "[CShellWindow] [%s - %d] Error! system returns: %d command: %s\n", __func__, __LINE__, *res, cmd.c_str()); } - return; } + else { + pid_t pid = 0; + cmd = command + " 2>&1"; + FILE *f = my_popen(pid, cmd.c_str(), "r"); + if (!f) { + if (res) + *res = -1; + dprintf(DEBUG_NORMAL, "[CShellWindow] [%s - %d] Error! my_popen returns: %d command: %s\n", __func__, __LINE__, *res, cmd.c_str()); + return; + } - pid_t pid = 0; - cmd = command + " 2>&1"; - FILE *f = my_popen(pid, cmd.c_str(), "r"); - if (!f) { - if (res) - *res = -1; - dprintf(DEBUG_NORMAL, "[CShellWindow] [%s - %d] Error! my_popen returns: %d command: %s\n", __func__, __LINE__, *res, cmd.c_str()); - return; - } + Font *font = g_Font[SNeutrinoSettings::FONT_TYPE_MENU_INFO]; + int h_shell = frameBuffer->getScreenHeight(); + int w_shell = frameBuffer->getScreenWidth(); + unsigned int lines_max = h_shell / font->getHeight(); + list lines; + CBox textBoxPosition(frameBuffer->getScreenX(), frameBuffer->getScreenX(), w_shell, h_shell); + if (textBox == NULL){ + textBox = new CTextBox(cmd.c_str(), font, CTextBox::BOTTOM, &textBoxPosition); + textBox->enableSaveScreen(false); + } + struct pollfd fds; + fds.fd = fileno(f); + fds.events = POLLIN | POLLHUP | POLLERR; + fcntl(fds.fd, F_SETFL, fcntl(fds.fd, F_GETFL, 0) | O_NONBLOCK); - Font *font = g_Font[SNeutrinoSettings::FONT_TYPE_MENU_INFO]; - int h_shell = frameBuffer->getScreenHeight(); - int w_shell = frameBuffer->getScreenWidth(); - unsigned int lines_max = h_shell / font->getHeight(); - list lines; - CBox textBoxPosition(frameBuffer->getScreenX(), frameBuffer->getScreenX(), w_shell, h_shell); - textBox = new CTextBox(cmd.c_str(), font, CTextBox::BOTTOM, &textBoxPosition); - textBox->enableSaveScreen(false); - struct pollfd fds; - fds.fd = fileno(f); - fds.events = POLLIN | POLLHUP | POLLERR; - fcntl(fds.fd, F_SETFL, fcntl(fds.fd, F_GETFL, 0) | O_NONBLOCK); + struct timeval tv; + gettimeofday(&tv,NULL); + uint64_t lastPaint = (uint64_t) tv.tv_usec + (uint64_t)((uint64_t) tv.tv_sec * (uint64_t) 1000000); + bool ok = true, nlseen = false, dirty = false, incomplete = false; + char output[1024]; + std::string txt = ""; + std::string line = ""; - struct timeval tv; - gettimeofday(&tv,NULL); - uint64_t lastPaint = (uint64_t) tv.tv_usec + (uint64_t)((uint64_t) tv.tv_sec * (uint64_t) 1000000); - bool ok = true, nlseen = false, dirty = false, incomplete = false; - char output[1024]; - std::string txt = ""; - std::string line = ""; + do { + uint64_t now; + fds.revents = 0; + int r = poll(&fds, 1, 300); + if (r > 0) { + if (!feof(f)) { + gettimeofday(&tv,NULL); + now = (uint64_t) tv.tv_usec + (uint64_t)((uint64_t) tv.tv_sec * (uint64_t) 1000000); - do { - uint64_t now; - fds.revents = 0; - int r = poll(&fds, 1, 300); - if (r > 0) { - if (!feof(f)) { - gettimeofday(&tv,NULL); - now = (uint64_t) tv.tv_usec + (uint64_t)((uint64_t) tv.tv_sec * (uint64_t) 1000000); + unsigned int lines_read = 0; + while (fgets(output, sizeof(output), f)) { + char *outputp = output; + dirty = true; - unsigned int lines_read = 0; - while (fgets(output, sizeof(output), f)) { - char *outputp = output; - dirty = true; + for (int i = 0; output[i] && !nlseen; i++) + switch (output[i]) { + case '\b': + if (outputp > output) + outputp--; + *outputp = 0; + break; + case '\r': + outputp = output; + break; + case '\n': + lines_read++; + nlseen = true; + *outputp = 0; + break; + default: + *outputp++ = output[i]; + break; + } - for (int i = 0; output[i] && !nlseen; i++) - switch (output[i]) { - case '\b': - if (outputp > output) - outputp--; - *outputp = 0; - break; - case '\r': - outputp = output; - break; - case '\n': - lines_read++; - nlseen = true; - *outputp = 0; - break; - default: - *outputp++ = output[i]; - break; + if (outputp < output + sizeof(output)) + *outputp = 0; + line += std::string(output); + if (incomplete) + lines.pop_back(); + if (nlseen) { + lines.push_back(line); + line.clear(); + nlseen = false; + incomplete = false; + } else { + lines.push_back(line); + incomplete = true; } - if (outputp < output + sizeof(output)) - *outputp = 0; - line += std::string(output); - if (incomplete) - lines.pop_back(); - if (nlseen) { - lines.push_back(line); - line.clear(); - nlseen = false; - incomplete = false; - } else { - lines.push_back(line); - incomplete = true; - } + //callback for line handler + std::string s_output = std::string((output)); + OnShellOutputLoop(&s_output, res, &ok); + dprintf(DEBUG_NORMAL, "[CShellWindow] [%s - %d] res=%d ok=%d\n", __func__, __LINE__, *res, ok); - //callback for line handler - std::string s_output = std::string((output)); - OnShellOutputLoop(&s_output, res, &ok); - dprintf(DEBUG_NORMAL, "[CShellWindow] [%s - %d] res=%d ok=%d\n", __func__, __LINE__, *res, ok); - - if (lines.size() > lines_max) - lines.pop_front(); - txt = ""; - bool first = true; - for (std::list::const_iterator it = lines.begin(), end = lines.end(); it != end; ++it) { - if (!first) - txt += '\n'; - first = false; - txt += *it; + if (lines.size() > lines_max) + lines.pop_front(); + txt = ""; + bool first = true; + for (std::list::const_iterator it = lines.begin(), end = lines.end(); it != end; ++it) { + if (!first) + txt += '\n'; + first = false; + txt += *it; + } + if (((lines_read == lines_max) && (lastPaint + 100000 < now)) || (lastPaint + 250000 < now)) { + textBox->setText(&txt, textBox->getWindowsPos().iWidth, false); + if (!textBox->isPainted()) + if (mode & VERBOSE) textBox->paint(); + lines_read = 0; + lastPaint = now; + dirty = false; + } } - if (((lines_read == lines_max) && (lastPaint + 100000 < now)) || (lastPaint + 250000 < now)) { - textBox->setText(&txt, textBox->getWindowsPos().iWidth, false); - if (!textBox->isPainted()) - textBox->paint(); - lines_read = 0; - lastPaint = now; - dirty = false; - } - } - } else + } else + ok = false; + } else if (r < 0) ok = false; - } else if (r < 0) - ok = false; - gettimeofday(&tv,NULL); - now = (uint64_t) tv.tv_usec + (uint64_t)((uint64_t) tv.tv_sec * (uint64_t) 1000000); - if (!ok || (r < 1 && dirty && lastPaint + 250000 < now)) { + gettimeofday(&tv,NULL); + now = (uint64_t) tv.tv_usec + (uint64_t)((uint64_t) tv.tv_sec * (uint64_t) 1000000); + if (!ok || (r < 1 && dirty && lastPaint + 250000 < now)) { + textBox->setText(&txt, textBox->getWindowsPos().iWidth, false); + if (!textBox->isPainted()) + if (mode & VERBOSE) textBox->paint(); + lastPaint = now; + dirty = false; + } + } while(ok); + + if (mode & VERBOSE) { + txt += "\n...ready"; textBox->setText(&txt, textBox->getWindowsPos().iWidth, false); - if (!textBox->isPainted()) - textBox->paint(); - lastPaint = now; - dirty = false; } - } while(ok); - txt += "\n...ready"; - textBox->setText(&txt, textBox->getWindowsPos().iWidth, false); + fclose(f); + int s; + errno = 0; + int r = waitpid(pid, &s, 0); - fclose(f); - int s; - errno = 0; - int r = waitpid(pid, &s, 0); - - if (res){ - //if res value was generated inside signal, then use foreign res from signal instead own res value - if (OnShellOutputLoop.empty()){ - if (r == -1) - *res = errno; - else - *res = WEXITSTATUS(s); + if (res){ + //if res value was generated inside signal, then use foreign res from signal instead own res value + if (OnShellOutputLoop.empty()){ + if (r == -1) + *res = errno; + else + *res = WEXITSTATUS(s); + } } + + showResult(); } - - showResult(); } void CShellWindow::showResult() @@ -233,31 +237,32 @@ void CShellWindow::showResult() show_button = true; }else{ OnResultOk(res); - exit = true; + exit = true; //TODO: evaluate plausible statement } } - if (show_button){ - int b_width = 150; - int b_height = 35; - int xpos = frameBuffer->getScreenWidth() - b_width; - int ypos = frameBuffer->getScreenHeight() - b_height; - CComponentsButton btn(xpos, ypos, b_width, b_height, LOCALE_MESSAGEBOX_BACK, NEUTRINO_ICON_BUTTON_OKAY, NULL, true, true); - btn.paint(); + if ((mode & VERBOSE)){ + if (show_button){ + int b_width = 150; + int b_height = 35; + int xpos = frameBuffer->getScreenWidth() - b_width; + int ypos = frameBuffer->getScreenHeight() - b_height; + CComponentsButton btn(xpos, ypos, b_width, b_height, LOCALE_MESSAGEBOX_BACK, NEUTRINO_ICON_BUTTON_OKAY, NULL, true, true); + btn.paint(); + } + + neutrino_msg_t msg; + neutrino_msg_data_t data; + uint64_t timeoutEnd = CRCInput::calcTimeoutEnd(g_settings.timing[SNeutrinoSettings::TIMING_MENU] == 0 ? 0xFFFF : g_settings.timing[SNeutrinoSettings::TIMING_MENU]); + + if (!exit) + { + do + g_RCInput->getMsgAbsoluteTimeout(&msg, &data, &timeoutEnd); + while (msg != CRCInput::RC_ok && msg != CRCInput::RC_home && msg != CRCInput::RC_timeout); + } + textBox->hide(); } - - neutrino_msg_t msg; - neutrino_msg_data_t data; - uint64_t timeoutEnd = CRCInput::calcTimeoutEnd(g_settings.timing[SNeutrinoSettings::TIMING_MENU] == 0 ? 0xFFFF : g_settings.timing[SNeutrinoSettings::TIMING_MENU]); - - if (!exit) - { - do - g_RCInput->getMsgAbsoluteTimeout(&msg, &data, &timeoutEnd); - while (msg != CRCInput::RC_ok && msg != CRCInput::RC_home && msg != CRCInput::RC_timeout); - } - - textBox->hide(); } } diff --git a/src/gui/widget/shellwindow.h b/src/gui/widget/shellwindow.h index 2f1171dd5..75cbd88f5 100644 --- a/src/gui/widget/shellwindow.h +++ b/src/gui/widget/shellwindow.h @@ -45,11 +45,14 @@ class CShellWindow : public sigc::trackable void showResult(); public: + //shell window modes for handled shell output. //NOTE: mode 0 use only system calls, with unhandled return values and no handled shell output enum shellwindow_modes { - VERBOSE = 1, - ACKNOWLEDGE = 2, - ACKNOWLEDGE_EVENT = 4 + /*SYSTEM = 0, */ + QUIET = 1, // no window + VERBOSE = 2, // show window + ACKNOWLEDGE = 4, // show result button inside window after execution, no message box NOTE: only in VERBOSE mode + ACKNOWLEDGE_EVENT = 8 // same like ACKNOWLEDGE but shows a default error message box or a slot handled action instead default error message box }; CShellWindow(const std::string &Command, const int Mode = 0, int* Res = NULL, bool auto_exec = true); ~CShellWindow();