]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/arguments.cc
also change d.root IP in expected test output
[thirdparty/pdns.git] / pdns / arguments.cc
CommitLineData
12c86877
BH
1/*
2 PowerDNS Versatile Database Driven Nameserver
5b2cb3be 3 Copyright (C) 2002 - 2008 PowerDNS.COM BV
12c86877
BH
4
5 This program is free software; you can redistribute it and/or modify
fd4b10f7
BH
6 it under the terms of the GNU General Public License version 2 as published
7 by the Free Software Foundation
12c86877
BH
8
9 This program 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 program; if not, write to the Free Software
06bd9ccf 16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12c86877 17*/
12c86877 18#include "arguments.hh"
5b2cb3be 19#include <boost/algorithm/string.hpp>
61b26744 20#include "namespaces.hh"
12c86877 21
12c86877
BH
22const ArgvMap::param_t::const_iterator ArgvMap::begin()
23{
24 return params.begin();
25}
26
27const ArgvMap::param_t::const_iterator ArgvMap::end()
28{
29 return params.end();
30}
31
32string & ArgvMap::set(const string &var)
33{
34 return params[var];
35}
36
37bool ArgvMap::mustDo(const string &var)
bd11bd1d 38{
12c86877
BH
39 return ((*this)[var]!="no") && ((*this)[var]!="off");
40}
41
42vector<string>ArgvMap::list()
43{
44 vector<string> ret;
45 for(map<string,string>::const_iterator i=params.begin();i!=params.end();++i)
46 ret.push_back(i->first);
47 return ret;
48}
49
50string ArgvMap::getHelp(const string &item)
51{
52 return helpmap[item];
53}
54
55string & ArgvMap::set(const string &var, const string &help)
56{
57 helpmap[var]=help;
58 d_typeMap[var]="Parameter";
59 return set(var);
60}
61
62void ArgvMap::setCmd(const string &var, const string &help)
63{
64 helpmap[var]=help;
65 d_typeMap[var]="Command";
66 set(var)="no";
67}
68
69string & ArgvMap::setSwitch(const string &var, const string &help)
70{
71 helpmap[var]=help;
72 d_typeMap[var]="Switch";
73 return set(var);
74}
75
76
12c86877
BH
77bool ArgvMap::contains(const string &var, const string &val)
78{
102eb646
BH
79 params_t::const_iterator param = params.find(var);
80 if(param == params.end() || param->second.empty()) {
81 return false;
82 }
562588a3
BH
83 vector<string> parts;
84 vector<string>::const_iterator i;
85
102eb646 86 stringtok( parts, param->second, ", \t" );
562588a3
BH
87 for( i = parts.begin(); i != parts.end(); i++ ) {
88 if( *i == val ) {
89 return true;
90 }
91 }
92
93 return false;
12c86877
BH
94}
95
12c86877
BH
96string ArgvMap::helpstring(string prefix)
97{
98 if(prefix=="no")
99 prefix="";
100
101 string help;
102
103 for(map<string,string>::const_iterator i=helpmap.begin();
104 i!=helpmap.end();
105 i++)
106 {
107 if(!prefix.empty() && i->first.find(prefix)) // only print items with prefix
4957a608 108 continue;
12c86877
BH
109
110 help+=" --";
111 help+=i->first;
112
113 string type=d_typeMap[i->first];
114
115 if(type=="Parameter")
4957a608 116 help+="=...";
12c86877 117 else if(type=="Switch")
4957a608
BH
118 {
119 help+=" | --"+i->first+"=yes";
120 help+=" | --"+i->first+"=no";
121 }
12c86877
BH
122
123
124 help+="\n\t";
125 help+=i->second;
126 help+="\n";
127
128 }
129 return help;
130}
131
132string ArgvMap::configstring()
133{
134 string help;
135
136 help="# Autogenerated configuration file template\n";
137 for(map<string,string>::const_iterator i=helpmap.begin();
138 i!=helpmap.end();
139 i++)
140 {
141 if(d_typeMap[i->first]=="Command")
4957a608 142 continue;
12c86877
BH
143
144 help+="#################################\n";
145 help+="# ";
146 help+=i->first;
147 help+="\t";
148 help+=i->second;
149 help+="\n#\n";
150 help+="# "+i->first+"="+params[i->first]+"\n\n";
151
152 }
153 return help;
154}
155
156
157const string & ArgvMap::operator[](const string &arg)
158{
159 if(!parmIsset(arg))
160 throw ArgException(string("Undefined but needed argument: '")+arg+"'");
161
162
163 return params[arg];
164}
165
cc2978dc
BH
166#ifndef WIN32
167mode_t ArgvMap::asMode(const string &arg)
168{
169 mode_t mode;
170 const char *cptr_orig;
171 char *cptr_ret = NULL;
172
173 if(!parmIsset(arg))
174 throw ArgException(string("Undefined but needed argument: '")+arg+"'");
175
176 cptr_orig = params[arg].c_str();
177 mode = static_cast<mode_t>(strtol(cptr_orig, &cptr_ret, 8));
178 if (mode == 0 && cptr_ret == cptr_orig)
179 throw ArgException("'" + arg + string("' contains invalid octal mode"));
180 return mode;
181}
182
183gid_t ArgvMap::asGid(const string &arg)
184{
185 gid_t gid;
186 const char *cptr_orig;
187 char *cptr_ret = NULL;
188
189 if(!parmIsset(arg))
190 throw ArgException(string("Undefined but needed argument: '")+arg+"'");
191
192 cptr_orig = params[arg].c_str();
193 gid = static_cast<gid_t>(strtol(cptr_orig, &cptr_ret, 0));
194 if (gid == 0 && cptr_ret == cptr_orig) {
195 // try to resolve
196 struct group *group = getgrnam(params[arg].c_str());
197 if (group == NULL)
198 throw ArgException("'" + arg + string("' contains invalid group"));
199 gid = group->gr_gid;
200 }
201 return gid;
202}
203
204uid_t ArgvMap::asUid(const string &arg)
205{
206 uid_t uid;
207 const char *cptr_orig;
208 char *cptr_ret = NULL;
209
210 if(!parmIsset(arg))
211 throw ArgException(string("Undefined but needed argument: '")+arg+"'");
212
213 cptr_orig = params[arg].c_str();
214 uid = static_cast<uid_t>(strtol(cptr_orig, &cptr_ret, 0));
215 if (uid == 0 && cptr_ret == cptr_orig) {
216 // try to resolve
217 struct passwd *pwent = getpwnam(params[arg].c_str());
218 if (pwent == NULL)
219 throw ArgException("'" + arg + string("' contains invalid group"));
220 uid = pwent->pw_uid;
221 }
222 return uid;
223}
224#endif
225
12c86877
BH
226int ArgvMap::asNum(const string &arg)
227{
cc2978dc
BH
228 int retval;
229 const char *cptr_orig;
230 char *cptr_ret = NULL;
231
12c86877
BH
232 if(!parmIsset(arg))
233 throw ArgException(string("Undefined but needed argument: '")+arg+"'");
234
cc2978dc
BH
235 // treat empty values as zeros
236 if (params[arg].empty())
237 return 0;
238
239 cptr_orig = params[arg].c_str();
240 retval = static_cast<int>(strtol(cptr_orig, &cptr_ret, 0));
241 if (!retval && cptr_ret == cptr_orig)
242 throw ArgException("'"+arg+string("' is not valid number"));
243
244 return retval;
245}
246
247bool ArgvMap::isEmpty(const string &arg)
248{
249 if(!parmIsset(arg))
250 return true;
251 return params[arg].empty();
12c86877
BH
252}
253
254double ArgvMap::asDouble(const string &arg)
255{
cc2978dc
BH
256 double retval;
257 const char *cptr_orig;
258 char *cptr_ret = NULL;
259
12c86877
BH
260 if(!parmIsset(arg))
261 throw ArgException(string("Undefined but needed argument: '")+arg+"'");
262
cc2978dc
BH
263 if (params[arg].empty())
264 return 0.0;
265
266 cptr_orig = params[arg].c_str();
267 retval = strtod(cptr_orig, &cptr_ret);
268
269 if (retval == 0 && cptr_ret == cptr_orig)
270 throw ArgException("'"+arg+string("' is not valid double"));
271
272 return retval;
12c86877
BH
273}
274
275ArgvMap::ArgvMap()
276{
277
278}
279
280bool ArgvMap::parmIsset(const string &var)
281{
282 return (params.find(var)!=params.end());
283}
284
285void ArgvMap::parseOne(const string &arg, const string &parseOnly, bool lax)
286{
287 string var, val;
bdf40704 288 string::size_type pos;
12c86877
BH
289
290 if(!arg.find("--") &&(pos=arg.find("="))!=string::npos) // this is a --port=25 case
291 {
292 var=arg.substr(2,pos-2);
293 val=arg.substr(pos+1);
294 }
295 else if(!arg.find("--") && (arg.find("=")==string::npos)) // this is a --daemon case
296 {
297 var=arg.substr(2);
298 val="";
299 }
300 else if(arg[0]=='-')
301 {
302 var=arg.substr(1);
303 val="";
304 }
305 else { // command
306 d_cmds.push_back(arg);
307 }
308
309 if(var!="" && (parseOnly.empty() || var==parseOnly)) {
bd11bd1d
BH
310
311 pos=val.find_first_not_of(" \t"); // strip leading whitespace
312 if(pos && pos!=string::npos)
313 val=val.substr(pos);
314
50e83e03
PD
315 if(parmIsset(var))
316 params[var]=val;
12c86877
BH
317 else
318 if(!lax)
4957a608 319 throw ArgException("Trying to set unexisting parameter '"+var+"'");
12c86877
BH
320 }
321}
322
323const vector<string>&ArgvMap::getCommands()
324{
325 return d_cmds;
326}
327
328void ArgvMap::parse(int &argc, char **argv, bool lax)
329{
330 for(int n=1;n<argc;n++) {
331 parseOne(argv[n],"",lax);
332 }
333}
334
335void ArgvMap::preParse(int &argc, char **argv, const string &arg)
336{
337 for(int n=1;n<argc;n++) {
338 string varval=argv[n];
339 if(!varval.find("--"+arg))
340 parseOne(argv[n]);
341 }
342}
343
f64de501 344bool ArgvMap::preParseFile(const char *fname, const string &arg, const string& theDefault)
12c86877 345{
f64de501 346 params[arg]=theDefault;
b56ac6fd 347
12c86877 348 ifstream f(fname);
eefd15f9 349 if(!f)
12c86877 350 return false;
eefd15f9 351
12c86877
BH
352 string line;
353 string pline;
bdf40704 354 string::size_type pos;
12c86877
BH
355
356 while(getline(f,pline)) {
5b2cb3be
BH
357 trim_right(pline);
358
12c86877
BH
359 if(pline[pline.size()-1]=='\\') {
360 line+=pline.substr(0,pline.length()-1);
361 continue;
362 }
eefd15f9 363 else
12c86877 364 line+=pline;
12c86877
BH
365
366 // strip everything after a #
367 if((pos=line.find("#"))!=string::npos)
368 line=line.substr(0,pos);
369
370 // strip trailing spaces
5b2cb3be 371 trim_right(line);
eefd15f9 372
12c86877
BH
373 // strip leading spaces
374 if((pos=line.find_first_not_of(" \t\r\n"))!=string::npos)
375 line=line.substr(pos);
eefd15f9 376
12c86877
BH
377 // gpgsql-basic-query=sdfsdfs dfsdfsdf sdfsdfsfd
378
eefd15f9 379 parseOne( string("--") + line, arg );
12c86877
BH
380 line="";
381 }
eefd15f9 382
12c86877
BH
383 return true;
384}
385
386
387bool ArgvMap::file(const char *fname, bool lax)
388{
389 ifstream f(fname);
390 if(!f) {
12c86877
BH
391 return false;
392 }
eefd15f9 393
12c86877
BH
394 string line;
395 string pline;
bdf40704 396 string::size_type pos;
eefd15f9 397
12c86877 398 while(getline(f,pline)) {
5b2cb3be 399 trim_right(pline);
ccd3ed60
BH
400 if(pline.empty())
401 continue;
12c86877
BH
402
403 if(pline[pline.size()-1]=='\\') {
404 line+=pline.substr(0,pline.length()-1);
405
406 continue;
407 }
eefd15f9 408 else
12c86877
BH
409 line+=pline;
410
411 // strip everything after a #
412 if((pos=line.find("#"))!=string::npos)
413 line=line.substr(0,pos);
414
415 // strip trailing spaces
9ff13837 416 trim(line);
eefd15f9
BH
417
418 parseOne(string("--")+line,"",lax);
12c86877
BH
419 line="";
420 }
eefd15f9 421
12c86877
BH
422 return true;
423}