From e0988607d575f25c16496e876e24f98c52e31c89 Mon Sep 17 00:00:00 2001 From: Thilo Graf Date: Thu, 28 May 2015 10:27:59 +0200 Subject: [PATCH] CShellWindow/COPKGManager: rework shell shell mode handling Modes were handled with bool values inside manager and this is not really enough. Now we use the real parameters for more flexibility. Origin commit data ------------------ Commit: https://github.com/neutrino-images/ni-neutrino/commit/e1e8cb0142f97a9605c2d845d29c64940296a201 Author: Thilo Graf Date: 2015-05-28 (Thu, 28 May 2015) --- src/gui/opkg_manager.cpp | 23 +-- src/gui/opkg_manager.h | 7 +- src/gui/widget/shellwindow.cpp | 295 +++++++++++++++++---------------- src/gui/widget/shellwindow.h | 9 +- 4 files changed, 172 insertions(+), 162 deletions(-) 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();