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