/user/oprofile/oprofile-0.9.2.1rc1/gui/oprof_start_util.cpp
C++ | 330 lines | 209 code | 54 blank | 67 comment | 38 complexity | 64734b1323120a8bafdaabb5d986fae7 MD5 | raw file
Possible License(s): LGPL-2.1, BSD-3-Clause, MPL-2.0-no-copyleft-exception, LGPL-3.0, Unlicense, GPL-2.0, GPL-3.0, CC-BY-SA-3.0, AGPL-1.0, ISC, MIT, 0BSD, LGPL-2.0
- /**
- * @file oprof_start_util.cpp
- * Miscellaneous helpers for the GUI start
- *
- * @remark Copyright 2002 OProfile authors
- * @remark Read the file COPYING
- *
- * @author Philippe Elie
- * @author John Levon
- */
- #include <dirent.h>
- #include <unistd.h>
- #include <glob.h>
- #include <cerrno>
- #include <vector>
- #include <cmath>
- #include <sstream>
- #include <iostream>
- #include <fstream>
- #include <qfiledialog.h>
- #include <qmessagebox.h>
- #include "op_file.h"
- #include "file_manip.h"
- #include "child_reader.h"
- #include "op_libiberty.h"
- #include "oprof_start.h"
- #include "oprof_start_util.h"
- using namespace std;
- namespace {
- // return the ~ expansion suffixed with a '/'
- string const get_config_dir()
- {
- return "/root";
- }
- string daemon_pid;
- } // namespace anon
- daemon_status::daemon_status()
- : running(false),
- nr_interrupts(0)
- {
- int HZ;
- if (!daemon_pid.empty()) {
- string proc_filename = string("/proc/") + daemon_pid + "/exe";
- string const exec = op_realpath(proc_filename);
- if (exec == proc_filename)
- daemon_pid.erase();
- else
- running = true;
- }
- if (daemon_pid.empty()) {
- DIR * dir;
- struct dirent * dirent;
- if (!(dir = opendir("/proc"))) {
- perror("oprofiled: /proc directory could not be opened. ");
- exit(EXIT_FAILURE);
- }
- while ((dirent = readdir(dir))) {
- string const exec =
- op_realpath(string("/proc/")
- + dirent->d_name + "/exe");
- string const name = op_basename(exec);
- if (name != "oprofiled")
- continue;
- daemon_pid = dirent->d_name;
- running = true;
- }
- closedir(dir);
- }
- HZ = sysconf(_SC_CLK_TCK);
- if (HZ == -1) {
- perror("oprofiled: Unable to determine clock ticks per second. ");
- exit(EXIT_FAILURE);
- }
- if (daemon_pid.empty())
- return;
- nr_interrupts = 0;
- switch (op_get_interface()) {
- case OP_INTERFACE_24:
- {
- ifstream ifs3("/proc/sys/dev/oprofile/nr_interrupts");
- if (ifs3)
- ifs3 >> nr_interrupts;
- }
- break;
- case OP_INTERFACE_26:
- {
- static unsigned int old_sum_interrupts;
- unsigned int sum_interrupts = 0;
- glob_t file_names;
- file_names.gl_offs = 0;
- glob("/dev/oprofile/stats/cpu*/sample_received",
- GLOB_DOOFFS, NULL, &file_names);
- for (size_t i = 0; i < file_names.gl_pathc; ++i) {
- ifstream ifs3(file_names.gl_pathv[i]);
- if (ifs3) {
- unsigned int file_interrupts;
- ifs3 >> file_interrupts;
- sum_interrupts += file_interrupts;
- }
- }
- if (old_sum_interrupts > sum_interrupts)
- // occur if we stop/restart daemon.
- old_sum_interrupts = 0;
- nr_interrupts = sum_interrupts - old_sum_interrupts;
- old_sum_interrupts = sum_interrupts;
- globfree(&file_names);
- }
- break;
- default:
- break;
- }
- }
- /**
- * get_config_filename - get absolute filename of file in user $HOME
- * @param filename the relative filename
- *
- * Get the absolute path of a file in a user's home directory.
- */
- string const get_config_filename(string const & filename)
- {
- return get_config_dir() + "/" + filename;
- }
- /**
- * check_and_create_config_dir - make sure config dir is accessible
- *
- * Returns %true if the dir is accessible.
- */
- bool check_and_create_config_dir()
- {
- string dir = get_config_filename(".oprofile");
- char * name = xstrdup(dir.c_str());
- if (create_dir(name)) {
- ostringstream out;
- out << "unable to create " << dir << " directory ";
- out << "cause: " << strerror(errno);
- QMessageBox::warning(0, 0, out.str().c_str());
- free(name);
- return false;
- }
- free(name);
- return true;
- }
- /**
- * format - re-format a string
- * @param orig string to format
- * @param maxlen width of line
- *
- * Re-formats a string to fit into a certain width,
- * breaking lines at spaces between words.
- *
- * Returns the formatted string
- */
- string const format(string const & orig, uint const maxlen)
- {
- string text(orig);
- istringstream ss(text);
- vector<string> lines;
- string oline;
- string line;
- while (getline(ss, oline)) {
- if (line.size() + oline.size() < maxlen) {
- lines.push_back(line + oline);
- line.erase();
- } else {
- lines.push_back(line);
- line.erase();
- string s;
- string word;
- istringstream oss(oline);
- while (oss >> word) {
- if (line.size() + word.size() > maxlen) {
- lines.push_back(line);
- line.erase();
- }
- line += word + " ";
- }
- }
- }
- if (line.size())
- lines.push_back(line);
- string ret;
- for(vector<string>::const_iterator it = lines.begin(); it != lines.end(); ++it)
- ret += *it + "\n";
- return ret;
- }
- /**
- * do_exec_command - execute a command
- * @param cmd command name
- * @param args arguments to command
- *
- * Execute a command synchronously. An error message is shown
- * if the command returns a non-zero status, which is also returned.
- *
- * The arguments are verified and will refuse to execute if they contain
- * shell metacharacters.
- */
- int do_exec_command(string const & cmd, vector<string> const & args)
- {
- ostringstream err;
- bool ok = true;
- // verify arguments
- for (vector<string>::const_iterator cit = args.begin();
- cit != args.end(); ++cit) {
- if (verify_argument(*cit))
- continue;
- QMessageBox::warning(0, 0,
- string(
- "Could not execute: Argument \"" + *cit +
- "\" contains shell metacharacters.\n").c_str());
- return EINVAL;
- }
- child_reader reader(cmd, args);
- if (reader.error())
- ok = false;
- if (ok)
- reader.get_data(cout, err);
- int ret = reader.terminate_process();
- if (ret) {
- string error = reader.error_str() + "\n";
- error += "Failed: \n" + err.str() + "\n";
- string cmdline = cmd;
- for (vector<string>::const_iterator cit = args.begin();
- cit != args.end(); ++cit) {
- cmdline += " " + *cit + " ";
- }
- error += "\n\nCommand was :\n\n" + cmdline + "\n";
- QMessageBox::warning(0, 0, format(error, 50).c_str());
- }
- return ret;
- }
- /**
- * do_open_file_or_dir - open file/directory
- * @param base_dir directory to start at
- * @param dir_only directory or filename to select
- *
- * Select a file or directory. The selection is returned;
- * an empty string if the selection was cancelled.
- */
- string const do_open_file_or_dir(string const & base_dir, bool dir_only)
- {
- QString result;
- if (dir_only) {
- result = QFileDialog::getExistingDirectory(base_dir.c_str(), 0,
- "open_file_or_dir", "Get directory name", true);
- } else {
- result = QFileDialog::getOpenFileName(base_dir.c_str(), 0, 0,
- "open_file_or_dir", "Get filename");
- }
- if (result.isNull())
- return string();
- else
- return result.latin1();
- }
- /**
- * verify_argument - check string for potentially dangerous characters
- *
- * This function returns false if the string contains dangerous shell
- * metacharacters.
- *
- * WWW Security FAQ dangerous chars:
- *
- * & ; ` ' \ " | * ? ~ < > ^ ( ) [ ] { } $ \n \r
- *
- * David Wheeler: ! #
- *
- * We allow '-' because we disallow whitespace. We allow ':' and '='
- */
- bool verify_argument(string const & str)
- {
- if (str.find_first_not_of(
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz0123456789_:=-+%,./")
- != string::npos)
- return false;
- return true;
- }