00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #ifdef HAVE_GETCAP
00040
00041 #include <sstream>
00042
00043 #include "cfg_getcap.h"
00044 #include "guard.h"
00045 #include "consmgr.h"
00046
00047 extern "C" {
00048 #include <netdb.h>
00049 #include <sys/socket.h>
00050 #include <netinet/in.h>
00051 };
00052
00053
00054
00055
00056
00057 Getcap::Getcap(const string &filename) : Config(filename), capent(NULL)
00058 {
00059 int ret;
00060
00061
00062 ret = pthread_mutex_init(&capent_mtx, NULL);
00063 PTHREAD_CHECK_AND_THROW(ret, "mutex_init(capent_mtx)");
00064
00065 this->filename = filename;
00066
00067 return;
00068 }
00069
00070 Getcap::~Getcap(void)
00071 {
00072 int ret;
00073
00074 ret = pthread_mutex_lock(&capent_mtx);
00075 PTHREAD_CHECK_AND_THROW(ret, "mutex_lock(capent_mtx)");
00076
00077 if (capent)
00078 free(capent);
00079 capent = NULL;
00080
00081 ret = pthread_mutex_unlock(&capent_mtx);
00082 PTHREAD_CHECK_AND_THROW(ret, "mutex_unlock(capent_mtx)");
00083
00084 ret = pthread_mutex_destroy(&capent_mtx);
00085 PTHREAD_CHECK_AND_THROW(ret, "mutex_destroy(capent_mtx)");
00086
00087 return;
00088 }
00089
00090
00091
00092
00093
00094 void
00095 Getcap::load_entry(const string &s)
00096 {
00097 int ret;
00098
00099 try {
00100
00101 Guard locker(&capent_mtx);
00102
00103
00104 if (capent) {
00105
00106
00107 if (cgetmatch(capent, (char *)s.c_str())) {
00108 ent_name = s;
00109 throw true;
00110 }
00111 free(capent);
00112 capent = NULL;
00113 }
00114
00115 char *files[2] = { const_cast<char*>(filename.c_str()), NULL };
00116 ret = cgetent(&capent, files, (char *)s.c_str());
00117
00118 if (ret == 0) {
00119 ent_name = s;
00120 throw true;
00121 }
00122
00123
00124 int eno = errno;
00125 std::ostringstream ostr;
00126
00127 switch (ret) {
00128 case -1:
00129 {
00130 ConfigUnfoundException e(s);
00131 e.set_file(filename);
00132 throw e;
00133 }
00134 break;
00135 case -2:
00136 ostr << "System error " << eno << " (" << strerror(eno)
00137 << ") from cgetent(" << s << ")";
00138
00139 break;
00140 case -3:
00141 default:
00142 ostr << "Got unknown non-zero response from cgetent(,," << s
00143 << "): " << ret;
00144 break;
00145 }
00146
00147 throw ConfigException(ostr.str());
00148 } catch (bool) {
00149 #ifdef CONFIGURATION_DEBUGGING
00150 clog << "Successfully read the capent for '" << s << "'" << endl;
00151 #endif
00152 } catch (...) {
00153 throw;
00154 }
00155
00156
00157
00158
00159
00162 try {
00163 this->insert(std::pair<string,string>("host", this->str("host")));
00164 } catch (ConfigUnfoundException) {
00165 #ifdef CONFIGURATION_DEBUGGING
00166 clog << "Failed to find 'host', but don't care." << endl;
00167 #endif
00168 } catch (...) {
00169 throw;
00170 }
00171 try {
00172 std::ostringstream str;
00173 str << this->num("port");
00174 this->insert(std::pair<string,string>("port", str.str()));
00175 } catch (ConfigUnfoundException) {
00176 #ifdef CONFIGURATION_DEBUGGING
00177 clog << "Failed to find 'port', but don't care." << endl;
00178 #endif
00179 } catch (...) {
00180 throw;
00181 }
00184 try {
00185 this->insert(std::pair<string,string>("local_socket", this->str("sf")));
00186 } catch (ConfigUnfoundException) {
00187 #ifdef CONFIGURATION_DEBUGGING
00188 clog << "Failed to find 'sf', but don't care." << endl;
00189 #endif
00190 } catch (...) {
00191 throw;
00192 }
00193
00194 try {
00195 this->insert(std::pair<string,string>("logfile", this->str("logfile")));
00196 } catch (ConfigUnfoundException &e) {
00197
00198 try {
00199 this->insert(std::pair<string,string>("logfile",
00200 this->str("lf")));
00201 } catch (ConfigUnfoundException) {
00202 #ifdef CONFIGURATION_DEBUGGING
00203 clog << "Failed to find 'logfile' or 'lf', but don't care." << endl;
00204 #endif
00205 } catch (...) {
00206 throw;
00207 }
00208 } catch (...) {
00209 throw;
00210 }
00211
00212 return;
00213 }
00214
00215
00216
00217
00218
00220 int32_t
00221 Getcap::num(const string &key)
00222 {
00223 int ret;
00224 long val;
00225
00226 if (capent == NULL)
00227 throw "No capent cached; cannot search for capabilities!!";
00228
00229
00230
00231 Guard locker(&capent_mtx);
00232
00233
00234
00235 if ((ret = cgetnum(this->capent, (char *)key.c_str(), &val)) != 0)
00236 throw ConfigUnfoundException(key, "Can't find requested numeric capability '" + key + "'...");
00237
00238 return(val);
00239 }
00240
00242 string
00243 Getcap::str(const string &key)
00244 {
00245 int ret;
00246 char *val;
00247
00248 if (capent == NULL)
00249 throw ConfigException("No capent cached; cannot search for capabilities!!");
00250
00251
00252 do {
00253
00254 Guard locker(&capent_mtx);
00255
00256
00257 ret = cgetstr(this->capent, (char *)key.c_str(), &val);
00258 if (ret > 0)
00259 break;
00260
00261 if (ret == -1)
00262 throw ConfigUnfoundException(key, "Can't find requested string "
00263 "capability '" + key + "'...");
00264 if (ret == -2)
00265 throw ConfigUnfoundException(key, "System error encountered while "
00266 "searching for capability '" + key +
00267 "'; storage allocation failure?");
00268
00269 throw ConfigException("Unknown error searching for string capability '"+
00270 key + "'.");
00271 } while (0);
00272
00273 string val_s(val);
00274
00275 free(val);
00276
00277
00278 #ifdef CONFIGURATION_DEBUGGING
00279 clog << "String of '" << key << "' is '" << val_s << "'" << endl;
00280 #endif
00281 string::size_type p = 0;
00282 while ((p = val_s.find("&", p)) != string::npos) {
00283 #ifdef CONFIGURATION_DEBUGGING
00284 clog << "Did replacement..." << endl;
00285 #endif
00286 val_s.replace(p, 1, this->ent_name);
00287 }
00288 #ifdef CONFIGURATION_DEBUGGING
00289 clog << "String of '" << key << "' is now '" << val_s << "'" << endl;
00290 #endif
00291
00292 return(val_s);
00293 }
00294 #endif