int main(int argc, char *argv[]) { if( argc != 2 ) { std::cout << "xstartonce 0.0.2\n" << "Usage: xstartonce <hotkey-name>\n" << "You need to define hotkeys in ~/.xstartonce in the format \"name=command --params\"."; return 1; } Config config; loadFile(QDir::home().absoluteFilePath(".xstartonce"), config); QString dbPath = QDir::temp().absoluteFilePath("xstartonce-db.%1").arg(userName()); for(Config::const_iterator i = config.begin(); i != config.end(); ++i) { qDebug() << i.key(); if( i.key() == argv[1] ) { qDebug() << "Found key" << i.key(); ProcList procs; if( loadFile(dbPath, procs) ) for(ProcList::const_iterator j = procs.begin(); j != procs.end(); ++j) { if( j.key() == i.key() ) { QString winId = findWindowForPid(qvariant_cast<int>(j.value())); if( !winId.isEmpty() ) { QProcess proc; QStringList args; args << "-i" << "-a" << winId; qDebug() << "Activating window" << winId; proc.start("wmctrl", args); proc.waitForFinished(2000); return 0; } else { qDebug() << "Could not find window for pid" << j.value(); break; } } } int i_pid = startProcess(i.value()); if( i_pid > 0 ) { QString pid = qvariant_cast<QString>(i_pid); procs[i.key()] = pid; writeFile(dbPath, procs); } return 0; } } qDebug() << "No such configuration " << argv[1] << "."; return 3; }
void Process::diffProcLists(const ProcList& oldList, const ProcList& newList, int& start, int& end) const { const int newSize = newList.size(); const int oldSize = oldList.size(); const int size = newSize <= oldSize ? newSize : oldSize; bool endDone = false; bool startDone = false; int x; start = 0; end = oldList.size() - 1; for ( int i = 0; i < size; i++ ) { x = size - i - 1; if ( !startDone && oldList.at(i) == newList.at(i) ) { start++; } else { startDone = true; } if ( !endDone && oldList.at(x) == newList.at(x) ) { end--; } else { endDone = true; } if ( (startDone && endDone) || start > end ) { return; } } }
static void refresh_list (ProcData *procdata, const pid_t* pid_list, const guint n) { typedef std::list<ProcInfo*> ProcList; ProcList addition; GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (procdata->tree)); guint i; // Add or update processes in the process list for(i = 0; i < n; ++i) { ProcInfo *info = ProcInfo::find(pid_list[i]); if (!info) { info = new ProcInfo(pid_list[i]); ProcInfo::all[info->pid] = info; addition.push_back(info); } update_info (procdata, info); } // Remove dead processes from the process list and from the // tree. children are queued to be readded at the right place // in the tree. const std::set<pid_t> pids(pid_list, pid_list + n); ProcInfo::Iterator it(ProcInfo::begin()); while (it != ProcInfo::end()) { ProcInfo * const info = it->second; ProcInfo::Iterator next(it); ++next; if (pids.find(info->pid) == pids.end()) { procman_debug("ripping %d", info->pid); remove_info_from_tree(procdata, model, info, addition); addition.remove(info); ProcInfo::all.erase(it); delete info; } it = next; } // INVARIANT // pid_list == ProcInfo::all + addition if (procdata->config.show_tree) { // insert process in the tree. walk through the addition list // (new process + process that have a new parent). This loop // handles the dependencies because we cannot insert a process // until its parent is in the tree. std::set<pid_t> in_tree(pids); for (ProcList::iterator it(addition.begin()); it != addition.end(); ++it) in_tree.erase((*it)->pid); while (not addition.empty()) { procman_debug("looking for %d parents", int(addition.size())); ProcList::iterator it(addition.begin()); while (it != addition.end()) { procman_debug("looking for %d's parent with ppid %d", int((*it)->pid), int((*it)->ppid)); // inserts the process in the treeview if : // - it is init // - its parent is already in tree // - its parent is unreachable // // rounds == 2 means that addition contains processes with // unreachable parents // // FIXME: this is broken if the unreachable parent becomes active // i.e. it gets active or changes ower // so we just clear the tree on __each__ update // see proctable_update_list (ProcData * const procdata) if ((*it)->ppid == 0 or in_tree.find((*it)->ppid) != in_tree.end()) { insert_info_to_tree(*it, procdata); in_tree.insert((*it)->pid); it = addition.erase(it); continue; } ProcInfo *parent = ProcInfo::find((*it)->ppid); // if the parent is unreachable if (not parent) { // or std::find(addition.begin(), addition.end(), parent) == addition.end()) { insert_info_to_tree(*it, procdata, true); in_tree.insert((*it)->pid); it = addition.erase(it); continue; } ++it; } } } else { // don't care of the tree for (ProcList::iterator it(addition.begin()); it != addition.end(); ++it) insert_info_to_tree(*it, procdata); } for (ProcInfo::Iterator it(ProcInfo::begin()); it != ProcInfo::end(); ++it) update_info_mutable_cols(it->second); }
// Display all processes and relevant network traffic using show function void do_refresh() { int rows; // number of terminal rows int cols; // number of terminal columns unsigned int proglen; // max length of the "PROGRAM" column getmaxyx(stdscr, rows, cols); /* find the boundaries of the screeen */ if (cols < 60) { clear(); mvprintw(0,0, "The terminal is too narrow! Please make it wider.\nI'll wait..."); return; } if (cols > PROGNAME_WIDTH) cols = PROGNAME_WIDTH; proglen = cols - 53; refreshconninode(); if (DEBUG || tracemode) { std::cout << "\nRefreshing:\n"; } else { clear(); mvprintw (0, 0, "%s", caption->c_str()); attron(A_REVERSE); mvprintw (2, 0, " PID USER %-*.*s DEV SENT RECEIVED ", proglen, proglen, "PROGRAM"); attroff(A_REVERSE); } ProcList * curproc = processes; ProcList * previousproc = NULL; int nproc = processes->size(); /* initialise to null pointers */ Line * lines [nproc]; int n = 0, i = 0; double sent_global = 0; double recv_global = 0; #ifndef NDEBUG // initialise to null pointers for (int i = 0; i < nproc; i++) lines[i] = NULL; #endif while (curproc != NULL) { // walk though its connections, summing up their data, and // throwing away connections that haven't received a package // in the last PROCESSTIMEOUT seconds. assert (curproc != NULL); assert (curproc->getVal() != NULL); assert (nproc == processes->size()); /* remove timed-out processes (unless it's one of the the unknown process) */ if ((curproc->getVal()->getLastPacket() + PROCESSTIMEOUT <= curtime.tv_sec) && (curproc->getVal() != unknowntcp) && (curproc->getVal() != unknownudp) && (curproc->getVal() != unknownip)) { if (DEBUG) std::cout << "PROC: Deleting process\n"; ProcList * todelete = curproc; Process * p_todelete = curproc->getVal(); if (previousproc) { previousproc->next = curproc->next; curproc = curproc->next; } else { processes = curproc->getNext(); curproc = processes; } delete todelete; delete p_todelete; nproc--; //continue; } else { // add a non-timed-out process to the list of stuff to show float value_sent = 0, value_recv = 0; if (viewMode == VIEWMODE_KBPS) { //std::cout << "kbps viemode" << std::endl; getkbps (curproc->getVal(), &value_recv, &value_sent); } else if (viewMode == VIEWMODE_TOTAL_KB) { //std::cout << "total viemode" << std::endl; gettotalkb(curproc->getVal(), &value_recv, &value_sent); } else if (viewMode == VIEWMODE_TOTAL_MB) { //std::cout << "total viemode" << std::endl; gettotalmb(curproc->getVal(), &value_recv, &value_sent); } else if (viewMode == VIEWMODE_TOTAL_B) { //std::cout << "total viemode" << std::endl; gettotalb(curproc->getVal(), &value_recv, &value_sent); } else { forceExit(false, "Invalid viewMode: %d", viewMode); } uid_t uid = curproc->getVal()->getUid(); #ifndef NDEBUG struct passwd * pwuid = getpwuid(uid); assert (pwuid != NULL); // value returned by pwuid should not be freed, according to // Petr Uzel. //free (pwuid); #endif assert (curproc->getVal()->pid >= 0); assert (n < nproc); lines[n] = new Line (curproc->getVal()->name, value_recv, value_sent, curproc->getVal()->pid, uid, curproc->getVal()->devicename); previousproc = curproc; curproc = curproc->next; n++; #ifndef NDEBUG assert (nproc == processes->size()); if (curproc == NULL) assert (n-1 < nproc); else assert (n < nproc); #endif } } /* sort the accumulated lines */ qsort (lines, nproc, sizeof(Line *), GreatestFirst); /* print them */ for (i=0; i<nproc; i++) { if (i+3 < rows) lines[i]->show(i+3, proglen); recv_global += lines[i]->recv_value; sent_global += lines[i]->sent_value; delete lines[i]; } if (tracemode || DEBUG) { /* print the 'unknown' connections, for debugging */ ConnList * curr_unknownconn = unknowntcp->connections; while (curr_unknownconn != NULL) { std::cout << "Unknown connection: " << curr_unknownconn->getVal()->refpacket->gethashstring() << std::endl; curr_unknownconn = curr_unknownconn->getNext(); } } if ((!tracemode) && (!DEBUG)){ attron(A_REVERSE); int totalrow = std::min(rows-1, 3+1+i); mvprintw (totalrow, 0, " TOTAL %-*.*s %10.3f %10.3f ", proglen, proglen, " ", sent_global, recv_global); if (viewMode == VIEWMODE_KBPS) { mvprintw (3+1+i, cols - 7, "KB/sec "); } else if (viewMode == VIEWMODE_TOTAL_B) { mvprintw (3+1+i, cols - 7, "B "); } else if (viewMode == VIEWMODE_TOTAL_KB) { mvprintw (3+1+i, cols - 7, "KB "); } else if (viewMode == VIEWMODE_TOTAL_MB) { mvprintw (3+1+i, cols - 7, "MB "); } attroff(A_REVERSE); mvprintw (totalrow+1, 0, ""); refresh(); } }
// Display all processes and relevant network traffic using show function void do_refresh() { refreshconninode(); refreshcount++; ProcList * curproc = processes; ProcList * previousproc = NULL; int nproc = processes->size(); /* initialise to null pointers */ Line * lines [nproc]; int n = 0; #ifndef NDEBUG // initialise to null pointers for (int i = 0; i < nproc; i++) lines[i] = NULL; #endif while (curproc != NULL) { // walk though its connections, summing up their data, and // throwing away connections that haven't received a package // in the last PROCESSTIMEOUT seconds. assert (curproc != NULL); assert (curproc->getVal() != NULL); assert (nproc == processes->size()); /* remove timed-out processes (unless it's one of the the unknown process) */ if ((curproc->getVal()->getLastPacket() + PROCESSTIMEOUT <= curtime.tv_sec) && (curproc->getVal() != unknowntcp) && (curproc->getVal() != unknownudp) && (curproc->getVal() != unknownip)) { if (DEBUG) std::cout << "PROC: Deleting process\n"; ProcList * todelete = curproc; Process * p_todelete = curproc->getVal(); if (previousproc) { previousproc->next = curproc->next; curproc = curproc->next; } else { processes = curproc->getNext(); curproc = processes; } delete todelete; delete p_todelete; nproc--; //continue; } else { // add a non-timed-out process to the list of stuff to show float value_sent = 0, value_recv = 0; if (viewMode == VIEWMODE_KBPS) { //std::cout << "kbps viemode" << std::endl; getkbps (curproc->getVal(), &value_recv, &value_sent); } else if (viewMode == VIEWMODE_TOTAL_KB) { //std::cout << "total viemode" << std::endl; gettotalkb(curproc->getVal(), &value_recv, &value_sent); } else if (viewMode == VIEWMODE_TOTAL_MB) { //std::cout << "total viemode" << std::endl; gettotalmb(curproc->getVal(), &value_recv, &value_sent); } else if (viewMode == VIEWMODE_TOTAL_B) { //std::cout << "total viemode" << std::endl; gettotalb(curproc->getVal(), &value_recv, &value_sent); } else { forceExit(false, "Invalid viewMode: %d", viewMode); } uid_t uid = curproc->getVal()->getUid(); #ifndef NDEBUG struct passwd * pwuid = getpwuid(uid); assert (pwuid != NULL); // value returned by pwuid should not be freed, according to // Petr Uzel. //free (pwuid); #endif assert (curproc->getVal()->pid >= 0); assert (n < nproc); lines[n] = new Line (curproc->getVal()->name, value_recv, value_sent, curproc->getVal()->pid, uid, curproc->getVal()->devicename); previousproc = curproc; curproc = curproc->next; n++; #ifndef NDEBUG assert (nproc == processes->size()); if (curproc == NULL) assert (n-1 < nproc); else assert (n < nproc); #endif } } /* sort the accumulated lines */ qsort (lines, nproc, sizeof(Line *), GreatestFirst); if (tracemode || DEBUG) show_trace(lines, nproc); else show_ncurses(lines, nproc); if (refreshlimit != 0 && refreshcount >= refreshlimit) quit_cb(0); }
static void refresh_list (GsmApplication *app, const pid_t* pid_list, const guint n) { typedef std::list<ProcInfo*> ProcList; ProcList addition; GtkTreeModel *model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER ( gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT ( gtk_tree_view_get_model (GTK_TREE_VIEW(app->tree)))))); guint i; // Add or update processes in the process list for(i = 0; i < n; ++i) { ProcInfo *info = app->processes.find(pid_list[i]); if (!info) { info = app->processes.add(pid_list[i]); addition.push_back(info); } update_info (app, info); } // Remove dead processes from the process list and from the // tree. children are queued to be readded at the right place // in the tree. const std::set<pid_t> pids(pid_list, pid_list + n); auto it = std::begin(app->processes); while (it != std::end(app->processes)) { auto& info = it->second; if (pids.find(info.pid) == pids.end()) { procman_debug("ripping %d", info.pid); remove_info_from_tree(app, model, info, addition); addition.remove(&info); it = app->processes.erase(it); } else { ++it; } } // INVARIANT // pid_list == ProcInfo::all + addition if (app->settings->get_boolean (GSM_SETTING_SHOW_DEPENDENCIES)) { // insert process in the tree. walk through the addition list // (new process + process that have a new parent). This loop // handles the dependencies because we cannot insert a process // until its parent is in the tree. std::set<pid_t> in_tree(pids); for (ProcList::iterator it(addition.begin()); it != addition.end(); ++it) in_tree.erase((*it)->pid); while (not addition.empty()) { procman_debug("looking for %d parents", int(addition.size())); ProcList::iterator it(addition.begin()); while (it != addition.end()) { procman_debug("looking for %d's parent with ppid %d", int((*it)->pid), int((*it)->ppid)); // inserts the process in the treeview if : // - it has no parent (ppid = -1), // ie it is for example the [kernel] on FreeBSD // - it is init // - its parent is already in tree // - its parent is unreachable // // rounds == 2 means that addition contains processes with // unreachable parents // // FIXME: this is broken if the unreachable parent becomes active // i.e. it gets active or changes ower // so we just clear the tree on __each__ update // see proctable_update (ProcData * const procdata) if ((*it)->ppid <= 0 or in_tree.find((*it)->ppid) != in_tree.end()) { insert_info_to_tree(*it, app); in_tree.insert((*it)->pid); it = addition.erase(it); continue; } ProcInfo *parent = app->processes.find((*it)->ppid); // if the parent is unreachable if (not parent) { // or std::find(addition.begin(), addition.end(), parent) == addition.end()) { insert_info_to_tree(*it, app, true); in_tree.insert((*it)->pid); it = addition.erase(it); continue; } ++it; } } } else { // don't care of the tree for (auto& v : addition) insert_info_to_tree(v, app); } for (auto& v : app->processes) update_info_mutable_cols(&v.second); }
static void nethogsmonitor_handle_update(NethogsMonitorCallback cb) { refreshconninode(); refreshcount++; ProcList *curproc = processes; ProcList *previousproc = NULL; int nproc = processes->size(); while (curproc != NULL) { // walk though its connections, summing up their data, and // throwing away connections that haven't received a package // in the last PROCESSTIMEOUT seconds. assert(curproc != NULL); assert(curproc->getVal() != NULL); assert(nproc == processes->size()); /* remove timed-out processes (unless it's one of the unknown process) */ if ((curproc->getVal()->getLastPacket() + PROCESSTIMEOUT <= curtime.tv_sec) && (curproc->getVal() != unknowntcp) && (curproc->getVal() != unknownudp) && (curproc->getVal() != unknownip)) { if (DEBUG) std::cout << "PROC: Deleting process\n"; NethogsRecordMap::iterator it = monitor_record_map.find(curproc); if (it != monitor_record_map.end()) { NethogsMonitorRecord &data = it->second; (*cb)(NETHOGS_APP_ACTION_REMOVE, &data); monitor_record_map.erase(curproc); } ProcList *todelete = curproc; Process *p_todelete = curproc->getVal(); if (previousproc) { previousproc->next = curproc->next; curproc = curproc->next; } else { processes = curproc->getNext(); curproc = processes; } delete todelete; delete p_todelete; nproc--; // continue; } else { const u_int32_t uid = curproc->getVal()->getUid(); u_int32_t sent_bytes; u_int32_t recv_bytes; float sent_kbs; float recv_kbs; curproc->getVal()->getkbps(&recv_kbs, &sent_kbs); curproc->getVal()->gettotal(&recv_bytes, &sent_bytes); // notify update bool const new_data = (monitor_record_map.find(curproc) == monitor_record_map.end()); NethogsMonitorRecord &data = monitor_record_map[curproc]; bool data_change = false; if (new_data) { data_change = true; static int record_id = 0; ++record_id; memset(&data, 0, sizeof(data)); data.record_id = record_id; data.name = curproc->getVal()->name; data.pid = curproc->getVal()->pid; } data.device_name = curproc->getVal()->devicename; #define NHM_UPDATE_ONE_FIELD(TO, FROM) \ if ((TO) != (FROM)) { \ TO = FROM; \ data_change = true; \ } NHM_UPDATE_ONE_FIELD(data.uid, uid) NHM_UPDATE_ONE_FIELD(data.sent_bytes, sent_bytes) NHM_UPDATE_ONE_FIELD(data.recv_bytes, recv_bytes) NHM_UPDATE_ONE_FIELD(data.sent_kbs, sent_kbs) NHM_UPDATE_ONE_FIELD(data.recv_kbs, recv_kbs) #undef NHM_UPDATE_ONE_FIELD if (data_change) { (*cb)(NETHOGS_APP_ACTION_SET, &data); } // next previousproc = curproc; curproc = curproc->next; } } }
void Process::sort(ProcList& list) { switch ( fSortBy ) { case 0: qSort(list.begin(), list.end(), CPUComparer()); break; case 1: qSort(list.begin(), list.end(), NameComparer()); break; } }