commandline_full.cpp
Go to the documentation of this file.
1 //
2 // Copyright (C) 2001-2013 Graeme Walker <graeme_walker@users.sourceforge.net>
3 //
4 // This program 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 3 of the License, or
7 // (at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
16 // ===
17 //
18 // commandline_full.cpp
19 //
20 
21 #include "gdef.h"
22 #include "gssl.h"
23 #include "gsmtp.h"
24 #include "legal.h"
25 #include "configuration.h"
26 #include "commandline.h"
27 #include "gmessagestore.h"
28 #include "gpopsecrets.h"
29 #include "ggetopt.h"
30 #include "gtest.h"
31 #include "gstr.h"
32 #include "gdebug.h"
33 
34 namespace Main
35 {
36  class Show ;
37 }
38 
43 {
44 public:
45  CommandLineImp( Main::Output & , const G::Arg & arg , const std::string & spec ,
46  const std::string & version , const std::string & capabilities ) ;
47  bool contains( const std::string & switch_ ) const ;
48  std::string value( const std::string & switch_ ) const ;
49  G::Arg::size_type argc() const ;
50  bool hasUsageErrors() const ;
51  bool hasSemanticError( const Configuration & ) const ;
52  void showHelp( bool error_stream ) const ;
53  void showUsageErrors( bool error_stream ) const ;
54  void showSemanticError( const Configuration & cfg , bool error_stream ) const ;
55  void logSemanticWarnings( const Configuration & cfg ) const ;
56  void showArgcError( bool error_stream ) const ;
57  void showNoop( bool error_stream = false ) const ;
58  void showError( std::string reason , bool error_stream = true ) const ;
59  void showVersion( bool error_stream = false ) const ;
60  void showBanner( bool error_stream = false , const std::string & = std::string() ) const ;
61  void showCopyright( bool error_stream = false , const std::string & = std::string() ) const ;
62  void showCapabilities( bool error_stream = false , const std::string & = std::string() ) const ;
63  static std::string switchSpec( bool is_windows ) ;
64 
65 public:
66  void showWarranty( bool error_stream = false , const std::string & = std::string() ) const ;
67  void showCredit( bool error_stream = false , const std::string & = std::string() ) const ;
68  void showTestFeatures( bool error_stream = false , const std::string & = std::string() ) const ;
69  void showShortHelp( bool error_stream ) const ;
70  std::string semanticError( const Configuration & , bool & ) const ;
71  void showUsage( bool e ) const ;
72  void showExtraHelp( bool error_stream ) const ;
73  static std::string switchSpec_unix() ;
74  static std::string switchSpec_windows() ;
75 
76 private:
77  Output & m_output ;
78  std::string m_version ;
79  std::string m_capabilities ;
80  G::Arg m_arg ;
81  G::GetOpt m_getopt ;
82 } ;
83 
87 class Main::Show
88 {
89 public:
90  Show( Main::Output & , bool e ) ;
91  std::ostream & s() ;
92  ~Show() ;
93 
94 private:
95  static Show * m_this ;
96  Show( const Show & ) ; // not implemented
97  void operator=( const Show & ) ; // not implemented
98  std::ostringstream m_ss ;
99  Main::Output & m_output ;
100  bool m_e ;
101 } ;
102 
103 // ==
104 
105 std::string Main::CommandLineImp::switchSpec( bool is_windows )
106 {
107  // single-character options unused: 012345678
108  std::string dir = GSmtp::MessageStore::defaultDirectory().str() ;
109  std::string pop_auth = GPop::Secrets::defaultPath() ;
110  std::ostringstream ss ;
111  ss <<
112  (is_windows?switchSpec_windows():switchSpec_unix()) << "|"
113  "q!as-client!runs as a client, forwarding all spooled mail to <host>!: "
114  "equivalent to \"--log --no-syslog --no-daemon --dont-serve --forward --forward-to\"!"
115  "1!host:port!1|"
116  "d!as-server!runs as a server, storing mail in the spool directory!: equivalent to \"--log --close-stderr\"!0!!1|"
117  "y!as-proxy!runs as a proxy server, forwarding each mail immediately to <host>!"
118  ": equivalent to \"--log --close-stderr --poll=0 --forward-to\"!"
119  "1!host:port!1|"
120  "v!verbose!generates more verbose output! (works with --help and --log)!0!!1|"
121  "h!help!displays help text and exits!!0!!1|"
122  ""
123  "p!port!specifies the smtp listening port number (default is 25)!!1!port!2|"
124  "r!remote-clients!allows remote clients to connect!!0!!2|"
125  "s!spool-dir!specifies the spool directory (default is \"" << dir << "\")!!1!dir!2|"
126  "V!version!displays version information and exits!!0!!2|"
127  ""
128  "j!client-tls!enables negotiated tls/ssl for smtp client! (if openssl built in)!0!!3|"
129  "b!client-tls-connection!enables smtp over tls/ssl for smtp client! (if openssl built in)!0!!3|"
130  "K!server-tls!enables negotiated tls/ssl for smtp server using the given openssl certificate file! (which must be in the directory trusted by openssl)!1!pem-file!3|"
131  "9!tls-config!sets tls configuration flags! (eg. 2 for SSLv2/3 support)!1!flags!3|"
132  "g!debug!generates debug-level logging if built in!!0!!3|"
133  "C!client-auth!enables smtp authentication with the remote server, using the given secrets file!!1!file!3|"
134  "L!log-time!adds a timestamp to the logging output!!0!!3|"
135  "N!log-file!log to file instead of stderr! (%d replaced by the date)!1!file!3|"
136  "S!server-auth!enables authentication of remote clients, using the given secrets file!!1!file!3|"
137  "e!close-stderr!closes the standard error stream soon after start-up!!0!!3|"
138  "a!admin!enables the administration interface and specifies its listening port number!!"
139  "1!admin-port!3|"
140  "x!dont-serve!disables acting as a server on any port! (part of --as-client and usually used with --forward)!0!!3|"
141  "X!no-smtp!disables listening for smtp connections! (usually used with --admin or --pop)!0!!3|"
142  "z!filter!specifies an external program to process messages as they are stored!!1!program!3|"
143  "W!filter-timeout!sets the timeout (in seconds) for running the --filter processor (default is 300)!!1!time!3|"
144  "w!prompt-timeout!sets the timeout (in seconds) for getting an initial prompt from the server (default is 20)!!1!time!3|"
145  "D!domain!sets an override for the host's fully qualified domain name!!1!fqdn!3|"
146  "f!forward!forwards stored mail on startup! (requires --forward-to)!0!!3|"
147  "o!forward-to!specifies the remote smtp server! (required by --forward, --poll, --immediate and --admin)!1!host:port!3|"
148  "T!response-timeout!sets the response timeout (in seconds) when talking to a remote server "
149  "(default is 1800)!!1!time!3|"
150  "U!connection-timeout!sets the timeout (in seconds) when connecting to a remote server "
151  "(default is 40)!!1!time!3|"
152  "m!immediate!enables immediate forwarding of messages as soon as they are received! (requires --forward-to)!0!!3|"
153  "I!interface!defines the listening interface(s) for incoming connections! (comma-separated list with optional smtp=,pop=,admin= qualifiers)!1!ip-list!3|"
154  "i!pid-file!defines a file for storing the daemon process-id!!1!pid-file!3|"
155  "O!poll!enables polling of the spool directory for messages to be forwarded with the specified period (zero means on client disconnection)! (requires --forward-to)!1!period!3|"
156  "P!postmaster!!!0!!0|"
157  "Z!verifier!specifies an external program for address verification!!1!program!3|"
158  "Y!client-filter!specifies an external program to process messages when they are forwarded!!1!program!3|"
159  "Q!admin-terminate!enables the terminate command on the admin interface!!0!!3|"
160  "A!anonymous!disables the smtp vrfy command and sends less verbose smtp responses!!0!!3|"
161  "B!pop!enables the pop server!!0!!3|"
162  "E!pop-port!specifies the pop listening port number (default is 110)! (requires --pop)!1!port!3|"
163  "F!pop-auth!defines the pop server secrets file (default is \"" << pop_auth << "\")!!1!file!3|"
164  "G!pop-no-delete!disables message deletion via pop! (requires --pop)!0!!3|"
165  "J!pop-by-name!modifies the pop spool directory according to the pop user name! (requires --pop)!0!!3|"
166  "M!size!limits the size of submitted messages!!1!bytes!3|"
167  ;
168  return ss.str() ;
169 }
170 
172 {
173  return
174  "l!log!writes log information on standard error and syslog! (but see --close-stderr and --no-syslog)!0!!2|"
175  "t!no-daemon!does not detach from the terminal!!0!!3|"
176  "u!user!names the effective user to switch to if started as root "
177  "(default is \"daemon\")!!1!username!3|"
178  "k!syslog!forces syslog output if logging is enabled (overrides --no-syslog)!!0!!3|"
179  "n!no-syslog!disables syslog output (always overridden by --syslog)!!0!!3" ;
180 }
181 
183 {
184  return
185  "l!log!writes log information on stderr and to the event log! (but see --close-stderr and --no-syslog)!0!!2|"
186  "t!no-daemon!uses an ordinary window, not the system tray!!0!!3|"
187  "k!syslog!forces system event log output if logging is enabled (overrides --no-syslog)!!0!!3|"
188  "n!no-syslog!disables use of the system event log!!0!!3|"
189  "c!icon!does nothing!!1!0^|1^|2^|3!0|"
190  "H!hidden!hides the application window and suppresses message boxes (requires --no-daemon)!!0!!3|"
191  "R!peer-lookup!lookup the account names of local peers! to put in the envelope files!0!!3" ;
192 }
193 
194 Main::CommandLineImp::CommandLineImp( Output & output , const G::Arg & arg , const std::string & spec ,
195  const std::string & version , const std::string & capabilities ) :
196  m_output(output) ,
197  m_version(version) ,
198  m_capabilities(capabilities) ,
199  m_arg(arg) ,
200  m_getopt(m_arg,spec,'|','!','^')
201 {
202 }
203 
205 {
206  return m_getopt.args().c() ;
207 }
208 
210 {
211  return m_getopt.hasErrors() ;
212 }
213 
215 {
216  Show show( m_output , e ) ;
217 
218  G::GetOpt::Level level = G::GetOpt::Level(2U) ;
219  std::string introducer = G::GetOpt::introducerDefault() ;
220  if( m_getopt.contains("verbose") )
221  level = G::GetOpt::levelDefault() ;
222  else
223  introducer = std::string("abbreviated ") + introducer ;
224 
225  std::string::size_type tab_stop = 34U ;
226  bool extra = m_getopt.contains("verbose") ;
227  m_getopt.showUsage( show.s() , m_arg.prefix() , "" , introducer , level , tab_stop ,
228  G::GetOpt::wrapDefault() , extra ) ;
229 }
230 
231 bool Main::CommandLineImp::contains( const std::string & name ) const
232 {
233  return m_getopt.contains( name ) ;
234 }
235 
236 std::string Main::CommandLineImp::value( const std::string & name ) const
237 {
238  return m_getopt.value( name ) ;
239 }
240 
241 std::string Main::CommandLineImp::semanticError( const Configuration & cfg , bool & fatal ) const
242 {
243  fatal = true ;
244 
245  if(
246  ( cfg.doAdmin() && cfg.adminPort() == cfg.port() ) ||
247  ( cfg.doPop() && cfg.popPort() == cfg.port() ) ||
248  ( cfg.doPop() && cfg.doAdmin() && cfg.popPort() == cfg.adminPort() ) )
249  {
250  return "the listening ports must be different" ;
251  }
252 
253  if( ! m_getopt.contains("pop") && (
254  m_getopt.contains("pop-port") ||
255  m_getopt.contains("pop-auth") ||
256  m_getopt.contains("pop-by-name") ||
257  m_getopt.contains("pop-no-delete") ) )
258  {
259  return "pop options require --pop" ;
260  }
261 
262  if( cfg.withTerminate() && !cfg.doAdmin() )
263  {
264  return "the --admin-terminate option requires --admin" ;
265  }
266 
267  if( cfg.daemon() && cfg.spoolDir().isRelative() )
268  {
269  return "in daemon mode the spool-dir must be an absolute path" ;
270  }
271 
272  if( cfg.daemon() && (
273  ( !cfg.clientSecretsFile().empty() && G::Path(cfg.clientSecretsFile()).isRelative() ) ||
274  ( !cfg.serverSecretsFile().empty() && G::Path(cfg.serverSecretsFile()).isRelative() ) ||
275  ( !cfg.popSecretsFile().empty() && G::Path(cfg.popSecretsFile()).isRelative() ) ) )
276  {
277  return "in daemon mode the authorisation secrets file(s) must be absolute paths" ;
278  }
279 
280  const bool forward_to =
281  m_getopt.contains("as-proxy") || // => forward-to
282  m_getopt.contains("as-client") || // => forward-to
283  m_getopt.contains("forward-to") ;
284 
285  if( ! forward_to && (
286  m_getopt.contains("forward") ||
287  m_getopt.contains("poll") ||
288  m_getopt.contains("immediate") ) )
289  {
290  return "the --forward, --immediate and --poll options require --forward-to" ;
291  }
292 
293  const bool forwarding =
294  m_getopt.contains("as-proxy") || // => poll
295  m_getopt.contains("as-client") || // => forward
296  m_getopt.contains("forward") ||
297  m_getopt.contains("immediate") ||
298  m_getopt.contains("poll") ;
299 
300  if( m_getopt.contains("client-filter") && ! forwarding )
301  {
302  return "the --client-filter option requires --as-proxy, --as-client, --poll, --immediate or --forward" ;
303  }
304 
305  const bool not_serving = m_getopt.contains("dont-serve") || m_getopt.contains("as-client") ;
306 
307  if( not_serving ) // ie. if not serving admin, smtp or pop
308  {
309  if( m_getopt.contains("filter") )
310  return "the --filter option cannot be used with --as-client or --dont-serve" ;
311 
312  if( m_getopt.contains("port") )
313  return "the --port option cannot be used with --as-client or --dont-serve" ;
314 
315  if( m_getopt.contains("server-auth") )
316  return "the --server-auth option cannot be used with --as-client or --dont-serve" ;
317 
318  if( m_getopt.contains("pop") )
319  return "the --pop option cannot be used with --as-client or --dont-serve" ;
320 
321  if( m_getopt.contains("admin") )
322  return "the --admin option cannot be used with --as-client or --dont-serve" ;
323 
324  if( m_getopt.contains("poll") )
325  return "the --poll option cannot be used with --as-client or --dont-serve" ;
326  }
327 
328  if( m_getopt.contains("no-smtp") ) // ie. if not serving smtp
329  {
330  if( m_getopt.contains("filter") )
331  return "the --filter option cannot be used with --no-smtp" ;
332 
333  if( m_getopt.contains("port") )
334  return "the --port option cannot be used with --no-smtp" ;
335 
336  if( m_getopt.contains("server-auth") )
337  return "the --server-auth option cannot be used with --no-smtp" ;
338  }
339 
340  const bool log =
341  m_getopt.contains("log") ||
342  m_getopt.contains("as-server") || // => log
343  m_getopt.contains("as-client") || // => log
344  m_getopt.contains("as-proxy") ; // => log
345 
346  if( m_getopt.contains("verbose") && ! ( m_getopt.contains("help") || log ) )
347  {
348  return "the --verbose option must be used with --log, --help, --as-client, --as-server or --as-proxy" ;
349  }
350 
351  if( m_getopt.contains("debug") && !log )
352  {
353  return "the --debug option requires --log, --as-client, --as-server or --as-proxy" ;
354  }
355 
356  const bool no_daemon =
357  m_getopt.contains("as-client") || // => no-daemon
358  m_getopt.contains("no-daemon") ;
359 
360  if( m_getopt.contains("hidden") && ! no_daemon ) // (win32)
361  {
362  return "the --hidden option requires --no-daemon or --as-client" ;
363  }
364 
365  if( m_getopt.contains("client-tls") && m_getopt.contains("client-tls-connection") )
366  {
367  return "the --client-tls and --client-tls-connection options cannot be used together" ;
368  }
369 
370  if( m_getopt.contains("server-auth") && m_getopt.value("server-auth") == "/pam" &&
371  !m_getopt.contains("server-tls" ) )
372  {
373  return "--server-auth using pam requires --server-tls" ;
374  }
375 
376  if( m_getopt.contains("pop-auth") && m_getopt.value("pop-auth") == "/pam" &&
377  !m_getopt.contains("server-tls" ) )
378  {
379  return "--pop-auth using pam requires --server-tls" ;
380  }
381 
382  // warnings...
383 
384  const bool no_syslog =
385  m_getopt.contains("no-syslog") ||
386  m_getopt.contains("as-client") ;
387 
388  const bool syslog =
389  ! ( no_syslog && ! m_getopt.contains("syslog") ) ;
390 
391  const bool close_stderr =
392  m_getopt.contains("close-stderr") ||
393  m_getopt.contains("as-server") ||
394  m_getopt.contains("as-proxy") ;
395 
396  if( log && close_stderr && !syslog ) // ie. logging to nowhere
397  {
398  std::string close_stderr_switch =
399  ( m_getopt.contains("close-stderr") ? "--close-stderr" :
400  ( m_getopt.contains("as-server") ? "--as-server" :
401  "--as-proxy" ) ) ;
402 
403  std::string warning = "logging is enabled but it has nowhere to go because " +
404  close_stderr_switch + " closes the standard error stream soon after startup and " +
405  "output to the system log is disabled" ;
406 
407  if( m_getopt.contains("as-server") && !m_getopt.contains("log") )
408  warning = warning + ": replace --as-server with --log" ;
409  else if( m_getopt.contains("as-server") )
410  warning = warning + ": remove --as-server" ;
411  else if( m_getopt.contains("as-proxy" ) )
412  warning = warning + ": replace --as-proxy with --log --poll 0 --forward-to" ;
413 
414  fatal = false ;
415  return warning ;
416  }
417 
418  fatal = false ;
419  return std::string() ;
420 }
421 
423 {
424  bool fatal = false ;
425  bool error = ! semanticError(cfg,fatal).empty() ;
426  return error && fatal ;
427 }
428 
429 void Main::CommandLineImp::showSemanticError( const Configuration & cfg , bool e ) const
430 {
431  Show show( m_output , e ) ;
432  bool fatal = false ;
433  show.s() << m_arg.prefix() << ": usage error: " << semanticError(cfg,fatal) << std::endl ;
434 }
435 
437 {
438  bool fatal = false ;
439  std::string warning = semanticError( cfg , fatal ) ;
440  if( !warning.empty() && !fatal )
441  G_WARNING( "CommandLine::logSemanticWarnings: " << warning ) ;
442 }
443 
445 {
446  Show show( m_output , e ) ;
447  m_getopt.showErrors( show.s() , m_arg.prefix() ) ;
448  showShortHelp( e ) ;
449 }
450 
452 {
453  Show show( m_output , e ) ;
454  show.s() << m_arg.prefix() << ": usage error: too many non-switch arguments" << std::endl ;
455  showShortHelp( e ) ;
456 }
457 
459 {
460  Show show( m_output , e ) ;
461  const std::string & exe = m_arg.prefix() ;
462  show.s()
463  << std::string(exe.length()+2U,' ')
464  << "try \"" << exe << " --help --verbose\" for more information" << std::endl ;
465 }
466 
467 void Main::CommandLineImp::showHelp( bool e ) const
468 {
469  Show show( m_output , e ) ;
470  showBanner( e ) ;
471  show.s() << std::endl ;
472  showUsage( e ) ;
473  showExtraHelp( e ) ;
474  showCopyright( e ) ;
475 }
476 
478 {
479  Show show( m_output , e ) ;
480  const std::string & exe = m_arg.prefix() ;
481 
482  show.s() << std::endl ;
483 
484  if( m_getopt.contains("verbose") )
485  {
486  show.s()
487  << "To start a 'storage' daemon in background..." << std::endl
488  << " " << exe << " --as-server" << std::endl
489  << std::endl ;
490 
491  show.s()
492  << "To forward stored mail to \"mail.myisp.net\"..." << std::endl
493  << " " << exe << " --as-client mail.myisp.net:smtp" << std::endl
494  << std::endl ;
495 
496  show.s()
497  << "To run as a proxy (on port 10025) to a local server (on port 25)..." << std::endl
498  << " " << exe << " --port 10025 --as-proxy localhost:25" << std::endl
499  << std::endl ;
500  }
501  else
502  {
503  show.s()
504  << "For complete usage information run \"" << exe
505  << " --help --verbose\"" << std::endl
506  << std::endl ;
507  }
508 }
509 
510 void Main::CommandLineImp::showNoop( bool e ) const
511 {
512  Show show( m_output , e ) ;
513  show.s() << m_arg.prefix() << ": no messages to send" << std::endl ;
514 }
515 
516 void Main::CommandLineImp::showError( std::string reason , bool e ) const
517 {
518  Show show( m_output , e ) ;
519  show.s() << m_arg.prefix() << ": " << reason << std::endl ;
520 }
521 
522 void Main::CommandLineImp::showBanner( bool e , const std::string & final ) const
523 {
524  Show show( m_output , e ) ;
525  show.s()
526  << "E-MailRelay V" << m_version << std::endl << final ;
527 }
528 
529 void Main::CommandLineImp::showCopyright( bool e , const std::string & final ) const
530 {
531  Show show( m_output , e ) ;
532  show.s() << Legal::copyright() << std::endl << final ;
533 }
534 
535 void Main::CommandLineImp::showCapabilities( bool e , const std::string & final ) const
536 {
537  if( !m_capabilities.empty() )
538  {
539  Show show( m_output , e ) ;
540  show.s() << "Build configuration [" << m_capabilities << "]" << std::endl << final ;
541  }
542 }
543 
544 void Main::CommandLineImp::showWarranty( bool e , const std::string & final ) const
545 {
546  Show show( m_output , e ) ;
547  show.s() << Legal::warranty("","\n") << final ;
548 }
549 
550 void Main::CommandLineImp::showCredit( bool e , const std::string & final ) const
551 {
552  Show show( m_output , e ) ;
553  show.s() << GSsl::Library::credit("","\n",final) ;
554 }
555 
556 void Main::CommandLineImp::showTestFeatures( bool e , const std::string & final ) const
557 {
558  Show show( m_output , e ) ;
559  show.s() << "Test features " << (G::Test::enabled()?"enabled":"disabled") << std::endl << final ;
560 }
561 
563 {
564  Show show( m_output , e ) ;
565  showBanner( e , "\n" ) ;
566  showCopyright( e , "\n" ) ;
567  if( contains("verbose") )
568  {
569  showCapabilities( e , "\n" ) ;
570  showTestFeatures( e , "\n" ) ;
571  }
572  showCredit( e , "\n" ) ;
573  showWarranty( e ) ;
574 }
575 
576 // ===
577 
578 Main::Show * Main::Show::m_this = NULL ;
579 
580 Main::Show::Show( Output & output , bool e ) :
581  m_output(output) ,
582  m_e(e)
583 {
584  if( m_this == NULL )
585  m_this = this ;
586 }
587 
588 std::ostream & Main::Show::s()
589 {
590  return m_this->m_ss ;
591 }
592 
594 {
595  if( m_this == this )
596  {
597  m_this = NULL ;
598  m_output.output( m_ss.str() , m_e ) ;
599  }
600 }
601 
602 // ==
603 
604 std::string Main::CommandLine::switchSpec( bool is_windows )
605 {
606  return CommandLineImp::switchSpec( is_windows ) ;
607 }
608 
609 Main::CommandLine::CommandLine( Main::Output & output , const G::Arg & arg , const std::string & spec ,
610  const std::string & version , const std::string & capabilities ) :
611  m_imp(new CommandLineImp(output,arg,spec,version,capabilities))
612 {
613 }
614 
616 {
617  delete m_imp ;
618 }
619 
621 {
622  return Configuration( *this ) ;
623 }
624 
625 bool Main::CommandLine::contains( const std::string & switch_ ) const
626 {
627  return m_imp->contains( switch_ ) ;
628 }
629 
630 std::string Main::CommandLine::value( const std::string & switch_ ) const
631 {
632  return m_imp->value( switch_ ) ;
633 }
634 
636 {
637  return m_imp->argc() ;
638 }
639 
641 {
642  return m_imp->hasUsageErrors() ;
643 }
644 
646 {
647  return m_imp->hasSemanticError( cfg() ) ;
648 }
649 
650 void Main::CommandLine::showHelp( bool error_stream ) const
651 {
652  m_imp->showHelp( error_stream ) ;
653 }
654 
655 void Main::CommandLine::showUsageErrors( bool error_stream ) const
656 {
657  m_imp->showUsageErrors( error_stream ) ;
658 }
659 
660 void Main::CommandLine::showSemanticError( bool error_stream ) const
661 {
662  m_imp->showSemanticError( cfg() , error_stream ) ;
663 }
664 
666 {
667  m_imp->logSemanticWarnings( cfg() ) ;
668 }
669 
670 void Main::CommandLine::showArgcError( bool error_stream ) const
671 {
672  m_imp->showArgcError( error_stream ) ;
673 }
674 
675 void Main::CommandLine::showNoop( bool error_stream ) const
676 {
677  m_imp->showNoop( error_stream ) ;
678 }
679 
680 void Main::CommandLine::showError( const std::string & reason , bool error_stream ) const
681 {
682  m_imp->showError( reason , error_stream ) ;
683 }
684 
685 void Main::CommandLine::showVersion( bool error_stream ) const
686 {
687  m_imp->showVersion( error_stream ) ;
688 }
689 
690 void Main::CommandLine::showBanner( bool error_stream , const std::string & s ) const
691 {
692  m_imp->showBanner( error_stream , s ) ;
693 }
694 
695 void Main::CommandLine::showCopyright( bool error_stream , const std::string & s ) const
696 {
697  m_imp->showCopyright( error_stream , s ) ;
698 }
699 
700 void Main::CommandLine::showCapabilities( bool error_stream , const std::string & s ) const
701 {
702  m_imp->showCapabilities( error_stream , s ) ;
703 }
704 
705 unsigned int Main::CommandLine::value( const std::string & switch_ , unsigned int default_ ) const
706 {
707  return m_imp->contains(switch_) ? G::Str::toUInt(value(switch_)) : default_ ;
708 }
709 
710 G::Strings Main::CommandLine::value( const std::string & switch_ , const std::string & separators ) const
711 {
712  G::Strings result ;
713  if( contains(switch_) )
714  {
715  G::Str::splitIntoFields( value(switch_) , result , separators ) ;
716  }
717  return result ;
718 }
719 
720 bool Main::CommandLine::contains( const char * switch_ ) const
721 {
722  return contains( std::string(switch_) ) ;
723 }
724 
725 std::string Main::CommandLine::value( const char * switch_ ) const
726 {
727  return value( std::string(switch_) ) ;
728 }
729 
730 unsigned int Main::CommandLine::value( const char * switch_ , unsigned int default_ ) const
731 {
732  return value( std::string(switch_) , default_ ) ;
733 }
734 
735 G::Strings Main::CommandLine::value( const char * switch_ , const char * separators ) const
736 {
737  return value( std::string(switch_) , std::string(separators) ) ;
738 }
739 
std::string str() const
Returns the path string.
Definition: gpath.cpp:135
Application-level classes.
static std::string copyright()
Returns the copyright text.
Definition: legal.cpp:26
void showError(std::string reason, bool error_stream=true) const
void showSemanticError(const Configuration &cfg, bool error_stream) const
void showCopyright(bool error_stream=false, const std::string &=std::string()) const
Writes a copyright message.
static std::string switchSpec_windows()
Configuration cfg() const
Returns a Configuration object.
std::string value(const std::string &switch_) const
static std::string warranty(const std::string &prefix, const std::string &eol)
Returns the warranty text.
Definition: legal.cpp:31
size_t size_type
Definition: garg.h:49
static unsigned int toUInt(const std::string &s, bool limited=false)
Converts string 's' to an unsigned int.
Definition: gstr.cpp:346
bool daemon() const
Returns true if running as a daemon.
std::list< std::string > Strings
A std::list of std::strings.
Definition: gstrings.h:39
void showCopyright(bool error_stream=false, const std::string &=std::string()) const
static void splitIntoFields(const std::string &in, Strings &out, const std::string &seperators, char escape= '\0', bool discard_bogus_escapes=true)
Splits the string into fields.
Definition: gstr.cpp:765
void showCapabilities(bool error_stream=false, const std::string &=std::string()) const
Writes a capability line.
unsigned int popPort() const
Returns the pop port number.
void showError(const std::string &reason, bool error_stream=true) const
Writes a failed message.
A private implementation class used by Main::CommandLine.
std::string::size_type size_type
A std::size_t type.
Definition: md5.h:43
CommandLine(Main::Output &output, const G::Arg &arg, const std::string &spec, const std::string &version, const std::string &capabilities)
Constructor.
void showNoop(bool error_stream=false) const
void showUsageErrors(bool error_stream) const
G::Path spoolDir() const
Returns the spool directory.
static std::string switchSpec(bool is_windows)
bool doAdmin() const
Returns true if listening for admin connections.
void showTestFeatures(bool error_stream=false, const std::string &=std::string()) const
~CommandLine()
Destructor.
void showBanner(bool error_stream=false, const std::string &=std::string()) const
Writes a startup banner.
void showExtraHelp(bool error_stream) const
An abstract interface for generating output on a command-line or a GUI.
Definition: output.h:38
void showVersion(bool error_stream=false) const
void logSemanticWarnings() const
Emits warnings about conflicting switches.
bool isRelative() const
Returns true if the path is a relative path.
Definition: gpath.cpp:145
bool hasSemanticError() const
Returns true if the command line has logical errors (eg. conflicting switches).
void showArgcError(bool error_stream=true) const
Writes a too-many-arguments error message.
A command line switch parser.
Definition: ggetopt.h:51
std::string value(const std::string &switch_) const
Returns the given switch's string value.
std::string semanticError(const Configuration &, bool &) const
static std::string switchSpec_unix()
bool contains(const std::string &switch_) const
Returns true if the command line contained the give switch.
std::string serverSecretsFile() const
Returns the server-side autentication secrets (password) file.
void showCapabilities(bool error_stream=false, const std::string &=std::string()) const
static bool enabled()
Returns true if test features are enabled.
Definition: gtest.cpp:46
Show(Main::Output &, bool e)
static std::string credit(const std::string &prefix, const std::string &eol, const std::string &final)
Returns a credit string.
void showBanner(bool error_stream=false, const std::string &=std::string()) const
static G::Path defaultDirectory()
Returns a default spool directory, such as "/usr/local/var/spool/emailrelay".
void showVersion(bool error_stream=false) const
Writes the version number.
void showUsage(bool e) const
std::ostream & s()
static size_type wrapDefault()
Returns a default word-wrapping width.
Definition: ggetopt.cpp:113
bool hasUsageErrors() const
Returns true if the command line has usage errors (eg. invalid switch).
void showUsageErrors(bool error_stream=true) const
Writes the usage errors.
void showWarranty(bool error_stream=false, const std::string &=std::string()) const
G::Arg::size_type argc() const
void showHelp(bool error_stream) const
CommandLineImp(Main::Output &, const G::Arg &arg, const std::string &spec, const std::string &version, const std::string &capabilities)
bool withTerminate() const
Returns true if the admin interface should support the terminate command.
unsigned int port() const
Returns the main listening port number.
void showArgcError(bool error_stream) const
static Level levelDefault()
Returns the default level.
Definition: ggetopt.cpp:134
A class which holds a represention of the argc/argv command line array, and supports simple command-l...
Definition: garg.h:46
void showCredit(bool error_stream=false, const std::string &=std::string()) const
unsigned int adminPort() const
Returns the admin port number.
void showHelp(bool error_stream=false) const
Writes help text.
std::string clientSecretsFile() const
Returns the client-side autentication secrets (password) file.
void logSemanticWarnings(const Configuration &cfg) const
static std::string introducerDefault()
Returns "usage: ".
Definition: ggetopt.cpp:129
A private implementation class used by Main::CommandLineImp.
static std::string defaultPath()
Returns the default path.
void showNoop(bool error_stream=false) const
Writes a nothing-to-do message.
A Path object represents a file system path.
Definition: gpath.h:44
Used by G::GetOpt for extra type safety.
Definition: ggetopt.h:55
An interface for returning application configuration information.
Definition: configuration.h:45
static std::string switchSpec(bool is_windows)
Returns an o/s-specific G::GetOpt switch specification string.
bool hasUsageErrors() const
void showShortHelp(bool error_stream) const
bool doPop() const
Returns true if listening for pop connections.
#define G_WARNING(expr)
Definition: glog.h:107
void showSemanticError(bool error_stream=true) const
Writes the logic errors.
bool contains(const std::string &switch_) const
G::Arg::size_type argc() const
Returns the number of non-switch arguments on the command line.
bool hasSemanticError(const Configuration &) const
std::string popSecretsFile() const
Returns the pop-server autentication secrets (password) file.