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

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