blob: a08260dd824e7d39898226d5416fb4b3eee7c39e [file] [log] [blame]
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved.
Peter Åstrande2ab84e2005-02-05 16:33:44 +00002 * Copyright (C) 2004-2005 Cendio AB. All rights reserved.
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00003 *
4 * This is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This software is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this software; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
17 * USA.
18 */
19
20// -=- Configuration.cxx
21
22#include <stdlib.h>
23#include <ctype.h>
24#include <string.h>
25#include <assert.h>
26#ifdef WIN32
27#define strcasecmp _stricmp
28#define strncasecmp _strnicmp
29#endif
30
31#include <rfb/util.h>
32#include <rfb/Configuration.h>
33#include <rfb/LogWriter.h>
34#include <rfb/Exception.h>
35
36#ifdef WIN32
37
38// Under Win32, we use these routines from several threads,
39// so we must provide suitable locking.
40#include <rfb/Threading.h>
41
42static rfb::Mutex configLock;
43
44#endif
45
46#include <rdr/HexOutStream.h>
47#include <rdr/HexInStream.h>
48
49using namespace rfb;
50
51static LogWriter vlog("Config");
52
53
54// -=- Configuration
55
56VoidParameter* Configuration::head = 0;
57
58bool Configuration::setParam(const char* n, const char* v, bool immutable) {
59 return setParam(n, strlen(n), v, immutable);
60}
61
62bool Configuration::setParam(const char* name, int len,
63 const char* val, bool immutable)
64{
65 VoidParameter* current = head;
66 while (current) {
67 if ((int)strlen(current->getName()) == len &&
68 strncasecmp(current->getName(), name, len) == 0)
69 {
70 bool b = current->setParam(val);
Peter Åstrand55855d52005-01-03 12:01:45 +000071 current->setHasBeenSet();
Peter Åstrand07350592005-01-03 14:47:42 +000072 if (b && immutable)
73 current->setImmutable();
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +000074 return b;
75 }
76 current = current->_next;
77 }
78 return false;
79}
80
81bool Configuration::setParam(const char* config, bool immutable) {
82 bool hyphen = false;
83 if (config[0] == '-') {
84 hyphen = true;
85 config++;
86 if (config[0] == '-') config++; // allow gnu-style --<option>
87 }
88 const char* equal = strchr(config, '=');
89 if (equal) {
90 return setParam(config, equal-config, equal+1, immutable);
91 } else if (hyphen) {
92 VoidParameter* current = head;
93 while (current) {
94 if (strcasecmp(current->getName(), config) == 0) {
95 bool b = current->setParam();
Peter Åstrand55855d52005-01-03 12:01:45 +000096 current->setHasBeenSet();
Peter Åstrand07350592005-01-03 14:47:42 +000097 if (b && immutable)
98 current->setImmutable();
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +000099 return b;
100 }
101 current = current->_next;
102 }
103 }
104 return false;
105}
106
107VoidParameter* Configuration::getParam(const char* param)
108{
109 VoidParameter* current = head;
110 while (current) {
111 if (strcasecmp(current->getName(), param) == 0)
112 return current;
113 current = current->_next;
114 }
115 return 0;
116}
117
118void Configuration::listParams(int width, int nameWidth) {
119 VoidParameter* current = head;
120 while (current) {
121 char* def_str = current->getDefaultStr();
122 const char* desc = current->getDescription();
123 fprintf(stderr," %-*s -", nameWidth, current->getName());
124 int column = strlen(current->getName());
125 if (column < nameWidth) column = nameWidth;
126 column += 4;
127 while (true) {
128 const char* s = strchr(desc, ' ');
129 int wordLen;
130 if (s) wordLen = s-desc;
131 else wordLen = strlen(desc);
132
133 if (column + wordLen + 1 > width) {
134 fprintf(stderr,"\n%*s",nameWidth+4,"");
135 column = nameWidth+4;
136 }
137 fprintf(stderr," %.*s",wordLen,desc);
138 column += wordLen + 1;
139 desc += wordLen + 1;
140 if (!s) break;
141 }
142
143 if (def_str) {
144 if (column + (int)strlen(def_str) + 11 > width)
145 fprintf(stderr,"\n%*s",nameWidth+4,"");
146 fprintf(stderr," (default=%s)\n",def_str);
147 strFree(def_str);
148 } else {
149 fprintf(stderr,"\n");
150 }
151 current = current->_next;
152 }
153}
154
155// -=- VoidParameter
156
157VoidParameter::VoidParameter(const char* name_, const char* desc_)
Peter Åstrand55855d52005-01-03 12:01:45 +0000158 : immutable(false), _hasBeenSet(false), name(name_), description(desc_) {
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000159 _next = Configuration::head;
160 Configuration::head = this;
161}
162
163VoidParameter::~VoidParameter() {
164}
165
166const char*
167VoidParameter::getName() const {
168 return name;
169}
170
171const char*
172VoidParameter::getDescription() const {
173 return description;
174}
175
176bool VoidParameter::setParam() {
177 return false;
178}
179
180bool VoidParameter::isBool() const {
181 return false;
182}
183
184void
185VoidParameter::setImmutable() {
186 vlog.debug("set immutable %s", getName());
187 immutable = true;
188}
189
Peter Åstrand55855d52005-01-03 12:01:45 +0000190void
191VoidParameter::setHasBeenSet() {
192 _hasBeenSet = true;
193}
194
195bool
196VoidParameter::hasBeenSet() {
197 return _hasBeenSet;
198}
199
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000200// -=- AliasParameter
201
202AliasParameter::AliasParameter(const char* name_, const char* desc_,
203 VoidParameter* param_)
204 : VoidParameter(name_, desc_), param(param_) {
205}
206
207bool
208AliasParameter::setParam(const char* v) {
209 return param->setParam(v);
210}
211
212bool AliasParameter::setParam() {
213 return param->setParam();
214}
215
216char*
217AliasParameter::getDefaultStr() const {
218 return 0;
219}
220
221char* AliasParameter::getValueStr() const {
222 return param->getValueStr();
223}
224
225bool AliasParameter::isBool() const {
226 return param->isBool();
227}
228
Peter Åstrand07350592005-01-03 14:47:42 +0000229void
230AliasParameter::setImmutable() {
231 vlog.debug("set immutable %s (Alias)", getName());
232 param->setImmutable();
233}
234
235
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000236// -=- BoolParameter
237
238BoolParameter::BoolParameter(const char* name_, const char* desc_, bool v)
239: VoidParameter(name_, desc_), value(v), def_value(v) {
240}
241
242bool
243BoolParameter::setParam(const char* v) {
244 if (immutable) return true;
245
246 if (*v == 0 || strcasecmp(v, "1") == 0 || strcasecmp(v, "on") == 0
247 || strcasecmp(v, "true") == 0 || strcasecmp(v, "yes") == 0)
248 value = 1;
249 else if (strcasecmp(v, "0") == 0 || strcasecmp(v, "off") == 0
250 || strcasecmp(v, "false") == 0 || strcasecmp(v, "no") == 0)
251 value = 0;
252 else {
253 vlog.error("Bool parameter %s: invalid value '%s'", getName(), v);
254 return false;
255 }
256
257 vlog.debug("set %s(Bool) to %s(%d)", getName(), v, value);
258 return true;
259}
260
261bool BoolParameter::setParam() {
262 setParam(true);
263 return true;
264}
265
266void BoolParameter::setParam(bool b) {
267 if (immutable) return;
268 value = b;
269 vlog.debug("set %s(Bool) to %d", getName(), value);
270}
271
272char*
273BoolParameter::getDefaultStr() const {
274 char* result = new char[8];
275 sprintf(result, "%d", (int)def_value);
276 return result;
277}
278
279char* BoolParameter::getValueStr() const {
280 char* result = new char[8];
281 sprintf(result, "%d", (int)value);
282 return result;
283}
284
285bool BoolParameter::isBool() const {
286 return true;
287}
288
289BoolParameter::operator bool() const {
290 return value;
291}
292
293// -=- IntParameter
294
295IntParameter::IntParameter(const char* name_, const char* desc_, int v)
296: VoidParameter(name_, desc_), value(v), def_value(v) {
297}
298
299bool
300IntParameter::setParam(const char* v) {
301 if (immutable) return true;
302 vlog.debug("set %s(Int) to %s", getName(), v);
303 value = atoi(v);
304 return true;
305}
306
307bool
308IntParameter::setParam(int v) {
309 if (immutable) return true;
310 vlog.debug("set %s(Int) to %d", getName(), v);
311 value = v;
312 return true;
313}
314
315char*
316IntParameter::getDefaultStr() const {
317 char* result = new char[16];
318 sprintf(result, "%d", def_value);
319 return result;
320}
321
322char* IntParameter::getValueStr() const {
323 char* result = new char[16];
324 sprintf(result, "%d", value);
325 return result;
326}
327
328IntParameter::operator int() const {
329 return value;
330}
331
332// -=- StringParameter
333
334StringParameter::StringParameter(const char* name_, const char* desc_,
335 const char* v)
336 : VoidParameter(name_, desc_), value(strDup(v)), def_value(v)
337{
338 if (!v) {
339 fprintf(stderr,"Default value <null> for %s not allowed\n",name_);
340 throw rfb::Exception("Default value <null> not allowed");
341 }
342}
343
344StringParameter::~StringParameter() {
345 strFree(value);
346}
347
348bool StringParameter::setParam(const char* v) {
349#ifdef WIN32
350 Lock l(configLock);
351#endif
352 if (immutable) return true;
353 if (!v)
354 throw rfb::Exception("setParam(<null>) not allowed");
355 vlog.debug("set %s(String) to %s", getName(), v);
356 strFree(value);
357 value = strDup(v);
358 return value != 0;
359}
360
361char* StringParameter::getDefaultStr() const {
362 return strDup(def_value);
363}
364
365char* StringParameter::getValueStr() const {
366#ifdef WIN32
367 Lock l(configLock);
368#endif
369 return strDup(value);
370}
371
372// -=- BinaryParameter
373
374BinaryParameter::BinaryParameter(const char* name_, const char* desc_, const void* v, int l)
375: VoidParameter(name_, desc_), value(0), length(0), def_value((char*)v), def_length(l) {
376 if (l) {
377 value = new char[l];
378 length = l;
379 memcpy(value, v, l);
380 }
381}
382BinaryParameter::~BinaryParameter() {
383 if (value)
384 delete [] value;
385}
386
387bool BinaryParameter::setParam(const char* v) {
388#ifdef WIN32
389 Lock l(configLock);
390#endif
391 if (immutable) return true;
392 vlog.debug("set %s(Binary) to %s", getName(), v);
393 return rdr::HexInStream::hexStrToBin(v, &value, &length);
394}
395
396void BinaryParameter::setParam(const void* v, int len) {
397#ifdef WIN32
398 Lock l(configLock);
399#endif
Peter Åstrand07350592005-01-03 14:47:42 +0000400 if (immutable) return;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000401 vlog.debug("set %s(Binary)", getName());
402 delete [] value; value = 0;
403 if (len) {
404 value = new char[len];
405 length = len;
406 memcpy(value, v, len);
407 }
408}
409
410char* BinaryParameter::getDefaultStr() const {
411 return rdr::HexOutStream::binToHexStr(def_value, def_length);
412}
413
414char* BinaryParameter::getValueStr() const {
415#ifdef WIN32
416 Lock l(configLock);
417#endif
418 return rdr::HexOutStream::binToHexStr(value, length);
419}
420
421void BinaryParameter::getData(void** data_, int* length_) const {
422#ifdef WIN32
423 Lock l(configLock);
424#endif
425 if (length_) *length_ = length;
426 if (data_) {
427 *data_ = new char[length];
428 memcpy(*data_, value, length);
429 }
430}