]> git.stg.codes - stg.git/blob - projects/sgconf/main.cpp
Some refactoring.
[stg.git] / projects / sgconf / main.cpp
1 /*
2  *    This program is free software; you can redistribute it and/or modify
3  *    it under the terms of the GNU General Public License as published by
4  *    the Free Software Foundation; either version 2 of the License, or
5  *    (at your option) any later version.
6  *
7  *    This program is distributed in the hope that it will be useful,
8  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  *    GNU General Public License for more details.
11  *
12  *    You should have received a copy of the GNU General Public License
13  *    along with this program; if not, write to the Free Software
14  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
15  */
16
17 /*
18  *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
19  *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
20  */
21
22 #include "xml.h"
23 #include "admins.h"
24 #include "tariffs.h"
25 #include "users.h"
26 #include "services.h"
27 #include "corps.h"
28
29 #include "options.h"
30 #include "actions.h"
31 #include "config.h"
32
33 #include <string>
34 #include <iostream>
35
36 #include <cstdlib> // getenv
37 #include <cstring> // basename
38
39 #include <unistd.h> // access
40
41 namespace
42 {
43
44 template <typename T>
45 struct nullary_function
46 {
47 typedef T result_type;
48 };
49
50 template <typename F>
51 class binder0 : public nullary_function<typename F::result_type>
52 {
53     public:
54         binder0(const F & func, const typename F::argument_type & arg)
55             : m_func(func), m_arg(arg) {}
56         typename F::result_type operator()() const { return m_func(m_arg); }
57     private:
58         F m_func;
59         typename F::argument_type m_arg;
60 };
61
62 template <typename F>
63 inline
64 binder0<F> bind0(const F & func, const typename F::argument_type & arg)
65 {
66 return binder0<F>(func, arg);
67 }
68
69 template <typename A, typename R>
70 class FUNC1_ADAPTER : public std::unary_function<A, R>
71 {
72     public:
73         FUNC1_ADAPTER(R (*func)(A)) : m_func(func) {}
74         const R operator()(A arg) const { return (m_func)(arg); }
75     private:
76         R (*m_func)(A);
77 };
78
79 template <typename C, typename A, typename R>
80 class METHOD1_ADAPTER : public std::unary_function<A, R>
81 {
82     public:
83         METHOD1_ADAPTER(R (C::* func)(A), C & obj) : m_func(func), m_obj(obj) {}
84         R operator()(A arg) { return (m_obj.*m_func)(arg); }
85     private:
86         R (C::* m_func)(A);
87         C & m_obj;
88 };
89
90 template <typename C, typename A, typename R>
91 class CONST_METHOD1_ADAPTER : public std::unary_function<A, R>
92 {
93     public:
94         CONST_METHOD1_ADAPTER(R (C::* func)(A) const, C & obj) : m_func(func), m_obj(obj) {}
95         R operator()(A arg) const { return (m_obj.*m_func)(arg); }
96     private:
97         R (C::* m_func)(A) const;
98         C & m_obj;
99 };
100
101 template <typename A, typename R>
102 FUNC1_ADAPTER<A, R> Func1Adapt(R (func)(A))
103 {
104 return FUNC1_ADAPTER<A, R>(func);
105 }
106
107 template <typename C, typename A, typename R>
108 METHOD1_ADAPTER<C, A, R> Method1Adapt(R (C::* func)(A), C & obj)
109 {
110 return METHOD1_ADAPTER<C, A, R>(func, obj);
111 }
112
113 template <typename C, typename A, typename R>
114 CONST_METHOD1_ADAPTER<C, A, R> Method1Adapt(R (C::* func)(A) const, C & obj)
115 {
116 return CONST_METHOD1_ADAPTER<C, A, R>(func, obj);
117 }
118
119 void Version(const std::string & self)
120 {
121 std::cout << self << ", version: 2.0.0-alpha.\n";
122 }
123
124 void ReadUserConfigFile(SGCONF::OPTION_BLOCK & block)
125 {
126 std::vector<std::string> paths;
127 const char * configHome = getenv("XDG_CONFIG_HOME");
128 if (configHome == NULL)
129     {
130     const char * home = getenv("HOME");
131     if (home == NULL)
132         return;
133     paths.push_back(std::string(home) + "/.config/sgconf/sgconf.conf");
134     paths.push_back(std::string(home) + "/.sgconf/sgconf.conf");
135     }
136 else
137     paths.push_back(std::string(configHome) + "/sgconf/sgconf.conf");
138 for (std::vector<std::string>::const_iterator it = paths.begin(); it != paths.end(); ++it)
139     if (access(it->c_str(), R_OK) == 0)
140         {
141         block.ParseFile(*it);
142         return;
143         }
144 }
145
146 } // namespace anonymous
147
148 namespace SGCONF
149 {
150
151 class CONFIG_ACTION : public ACTION
152 {
153     public:
154         CONFIG_ACTION(SGCONF::CONFIG & config,
155                       const std::string & paramDescription)
156             : m_config(config),
157               m_description(paramDescription)
158         {}
159
160         virtual ACTION * Clone() const { return new CONFIG_ACTION(*this); }
161
162         virtual std::string ParamDescription() const { return m_description; }
163         virtual std::string DefaultDescription() const { return ""; }
164         virtual OPTION_BLOCK & Suboptions() { return m_suboptions; }
165         virtual PARSER_STATE Parse(int argc, char ** argv);
166
167     private:
168         SGCONF::CONFIG & m_config;
169         std::string m_description;
170         OPTION_BLOCK m_suboptions;
171
172         void ParseCredentials(const std::string & credentials);
173         void ParseHostAndPort(const std::string & hostAndPort);
174 };
175
176 typedef bool (* API_FUNCTION) (const SGCONF::CONFIG &,
177                                const std::string &,
178                                const std::map<std::string, std::string> &);
179
180 class COMMAND
181 {
182     public:
183         COMMAND(API_FUNCTION funPtr,
184                 const std::string & arg,
185                 const std::map<std::string, std::string> & options)
186             : m_funPtr(funPtr),
187               m_arg(arg),
188               m_options(options)
189         {}
190         bool Execute(const SGCONF::CONFIG & config) const
191         {
192             return m_funPtr(config, m_arg, m_options);
193         }
194
195     private:
196         API_FUNCTION m_funPtr;
197         std::string m_arg;
198         std::map<std::string, std::string> m_options;
199 };
200
201 class COMMANDS
202 {
203     public:
204         void Add(API_FUNCTION funPtr,
205                  const std::string & arg,
206                  const std::map<std::string, std::string> & options) { m_commands.push_back(COMMAND(funPtr, arg, options)); }
207         bool Execute(const SGCONF::CONFIG & config) const
208         {
209             std::list<COMMAND>::const_iterator it(m_commands.begin());
210             bool res = true;
211             while (it != m_commands.end() && res)
212             {
213                 res = res && it->Execute(config);
214                 ++it;
215             }
216             return res;
217         }
218     private:
219         std::list<COMMAND> m_commands;
220 };
221
222 class API_ACTION : public ACTION
223 {
224     public:
225         API_ACTION(COMMANDS & commands,
226                    const std::string & paramDescription,
227                    bool needArgument,
228                    const OPTION_BLOCK& suboptions,
229                    API_FUNCTION funPtr)
230             : m_commands(commands),
231               m_description(paramDescription),
232               m_argument(needArgument ? "1" : ""), // Hack
233               m_suboptions(suboptions),
234               m_funPtr(funPtr)
235         {}
236         API_ACTION(COMMANDS & commands,
237                    const std::string & paramDescription,
238                    bool needArgument,
239                    API_FUNCTION funPtr)
240             : m_commands(commands),
241               m_description(paramDescription),
242               m_argument(needArgument ? "1" : ""), // Hack
243               m_funPtr(funPtr)
244         {}
245
246         virtual ACTION * Clone() const { return new API_ACTION(*this); }
247
248         virtual std::string ParamDescription() const { return m_description; }
249         virtual std::string DefaultDescription() const { return ""; }
250         virtual OPTION_BLOCK & Suboptions() { return m_suboptions; }
251         virtual PARSER_STATE Parse(int argc, char ** argv)
252         {
253         PARSER_STATE state(false, argc, argv);
254         if (!m_argument.empty())
255             {
256             if (argc == 0 ||
257                 argv == NULL ||
258                 *argv == NULL)
259                 throw ERROR("Missing argument.");
260             m_argument = *argv;
261             --state.argc;
262             ++state.argv;
263             }
264         m_suboptions.Parse(state.argc, state.argv);
265         m_commands.Add(m_funPtr, m_argument, m_params);
266         return state;
267         }
268
269     private:
270         COMMANDS & m_commands;
271         std::string m_description;
272         std::string m_argument;
273         OPTION_BLOCK m_suboptions;
274         std::map<std::string, std::string> m_params;
275         API_FUNCTION m_funPtr;
276 };
277
278 PARSER_STATE CONFIG_ACTION::Parse(int argc, char ** argv)
279 {
280 if (argc == 0 ||
281     argv == NULL ||
282     *argv == NULL)
283     throw ERROR("Missing argument.");
284 char * pos = strchr(*argv, '@');
285 if (pos != NULL)
286     {
287     ParseCredentials(std::string(*argv, pos));
288     ParseHostAndPort(std::string(pos + 1));
289     }
290 else
291     {
292     ParseHostAndPort(std::string(*argv));
293     }
294 return PARSER_STATE(false, --argc, ++argv);
295 }
296
297 void CONFIG_ACTION::ParseCredentials(const std::string & credentials)
298 {
299 std::string::size_type pos = credentials.find_first_of(':');
300 if (pos != std::string::npos)
301     {
302     m_config.userName = credentials.substr(0, pos);
303     m_config.userPass = credentials.substr(pos + 1);
304     }
305 else
306     {
307     m_config.userName = credentials;
308     }
309 }
310
311 void CONFIG_ACTION::ParseHostAndPort(const std::string & hostAndPort)
312 {
313 std::string::size_type pos = hostAndPort.find_first_of(':');
314 if (pos != std::string::npos)
315     {
316     m_config.server = hostAndPort.substr(0, pos);
317     uint16_t port = 0;
318     if (str2x(hostAndPort.substr(pos + 1), port))
319         throw ERROR("Invalid port value: '" + hostAndPort.substr(pos + 1) + "'");
320     m_config.port = port;
321     }
322 else
323     {
324     m_config.server = hostAndPort;
325     }
326 }
327
328 inline
329 CONFIG_ACTION * MakeParamAction(SGCONF::CONFIG & config,
330                                 const std::string & paramDescription)
331 {
332 return new CONFIG_ACTION(config, paramDescription);
333 }
334
335 inline
336 ACTION * MakeAPIAction(COMMANDS & commands,
337                        const std::string & paramDescription,
338                        bool needArgument,
339                        API_FUNCTION funPtr)
340 {
341 return new API_ACTION(commands, paramDescription, needArgument, funPtr);
342 }
343
344 inline
345 ACTION * MakeAPIAction(COMMANDS & commands,
346                        API_FUNCTION funPtr)
347 {
348 return new API_ACTION(commands, "", false, funPtr);
349 }
350
351 } // namespace SGCONF
352
353 time_t stgTime;
354
355 //-----------------------------------------------------------------------------
356 int main(int argc, char **argv)
357 {
358 std::string self(basename(argv[0]));
359 SGCONF::CONFIG config;
360 SGCONF::COMMANDS commands;
361
362 SGCONF::OPTION_BLOCKS blocks;
363 blocks.Add("General options")
364       .Add("c", "config", SGCONF::MakeParamAction(config.configFile, std::string("~/.config/stg/sgconf.conf"), "<config file>"), "override default config file")
365       .Add("h", "help", SGCONF::MakeFunc0Action(bind0(Method1Adapt(&SGCONF::OPTION_BLOCKS::Help, blocks), 0)), "\t\tshow this help and exit")
366       //.Add("help-all", SGCONF::MakeFunc0Action(UsageAll), "\t\tshow full help and exit")
367       .Add("v", "version", SGCONF::MakeFunc0Action(bind0(Func1Adapt(Version), self)), "\t\tshow version information and exit");
368 SGCONF::OPTION_BLOCK & block = blocks.Add("Connection options")
369       .Add("s", "server", SGCONF::MakeParamAction(config.server, std::string("localhost"), "<address>"), "\t\thost to connect")
370       .Add("p", "port", SGCONF::MakeParamAction(config.port, uint16_t(5555), "<port>"), "\t\tport to connect")
371       .Add("u", "username", SGCONF::MakeParamAction(config.userName, std::string("admin"), "<username>"), "\tadministrative login")
372       .Add("w", "userpass", SGCONF::MakeParamAction(config.userPass, "<password>"), "\tpassword for the administrative login")
373       .Add("a", "address", SGCONF::MakeParamAction(config, "<connection string>"), "connection params as a single string in format: <login>:<password>@<host>:<port>");
374 blocks.Add("Raw XML")
375       .Add("r", "raw", SGCONF::MakeAPIAction(commands, "<xml>", true, SGCONF::RawXMLFunction), "\tmake raw XML request");
376 blocks.Add("Admin management options")
377       .Add("get-admins", SGCONF::MakeAPIAction(commands, SGCONF::GetAdminsFunction), "\tget admin list")
378       .Add("get-admin", SGCONF::MakeAPIAction(commands, "<login>", true, SGCONF::GetAdminFunction), "get admin")
379       .Add("add-admin", SGCONF::MakeAPIAction(commands, "<login>", true, SGCONF::AddAdminFunction), "add admin")
380       .Add("del-admin", SGCONF::MakeAPIAction(commands, "<login>", true, SGCONF::DelAdminFunction), "del admin")
381       .Add("chg-admin", SGCONF::MakeAPIAction(commands, "<login>", true, SGCONF::ChgAdminFunction), "change admin");
382 blocks.Add("Tariff management options")
383       .Add("get-tariffs", SGCONF::MakeAPIAction(commands, SGCONF::GetTariffsFunction), "\tget tariff list")
384       .Add("get-tariff", SGCONF::MakeAPIAction(commands, "<name>", true, SGCONF::GetTariffFunction), "get tariff")
385       .Add("add-tariff", SGCONF::MakeAPIAction(commands, "<name>", true, SGCONF::AddTariffFunction), "add tariff")
386       .Add("del-tariff", SGCONF::MakeAPIAction(commands, "<name>", true, SGCONF::DelTariffFunction), "del tariff")
387       .Add("chg-tariff", SGCONF::MakeAPIAction(commands, "<name>", true, SGCONF::ChgTariffFunction), "change tariff");
388 blocks.Add("User management options")
389       .Add("get-users", SGCONF::MakeAPIAction(commands, SGCONF::GetUsersFunction), "\tget user list")
390       .Add("get-user", SGCONF::MakeAPIAction(commands, "<login>", true, SGCONF::GetUserFunction), "get user")
391       .Add("add-user", SGCONF::MakeAPIAction(commands, "<login>", true, SGCONF::AddUserFunction), "add user")
392       .Add("del-user", SGCONF::MakeAPIAction(commands, "<login>", true, SGCONF::DelUserFunction), "del user")
393       .Add("chg-user", SGCONF::MakeAPIAction(commands, "<login>", true, SGCONF::ChgUserFunction), "change user")
394       .Add("check-user", SGCONF::MakeAPIAction(commands, "<login>", true, SGCONF::CheckUserFunction), "check user existance and credentials")
395       .Add("send-message", SGCONF::MakeAPIAction(commands, "<login>", true, SGCONF::SendMessageFunction), "send message");
396 blocks.Add("Service management options")
397       .Add("get-services", SGCONF::MakeAPIAction(commands, SGCONF::GetServicesFunction), "\tget service list")
398       .Add("get-service", SGCONF::MakeAPIAction(commands, "<name>", true, SGCONF::GetServiceFunction), "get service")
399       .Add("add-service", SGCONF::MakeAPIAction(commands, "<name>", true, SGCONF::AddServiceFunction), "add service")
400       .Add("del-service", SGCONF::MakeAPIAction(commands, "<name>", true, SGCONF::DelServiceFunction), "del service")
401       .Add("chg-service", SGCONF::MakeAPIAction(commands, "<name>", true, SGCONF::ChgServiceFunction), "change service");
402 blocks.Add("Corporation management options")
403       .Add("get-corps", SGCONF::MakeAPIAction(commands, SGCONF::GetCorpsFunction), "\tget corporation list")
404       .Add("get-corp", SGCONF::MakeAPIAction(commands, "<name>", true, SGCONF::GetCorpFunction), "get corporation")
405       .Add("add-corp", SGCONF::MakeAPIAction(commands, "<name>", true, SGCONF::AddCorpFunction), "add corporation")
406       .Add("del-corp", SGCONF::MakeAPIAction(commands, "<name>", true, SGCONF::DelCorpFunction), "del corporation")
407       .Add("chg-corp", SGCONF::MakeAPIAction(commands, "<name>", true, SGCONF::ChgCorpFunction), "change corporation");
408
409 SGCONF::PARSER_STATE state(false, argc, argv);
410
411 try
412 {
413 state = blocks.Parse(--argc, ++argv); // Skipping self name
414 }
415 catch (const SGCONF::OPTION::ERROR& ex)
416 {
417 std::cerr << ex.what() << "\n";
418 return -1;
419 }
420
421 if (state.stop)
422     return 0;
423
424 if (state.argc > 0)
425     {
426     std::cerr << "Unknown option: '" << *state.argv << "'\n";
427     return -1;
428     }
429
430 try
431 {
432 SGCONF::CONFIG configOverride(config);
433
434 if (config.configFile.empty())
435     {
436     const char * mainConfigFile = "/etc/sgconf/sgconf.conf";
437     if (access(mainConfigFile, R_OK) == 0)
438         block.ParseFile(mainConfigFile);
439     ReadUserConfigFile(block);
440     }
441 else
442     {
443     block.ParseFile(config.configFile.data());
444     }
445
446 config = configOverride;
447 }
448 catch (const std::exception& ex)
449 {
450 std::cerr << ex.what() << "\n";
451 return -1;
452 }
453
454 std::cerr << "Config: " << config.Serialize() << std::endl;
455 return commands.Execute(config) ? 0 : -1;
456 }
457 //-----------------------------------------------------------------------------
458
459 namespace
460 {
461
462 /*void UsageTariffs(bool full)
463 {
464 std::cout << "Tariffs management options:\n"
465           << "\t--get-tariffs\t\t\t\tget a list of tariffs (subsequent options will define what to show)\n";
466 if (full)
467     std::cout << "\t\t--name\t\t\t\tshow tariff's name\n"
468               << "\t\t--fee\t\t\t\tshow tariff's fee\n"
469               << "\t\t--free\t\t\t\tshow tariff's prepaid traffic in terms of cost\n"
470               << "\t\t--passive-cost\t\t\tshow tariff's cost of \"freeze\"\n"
471               << "\t\t--traff-type\t\t\tshow what type of traffix will be accounted by the tariff\n"
472               << "\t\t--dirs\t\t\t\tshow tarification rules for directions\n\n";
473 std::cout << "\t--get-tariff\t\t\t\tget the information about tariff\n";
474 if (full)
475     std::cout << "\t\t--name <name>\t\t\tname of the tariff to show\n"
476               << "\t\t--fee\t\t\t\tshow tariff's fee\n"
477               << "\t\t--free\t\t\t\tshow tariff's prepaid traffic in terms of cost\n"
478               << "\t\t--passive-cost\t\t\tshow tariff's cost of \"freeze\"\n"
479               << "\t\t--traff-type\t\t\tshow what type of traffix will be accounted by the tariff\n"
480               << "\t\t--dirs\t\t\t\tshow tarification rules for directions\n\n";
481 std::cout << "\t--add-tariff\t\t\t\tadd a new tariff\n";
482 if (full)
483     std::cout << "\t\t--name <name>\t\t\tname of the tariff to add\n"
484               << "\t\t--fee <fee>\t\t\tstariff's fee\n"
485               << "\t\t--free <free>\t\t\ttariff's prepaid traffic in terms of cost\n"
486               << "\t\t--passive-cost <cost>\t\ttariff's cost of \"freeze\"\n"
487               << "\t\t--traff-type <type>\t\twhat type of traffi will be accounted by the tariff\n"
488               << "\t\t--times <times>\t\t\tslash-separated list of \"day\" time-spans (in form \"hh:mm-hh:mm\") for each direction\n"
489               << "\t\t--prices-day-a <prices>\t\tslash-separated list of prices for \"day\" traffic before threshold for each direction\n"
490               << "\t\t--prices-night-a <prices>\tslash-separated list of prices for \"night\" traffic before threshold for each direction\n"
491               << "\t\t--prices-day-b <prices>\t\tslash-separated list of prices for \"day\" traffic after threshold for each direction\n"
492               << "\t\t--prices-night-b <prices>\tslash-separated list of prices for \"night\" traffic after threshold for each direction\n"
493               << "\t\t--single-prices <yes|no>\tslash-separated list of \"single price\" flags for each direction\n"
494               << "\t\t--no-discounts <yes|no>\t\tslash-separated list of \"no discount\" flags for each direction\n"
495               << "\t\t--thresholds <thresholds>\tslash-separated list of thresholds (in Mb) for each direction\n\n";
496 std::cout << "\t--del-tariff\t\t\t\tdelete an existing tariff\n";
497 if (full)
498     std::cout << "\t\t--name <name>\t\t\tname of the tariff to delete\n\n";
499 std::cout << "\t--chg-tariff\t\t\t\tchange an existing tariff\n";
500 if (full)
501     std::cout << "\t\t--name <name>\t\t\tname of the tariff to change\n"
502               << "\t\t--fee <fee>\t\t\tstariff's fee\n"
503               << "\t\t--free <free>\t\t\ttariff's prepaid traffic in terms of cost\n"
504               << "\t\t--passive-cost <cost>\t\ttariff's cost of \"freeze\"\n"
505               << "\t\t--traff-type <type>\t\twhat type of traffix will be accounted by the tariff\n"
506               << "\t\t--dir <N>\t\t\tnumber of direction data to change\n"
507               << "\t\t\t--time <time>\t\t\"day\" time-span (in form \"hh:mm-hh:mm\")\n"
508               << "\t\t\t--price-day-a <price>\tprice for \"day\" traffic before threshold\n"
509               << "\t\t\t--price-night-a <price>\tprice for \"night\" traffic before threshold\n"
510               << "\t\t\t--price-day-b <price>\tprice for \"day\" traffic after threshold\n"
511               << "\t\t\t--price-night-b <price>\tprice for \"night\" traffic after threshold\n"
512               << "\t\t\t--single-price <yes|no>\t\"single price\" flag\n"
513               << "\t\t\t--no-discount <yes|no>\t\"no discount\" flag\n"
514               << "\t\t\t--threshold <threshold>\tthreshold (in Mb)\n\n";
515 }
516 //-----------------------------------------------------------------------------
517 void UsageUsers(bool full)
518 {
519 std::cout << "Users management options:\n"
520           << "\t--get-users\t\t\t\tget a list of users (subsequent options will define what to show)\n";
521 if (full)
522     std::cout << "\n\n";
523 std::cout << "\t--get-user\t\t\t\tget the information about user\n";
524 if (full)
525     std::cout << "\n\n";
526 std::cout << "\t--add-user\t\t\t\tadd a new user\n";
527 if (full)
528     std::cout << "\n\n";
529 std::cout << "\t--del-user\t\t\t\tdelete an existing user\n";
530 if (full)
531     std::cout << "\n\n";
532 std::cout << "\t--chg-user\t\t\t\tchange an existing user\n";
533 if (full)
534     std::cout << "\n\n";
535 std::cout << "\t--check-user\t\t\t\tcheck credentials is valid\n";
536 if (full)
537     std::cout << "\n\n";
538 std::cout << "\t--send-message\t\t\t\tsend a message to a user\n";
539 if (full)
540     std::cout << "\n\n";
541 }
542 //-----------------------------------------------------------------------------
543 void UsageServices(bool full)
544 {
545 std::cout << "Services management options:\n"
546           << "\t--get-services\t\t\t\tget a list of services (subsequent options will define what to show)\n";
547 if (full)
548     std::cout << "\t\t--name\t\t\t\tshow service's name\n"
549               << "\t\t--comment\t\t\tshow a comment to the service\n"
550               << "\t\t--cost\t\t\t\tshow service's cost\n"
551               << "\t\t--pay-day\t\t\tshow service's pay day\n\n";
552 std::cout << "\t--get-service\t\t\t\tget the information about service\n";
553 if (full)
554     std::cout << "\t\t--name <name>\t\t\tname of the service to show\n"
555               << "\t\t--comment\t\t\tshow a comment to the service\n"
556               << "\t\t--cost\t\t\t\tshow service's cost\n"
557               << "\t\t--pay-day\t\t\tshow service's pay day\n\n";
558 std::cout << "\t--add-service\t\t\t\tadd a new service\n";
559 if (full)
560     std::cout << "\t\t--name <name>\t\t\tname of the service to add\n"
561               << "\t\t--comment <comment>\t\ta comment to the service\n"
562               << "\t\t--cost <cost>\t\t\tservice's cost\n"
563               << "\t\t--pay-day <day>\t\t\tservice's pay day\n\n";
564 std::cout << "\t--del-service\t\t\t\tdelete an existing service\n";
565 if (full)
566     std::cout << "\t\t--name <name>\t\t\tname of the service to delete\n\n";
567 std::cout << "\t--chg-service\t\t\t\tchange an existing service\n";
568 if (full)
569     std::cout << "\t\t--name <name>\t\t\tname of the service to change\n"
570               << "\t\t--comment <comment>\t\ta comment to the service\n"
571               << "\t\t--cost <cost>\t\t\tservice's cost\n"
572               << "\t\t--pay-day <day>\t\t\tservice's pay day\n\n";
573 }
574 //-----------------------------------------------------------------------------
575 void UsageCorporations(bool full)
576 {
577 std::cout << "Corporations management options:\n"
578           << "\t--get-corporations\t\t\tget a list of corporations (subsequent options will define what to show)\n";
579 if (full)
580     std::cout << "\t\t--name\t\t\t\tshow corporation's name\n"
581               << "\t\t--cash\t\t\t\tshow corporation's cash\n\n";
582 std::cout << "\t--get-corp\t\t\t\tget the information about corporation\n";
583 if (full)
584     std::cout << "\t\t--name <name>\t\t\tname of the corporation to show\n"
585               << "\t\t--cash\t\t\t\tshow corporation's cash\n\n";
586 std::cout << "\t--add-corp\t\t\t\tadd a new corporation\n";
587 if (full)
588     std::cout << "\t\t--name <name>\t\t\tname of the corporation to add\n"
589               << "\t\t--cash <cash>\t\t\tinitial corporation's cash (default: \"0\")\n\n";
590 std::cout << "\t--del-corp\t\t\t\tdelete an existing corporation\n";
591 if (full)
592     std::cout << "\t\t--name <name>\t\t\tname of the corporation to delete\n\n";
593 std::cout << "\t--chg-corp\t\t\t\tchange an existing corporation\n";
594 if (full)
595     std::cout << "\t\t--name <name>\t\t\tname of the corporation to change\n"
596               << "\t\t--add-cash <amount>[:<message>]\tadd cash to the corporation's account and optional comment message\n"
597               << "\t\t--set-cash <cash>[:<message>]\tnew corporation's cash and optional comment message\n\n";
598 }*/
599
600 } // namespace anonymous