You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Configuration.cxx 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
  2. * Copyright 2004-2005 Cendio AB.
  3. * Copyright 2017 Peter Astrand <astrand@cendio.se> for Cendio AB
  4. *
  5. * This is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This software is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this software; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  18. * USA.
  19. */
  20. // -=- Configuration.cxx
  21. #ifdef HAVE_CONFIG_H
  22. #include <config.h>
  23. #endif
  24. #include <stdlib.h>
  25. #include <ctype.h>
  26. #include <string.h>
  27. #include <os/Mutex.h>
  28. #include <rfb/util.h>
  29. #include <rfb/Configuration.h>
  30. #include <rfb/LogWriter.h>
  31. #include <rfb/Exception.h>
  32. #define LOCK_CONFIG os::AutoMutex a(mutex)
  33. #include <rdr/HexOutStream.h>
  34. #include <rdr/HexInStream.h>
  35. using namespace rfb;
  36. static LogWriter vlog("Config");
  37. // -=- The Global/server/viewer Configuration objects
  38. Configuration* Configuration::global_ = 0;
  39. Configuration* Configuration::server_ = 0;
  40. Configuration* Configuration::viewer_ = 0;
  41. Configuration* Configuration::global() {
  42. if (!global_)
  43. global_ = new Configuration("Global");
  44. return global_;
  45. }
  46. Configuration* Configuration::server() {
  47. if (!server_)
  48. server_ = new Configuration("Server");
  49. return server_;
  50. }
  51. Configuration* Configuration::viewer() {
  52. if (!viewer_)
  53. viewer_ = new Configuration("Viewer");
  54. return viewer_;
  55. }
  56. // -=- Configuration implementation
  57. bool Configuration::set(const char* n, const char* v, bool immutable) {
  58. return set(n, strlen(n), v, immutable);
  59. }
  60. bool Configuration::set(const char* name, int len,
  61. const char* val, bool immutable)
  62. {
  63. VoidParameter* current = head;
  64. while (current) {
  65. if ((int)strlen(current->getName()) == len &&
  66. strncasecmp(current->getName(), name, len) == 0)
  67. {
  68. bool b = current->setParam(val);
  69. if (b && immutable)
  70. current->setImmutable();
  71. return b;
  72. }
  73. current = current->_next;
  74. }
  75. return _next ? _next->set(name, len, val, immutable) : false;
  76. }
  77. bool Configuration::set(const char* config, bool immutable) {
  78. bool hyphen = false;
  79. if (config[0] == '-') {
  80. hyphen = true;
  81. config++;
  82. if (config[0] == '-') config++; // allow gnu-style --<option>
  83. }
  84. const char* equal = strchr(config, '=');
  85. if (equal) {
  86. return set(config, equal-config, equal+1, immutable);
  87. } else if (hyphen) {
  88. VoidParameter* current = head;
  89. while (current) {
  90. if (strcasecmp(current->getName(), config) == 0) {
  91. bool b = current->setParam();
  92. if (b && immutable)
  93. current->setImmutable();
  94. return b;
  95. }
  96. current = current->_next;
  97. }
  98. }
  99. return _next ? _next->set(config, immutable) : false;
  100. }
  101. VoidParameter* Configuration::get(const char* param)
  102. {
  103. VoidParameter* current = head;
  104. while (current) {
  105. if (strcasecmp(current->getName(), param) == 0)
  106. return current;
  107. current = current->_next;
  108. }
  109. return _next ? _next->get(param) : 0;
  110. }
  111. void Configuration::list(int width, int nameWidth) {
  112. VoidParameter* current = head;
  113. fprintf(stderr, "%s Parameters:\n", name.buf);
  114. while (current) {
  115. char* def_str = current->getDefaultStr();
  116. const char* desc = current->getDescription();
  117. fprintf(stderr," %-*s -", nameWidth, current->getName());
  118. int column = strlen(current->getName());
  119. if (column < nameWidth) column = nameWidth;
  120. column += 4;
  121. while (true) {
  122. const char* s = strchr(desc, ' ');
  123. int wordLen;
  124. if (s) wordLen = s-desc;
  125. else wordLen = strlen(desc);
  126. if (column + wordLen + 1 > width) {
  127. fprintf(stderr,"\n%*s",nameWidth+4,"");
  128. column = nameWidth+4;
  129. }
  130. fprintf(stderr," %.*s",wordLen,desc);
  131. column += wordLen + 1;
  132. desc += wordLen + 1;
  133. if (!s) break;
  134. }
  135. if (def_str) {
  136. if (column + (int)strlen(def_str) + 11 > width)
  137. fprintf(stderr,"\n%*s",nameWidth+4,"");
  138. fprintf(stderr," (default=%s)\n",def_str);
  139. strFree(def_str);
  140. } else {
  141. fprintf(stderr,"\n");
  142. }
  143. current = current->_next;
  144. }
  145. if (_next)
  146. _next->list(width, nameWidth);
  147. }
  148. bool Configuration::remove(const char* param) {
  149. VoidParameter *current = head;
  150. VoidParameter **prevnext = &head;
  151. while (current) {
  152. if (strcasecmp(current->getName(), param) == 0) {
  153. *prevnext = current->_next;
  154. return true;
  155. }
  156. prevnext = &current->_next;
  157. current = current->_next;
  158. }
  159. return false;
  160. }
  161. // -=- VoidParameter
  162. VoidParameter::VoidParameter(const char* name_, const char* desc_,
  163. ConfigurationObject co)
  164. : immutable(false), name(name_), description(desc_)
  165. {
  166. Configuration *conf = NULL;
  167. switch (co) {
  168. case ConfGlobal: conf = Configuration::global();
  169. break;
  170. case ConfServer: conf = Configuration::server();
  171. break;
  172. case ConfViewer: conf = Configuration::viewer();
  173. break;
  174. }
  175. _next = conf->head;
  176. conf->head = this;
  177. mutex = new os::Mutex();
  178. }
  179. VoidParameter::~VoidParameter() {
  180. delete mutex;
  181. }
  182. const char*
  183. VoidParameter::getName() const {
  184. return name;
  185. }
  186. const char*
  187. VoidParameter::getDescription() const {
  188. return description;
  189. }
  190. bool VoidParameter::setParam() {
  191. return false;
  192. }
  193. bool VoidParameter::isBool() const {
  194. return false;
  195. }
  196. void
  197. VoidParameter::setImmutable() {
  198. vlog.debug("set immutable %s", getName());
  199. immutable = true;
  200. }
  201. // -=- AliasParameter
  202. AliasParameter::AliasParameter(const char* name_, const char* desc_,
  203. VoidParameter* param_, ConfigurationObject co)
  204. : VoidParameter(name_, desc_, co), param(param_) {
  205. }
  206. bool
  207. AliasParameter::setParam(const char* v) {
  208. return param->setParam(v);
  209. }
  210. bool AliasParameter::setParam() {
  211. return param->setParam();
  212. }
  213. char*
  214. AliasParameter::getDefaultStr() const {
  215. return 0;
  216. }
  217. char* AliasParameter::getValueStr() const {
  218. return param->getValueStr();
  219. }
  220. bool AliasParameter::isBool() const {
  221. return param->isBool();
  222. }
  223. void
  224. AliasParameter::setImmutable() {
  225. vlog.debug("set immutable %s (Alias)", getName());
  226. param->setImmutable();
  227. }
  228. // -=- BoolParameter
  229. BoolParameter::BoolParameter(const char* name_, const char* desc_, bool v,
  230. ConfigurationObject co)
  231. : VoidParameter(name_, desc_, co), value(v), def_value(v) {
  232. }
  233. bool
  234. BoolParameter::setParam(const char* v) {
  235. if (immutable) return true;
  236. if (*v == 0 || strcasecmp(v, "1") == 0 || strcasecmp(v, "on") == 0
  237. || strcasecmp(v, "true") == 0 || strcasecmp(v, "yes") == 0)
  238. value = 1;
  239. else if (strcasecmp(v, "0") == 0 || strcasecmp(v, "off") == 0
  240. || strcasecmp(v, "false") == 0 || strcasecmp(v, "no") == 0)
  241. value = 0;
  242. else {
  243. vlog.error("Bool parameter %s: invalid value '%s'", getName(), v);
  244. return false;
  245. }
  246. vlog.debug("set %s(Bool) to %s(%d)", getName(), v, value);
  247. return true;
  248. }
  249. bool BoolParameter::setParam() {
  250. setParam(true);
  251. return true;
  252. }
  253. void BoolParameter::setParam(bool b) {
  254. if (immutable) return;
  255. value = b;
  256. vlog.debug("set %s(Bool) to %d", getName(), value);
  257. }
  258. char*
  259. BoolParameter::getDefaultStr() const {
  260. return strDup(def_value ? "1" : "0");
  261. }
  262. char* BoolParameter::getValueStr() const {
  263. return strDup(value ? "1" : "0");
  264. }
  265. bool BoolParameter::isBool() const {
  266. return true;
  267. }
  268. BoolParameter::operator bool() const {
  269. return value;
  270. }
  271. // -=- IntParameter
  272. IntParameter::IntParameter(const char* name_, const char* desc_, int v,
  273. int minValue_, int maxValue_, ConfigurationObject co)
  274. : VoidParameter(name_, desc_, co), value(v), def_value(v),
  275. minValue(minValue_), maxValue(maxValue_)
  276. {
  277. }
  278. bool
  279. IntParameter::setParam(const char* v) {
  280. if (immutable) return true;
  281. vlog.debug("set %s(Int) to %s", getName(), v);
  282. int i = strtol(v, NULL, 0);
  283. if (i < minValue || i > maxValue)
  284. return false;
  285. value = i;
  286. return true;
  287. }
  288. bool
  289. IntParameter::setParam(int v) {
  290. if (immutable) return true;
  291. vlog.debug("set %s(Int) to %d", getName(), v);
  292. if (v < minValue || v > maxValue)
  293. return false;
  294. value = v;
  295. return true;
  296. }
  297. char*
  298. IntParameter::getDefaultStr() const {
  299. char* result = new char[16];
  300. sprintf(result, "%d", def_value);
  301. return result;
  302. }
  303. char* IntParameter::getValueStr() const {
  304. char* result = new char[16];
  305. sprintf(result, "%d", value);
  306. return result;
  307. }
  308. IntParameter::operator int() const {
  309. return value;
  310. }
  311. // -=- StringParameter
  312. StringParameter::StringParameter(const char* name_, const char* desc_,
  313. const char* v, ConfigurationObject co)
  314. : VoidParameter(name_, desc_, co), value(strDup(v)), def_value(strDup(v))
  315. {
  316. if (!v) {
  317. vlog.error("Default value <null> for %s not allowed",name_);
  318. throw rfb::Exception("Default value <null> not allowed");
  319. }
  320. }
  321. StringParameter::~StringParameter() {
  322. strFree(value);
  323. strFree(def_value);
  324. }
  325. bool StringParameter::setParam(const char* v) {
  326. LOCK_CONFIG;
  327. if (immutable) return true;
  328. if (!v)
  329. throw rfb::Exception("setParam(<null>) not allowed");
  330. vlog.debug("set %s(String) to %s", getName(), v);
  331. CharArray oldValue(value);
  332. value = strDup(v);
  333. return value != 0;
  334. }
  335. char* StringParameter::getDefaultStr() const {
  336. return strDup(def_value);
  337. }
  338. char* StringParameter::getValueStr() const {
  339. LOCK_CONFIG;
  340. return strDup(value);
  341. }
  342. StringParameter::operator const char *() const {
  343. return value;
  344. }
  345. // -=- BinaryParameter
  346. BinaryParameter::BinaryParameter(const char* name_, const char* desc_,
  347. const void* v, size_t l, ConfigurationObject co)
  348. : VoidParameter(name_, desc_, co), value(0), length(0), def_value(0), def_length(0) {
  349. if (l) {
  350. value = new char[l];
  351. length = l;
  352. memcpy(value, v, l);
  353. def_value = new char[l];
  354. def_length = l;
  355. memcpy(def_value, v, l);
  356. }
  357. }
  358. BinaryParameter::~BinaryParameter() {
  359. delete [] value;
  360. delete [] def_value;
  361. }
  362. bool BinaryParameter::setParam(const char* v) {
  363. LOCK_CONFIG;
  364. if (immutable) return true;
  365. vlog.debug("set %s(Binary) to %s", getName(), v);
  366. return rdr::HexInStream::hexStrToBin(v, &value, &length);
  367. }
  368. void BinaryParameter::setParam(const void* v, size_t len) {
  369. LOCK_CONFIG;
  370. if (immutable) return;
  371. vlog.debug("set %s(Binary)", getName());
  372. delete [] value; value = 0;
  373. if (len) {
  374. value = new char[len];
  375. length = len;
  376. memcpy(value, v, len);
  377. }
  378. }
  379. char* BinaryParameter::getDefaultStr() const {
  380. return rdr::HexOutStream::binToHexStr(def_value, def_length);
  381. }
  382. char* BinaryParameter::getValueStr() const {
  383. LOCK_CONFIG;
  384. return rdr::HexOutStream::binToHexStr(value, length);
  385. }
  386. void BinaryParameter::getData(void** data_, size_t* length_) const {
  387. LOCK_CONFIG;
  388. if (length_) *length_ = length;
  389. if (data_) {
  390. *data_ = new char[length];
  391. memcpy(*data_, value, length);
  392. }
  393. }