16
16
#include " ServerDB.h"
17
17
#include " Version.h"
18
18
19
+ #include < boost/logic/tribool.hpp>
20
+ #include < boost/optional/optional_io.hpp>
21
+ #include < boost/tuple/tuple_io.hpp>
19
22
#include < csignal>
20
23
#include < iostream>
21
24
46
49
# include < sys/syslog.h>
47
50
#endif
48
51
52
+ #include < CLI/CLI.hpp>
53
+
49
54
QFile *qfLog = nullptr ;
50
55
51
56
static bool bVerbose = false ;
@@ -200,6 +205,114 @@ void cleanup(int signum) {
200
205
exit (signum);
201
206
}
202
207
208
+ auto parseCLI (int argc, char **argv) {
209
+ struct {
210
+ bool quit = false ;
211
+ boost::optional< std::string > ini_file;
212
+ boost::tuple< std::string, boost::optional< int > > supw_srv;
213
+ boost::optional< int > disable_su_srv;
214
+ bool verbose_logging = false ;
215
+ #ifdef QT_NO_DEBUG
216
+ bool detach = true ;
217
+ #else
218
+ boost::logic::tribool detach = boost::logic::indeterminate;
219
+ #endif
220
+ bool wipe_ssl = false ;
221
+ bool wipe_logs = false ;
222
+ bool log_groups = false ;
223
+ bool log_acls = false ;
224
+
225
+ bool print_authors = false ;
226
+ bool print_license = false ;
227
+ bool print_3rd_party_licenses = false ;
228
+
229
+ #ifdef Q_OS_UNIX
230
+ bool limits = false ;
231
+ boost::optional< int > read_supw_srv;
232
+ #endif
233
+ } options;
234
+
235
+ CLI::App app;
236
+ app.set_version_flag (" -v,--version" , " Mumble server version " + Version::getRelease ().toStdString ());
237
+
238
+ app.add_option_no_stream (" -i,--ini" , options.ini_file , " Specify ini file to use." )
239
+ ->option_text (" <inifile>" )
240
+ ->expected (1 , 2 )
241
+ ->check (CLI::ExistingFile)
242
+ ->group (" Configuration" );
243
+
244
+ app.add_option (" -w,--supw" , options.supw_srv , " Set password for 'SuperUser' account on server srv." )
245
+ ->option_text (" <pw> [srv]" )
246
+ ->allow_extra_args ()
247
+ ->expected (0 , 1 )
248
+ ->group (" Administration" );
249
+
250
+ #ifdef Q_OS_UNIX
251
+ app.add_option_no_stream (" -r,--readsupw" , options.read_supw_srv ,
252
+ " Reads password for server srv from standard input." )
253
+ ->option_text (" [srv]" )
254
+ ->default_val (1 )
255
+ ->expected (0 , 1 )
256
+ ->group (" Administration" );
257
+
258
+ app.add_flag (" -l,--limits" , options.limits ,
259
+ " Tests and shows how many file descriptors and threads can be created.\n "
260
+ " The purpose of this option is to test how many clients Murmur can handle.\n "
261
+ " Murmur will exit after this test." )
262
+ ->group (" Testing" );
263
+ #endif
264
+
265
+ app.add_option_no_stream (" -d,--disablesu" , options.disable_su_srv ,
266
+ " Disable password for 'SuperUser' account on server srv." )
267
+ ->option_text (" [srv]" )
268
+ ->expected (0 , 1 )
269
+ ->group (" Administration" );
270
+ app.add_flag (" -s,--wipessl" , options.wipe_ssl , " Remove SSL certificates from database." )->group (" Administration" );
271
+
272
+ app.add_flag (" -b,--verbose" , options.verbose_logging , " Use verbose logging (include debug-logs)." )
273
+ ->group (" Logging" );
274
+ app.add_flag (" !-f,!--force-fg" , options.detach ,
275
+ #ifdef Q_OS_UNIX
276
+ " Don't detach from console."
277
+ #else
278
+ " Don't write to the log file."
279
+ #endif
280
+ )
281
+ ->group (" Logging" );
282
+
283
+ app.add_flag (" -p,--wipelogs" , options.wipe_logs , " Remove all log entries from database." )->group (" Logging" );
284
+ app.add_flag (" -g,--loggroups" , options.log_groups , " Turns on logging for group changes for all servers." )
285
+ ->group (" Logging" );
286
+ app.add_flag (" -a,--logacls" , options.log_acls , " Turns on logging for ACL changes for all servers." )
287
+ ->group (" Logging" );
288
+
289
+
290
+ app.add_flag (" -A,--authors" , options.print_authors , " Show Murmur's authors." )->group (" About" );
291
+ app.add_flag (" -L,--license" , options.print_license , " Show Murmur's license." )->group (" About" );
292
+ app.add_flag (" -3,--3rd-party-licenses" , options.print_3rd_party_licenses ,
293
+ " Show licenses for third-party software used by Murmur." )
294
+ ->group (" About" );
295
+
296
+
297
+ app.footer (" If no inifile is provided, murmur will search for one in\n default locations." );
298
+
299
+ try {
300
+ (app).parse (argc, argv);
301
+ } catch (const CLI::ParseError &e) {
302
+ std::stringstream info_stream, error_stream;
303
+ app.exit (e, info_stream, error_stream);
304
+
305
+ if (e.get_exit_code () != static_cast < int >(CLI::ExitCodes::Success)) {
306
+ qFatal (" %s" , error_stream.str ().c_str ());
307
+ } else {
308
+ qInfo (" %s" , info_stream.str ().c_str ());
309
+ }
310
+ options.quit = true ;
311
+ }
312
+
313
+ return options;
314
+ }
315
+
203
316
int main (int argc, char **argv) {
204
317
// Check for SSE and MMX, but only in the windows binaries
205
318
#ifdef Q_OS_WIN
@@ -266,17 +379,6 @@ int main(int argc, char **argv) {
266
379
}
267
380
#endif
268
381
269
- QString inifile;
270
- QString supw;
271
- bool disableSu = false ;
272
- bool wipeSsl = false ;
273
- bool wipeLogs = false ;
274
- int sunum = 1 ;
275
- #ifdef Q_OS_UNIX
276
- bool readPw = false ;
277
- #endif
278
- bool logGroups = false ;
279
- bool logACL = false ;
280
382
281
383
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
282
384
// For Qt >= 5.10 we use QRandomNumberGenerator that is seeded automatically
@@ -285,153 +387,87 @@ int main(int argc, char **argv) {
285
387
286
388
qInstallMessageHandler (murmurMessageOutputWithContext);
287
389
288
- #ifdef Q_OS_WIN
289
- Tray tray (nullptr , &le);
290
- #endif
390
+ auto cli_options = parseCLI (argc, argv);
291
391
292
- QStringList args = a.arguments ();
293
- for (int i = 1 ; i < args.size (); i++) {
294
- bool bLast = false ;
295
- QString arg = args.at (i).toLower ();
296
- if ((arg == " -supw" )) {
297
- detach = false ;
298
- if (i + 1 < args.size ()) {
299
- i++;
300
- supw = args.at (i);
301
- if (i + 1 < args.size ()) {
302
- i++;
303
- sunum = args.at (i).toInt ();
304
- }
305
- bLast = true ;
306
- } else {
307
- #ifdef Q_OS_UNIX
308
- qFatal (" -supw expects the password on the command line - maybe you meant -readsupw?" );
309
- #else
310
- qFatal (" -supw expects the password on the command line" );
311
- #endif
312
- }
313
- #ifdef Q_OS_UNIX
314
- } else if ((arg == " -readsupw" )) {
315
- // Note that it is essential to set detach = false here. If this is ever to be changed, the code part
316
- // handling the readPw = true part has to be moved up so that it is executed before fork is called on Unix
317
- // systems.
318
- detach = false ;
319
- readPw = true ;
320
- if (i + 1 < args.size ()) {
321
- i++;
322
- sunum = args.at (i).toInt ();
323
- }
324
- bLast = true ;
325
- #endif
326
- } else if ((arg == " -disablesu" )) {
327
- detach = false ;
328
- disableSu = true ;
329
- if (i + 1 < args.size ()) {
330
- i++;
331
- sunum = args.at (i).toInt ();
332
- }
333
- bLast = true ;
334
- } else if ((arg == " -ini" ) && (i + 1 < args.size ())) {
335
- i++;
336
- inifile = args.at (i);
337
- } else if ((arg == " -wipessl" )) {
338
- wipeSsl = true ;
339
- } else if ((arg == " -wipelogs" )) {
340
- wipeLogs = true ;
341
- } else if ((arg == " -fg" )) {
342
- detach = false ;
343
- } else if ((arg == " -v" )) {
344
- bVerbose = true ;
345
- } else if ((arg == " -version" ) || (arg == " --version" )) {
346
- // Print version and exit (print to regular std::cout to avoid adding any useless meta-information from
347
- // using e.g. qWarning
348
- std::cout << " Mumble server version " << Version::getRelease ().toStdString () << std::endl;
349
- return 0 ;
350
- } else if (args.at (i) == QLatin1String (" -license" ) || args.at (i) == QLatin1String (" --license" )) {
392
+ if (cli_options.quit )
393
+ return 0 ;
394
+
395
+ if (cli_options.print_license ) {
351
396
#ifdef Q_OS_WIN
352
- AboutDialog ad (nullptr , AboutDialogOptionsShowLicense);
353
- ad.exec ();
354
- return 0 ;
397
+ AboutDialog ad (nullptr , AboutDialogOptionsShowLicense);
398
+ ad.exec ();
399
+ return 0 ;
355
400
#else
356
- qInfo (" %s\n " , qPrintable (License::license ()));
357
- return 0 ;
401
+ qInfo (" %s\n " , qPrintable (License::license ()));
402
+ return 0 ;
403
+ bool readPw = false ;
358
404
#endif
359
- } else if (args. at (i) == QLatin1String ( " -authors " ) || args. at (i) == QLatin1String ( " --authors " ) ) {
405
+ } else if (cli_options. print_authors ) {
360
406
#ifdef Q_OS_WIN
361
- AboutDialog ad (nullptr , AboutDialogOptionsShowAuthors);
362
- ad.exec ();
363
- return 0 ;
407
+ AboutDialog ad (nullptr , AboutDialogOptionsShowAuthors);
408
+ ad.exec ();
409
+ return 0 ;
364
410
#else
365
- qInfo (" %s\n " ,
366
- " For a list of authors, please see https://github.com/mumble-voip/mumble/graphs/contributors" );
367
- return 0 ;
411
+ qInfo (" %s\n " , " For a list of authors, please see https://github.com/mumble-voip/mumble/graphs/contributors" );
412
+ return 0 ;
368
413
#endif
369
- } else if (args.at (i) == QLatin1String (" -third-party-licenses" )
370
- || args.at (i) == QLatin1String (" --third-party-licenses" )) {
414
+ } else if (cli_options.print_3rd_party_licenses ) {
371
415
#ifdef Q_OS_WIN
372
- AboutDialog ad (nullptr , AboutDialogOptionsShowThirdPartyLicenses);
373
- ad.exec ();
374
- return 0 ;
416
+ AboutDialog ad (nullptr , AboutDialogOptionsShowThirdPartyLicenses);
417
+ ad.exec ();
418
+ return 0 ;
375
419
#else
376
- qInfo (" %s" , qPrintable (License::printableThirdPartyLicenseInfo ()));
377
- return 0 ;
378
- #endif
379
- } else if ((arg == " -h" ) || (arg == " -help" ) || (arg == " --help" )) {
380
- detach = false ;
381
- qInfo (" Usage: %s [-ini <inifile>] [-supw <password>]\n "
382
- " --version Print version information and exit\n "
383
- " -ini <inifile> Specify ini file to use.\n "
384
- " -supw <pw> [srv] Set password for 'SuperUser' account on server srv.\n "
385
- #ifdef Q_OS_UNIX
386
- " -readsupw [srv] Reads password for server srv from standard input.\n "
420
+ qInfo (" %s" , qPrintable (License::printableThirdPartyLicenseInfo ()));
421
+ return 0 ;
387
422
#endif
388
- " -disablesu [srv] Disable password for 'SuperUser' account on server srv.\n "
423
+ }
424
+
425
+ detach = boost::logic::indeterminate (cli_options.detach ) ? detach : static_cast < bool >(cli_options.detach );
426
+ QString inifile = QString::fromStdString (cli_options.ini_file .get_value_or (" " ));
427
+ QString supw;
428
+ bool disableSu = false ;
429
+ bool wipeSsl = cli_options.wipe_ssl ;
430
+ bool wipeLogs = cli_options.wipe_logs ;
431
+ int sunum = 1 ;
389
432
#ifdef Q_OS_UNIX
390
- " -limits Tests and shows how many file descriptors and threads can be created.\n "
391
- " The purpose of this option is to test how many clients Murmur can handle.\n "
392
- " Murmur will exit after this test.\n "
433
+ bool readPw = false ;
434
+ #endif
435
+ bool logGroups = cli_options.log_groups ;
436
+ bool logACL = cli_options.log_acls ;
437
+
438
+ bVerbose = cli_options.verbose_logging ;
439
+
440
+ if (cli_options.disable_su_srv .has_value ()) {
441
+ detach = false ;
442
+ disableSu = true ;
443
+ sunum = cli_options.disable_su_srv .get ();
444
+ }
445
+
446
+ if (!cli_options.supw_srv .get < 0 >().empty ()) {
447
+ supw = QString::fromStdString (cli_options.supw_srv .get < 0 >());
448
+ sunum = cli_options.supw_srv .get < 1 >().get_value_or (1 );
449
+ #ifdef Q_OS_LINUX
450
+ } else if (cli_options.read_supw_srv .has_value ()) {
451
+ // Note that it is essential to set detach = false here. If this is ever to be changed, the code part
452
+ // handling the readPw = true part has to be moved up so that it is executed before fork is called on Unix
453
+ // systems.
454
+
455
+ detach = false ;
456
+ readPw = true ;
457
+ sunum = cli_options.read_supw_srv .get ();
458
+ }
459
+
460
+ if (cli_options.limits ) {
461
+ detach = false ;
462
+ Meta::mp.read (inifile);
463
+ unixhandler.setuid ();
464
+ unixhandler.finalcap ();
465
+ LimitTest::testLimits (a);
393
466
#endif
394
- " -v Use verbose logging (include debug-logs).\n "
395
- #ifdef Q_OS_UNIX
396
- " -fg Don't detach from console.\n "
397
- #else
398
- " -fg Don't write to the log file.\n "
399
- #endif
400
- " -wipessl Remove SSL certificates from database.\n "
401
- " -wipelogs Remove all log entries from database.\n "
402
- " -loggroups Turns on logging for group changes for all servers.\n "
403
- " -logacls Turns on logging for ACL changes for all servers.\n "
404
- " -version Show version information.\n "
405
- " \n "
406
- " -license Show Murmur's license.\n "
407
- " -authors Show Murmur's authors.\n "
408
- " -third-party-licenses Show licenses for third-party software used by Murmur.\n "
409
- " \n "
410
- " If no inifile is provided, murmur will search for one in \n "
411
- " default locations." ,
412
- qPrintable (args.at (0 )));
413
- return 0 ;
414
- #ifdef Q_OS_UNIX
415
- } else if (arg == " -limits" ) {
416
- detach = false ;
417
- Meta::mp.read (inifile);
418
- unixhandler.setuid ();
419
- unixhandler.finalcap ();
420
- LimitTest::testLimits (a);
421
- #endif
422
- } else if (arg == " -loggroups" ) {
423
- logGroups = true ;
424
- } else if (arg == " -logacls" ) {
425
- logACL = true ;
426
- } else {
427
- detach = false ;
428
- qFatal (" Unknown argument %s" , qPrintable (args.at (i)));
429
- }
430
- if (bLast && (i + 1 != args.size ())) {
431
- detach = false ;
432
- qFatal (" Password arguments must be last." );
433
- }
434
467
}
468
+ #ifdef Q_OS_WIN
469
+ Tray tray (nullptr , &le);
470
+ #endif
435
471
436
472
if (QSslSocket::supportsSsl ()) {
437
473
qInfo (" SSL: OpenSSL version is '%s'" , SSLeay_version (SSLEAY_VERSION));
0 commit comments