1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
|
#ifndef APPLICATIONS_DEF
#define APPLICATIONS_DEF
#include <map>
#include "Application.hh"
class Applications : public std::map<std::string, Application*>
{
public:
~Applications() {
for(auto app : *this) {
delete app.second;
}
}
std::pair<Application *, std::string> search(const std::string &choice) {
Application *app = 0;
std::string args;
size_t match_length = 0;
// Find longest match amongst apps
for(auto ¤t_app : *this) {
const std::string &name = current_app.second->name;
if(name.size() > match_length && startswith(choice, name)) {
app = current_app.second;
match_length = name.length();
}
const std::string &generic_name = current_app.second->generic_name;
if(generic_name.size() > match_length && startswith(choice, generic_name)) {
app = current_app.second;
match_length = generic_name.length();
}
}
if(!match_length) {
// No matching app found, just execute the input in a shell
const char *shell = 0;
if((shell = getenv("SHELL")) == 0)
shell = "/bin/sh";
fprintf(stderr, "%s -i -c '%s'\n", shell, choice.c_str());
// -i -c was tested with both bash and zsh.
exit(execl(shell, shell, "-i", "-c", choice.c_str(), 0, nullptr));
}
// +1 b/c there must be whitespace we add back later...
args = choice.substr(match_length, choice.length()-1);
//args = choice;
return std::make_pair(app, args);
}
void load_log(const char *log) {
FILE *fp = fopen(log, "r");
if(!fp) {
fprintf(stderr, "Can't read usage log '%s': %s\n", log, strerror(errno));
return;
}
unsigned count;
char *name = new char[256];
while(fscanf(fp, "%u,%255[^\n]\n", &count, name) == 2) {
const_iterator it = find(name);
if(it == end())
continue;
it->second->usage_count = count;
}
delete[] name;
fclose(fp);
}
void update_log(const char *log, Application *app) {
std::stringstream write_file;
write_file << log << "." << getpid();
FILE *fp = fopen(write_file.str().c_str(), "w");
if(!fp) {
fprintf(stderr, "Can't write usage log '%s': %s\n", log, strerror(errno));
return;
}
app->usage_count++;
for(auto &app : *this) {
if(app.second->usage_count < 1)
continue;
if(fprintf(fp, "%u,%s\n", app.second->usage_count, app.first.c_str()) < 0) {
perror("Write error");
fclose(fp);
return;
}
}
fclose(fp);
if(rename(write_file.str().c_str(), log)) {
perror("rename failed");
}
}
};
#endif
|