expander.cpp (2849B)
1 // Copyright (c) 2003 - 2009 Anselm R Garbe <anselm@garbe.us> 2 // See LICENSE for license details. 3 4 extern "C" { 5 #include <unistd.h> 6 #include <stdlib.h> 7 8 #include <sys/types.h> 9 #include <dirent.h> 10 #include <sys/stat.h> 11 } 12 13 #include "expander.h" 14 #include "util.h" 15 16 17 Expander::Expander(){ 18 this->key_ = ""; 19 this->path_ = ""; 20 this->rehash(); 21 } 22 23 bool Expander::rehash(){ 24 string path_env; 25 char *p_c = getenv("PATH"); 26 if (p_c != NULL) { 27 path_env = (string)p_c; 28 } 29 else{ 30 return(false); 31 } 32 paths_ = Util::stringSplit(path_env, ":"); 33 pathExpands_ = this->read(); 34 return true; 35 } 36 37 bool Expander::queryString (string s){ 38 paths_.clear(); 39 if ((s.find('/') == string::npos) || (Util::trimL(s).substr(0,1) == ".")) { 40 //so performing on PATH 41 key_ = s; 42 pathSearch_=true; 43 } 44 else{ 45 //we're using the given string as search-base 46 47 path_ = s.substr(0, s.find_last_of('/')+1); 48 key_= s.substr(s.find_last_of('/')+1); 49 50 paths_.insert(path_); 51 pathSearch_=false; 52 } 53 return(true); 54 } 55 56 set<string> Expander::expands (){ 57 58 set<string> *target; 59 if (pathSearch_) { 60 target = &pathExpands_; 61 } 62 else 63 { 64 target = &expands_; 65 *target = this->read(); 66 } 67 68 return *target; 69 } 70 71 set<string> Expander::read(){ 72 set<string> expands; 73 DIR *dir; 74 dirent *entry; 75 76 for (set<string>::iterator iter = paths_.begin(); iter != paths_.end(); iter++){ 77 dir=opendir(iter->c_str()); 78 if (dir != NULL) { 79 do { 80 entry=readdir(dir); 81 if (entry != NULL) { 82 bool expand = false; 83 string filename = (string)(*iter) + "/" 84 + (string)(entry->d_name); 85 86 /* if we're dealing with a directory, its 87 sufficient to have read-permission (bash 88 acts like this) */ 89 90 struct stat Buf; 91 if (stat(filename.c_str(), &Buf) == 0) 92 { 93 if (S_ISDIR(Buf.st_mode)) { 94 expand = true; 95 } 96 } 97 /* this test for executability uses the real 98 ids (see man 2 access) and thats why may 99 be incorrect if wmi is s(u/g)id'd */ 100 101 if (0 == access(filename.c_str(), X_OK)) { 102 expand = true; 103 } 104 105 if (expand == true) { 106 expands.insert((string)(entry->d_name)); 107 } 108 } 109 } while (entry != NULL); 110 closedir(dir); 111 } 112 } 113 expands.erase("."); 114 expands.erase(".."); 115 return(expands); 116 }