MythTV  master
mythcommandlineparser.cpp
Go to the documentation of this file.
1 /* -*- Mode: c++ -*-
2 *
3 * Class CommandLineArg
4 * Class MythCommandLineParser
5 *
6 * Copyright (C) Raymond Wagner 2011
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
21 */
22 
23 #if defined ANDROID && __ANDROID_API__ < 24
24 // ftello and fseeko do not exist in android before api level 24
25 #define ftello ftell
26 #define fseeko fseek
27 #endif
28 
29 // C++ headers
30 #include <algorithm>
31 #include <csignal>
32 #include <cstdio>
33 #include <cstdlib>
34 #include <fstream>
35 #include <iostream>
36 #include <unistd.h>
37 
38 // System headers
39 #include <sys/types.h>
40 #ifndef _WIN32
41 #include <sys/ioctl.h>
42 #include <pwd.h>
43 #include <grp.h>
44 #if defined(__linux__) || defined(__LINUX__)
45 #include <sys/prctl.h>
46 #endif
47 #endif
48 
49 // Qt headers
50 #include <QtGlobal>
51 #include <QCoreApplication>
52 #include <QDateTime>
53 #include <QDir>
54 #include <QFile>
55 #include <QFileInfo>
56 #include <QRegularExpression>
57 #include <QSize>
58 #include <QString>
59 #include <QTextStream>
60 #include <QVariant>
61 #include <QVariantList>
62 #include <QVariantMap>
63 #include <utility>
64 
65 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
66  #define QT_ENDL endl
67 #else
68  #define QT_ENDL Qt::endl
69 #endif
70 
71 #include "mythcommandlineparser.h"
72 #include "mythcorecontext.h"
73 #include "exitcodes.h"
74 #include "mythconfig.h"
75 #include "mythlogging.h"
76 #include "mythversion.h"
77 #include "logging.h"
78 #include "mythmiscutil.h"
79 #include "mythdate.h"
80 
81 #define TERMWIDTH 79
82 
83 bool openPidfile(std::ofstream &pidfs, const QString &pidfile);
84 bool setUser(const QString &username);
85 int GetTermWidth(void);
86 QByteArray strip_quotes (QByteArray val);
87 
91 int GetTermWidth(void)
92 {
93 #if defined(_WIN32) || defined(Q_OS_ANDROID)
94  return TERMWIDTH;
95 #else
96  struct winsize ws {};
97 
98  if (ioctl(0, TIOCGWINSZ, &ws) != 0)
99  return TERMWIDTH;
100 
101  return static_cast<int>(ws.ws_col);
102 #endif
103 }
104 
105 QByteArray strip_quotes (QByteArray val)
106 {
107  if (val.startsWith('"') && val.endsWith('"'))
108  return val.mid(1,val.size()-2);
109  if (val.startsWith('\'') && val.endsWith('\''))
110  return val.mid(1,val.size()-2);
111  return val;
112 }
113 
118 {
119  switch (type)
120  {
121  case Result::kEnd:
122  return "kEnd";
123 
124  case Result::kEmpty:
125  return "kEmpty";
126 
127  case Result::kOptOnly:
128  return "kOptOnly";
129 
130  case Result::kOptVal:
131  return "kOptVal";
132 
133  case Result::kCombOptVal:
134  return "kCombOptVal";
135 
136  case Result::kArg:
137  return "kArg";
138 
140  return "kPassthrough";
141 
142  case Result::kInvalid:
143  return "kInvalid";
144  }
145  return "kUnknown";
146 }
147 
182 CommandLineArg::CommandLineArg(const QString& name, QVariant::Type type,
183  QVariant def, QString help, QString longhelp) :
184  ReferenceCounter(QString("CommandLineArg:%1").arg(name)),
185  m_name(name), m_type(type), m_default(std::move(def)),
186  m_help(std::move(help)), m_longhelp(std::move(longhelp))
187 {
188  if ((m_type != QVariant::String) && (m_type != QVariant::StringList) &&
189  (m_type != QVariant::Map))
190  m_converted = true;
191 }
192 
199 CommandLineArg::CommandLineArg(const QString& name, QVariant::Type type, QVariant def)
200  : ReferenceCounter(QString("CommandLineArg:%1").arg(name)),
201  m_name(name), m_type(type), m_default(std::move(def))
202 {
203  if ((m_type != QVariant::String) && (m_type != QVariant::StringList) &&
204  (m_type != QVariant::Map))
205  m_converted = true;
206 }
207 
215 CommandLineArg::CommandLineArg(const QString& name) :
216  ReferenceCounter(QString("CommandLineArg:%1").arg(name)),
217  m_name(name)
218 {
219 }
220 
225 {
226  // this may cause problems if the terminal is too narrow, or if too
227  // many keywords for the same argument are used
228  return m_keywords.join(" OR ");
229 }
230 
235 {
236  int len = GetKeywordString().length();
237 
238  QList<CommandLineArg*>::const_iterator i1;
239  for (i1 = m_parents.begin(); i1 != m_parents.end(); ++i1)
240  len = std::max(len, (*i1)->GetKeywordLength()+2);
241 
242  return len;
243 }
244 
260 QString CommandLineArg::GetHelpString(int off, const QString& group, bool force) const
261 {
262  QString helpstr;
263  QTextStream msg(&helpstr, QIODevice::WriteOnly);
264  int termwidth = GetTermWidth();
265  if (termwidth < off)
266  {
267  if (off > 70)
268  {
269  // developer has configured some absurdly long command line
270  // arguments, but we still need to do something
271  termwidth = off+40;
272  }
273  else
274  {
275  // user is running uselessly narrow console, use a sane console
276  // width instead
277  termwidth = 79;
278  }
279  }
280 
281  if (m_help.isEmpty() && !force)
282  // only print if there is a short help to print
283  return helpstr;
284 
285  if ((m_group != group) && !force)
286  // only print if looping over the correct group
287  return helpstr;
288 
289  if (!m_parents.isEmpty() && !force)
290  {
291  // only print if an independent option, not subject
292  // to a parent option
293  return helpstr;
294  }
295 
296  if (!m_deprecated.isEmpty())
297  // option is marked as deprecated, do not show
298  return helpstr;
299 
300  if (!m_removed.isEmpty())
301  // option is marked as removed, do not show
302  return helpstr;
303 
304  QString pad;
305  pad.fill(' ', off);
306 
307  // print the first line with the available keywords
308  QStringList hlist = m_help.split('\n');
309  wrapList(hlist, termwidth-off);
310  if (!m_parents.isEmpty())
311  msg << " ";
312  msg << GetKeywordString().leftJustified(off, ' ')
313  << hlist.takeFirst() << QT_ENDL;
314 
315  // print remaining lines with necessary padding
316  for (const auto & line : qAsConst(hlist))
317  msg << pad << line << QT_ENDL;
318 
319  // loop through any child arguments to print underneath
320  for (auto * arg : qAsConst(m_children))
321  msg << arg->GetHelpString(off, group, true);
322 
323  msg.flush();
324  return helpstr;
325 }
326 
334 QString CommandLineArg::GetLongHelpString(QString keyword) const
335 {
336  QString helpstr;
337  QTextStream msg(&helpstr, QIODevice::WriteOnly);
338  int termwidth = GetTermWidth();
339 
340  // help called for an argument that is not me, this should not happen
341  if (!m_keywords.contains(keyword))
342  return helpstr;
343 
344  // argument has been marked as removed, so warn user of such
345  if (!m_removed.isEmpty())
346  {
347  PrintRemovedWarning(keyword);
348  // argument has been marked as deprecated, so warn user of such
349  }
350  else if (!m_deprecated.isEmpty())
351  {
352  PrintDeprecatedWarning(keyword);
353  }
354 
355  msg << "Option: " << keyword << QT_ENDL << QT_ENDL;
356 
357  bool first = true;
358 
359  // print all related keywords, padding for multiples
360  for (const auto & word : qAsConst(m_keywords))
361  {
362  if (word != keyword)
363  {
364  if (first)
365  {
366  msg << "Aliases: " << word << QT_ENDL;
367  first = false;
368  }
369  else
370  msg << " " << word << QT_ENDL;
371  }
372  }
373 
374  // print type and default for the stored value
375  msg << "Type: " << QVariant::typeToName(static_cast<int>(m_type)) << QT_ENDL;
376  if (m_default.canConvert(QVariant::String))
377  msg << "Default: " << m_default.toString() << QT_ENDL;
378 
379  QStringList help;
380  if (m_longhelp.isEmpty())
381  help = m_help.split("\n");
382  else
383  help = m_longhelp.split("\n");
384  wrapList(help, termwidth-13);
385 
386  // print description, wrapping and padding as necessary
387  msg << "Description: " << help.takeFirst() << QT_ENDL;
388  for (const auto & line : qAsConst(help))
389  msg << " " << line << QT_ENDL;
390 
391  QList<CommandLineArg*>::const_iterator i2;
392 
393  // loop through the four relation types and print
394  if (!m_parents.isEmpty())
395  {
396  msg << QT_ENDL << "Can be used in combination with:" << QT_ENDL;
397  for (auto * parent : qAsConst(m_parents))
398  msg << " " << parent->GetPreferredKeyword()
399  .toLocal8Bit().constData();
400  msg << QT_ENDL;
401  }
402 
403  if (!m_children.isEmpty())
404  {
405  msg << QT_ENDL << "Allows the use of:" << QT_ENDL;
406  for (i2 = m_children.constBegin(); i2 != m_children.constEnd(); ++i2)
407  msg << " " << (*i2)->GetPreferredKeyword()
408  .toLocal8Bit().constData();
409  msg << QT_ENDL;
410  }
411 
412  if (!m_requires.isEmpty())
413  {
414  msg << QT_ENDL << "Requires the use of:" << QT_ENDL;
415  for (i2 = m_requires.constBegin(); i2 != m_requires.constEnd(); ++i2)
416  msg << " " << (*i2)->GetPreferredKeyword()
417  .toLocal8Bit().constData();
418  msg << QT_ENDL;
419  }
420 
421  if (!m_blocks.isEmpty())
422  {
423  msg << QT_ENDL << "Prevents the use of:" << QT_ENDL;
424  for (i2 = m_blocks.constBegin(); i2 != m_blocks.constEnd(); ++i2)
425  msg << " " << (*i2)->GetPreferredKeyword()
426  .toLocal8Bit().constData();
427  msg << QT_ENDL;
428  }
429 
430  msg.flush();
431  return helpstr;
432 }
433 
440 bool CommandLineArg::Set(const QString& opt)
441 {
442  m_usedKeyword = opt;
443 
444  switch (m_type)
445  {
446  case QVariant::Bool:
447  m_stored = QVariant(!m_default.toBool());
448  break;
449 
450  case QVariant::Int:
451  if (m_stored.isNull())
452  m_stored = QVariant(1);
453  else
454  m_stored = QVariant(m_stored.toInt() + 1);
455  break;
456 
457  case QVariant::String:
459  break;
460 
461  default:
462  std::cerr << "Command line option did not receive value:" << std::endl
463  << " " << opt.toLocal8Bit().constData() << std::endl;
464  return false;
465  }
466 
467  m_given = true;
468  return true;
469 }
470 
473 bool CommandLineArg::Set(const QString& opt, const QByteArray& val)
474 {
475  QVariantList vlist;
476  QList<QByteArray> blist;
477  QVariantMap vmap;
478  m_usedKeyword = opt;
479 
480  switch (m_type)
481  {
482  case QVariant::Bool:
483  std::cerr << "Boolean type options do not accept values:" << std::endl
484  << " " << opt.toLocal8Bit().constData() << std::endl;
485  return false;
486 
487  case QVariant::String:
488  m_stored = QVariant(val);
489  break;
490 
491  case QVariant::Int:
492  m_stored = QVariant(val.toInt());
493  break;
494 
495  case QVariant::UInt:
496  m_stored = QVariant(val.toUInt());
497  break;
498 
499  case QVariant::LongLong:
500  m_stored = QVariant(val.toLongLong());
501  break;
502 
503  case QVariant::Double:
504  m_stored = QVariant(val.toDouble());
505  break;
506 
507  case QVariant::DateTime:
508  m_stored = QVariant(MythDate::fromString(QString(val)));
509  break;
510 
511  case QVariant::StringList:
512  if (!m_stored.isNull())
513  vlist = m_stored.toList();
514  vlist << val;
515  m_stored = QVariant(vlist);
516  break;
517 
518  case QVariant::Map:
519  if (!val.contains('='))
520  {
521  std::cerr << "Command line option did not get expected "
522  << "key/value pair" << std::endl;
523  return false;
524  }
525 
526  blist = val.split('=');
527 
528  if (!m_stored.isNull())
529  vmap = m_stored.toMap();
530  vmap[QString(strip_quotes(blist[0]))] = QVariant(strip_quotes(blist[1]));
531  m_stored = QVariant(vmap);
532  break;
533 
534  case QVariant::Size:
535  if (!val.contains('x'))
536  {
537  std::cerr << "Command line option did not get expected "
538  << "XxY pair" << std::endl;
539  return false;
540  }
541 
542  blist = val.split('x');
543  m_stored = QVariant(QSize(blist[0].toInt(), blist[1].toInt()));
544  break;
545 
546  default:
547  m_stored = QVariant(val);
548  }
549 
550  m_given = true;
551  return true;
552 }
553 
557 {
558  m_children << new CommandLineArg(opt);
559  return this;
560 }
561 
565 {
566  for (const auto& opt : qAsConst(opts))
567  m_children << new CommandLineArg(opt);
568  return this;
569 }
570 
574 {
575  m_parents << new CommandLineArg(opt);
576  return this;
577 }
578 
582 {
583  for (const auto& opt : qAsConst(opts))
584  m_parents << new CommandLineArg(opt);
585  return this;
586 }
587 
591 {
592  m_parents << new CommandLineArg(opt);
593  return this;
594 }
595 
599 {
600  for (const auto& opt : qAsConst(opts))
601  m_parents << new CommandLineArg(opt);
602  return this;
603 }
604 
608 {
609  m_children << new CommandLineArg(opt);
610  return this;
611 }
612 
616 {
617  for (const auto& opt : qAsConst(opts))
618  m_children << new CommandLineArg(opt);
619  return this;
620 }
621 
625 {
626  m_children << new CommandLineArg(opt);
627  m_requires << new CommandLineArg(opt);
628  return this;
629 }
630 
634 {
635  for (const auto& opt : qAsConst(opts))
636  {
637  m_children << new CommandLineArg(opt);
638  m_requires << new CommandLineArg(opt);
639  }
640  return this;
641 }
642 
646 {
647  m_parents << new CommandLineArg(opt);
648  m_requiredby << new CommandLineArg(opt);
649  return this;
650 }
651 
655 {
656  for (const auto& opt : qAsConst(opts))
657  {
658  m_parents << new CommandLineArg(opt);
659  m_requiredby << new CommandLineArg(opt);
660  }
661  return this;
662 }
663 
667 {
668  m_requires << new CommandLineArg(opt);
669  return this;
670 }
671 
675 {
676  for (const auto& opt : qAsConst(opts))
677  m_requires << new CommandLineArg(opt);
678  return this;
679 }
680 
684 {
685  m_blocks << new CommandLineArg(opt);
686  return this;
687 }
688 
692 {
693  for (const auto& opt : qAsConst(opts))
694  m_blocks << new CommandLineArg(opt);
695  return this;
696 }
697 
701 {
702  if (depstr.isEmpty())
703  depstr = "and will be removed in a future version.";
704  m_deprecated = depstr;
705  return this;
706 }
707 
710 CommandLineArg* CommandLineArg::SetRemoved(QString remstr, QString remver)
711 {
712  if (remstr.isEmpty())
713  remstr = "and is no longer available in this version.";
714  m_removed = remstr;
715  m_removedversion = std::move(remver);
716  return this;
717 }
718 
724 void CommandLineArg::SetParentOf(CommandLineArg *other, bool forward)
725 {
726  bool replaced = false;
727  other->IncrRef();
728 
729  for (int i = 0; i < m_children.size(); i++)
730  {
731  if (m_children[i]->m_name == other->m_name)
732  {
733  m_children[i]->DecrRef();
734  m_children.replace(i, other);
735  replaced = true;
736  break;
737  }
738  }
739 
740  if (!replaced)
741  m_children << other;
742 
743  if (forward)
744  other->SetChildOf(this, false);
745 }
746 
752 void CommandLineArg::SetChildOf(CommandLineArg *other, bool forward)
753 {
754  bool replaced = false;
755  other->IncrRef();
756 
757  for (int i = 0; i < m_parents.size(); i++)
758  {
759  if (m_parents[i]->m_name == other->m_name)
760  {
761  m_parents[i]->DecrRef();
762  m_parents.replace(i, other);
763  replaced = true;
764  break;
765  }
766  }
767 
768  if (!replaced)
769  m_parents << other;
770 
771  if (forward)
772  other->SetParentOf(this, false);
773 }
774 
780 void CommandLineArg::SetRequires(CommandLineArg *other, bool /*forward*/)
781 {
782  bool replaced = false;
783  other->IncrRef();
784 
785  for (int i = 0; i < m_requires.size(); i++)
786  {
787  if (m_requires[i]->m_name == other->m_name)
788  {
789  m_requires[i]->DecrRef();
790  m_requires.replace(i, other);
791  replaced = true;
792  break;
793  }
794  }
795 
796  if (!replaced)
797  m_requires << other;
798 
799 // requirements need not be reciprocal
800 // if (forward)
801 // other->SetRequires(this, false);
802 }
803 
809 void CommandLineArg::SetBlocks(CommandLineArg *other, bool forward)
810 {
811  bool replaced = false;
812  other->IncrRef();
813 
814  for (int i = 0; i < m_blocks.size(); i++)
815  {
816  if (m_blocks[i]->m_name == other->m_name)
817  {
818  m_blocks[i]->DecrRef();
819  m_blocks.replace(i, other);
820  replaced = true;
821  break;
822  }
823  }
824 
825  if (!replaced)
826  m_blocks << other;
827 
828  if (forward)
829  other->SetBlocks(this, false);
830 }
831 
834 void CommandLineArg::AllowOneOf(const QList<CommandLineArg*>& args)
835 {
836  // TODO: blocks do not get set properly if multiple dummy arguments
837  // are provided. since this method will not have access to the
838  // argument list, this issue will have to be resolved later in
839  // ReconcileLinks().
840 
841  // loop through all but the last entry
842  for (auto i1 = args.cbegin(); i1 != args.cend()-1; ++i1)
843  {
844  // loop through the next to the last entry
845  // and block use with the current
846  for (auto i2 = i1+1; i2 != args.cend(); ++i2)
847  {
848  (*i1)->SetBlocks(*i2);
849  }
850 
851  if ((*i1)->m_type == QVariant::Invalid)
852  (*i1)->DecrRef();
853  }
854 }
855 
863 {
864  if (!QCoreApplication::instance())
865  // QApplication not available, no sense doing anything yet
866  return;
867 
868  if (m_converted)
869  // already run, abort
870  return;
871 
872  if (!m_given)
873  {
874  // nothing to work on, abort
875  m_converted = true;
876  return;
877  }
878 
879  if (m_type == QVariant::String)
880  {
881  if (m_stored.type() == QVariant::ByteArray)
882  {
883  m_stored = QString::fromLocal8Bit(m_stored.toByteArray());
884  }
885  // else
886  // not sure why this isnt a bytearray, but ignore it and
887  // set it as converted
888  }
889  else if (m_type == QVariant::StringList)
890  {
891  if (m_stored.type() == QVariant::List)
892  {
893  QVariantList vlist = m_stored.toList();
894  QStringList slist;
895  for (const auto& item : qAsConst(vlist))
896  slist << QString::fromLocal8Bit(item.toByteArray());
897  m_stored = QVariant(slist);
898  }
899  }
900  else if (m_type == QVariant::Map)
901  {
902  QVariantMap vmap = m_stored.toMap();
903  // NOLINTNEXTLINE(modernize-loop-convert)
904  for (auto iter = vmap.begin(); iter != vmap.end(); ++iter)
905  (*iter) = QString::fromLocal8Bit(iter->toByteArray());
906  }
907  else
908  return;
909 
910  m_converted = true;
911 }
912 
913 
920 {
921  QStringList::const_iterator it;
922  QString preferred;
923  int len = 0;
924 
925  for (it = m_keywords.constBegin(); it != m_keywords.constEnd(); ++it)
926  {
927  int len2 = (*it).size();
928  if (len2 > len)
929  {
930  preferred = *it;
931  len = len2;
932  }
933  }
934 
935  return preferred;
936 }
937 
942 {
943  if (!m_given)
944  return true; // not in use, no need for checks
945 
946  QList<CommandLineArg*>::const_iterator i;
947 
948  bool passes = false;
949  for (i = m_parents.constBegin(); i != m_parents.constEnd(); ++i)
950  {
951  // one of these must have been defined
952  if ((*i)->m_given)
953  {
954  passes = true;
955  break;
956  }
957  }
958  if (!passes && !m_parents.isEmpty())
959  {
960  std::cerr << "ERROR: " << m_usedKeyword.toLocal8Bit().constData()
961  << " requires at least one of the following arguments" << std::endl;
962  for (i = m_parents.constBegin(); i != m_parents.constEnd(); ++i)
963  std::cerr << " "
964  << (*i)->GetPreferredKeyword().toLocal8Bit().constData();
965  std::cerr << std::endl << std::endl;
966  return false;
967  }
968 
969  // we dont care about children
970 
971  for (i = m_requires.constBegin(); i != m_requires.constEnd(); ++i)
972  {
973  // all of these must have been defined
974  if (!(*i)->m_given)
975  {
976  std::cerr << "ERROR: " << m_usedKeyword.toLocal8Bit().constData()
977  << " requires all of the following be defined as well"
978  << std::endl;
979  for (i = m_requires.constBegin(); i != m_requires.constEnd(); ++i)
980  {
981  std::cerr << " "
982  << (*i)->GetPreferredKeyword().toLocal8Bit()
983  .constData();
984  }
985  std::cerr << std::endl << std::endl;
986  return false;
987  }
988  }
989 
990  for (i = m_blocks.constBegin(); i != m_blocks.constEnd(); ++i)
991  {
992  // none of these can be defined
993  if ((*i)->m_given)
994  {
995  std::cerr << "ERROR: " << m_usedKeyword.toLocal8Bit().constData()
996  << " requires that none of the following be defined" << std::endl;
997  for (i = m_blocks.constBegin(); i != m_blocks.constEnd(); ++i)
998  {
999  std::cerr << " "
1000  << (*i)->GetPreferredKeyword().toLocal8Bit()
1001  .constData();
1002  }
1003  std::cerr << std::endl << std::endl;
1004  return false;
1005  }
1006  }
1007 
1008  return true;
1009 }
1010 
1014 {
1015  // clear out interdependent pointers in preparation for deletion
1016  while (!m_parents.isEmpty())
1017  m_parents.takeFirst()->DecrRef();
1018 
1019  while (!m_children.isEmpty())
1020  m_children.takeFirst()->DecrRef();
1021 
1022  while (!m_blocks.isEmpty())
1023  m_blocks.takeFirst()->DecrRef();
1024 
1025  while (!m_requires.isEmpty())
1026  m_requires.takeFirst()->DecrRef();
1027 
1028  while (!m_requiredby.isEmpty())
1029  m_requiredby.takeFirst()->DecrRef();
1030 }
1031 
1035 {
1036  if (!m_given)
1037  return;
1038 
1039  std::cerr << " " << m_name.leftJustified(30).toLocal8Bit().constData();
1040 
1041  QSize tmpsize;
1042  QMap<QString, QVariant> tmpmap;
1043  QMap<QString, QVariant>::const_iterator it;
1044  QVariantList vlist;
1045  bool first = true;
1046 
1047  switch (m_type)
1048  {
1049  case QVariant::Bool:
1050  std::cerr << (m_stored.toBool() ? "True" : "False") << std::endl;
1051  break;
1052 
1053  case QVariant::Int:
1054  std::cerr << m_stored.toInt() << std::endl;
1055  break;
1056 
1057  case QVariant::UInt:
1058  std::cerr << m_stored.toUInt() << std::endl;
1059  break;
1060 
1061  case QVariant::LongLong:
1062  std::cerr << m_stored.toLongLong() << std::endl;
1063  break;
1064 
1065  case QVariant::Double:
1066  std::cerr << m_stored.toDouble() << std::endl;
1067  break;
1068 
1069  case QVariant::Size:
1070  tmpsize = m_stored.toSize();
1071  std::cerr << "x=" << tmpsize.width()
1072  << " y=" << tmpsize.height()
1073  << std::endl;
1074  break;
1075 
1076  case QVariant::String:
1077  std::cerr << '"' << m_stored.toByteArray().constData()
1078  << '"' << std::endl;
1079  break;
1080 
1081  case QVariant::StringList:
1082  vlist = m_stored.toList();
1083  std::cerr << '"' << vlist.takeFirst().toByteArray().constData() << '"';
1084  for (const auto& str : qAsConst(vlist))
1085  {
1086  std::cerr << ", \""
1087  << str.constData()
1088  << '"';
1089  }
1090  std::cerr << std::endl;
1091  break;
1092 
1093  case QVariant::Map:
1094  tmpmap = m_stored.toMap();
1095  for (it = tmpmap.cbegin(); it != tmpmap.cend(); ++it)
1096  {
1097  if (first)
1098  first = false;
1099  else
1100  std::cerr << QString("").leftJustified(32)
1101  .toLocal8Bit().constData();
1102 
1103  std::cerr << it.key().toLocal8Bit().constData()
1104  << '='
1105  << it->toByteArray().constData()
1106  << std::endl;
1107  }
1108 
1109  break;
1110 
1111  case QVariant::DateTime:
1112  std::cerr << m_stored.toDateTime().toString(Qt::ISODate)
1113  .toLocal8Bit().constData()
1114  << std::endl;
1115  break;
1116 
1117  default:
1118  std::cerr << std::endl;
1119  }
1120 }
1121 
1124 void CommandLineArg::PrintRemovedWarning(QString &keyword) const
1125 {
1126  QString warn = QString("%1 has been removed").arg(keyword);
1127  if (!m_removedversion.isEmpty())
1128  warn += QString(" as of MythTV %1").arg(m_removedversion);
1129 
1130  std::cerr << QString("****************************************************\n"
1131  " WARNING: %1\n"
1132  " %2\n"
1133  "****************************************************\n\n")
1134  .arg(warn).arg(m_removed)
1135  .toLocal8Bit().constData();
1136 }
1137 
1140 void CommandLineArg::PrintDeprecatedWarning(QString &keyword) const
1141 {
1142  std::cerr << QString("****************************************************\n"
1143  " WARNING: %1 has been deprecated\n"
1144  " %2\n"
1145  "****************************************************\n\n")
1146  .arg(keyword).arg(m_deprecated)
1147  .toLocal8Bit().constData();
1148 }
1149 
1164  : m_appname(std::move(appname))
1165 {
1166  if (qEnvironmentVariableIsSet("VERBOSE_PARSER"))
1167  {
1168  std::cerr << "MythCommandLineParser is now operating verbosely." << std::endl;
1169  m_verbose = true;
1170  }
1171 
1173 }
1174 
1176 {
1177  QMap<QString, CommandLineArg*>::iterator i;
1178 
1179  i = m_namedArgs.begin();
1180  while (i != m_namedArgs.end())
1181  {
1182  (*i)->CleanupLinks();
1183  (*i)->DecrRef();
1184  i = m_namedArgs.erase(i);
1185  }
1186 
1187  i = m_optionedArgs.begin();
1188  while (i != m_optionedArgs.end())
1189  {
1190  (*i)->DecrRef();
1191  i = m_optionedArgs.erase(i);
1192  }
1193 }
1194 
1229  const QString& name, QVariant::Type type, QVariant def,
1230  QString help, QString longhelp)
1231 {
1232  CommandLineArg *arg = nullptr;
1233 
1234  if (m_namedArgs.contains(name))
1235  arg = m_namedArgs[name];
1236  else
1237  {
1238  arg = new CommandLineArg(name, type, std::move(def), std::move(help), std::move(longhelp));
1239  m_namedArgs.insert(name, arg);
1240  }
1241 
1242  for (const auto & str : qAsConst(arglist))
1243  {
1244  if (!m_optionedArgs.contains(str))
1245  {
1246  arg->AddKeyword(str);
1247  if (m_verbose)
1248  {
1249  std::cerr << "Adding " << str.toLocal8Bit().constData()
1250  << " as taking type '" << QVariant::typeToName(static_cast<int>(type))
1251  << "'" << std::endl;
1252  }
1253  arg->IncrRef();
1254  m_optionedArgs.insert(str, arg);
1255  }
1256  }
1257 
1258  return arg;
1259 }
1260 
1264 {
1265  std::cout << "Please attach all output as a file in bug reports." << std::endl;
1266  std::cout << "MythTV Version : " << GetMythSourceVersion() << std::endl;
1267  std::cout << "MythTV Branch : " << GetMythSourcePath() << std::endl;
1268  std::cout << "Network Protocol : " << MYTH_PROTO_VERSION << std::endl;
1269  std::cout << "Library API : " << MYTH_BINARY_VERSION << std::endl;
1270  std::cout << "QT Version : " << QT_VERSION_STR << std::endl;
1271 #ifdef MYTH_BUILD_CONFIG
1272  std::cout << "Options compiled in:" <<std::endl;
1273  std::cout << MYTH_BUILD_CONFIG << std::endl;
1274 #endif
1275 }
1276 
1280 {
1281  QString help = GetHelpString();
1282  std::cerr << help.toLocal8Bit().constData();
1283 }
1284 
1291 {
1292  QString helpstr;
1293  QTextStream msg(&helpstr, QIODevice::WriteOnly);
1294 
1295  QString versionStr = QString("%1 version: %2 [%3] www.mythtv.org")
1296  .arg(m_appname).arg(GetMythSourcePath()).arg(GetMythSourceVersion());
1297  msg << versionStr << QT_ENDL;
1298 
1299  if (toString("showhelp").isEmpty())
1300  {
1301  // build generic help text
1302 
1303  QString descr = GetHelpHeader();
1304  if (descr.size() > 0)
1305  msg << QT_ENDL << descr << QT_ENDL << QT_ENDL;
1306 
1307  // loop through registered arguments to populate list of groups
1308  QStringList groups("");
1309  int maxlen = 0;
1310  for (auto * cmdarg : qAsConst(m_namedArgs))
1311  {
1312  maxlen = std::max(cmdarg->GetKeywordLength(), maxlen);
1313  if (!groups.contains(cmdarg->m_group))
1314  groups << cmdarg->m_group;
1315  }
1316 
1317  // loop through list of groups and print help string for each
1318  // arguments will filter themselves if they are not in the group
1319  maxlen += 4;
1320  for (const auto & group : qAsConst(groups))
1321  {
1322  if (group.isEmpty())
1323  msg << "Misc. Options:" << QT_ENDL;
1324  else
1325  msg << group.toLocal8Bit().constData() << " Options:" << QT_ENDL;
1326 
1327  for (auto * cmdarg : qAsConst(m_namedArgs))
1328  msg << cmdarg->GetHelpString(maxlen, group);
1329  msg << QT_ENDL;
1330  }
1331  }
1332  else
1333  {
1334  // build help for a specific argument
1335  QString optstr = "-" + toString("showhelp");
1336  if (!m_optionedArgs.contains(optstr))
1337  {
1338  optstr = "-" + optstr;
1339  if (!m_optionedArgs.contains(optstr))
1340  return QString("Could not find option matching '%1'\n")
1341  .arg(toString("showhelp"));
1342  }
1343 
1344  if (m_optionedArgs[optstr] != nullptr)
1345  msg << m_optionedArgs[optstr]->GetLongHelpString(optstr);
1346  }
1347 
1348  msg.flush();
1349  return helpstr;
1350 }
1351 
1355  int &argpos, QString &opt, QByteArray &val)
1356 {
1357  opt.clear();
1358  val.clear();
1359 
1360  if (argpos >= argc)
1361  // this shouldnt happen, return and exit
1362  return Result::kEnd;
1363 
1364  QByteArray tmp(argv[argpos]);
1365  if (tmp.isEmpty())
1366  // string is empty, return and loop
1367  return Result::kEmpty;
1368 
1369  if (m_passthroughActive)
1370  {
1371  // pass through has been activated
1372  val = tmp;
1373  return Result::kArg;
1374  }
1375 
1376  if (tmp.startsWith('-') && tmp.size() > 1)
1377  {
1378  if (tmp == "--")
1379  {
1380  // all options beyond this will be passed as a single string
1381  m_passthroughActive = true;
1382  return Result::kPassthrough;
1383  }
1384 
1385  if (tmp.contains('='))
1386  {
1387  // option contains '=', split
1388  QList<QByteArray> blist = tmp.split('=');
1389 
1390  if (blist.size() != 2)
1391  {
1392  // more than one '=' in option, this is not handled
1393  opt = QString(tmp);
1394  return Result::kInvalid;
1395  }
1396 
1397  opt = QString(strip_quotes(blist[0]));
1398  val = strip_quotes(blist[1]);
1399  return Result::kCombOptVal;
1400  }
1401 
1402  opt = QString(tmp);
1403 
1404  if (argpos+1 >= argc)
1405  // end of input, option only
1406  return Result::kOptOnly;
1407 
1408  tmp = QByteArray(argv[++argpos]);
1409  if (tmp.isEmpty())
1410  // empty string, option only
1411  return Result::kOptOnly;
1412 
1413  if (tmp.startsWith("-") && tmp.size() > 1)
1414  {
1415  // no value found for option, backtrack
1416  argpos--;
1417  return Result::kOptOnly;
1418  }
1419 
1420  val = tmp;
1421  return Result::kOptVal;
1422  }
1423 
1424  // input is not an option string, return as arg
1425  val = tmp;
1426  return Result::kArg;
1427 }
1428 
1435 bool MythCommandLineParser::Parse(int argc, const char * const * argv)
1436 {
1437  Result res = Result::kEnd;
1438  QString opt;
1439  QByteArray val;
1440  CommandLineArg *argdef = nullptr;
1441 
1442  // reconnect interdependencies between command line options
1443  if (!ReconcileLinks())
1444  return false;
1445 
1446  // loop through command line arguments until all are spent
1447  for (int argpos = 1; argpos < argc; ++argpos)
1448  {
1449 
1450  // pull next option
1451  res = getOpt(argc, argv, argpos, opt, val);
1452 
1453  if (m_verbose)
1454  {
1455  std::cerr << "res: " << NamedOptType(res) << std::endl
1456  << "opt: " << opt.toLocal8Bit().constData() << std::endl
1457  << "val: " << val.constData() << std::endl << std::endl;
1458  }
1459 
1460  // '--' found on command line, enable passthrough mode
1461  if (res == Result::kPassthrough && !m_namedArgs.contains("_passthrough"))
1462  {
1463  std::cerr << "Received '--' but passthrough has not been enabled" << std::endl;
1464  SetValue("showhelp", "");
1465  return false;
1466  }
1467 
1468  // end of options found, terminate loop
1469  if (res == Result::kEnd)
1470  break;
1471 
1472  // GetOpt pulled an empty option, this shouldnt happen by ignore
1473  // it and continue
1474  if (res == Result::kEmpty)
1475  continue;
1476 
1477  // more than one equal found in key/value pair, fault out
1478  if (res == Result::kInvalid)
1479  {
1480  std::cerr << "Invalid option received:" << std::endl << " "
1481  << opt.toLocal8Bit().constData();
1482  SetValue("showhelp", "");
1483  return false;
1484  }
1485 
1486  // passthrough is active, so add the data to the stringlist
1487  if (m_passthroughActive)
1488  {
1489  m_namedArgs["_passthrough"]->Set("", val);
1490  continue;
1491  }
1492 
1493  // argument with no preceeding '-' encountered, add to stringlist
1494  if (res == Result::kArg)
1495  {
1496  if (!m_namedArgs.contains("_args"))
1497  {
1498  std::cerr << "Received '"
1499  << val.constData()
1500  << "' but unassociated arguments have not been enabled"
1501  << std::endl;
1502  SetValue("showhelp", "");
1503  return false;
1504  }
1505 
1506  m_namedArgs["_args"]->Set("", val);
1507  continue;
1508  }
1509 
1510  // this line should not be passed once arguments have started collecting
1511  if (toBool("_args"))
1512  {
1513  std::cerr << "Command line arguments received out of sequence"
1514  << std::endl;
1515  SetValue("showhelp", "");
1516  return false;
1517  }
1518 
1519 #ifdef Q_OS_MAC
1520  if (opt.startsWith("-psn_"))
1521  {
1522  std::cerr << "Ignoring Process Serial Number from command line"
1523  << std::endl;
1524  continue;
1525  }
1526 #endif
1527 
1528  if (!m_optionedArgs.contains(opt))
1529  {
1530  // argument is unhandled, check if parser allows arbitrary input
1531  if (m_namedArgs.contains("_extra"))
1532  {
1533  // arbitrary allowed, specify general collection pool
1534  argdef = m_namedArgs["_extra"];
1535  QByteArray tmp = opt.toLocal8Bit();
1536  tmp += '=';
1537  tmp += val;
1538  val = tmp;
1539  res = Result::kOptVal;
1540  }
1541  else
1542  {
1543  // arbitrary not allowed, fault out
1544  std::cerr << "Unhandled option given on command line:" << std::endl
1545  << " " << opt.toLocal8Bit().constData() << std::endl;
1546  SetValue("showhelp", "");
1547  return false;
1548  }
1549  }
1550  else
1551  argdef = m_optionedArgs[opt];
1552 
1553  // argument has been marked as removed, warn user and fail
1554  if (!argdef->m_removed.isEmpty())
1555  {
1556  argdef->PrintRemovedWarning(opt);
1557  SetValue("showhelp", "");
1558  return false;
1559  }
1560 
1561  // argument has been marked as deprecated, warn user
1562  if (!argdef->m_deprecated.isEmpty())
1563  argdef->PrintDeprecatedWarning(opt);
1564 
1565  if (m_verbose)
1566  std::cerr << "name: " << argdef->GetName().toLocal8Bit().constData()
1567  << std::endl;
1568 
1569  // argument is keyword only, no value
1570  if (res == Result::kOptOnly)
1571  {
1572  if (!argdef->Set(opt))
1573  {
1574  SetValue("showhelp", "");
1575  return false;
1576  }
1577  }
1578  // argument has keyword and value
1579  else if ((res == Result::kOptVal) || (res == Result::kCombOptVal))
1580  {
1581  if (!argdef->Set(opt, val))
1582  {
1583  // if option and value were combined with a '=', abort directly
1584  // otherwise, attempt processing them independenly
1585  if ((res == Result::kCombOptVal) || !argdef->Set(opt))
1586  {
1587  SetValue("showhelp", "");
1588  return false;
1589  }
1590  // drop back an iteration so the unused value will get
1591  // processed a second time as a keyword-less argument
1592  --argpos;
1593  }
1594  }
1595  else
1596  {
1597  SetValue("showhelp", "");
1598  return false; // this should not occur
1599  }
1600 
1601  if (m_verbose)
1602  std::cerr << "value: " << argdef->m_stored.toString().toLocal8Bit().constData()
1603  << std::endl;
1604  }
1605 
1606  if (m_verbose)
1607  {
1608  std::cerr << "Processed option list:" << std::endl;
1609  for (auto * cmdarg : qAsConst(m_namedArgs))
1610  cmdarg->PrintVerbose();
1611 
1612  if (m_namedArgs.contains("_args"))
1613  {
1614  std::cerr << std::endl << "Extra argument list:" << std::endl;
1615  QStringList slist = toStringList("_args");
1616  for (const auto& lopt : qAsConst(slist))
1617  std::cerr << " " << (lopt).toLocal8Bit().constData() << std::endl;
1618  }
1619 
1620  if (m_namedArgs.contains("_passthrough"))
1621  {
1622  std::cerr << std::endl << "Passthrough string:" << std::endl;
1623  std::cerr << " " << GetPassthrough().toLocal8Bit().constData() << std::endl;
1624  }
1625 
1626  std::cerr << std::endl;
1627  }
1628 
1629  // make sure all interdependencies are fulfilled
1630  for (auto * cmdarg : qAsConst(m_namedArgs))
1631  {
1632  if (!cmdarg->TestLinks())
1633  {
1634  QString keyword = cmdarg->m_usedKeyword;
1635  if (keyword.startsWith('-'))
1636  {
1637  if (keyword.startsWith("--"))
1638  keyword.remove(0,2);
1639  else
1640  keyword.remove(0,1);
1641  }
1642 
1643  SetValue("showhelp", keyword);
1644  return false;
1645  }
1646  }
1647 
1648  return true;
1649 }
1650 
1651 CommandLineArg* MythCommandLineParser::add(const QString& arg, const QString& name, bool def,
1652  QString help, QString longhelp)
1653 {
1654  return add(QStringList(arg), name, QVariant::Bool, QVariant(def), std::move(help), std::move(longhelp));
1655 }
1656 
1657 CommandLineArg* MythCommandLineParser::add(const QString& arg, const QString& name, int def,
1658  QString help, QString longhelp)
1659 {
1660  return add(QStringList(arg), name, QVariant::Int, QVariant(def), std::move(help), std::move(longhelp));
1661 }
1662 
1663 CommandLineArg* MythCommandLineParser::add(const QString& arg, const QString& name, uint def,
1664  QString help, QString longhelp)
1665 {
1666  return add(QStringList(arg), name, QVariant::UInt, QVariant(def), std::move(help), std::move(longhelp));
1667 }
1668 
1669 CommandLineArg* MythCommandLineParser::add(const QString& arg, const QString& name, long long def,
1670  QString help, QString longhelp)
1671 {
1672  return add(QStringList(arg), name, QVariant::LongLong, QVariant(def), std::move(help), std::move(longhelp));
1673 }
1674 
1675 CommandLineArg* MythCommandLineParser::add(const QString& arg, const QString& name, double def,
1676  QString help, QString longhelp)
1677 {
1678  return add(QStringList(arg), name, QVariant::Double, QVariant(def), std::move(help), std::move(longhelp));
1679 }
1680 
1681 CommandLineArg* MythCommandLineParser::add(const QString& arg, const QString& name, const char *def,
1682  QString help, QString longhelp)
1683 {
1684  return add(QStringList(arg), name, QVariant::String, QVariant(def), std::move(help), std::move(longhelp));
1685 }
1686 
1687 CommandLineArg* MythCommandLineParser::add(const QString& arg, const QString& name, const QString& def,
1688  QString help, QString longhelp)
1689 {
1690  return add(QStringList(arg), name, QVariant::String, QVariant(def), std::move(help), std::move(longhelp));
1691 }
1692 
1693 CommandLineArg* MythCommandLineParser::add(const QString& arg, const QString& name, QSize def,
1694  QString help, QString longhelp)
1695 {
1696  return add(QStringList(arg), name, QVariant::Size, QVariant(def), std::move(help), std::move(longhelp));
1697 }
1698 
1699 CommandLineArg* MythCommandLineParser::add(const QString& arg, const QString& name, const QDateTime& def,
1700  QString help, QString longhelp)
1701 {
1702  return add(QStringList(arg), name, QVariant::DateTime, QVariant(def), std::move(help), std::move(longhelp));
1703 }
1704 
1705 CommandLineArg* MythCommandLineParser::add(const QString& arg, const QString& name, QVariant::Type type,
1706  QString help, QString longhelp)
1707 {
1708  return add(QStringList(arg), name, type, QVariant(type), std::move(help), std::move(longhelp));
1709 }
1710 
1711 CommandLineArg* MythCommandLineParser::add(const QString& arg, const QString& name, QVariant::Type type,
1712  QVariant def, QString help, QString longhelp)
1713 {
1714  return add(QStringList(arg), name, type, std::move(def), std::move(help), std::move(longhelp));
1715 }
1716 
1717 CommandLineArg* MythCommandLineParser::add(QStringList arglist, const QString& name, bool def,
1718  QString help, QString longhelp)
1719 {
1720  return add(std::move(arglist), name, QVariant::Bool, QVariant(def), std::move(help), std::move(longhelp));
1721 }
1722 
1723 CommandLineArg* MythCommandLineParser::add(QStringList arglist, const QString& name, int def,
1724  QString help, QString longhelp)
1725 {
1726  return add(std::move(arglist), name, QVariant::Int, QVariant(def), std::move(help), std::move(longhelp));
1727 }
1728 
1729 CommandLineArg* MythCommandLineParser::add(QStringList arglist, const QString& name, uint def,
1730  QString help, QString longhelp)
1731 {
1732  return add(std::move(arglist), name, QVariant::UInt, QVariant(def), std::move(help), std::move(longhelp));
1733 }
1734 
1735 CommandLineArg* MythCommandLineParser::add(QStringList arglist, const QString& name, long long def,
1736  QString help, QString longhelp)
1737 {
1738  return add(std::move(arglist), name, QVariant::LongLong, QVariant(def), std::move(help), std::move(longhelp));
1739 }
1740 
1741 CommandLineArg* MythCommandLineParser::add(QStringList arglist, const QString& name, double def,
1742  QString help, QString longhelp)
1743 {
1744  return add(std::move(arglist), name, QVariant::Double, QVariant(def), std::move(help), std::move(longhelp));
1745 }
1746 
1747 CommandLineArg* MythCommandLineParser::add(QStringList arglist, const QString& name, const char *def,
1748  QString help, QString longhelp)
1749 {
1750  return add(std::move(arglist), name, QVariant::String, QVariant(def), std::move(help), std::move(longhelp));
1751 }
1752 
1753 CommandLineArg* MythCommandLineParser::add(QStringList arglist, const QString& name, const QString& def,
1754  QString help, QString longhelp)
1755 {
1756  return add(std::move(arglist), name, QVariant::String, QVariant(def), std::move(help), std::move(longhelp));
1757 }
1758 
1759 CommandLineArg* MythCommandLineParser::add(QStringList arglist, const QString& name, QSize def,
1760  QString help, QString longhelp)
1761 {
1762  return add(std::move(arglist), name, QVariant::Size, QVariant(def), std::move(help), std::move(longhelp));
1763 }
1764 
1765 CommandLineArg* MythCommandLineParser::add(QStringList arglist, const QString& name, const QDateTime& def,
1766  QString help, QString longhelp)
1767 {
1768  return add(std::move(arglist), name, QVariant::DateTime, QVariant(def), std::move(help), std::move(longhelp));
1769 }
1770 
1771 CommandLineArg* MythCommandLineParser::add(QStringList arglist, const QString& name, QVariant::Type type,
1772  QString help, QString longhelp)
1773 {
1774  return add(std::move(arglist), name, type, QVariant(type), std::move(help), std::move(longhelp));
1775 }
1776 
1781 {
1782  if (m_verbose)
1783  std::cerr << "Reconciling links for option interdependencies." << std::endl;
1784 
1785  QMap<QString,CommandLineArg*>::iterator args_it;
1786  for (args_it = m_namedArgs.begin(); args_it != m_namedArgs.end(); ++args_it)
1787  {
1788  QList<CommandLineArg*> links = (*args_it)->m_parents;
1789  QList<CommandLineArg*>::iterator links_it;
1790  for (links_it = links.begin(); links_it != links.end(); ++links_it)
1791  {
1792  if ((*links_it)->m_type != QVariant::Invalid)
1793  continue; // already handled
1794 
1795  if (!m_namedArgs.contains((*links_it)->m_name))
1796  {
1797  // not found
1798  std::cerr << "ERROR: could not reconcile linked argument." << std::endl
1799  << " '" << (*args_it)->m_name.toLocal8Bit().constData()
1800  << "' could not find '"
1801  << (*links_it)->m_name.toLocal8Bit().constData()
1802  << "'." << std::endl
1803  << " Please resolve dependency and recompile." << std::endl;
1804  return false;
1805  }
1806 
1807  // replace linked argument
1808  if (m_verbose)
1809  {
1810  std::cerr << QString(" Setting %1 as child of %2")
1811  .arg((*args_it)->m_name).arg((*links_it)->m_name)
1812  .toLocal8Bit().constData()
1813  << std::endl;
1814  }
1815  (*args_it)->SetChildOf(m_namedArgs[(*links_it)->m_name]);
1816  }
1817 
1818  links = (*args_it)->m_children;
1819  for (links_it = links.begin(); links_it != links.end(); ++links_it)
1820  {
1821  if ((*links_it)->m_type != QVariant::Invalid)
1822  continue; // already handled
1823 
1824  if (!m_namedArgs.contains((*links_it)->m_name))
1825  {
1826  // not found
1827  std::cerr << "ERROR: could not reconcile linked argument." << std::endl
1828  << " '" << (*args_it)->m_name.toLocal8Bit().constData()
1829  << "' could not find '"
1830  << (*links_it)->m_name.toLocal8Bit().constData()
1831  << "'." << std::endl
1832  << " Please resolve dependency and recompile." << std::endl;
1833  return false;
1834  }
1835 
1836  // replace linked argument
1837  if (m_verbose)
1838  {
1839  std::cerr << QString(" Setting %1 as parent of %2")
1840  .arg((*args_it)->m_name).arg((*links_it)->m_name)
1841  .toLocal8Bit().constData()
1842  << std::endl;
1843  }
1844  (*args_it)->SetParentOf(m_namedArgs[(*links_it)->m_name]);
1845  }
1846 
1847  links = (*args_it)->m_requires;
1848  for (links_it = links.begin(); links_it != links.end(); ++links_it)
1849  {
1850  if ((*links_it)->m_type != QVariant::Invalid)
1851  continue; // already handled
1852 
1853  if (!m_namedArgs.contains((*links_it)->m_name))
1854  {
1855  // not found
1856  std::cerr << "ERROR: could not reconcile linked argument." << std::endl
1857  << " '" << (*args_it)->m_name.toLocal8Bit().constData()
1858  << "' could not find '"
1859  << (*links_it)->m_name.toLocal8Bit().constData()
1860  << "'." << std::endl
1861  << " Please resolve dependency and recompile." << std::endl;
1862  return false;
1863  }
1864 
1865  // replace linked argument
1866  if (m_verbose)
1867  {
1868  std::cerr << QString(" Setting %1 as requiring %2")
1869  .arg((*args_it)->m_name).arg((*links_it)->m_name)
1870  .toLocal8Bit().constData()
1871  << std::endl;
1872  }
1873  (*args_it)->SetRequires(m_namedArgs[(*links_it)->m_name]);
1874  }
1875 
1876  QList<CommandLineArg*>::iterator req_it =
1877  (*args_it)->m_requiredby.begin();
1878  while (req_it != (*args_it)->m_requiredby.end())
1879  {
1880  if ((*req_it)->m_type == QVariant::Invalid)
1881  {
1882  // if its not an invalid, it shouldnt be here anyway
1883  if (m_namedArgs.contains((*req_it)->m_name))
1884  {
1885  m_namedArgs[(*req_it)->m_name]->SetRequires(*args_it);
1886  if (m_verbose)
1887  {
1888  std::cerr << QString(" Setting %1 as blocking %2")
1889  .arg((*args_it)->m_name)
1890  .arg((*req_it)->m_name)
1891  .toLocal8Bit().constData()
1892  << std::endl;
1893  }
1894  }
1895  }
1896 
1897  (*req_it)->DecrRef();
1898  req_it = (*args_it)->m_requiredby.erase(req_it);
1899  }
1900 
1901  QList<CommandLineArg*>::iterator block_it =
1902  (*args_it)->m_blocks.begin();
1903  while (block_it != (*args_it)->m_blocks.end())
1904  {
1905  if ((*block_it)->m_type != QVariant::Invalid)
1906  {
1907  ++block_it;
1908  continue; // already handled
1909  }
1910 
1911  if (!m_namedArgs.contains((*block_it)->m_name))
1912  {
1913  (*block_it)->DecrRef();
1914  block_it = (*args_it)->m_blocks.erase(block_it);
1915  continue; // if it doesnt exist, it cant block this command
1916  }
1917 
1918  // replace linked argument
1919  if (m_verbose)
1920  {
1921  std::cerr << QString(" Setting %1 as blocking %2")
1922  .arg((*args_it)->m_name).arg((*block_it)->m_name)
1923  .toLocal8Bit().constData()
1924  << std::endl;
1925  }
1926  (*args_it)->SetBlocks(m_namedArgs[(*block_it)->m_name]);
1927  ++block_it;
1928  }
1929  }
1930 
1931  return true;
1932 }
1933 
1937 QVariant MythCommandLineParser::operator[](const QString &name)
1938 {
1939  QVariant var("");
1940  if (!m_namedArgs.contains(name))
1941  return var;
1942 
1943  CommandLineArg *arg = m_namedArgs[name];
1944 
1945  if (arg->m_given)
1946  var = arg->m_stored;
1947  else
1948  var = arg->m_default;
1949 
1950  return var;
1951 }
1952 
1956 QStringList MythCommandLineParser::GetArgs(void) const
1957 {
1958  return toStringList("_args");
1959 }
1960 
1964 QMap<QString,QString> MythCommandLineParser::GetExtra(void) const
1965 {
1966  return toMap("_extra");
1967 }
1968 
1972 {
1973  return toStringList("_passthrough").join(" ");
1974 }
1975 
1984 {
1985  QMap<QString,QString> smap = toMap("overridesettings");
1986 
1987  if (!m_overridesImported)
1988  {
1989  if (toBool("overridesettingsfile"))
1990  {
1991  QString filename = toString("overridesettingsfile");
1992  if (!filename.isEmpty())
1993  {
1994  QFile f(filename);
1995  if (f.open(QIODevice::ReadOnly))
1996  {
1997  QTextStream in(&f);
1998  while (!in.atEnd()) {
1999  QString line = in.readLine().trimmed();
2000 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
2001  QStringList tokens = line.split("=",
2002  QString::SkipEmptyParts);
2003 #else
2004  QStringList tokens = line.split("=",
2005  Qt::SkipEmptyParts);
2006 #endif
2007  if (tokens.size() == 2)
2008  {
2009  tokens[0].remove(QRegularExpression("^[\"']"));
2010  tokens[0].remove(QRegularExpression("[\"']$"));
2011  tokens[1].remove(QRegularExpression("^[\"']"));
2012  tokens[1].remove(QRegularExpression("[\"']$"));
2013  if (!tokens[0].isEmpty())
2014  smap[tokens[0]] = tokens[1];
2015  }
2016  }
2017  }
2018  else
2019  {
2020  QByteArray tmp = filename.toLatin1();
2021  std::cerr << "Failed to open the override settings file: '"
2022  << tmp.constData() << "'" << std::endl;
2023  }
2024  }
2025  }
2026 
2027  if (toBool("windowed"))
2028  smap["RunFrontendInWindow"] = "1";
2029  else if (toBool("notwindowed"))
2030  smap["RunFrontendInWindow"] = "0";
2031 
2032  if (toBool("mousecursor"))
2033  smap["HideMouseCursor"] = "0";
2034  else if (toBool("nomousecursor"))
2035  smap["HideMouseCursor"] = "1";
2036 
2037  m_overridesImported = true;
2038 
2039  if (!smap.isEmpty())
2040  {
2041  QVariantMap vmap;
2042  for (auto it = smap.cbegin(); it != smap.cend(); ++it)
2043  vmap[it.key()] = QVariant(it.value());
2044 
2045  m_namedArgs["overridesettings"]->Set(QVariant(vmap));
2046  }
2047  }
2048 
2049  if (m_verbose)
2050  {
2051  std::cerr << "Option Overrides:" << std::endl;
2052  QMap<QString, QString>::const_iterator it;
2053  for (it = smap.constBegin(); it != smap.constEnd(); ++it)
2054  std::cerr << QString(" %1 - %2").arg(it.key(), 30).arg(*it)
2055  .toLocal8Bit().constData() << std::endl;
2056  }
2057 
2058  return smap;
2059 }
2060 
2067 bool MythCommandLineParser::toBool(const QString& key) const
2068 {
2069  if (!m_namedArgs.contains(key))
2070  return false;
2071 
2072  CommandLineArg *arg = m_namedArgs[key];
2073  if (arg == nullptr)
2074  return false;
2075 
2076  if (arg->m_type == QVariant::Bool)
2077  {
2078  if (arg->m_given)
2079  return arg->m_stored.toBool();
2080  return arg->m_default.toBool();
2081  }
2082 
2083  return arg->m_given;
2084 }
2085 
2089 int MythCommandLineParser::toInt(const QString& key) const
2090 {
2091  int val = 0;
2092  if (!m_namedArgs.contains(key))
2093  return val;
2094 
2095  CommandLineArg *arg = m_namedArgs[key];
2096  if (arg == nullptr)
2097  return val;
2098 
2099  if (arg->m_given)
2100  {
2101  if (arg->m_stored.canConvert(QVariant::Int))
2102  val = arg->m_stored.toInt();
2103  }
2104  else
2105  {
2106  if (arg->m_default.canConvert(QVariant::Int))
2107  val = arg->m_default.toInt();
2108  }
2109 
2110  return val;
2111 }
2112 
2116 uint MythCommandLineParser::toUInt(const QString& key) const
2117 {
2118  uint val = 0;
2119  if (!m_namedArgs.contains(key))
2120  return val;
2121 
2122  CommandLineArg *arg = m_namedArgs[key];
2123  if (arg == nullptr)
2124  return val;
2125 
2126  if (arg->m_given)
2127  {
2128  if (arg->m_stored.canConvert(QVariant::UInt))
2129  val = arg->m_stored.toUInt();
2130  }
2131  else
2132  {
2133  if (arg->m_default.canConvert(QVariant::UInt))
2134  val = arg->m_default.toUInt();
2135  }
2136 
2137  return val;
2138 }
2139 
2143 long long MythCommandLineParser::toLongLong(const QString& key) const
2144 {
2145  long long val = 0;
2146  if (!m_namedArgs.contains(key))
2147  return val;
2148 
2149  CommandLineArg *arg = m_namedArgs[key];
2150  if (arg == nullptr)
2151  return val;
2152 
2153  if (arg->m_given)
2154  {
2155  if (arg->m_stored.canConvert(QVariant::LongLong))
2156  val = arg->m_stored.toLongLong();
2157  }
2158  else
2159  {
2160  if (arg->m_default.canConvert(QVariant::LongLong))
2161  val = arg->m_default.toLongLong();
2162  }
2163 
2164  return val;
2165 }
2166 
2170 double MythCommandLineParser::toDouble(const QString& key) const
2171 {
2172  double val = 0.0;
2173  if (!m_namedArgs.contains(key))
2174  return val;
2175 
2176  CommandLineArg *arg = m_namedArgs[key];
2177  if (arg == nullptr)
2178  return val;
2179 
2180  if (arg->m_given)
2181  {
2182  if (arg->m_stored.canConvert(QVariant::Double))
2183  val = arg->m_stored.toDouble();
2184  }
2185  else
2186  {
2187  if (arg->m_default.canConvert(QVariant::Double))
2188  val = arg->m_default.toDouble();
2189  }
2190 
2191  return val;
2192 }
2193 
2197 QSize MythCommandLineParser::toSize(const QString& key) const
2198 {
2199  QSize val(0,0);
2200  if (!m_namedArgs.contains(key))
2201  return val;
2202 
2203  CommandLineArg *arg = m_namedArgs[key];
2204  if (arg == nullptr)
2205  return val;
2206 
2207  if (arg->m_given)
2208  {
2209  if (arg->m_stored.canConvert(QVariant::Size))
2210  val = arg->m_stored.toSize();
2211  }
2212  else
2213  {
2214  if (arg->m_default.canConvert(QVariant::Size))
2215  val = arg->m_default.toSize();
2216  }
2217 
2218  return val;
2219 }
2220 
2224 QString MythCommandLineParser::toString(const QString& key) const
2225 {
2226  QString val("");
2227  if (!m_namedArgs.contains(key))
2228  return val;
2229 
2230  CommandLineArg *arg = m_namedArgs[key];
2231  if (arg == nullptr)
2232  return val;
2233 
2234  if (arg->m_given)
2235  {
2236  if (!arg->m_converted)
2237  arg->Convert();
2238 
2239  if (arg->m_stored.canConvert(QVariant::String))
2240  val = arg->m_stored.toString();
2241  }
2242  else
2243  {
2244  if (arg->m_default.canConvert(QVariant::String))
2245  val = arg->m_default.toString();
2246  }
2247 
2248  return val;
2249 }
2250 
2255 QStringList MythCommandLineParser::toStringList(const QString& key, const QString& sep) const
2256 {
2257  QVariant varval;
2258  QStringList val;
2259  if (!m_namedArgs.contains(key))
2260  return val;
2261 
2262  CommandLineArg *arg = m_namedArgs[key];
2263  if (arg == nullptr)
2264  return val;
2265 
2266  if (arg->m_given)
2267  {
2268  if (!arg->m_converted)
2269  arg->Convert();
2270 
2271  varval = arg->m_stored;
2272  }
2273  else
2274  varval = arg->m_default;
2275 
2276  if (arg->m_type == QVariant::String && !sep.isEmpty())
2277  val = varval.toString().split(sep);
2278  else if (varval.canConvert(QVariant::StringList))
2279  val = varval.toStringList();
2280 
2281  return val;
2282 }
2283 
2287 QMap<QString,QString> MythCommandLineParser::toMap(const QString& key) const
2288 {
2289  QMap<QString, QString> val;
2290  QMap<QString, QVariant> tmp;
2291  if (!m_namedArgs.contains(key))
2292  return val;
2293 
2294  CommandLineArg *arg = m_namedArgs[key];
2295  if (arg == nullptr)
2296  return val;
2297 
2298  if (arg->m_given)
2299  {
2300  if (!arg->m_converted)
2301  arg->Convert();
2302 
2303  if (arg->m_stored.canConvert(QVariant::Map))
2304  tmp = arg->m_stored.toMap();
2305  }
2306  else
2307  {
2308  if (arg->m_default.canConvert(QVariant::Map))
2309  tmp = arg->m_default.toMap();
2310  }
2311 
2312  for (auto i = tmp.cbegin(); i != tmp.cend(); ++i)
2313  val[i.key()] = i.value().toString();
2314 
2315  return val;
2316 }
2317 
2321 QDateTime MythCommandLineParser::toDateTime(const QString& key) const
2322 {
2323  QDateTime val;
2324  if (!m_namedArgs.contains(key))
2325  return val;
2326 
2327  CommandLineArg *arg = m_namedArgs[key];
2328  if (arg == nullptr)
2329  return val;
2330 
2331  if (arg->m_given)
2332  {
2333  if (arg->m_stored.canConvert(QVariant::DateTime))
2334  val = arg->m_stored.toDateTime();
2335  }
2336  else
2337  {
2338  if (arg->m_default.canConvert(QVariant::DateTime))
2339  val = arg->m_default.toDateTime();
2340  }
2341 
2342  return val;
2343 }
2344 
2349 {
2350  if (m_namedArgs.contains("_args"))
2351  {
2352  if (!allow)
2353  m_namedArgs.remove("_args");
2354  }
2355  else if (!allow)
2356  return;
2357 
2358  auto *arg = new CommandLineArg("_args", QVariant::StringList, QStringList());
2359  m_namedArgs["_args"] = arg;
2360 }
2361 
2366 {
2367  if (m_namedArgs.contains("_extra"))
2368  {
2369  if (!allow)
2370  m_namedArgs.remove("_extra");
2371  }
2372  else if (!allow)
2373  return;
2374 
2375  QMap<QString,QVariant> vmap;
2376  auto *arg = new CommandLineArg("_extra", QVariant::Map, vmap);
2377 
2378  m_namedArgs["_extra"] = arg;
2379 }
2380 
2385 {
2386  if (m_namedArgs.contains("_passthrough"))
2387  {
2388  if (!allow)
2389  m_namedArgs.remove("_passthrough");
2390  }
2391  else if (!allow)
2392  return;
2393 
2394  auto *arg = new CommandLineArg("_passthrough",
2395  QVariant::StringList, QStringList());
2396  m_namedArgs["_passthrough"] = arg;
2397 }
2398 
2402 {
2403  add(QStringList{"-h", "--help", "--usage"},
2404  "showhelp", "", "Display this help printout, or give detailed "
2405  "information of selected option.",
2406  "Displays a list of all commands available for use with "
2407  "this application. If another option is provided as an "
2408  "argument, it will provide detailed information on that "
2409  "option.");
2410 }
2411 
2415 {
2416  add("--version", "showversion", false, "Display version information.",
2417  "Display informtion about build, including:\n"
2418  " version, branch, protocol, library API, Qt "
2419  "and compiled options.");
2420 }
2421 
2425 {
2426  add(QStringList{"-nw", "--no-windowed"},
2427  "notwindowed", false,
2428  "Prevent application from running in a window.", "")
2429  ->SetBlocks("windowed")
2430  ->SetGroup("User Interface");
2431 
2432  add(QStringList{"-w", "--windowed"}, "windowed",
2433  false, "Force application to run in a window.", "")
2434  ->SetGroup("User Interface");
2435 }
2436 
2440 {
2441  add("--mouse-cursor", "mousecursor", false,
2442  "Force visibility of the mouse cursor.", "")
2443  ->SetBlocks("nomousecursor")
2444  ->SetGroup("User Interface");
2445 
2446  add("--no-mouse-cursor", "nomousecursor", false,
2447  "Force the mouse cursor to be hidden.", "")
2448  ->SetGroup("User Interface");
2449 }
2450 
2454 {
2455  add(QStringList{"-d", "--daemon"}, "daemon", false,
2456  "Fork application into background after startup.",
2457  "Fork application into background, detatching from "
2458  "the local terminal.\nOften used with: "
2459  " --logpath --pidfile --user");
2460 }
2461 
2466 {
2467  add(QStringList{"-O", "--override-setting"},
2468  "overridesettings", QVariant::Map,
2469  "Override a single setting defined by a key=value pair.",
2470  "Override a single setting from the database using "
2471  "options defined as one or more key=value pairs\n"
2472  "Multiple can be defined by multiple uses of the "
2473  "-O option.");
2474  add("--override-settings-file", "overridesettingsfile", "",
2475  "Define a file of key=value pairs to be "
2476  "loaded for setting overrides.", "");
2477 }
2478 
2482 {
2483  add("--chanid", "chanid", 0U,
2484  "Specify chanid of recording to operate on.", "")
2485  ->SetRequires("starttime");
2486 
2487  add("--starttime", "starttime", QDateTime(),
2488  "Specify start time of recording to operate on.", "")
2489  ->SetRequires("chanid");
2490 }
2491 
2495 {
2496  add(QStringList{"-geometry", "--geometry"}, "geometry",
2497  "", "Specify window size and position (WxH[+X+Y])", "")
2498  ->SetGroup("User Interface");
2499 }
2500 
2504 {
2505  add("--noupnp", "noupnp", false, "Disable use of UPnP.", "");
2506 }
2507 
2511 {
2512  add("--dvbv3", "dvbv3", false, "Use legacy DVBv3 API.", "");
2513 }
2514 
2519  const QString &defaultVerbosity, LogLevel_t defaultLogLevel)
2520 {
2521  defaultLogLevel =
2522  ((defaultLogLevel >= LOG_UNKNOWN) || (defaultLogLevel <= LOG_ANY)) ?
2523  LOG_INFO : defaultLogLevel;
2524 
2525  QString logLevelStr = logLevelGetName(defaultLogLevel);
2526 
2527  add(QStringList{"-v", "--verbose"}, "verbose",
2528  defaultVerbosity,
2529  "Specify log filtering. Use '-v help' for level info.", "")
2530  ->SetGroup("Logging");
2531  add("-V", "verboseint", 0LL, "",
2532  "This option is intended for internal use only.\n"
2533  "This option takes an unsigned value corresponding "
2534  "to the bitwise log verbosity operator.")
2535  ->SetGroup("Logging");
2536  add("--logpath", "logpath", "",
2537  "Writes logging messages to a file in the directory logpath with "
2538  "filenames in the format: applicationName.date.pid.log.\n"
2539  "This is typically used in combination with --daemon, and if used "
2540  "in combination with --pidfile, this can be used with log "
2541  "rotators, using the HUP call to inform MythTV to reload the "
2542  "file", "")
2543  ->SetGroup("Logging");
2544  add(QStringList{"-q", "--quiet"}, "quiet", 0,
2545  "Don't log to the console (-q). Don't log anywhere (-q -q)", "")
2546  ->SetGroup("Logging");
2547  add("--loglevel", "loglevel", logLevelStr,
2548  QString(
2549  "Set the logging level. All log messages at lower levels will be "
2550  "discarded.\n"
2551  "In descending order: emerg, alert, crit, err, warning, notice, "
2552  "info, debug\ndefaults to ") + logLevelStr, "")
2553  ->SetGroup("Logging");
2554  add("--syslog", "syslog", "none",
2555  "Set the syslog logging facility.\nSet to \"none\" to disable, "
2556  "defaults to none.", "")
2557  ->SetGroup("Logging");
2558 #if CONFIG_SYSTEMD_JOURNAL
2559  add("--systemd-journal", "systemd-journal", "false",
2560  "Use systemd-journal instead of syslog.", "")
2561  ->SetBlocks(QStringList()
2562  << "syslog"
2563  )
2564  ->SetGroup("Logging");
2565 #endif
2566  add("--nodblog", "nodblog", false, "Disable database logging.", "")
2567  ->SetGroup("Logging")
2568  ->SetDeprecated("this is now the default, see --enable-dblog");
2569  add("--enable-dblog", "enabledblog", false, "Enable logging to database.", "")
2570  ->SetGroup("Logging");
2571 
2572  add(QStringList{"-l", "--logfile"},
2573  "logfile", "", "", "")
2574  ->SetGroup("Logging")
2575  ->SetRemoved("This option has been removed as part of "
2576  "rewrite of the logging interface. Please update your init "
2577  "scripts to use --syslog to interface with your system's "
2578  "existing system logging daemon, or --logpath to specify a "
2579  "dirctory for MythTV to write its logs to.", "0.25");
2580 }
2581 
2585 {
2586  add(QStringList{"-p", "--pidfile"}, "pidfile", "",
2587  "Write PID of application to filename.",
2588  "Write the PID of the currently running process as a single "
2589  "line to this file. Used for init scripts to know what "
2590  "process to terminate, and with log rotators "
2591  "to send a HUP signal to process to have it re-open files.");
2592 }
2593 
2597 {
2598  add(QStringList{"-j", "--jobid"}, "jobid", 0, "",
2599  "Intended for internal use only, specify the JobID to match "
2600  "up with in the database for additional information and the "
2601  "ability to update runtime status in the database.");
2602 }
2603 
2607 {
2608  add("--infile", "infile", "", "Input file URI", "");
2609  if (addOutFile)
2610  add("--outfile", "outfile", "", "Output file URI", "");
2611 }
2612 
2616 {
2617 #ifdef USING_X11
2618  add(QStringList{"-display", "--display"}, "display", "",
2619  "Qt (QPA) X11 connection name when using xcb (X11) platform plugin", "")
2620  ->SetGroup("Qt");
2621 #endif
2622 }
2623 
2627 {
2628  add(QStringList{"-platform", "--platform"}, "platform", "", "Qt (QPA) platform argument",
2629  "Qt platform argument that is passed through to Qt")
2630  ->SetGroup("Qt");
2631 }
2632 
2636 {
2637  QString logfile = toString("logpath");
2638  pid_t pid = getpid();
2639 
2640  if (logfile.isEmpty())
2641  return logfile;
2642 
2643  QFileInfo finfo(logfile);
2644  if (!finfo.isDir())
2645  {
2646  LOG(VB_GENERAL, LOG_ERR,
2647  QString("%1 is not a directory, disabling logfiles")
2648  .arg(logfile));
2649  return QString();
2650  }
2651 
2652  QString logdir = finfo.filePath();
2653  logfile = QCoreApplication::applicationName() + "." +
2655  QString(".%1").arg(pid) + ".log";
2656 
2657  SetValue("logdir", logdir);
2658  SetValue("logfile", logfile);
2659  SetValue("filepath", QFileInfo(QDir(logdir), logfile).filePath());
2660 
2661  return toString("filepath");
2662 }
2663 
2667 {
2668  QString setting = toString("syslog").toLower();
2669  if (setting == "none")
2670  return -2;
2671 
2672  return syslogGetFacility(setting);
2673 }
2674 
2678 {
2679  QString setting = toString("loglevel");
2680  if (setting.isEmpty())
2681  return LOG_INFO;
2682 
2683  LogLevel_t level = logLevelGet(setting);
2684  if (level == LOG_UNKNOWN)
2685  std::cerr << "Unknown log level: " << setting.toLocal8Bit().constData()
2686  << std::endl;
2687 
2688  return level;
2689 }
2690 
2695 bool MythCommandLineParser::SetValue(const QString &key, const QVariant& value)
2696 {
2697  CommandLineArg *arg = nullptr;
2698 
2699  if (!m_namedArgs.contains(key))
2700  {
2701  const QVariant& val(value);
2702  arg = new CommandLineArg(key, val.type(), val);
2703  m_namedArgs.insert(key, arg);
2704  }
2705  else
2706  {
2707  arg = m_namedArgs[key];
2708  if (arg->m_type != value.type())
2709  return false;
2710  }
2711 
2712  arg->Set(value);
2713  return true;
2714 }
2715 
2719 {
2720  int err = 0;
2721 
2722  // Setup the defaults
2723  verboseString = "";
2724  verboseMask = 0;
2725  verboseArgParse(mask);
2726 
2727  if (toBool("verbose"))
2728  {
2729  if ((err = verboseArgParse(toString("verbose"))) != 0)
2730  return err;
2731  }
2732  else if (toBool("verboseint"))
2733  verboseMask = static_cast<uint64_t>(toLongLong("verboseint"));
2734 
2735  verboseMask |= VB_STDIO|VB_FLUSH;
2736 
2737  int quiet = toInt("quiet");
2738  if (std::max(quiet, static_cast<int>(progress)) > 1)
2739  {
2740  verboseMask = VB_NONE|VB_FLUSH;
2741  verboseArgParse("none");
2742  }
2743 
2744  int facility = GetSyslogFacility();
2745 #if CONFIG_SYSTEMD_JOURNAL
2746  bool journal = toBool("systemd-journal");
2747  if (journal)
2748  {
2749  if (facility >= 0)
2751  facility = SYSTEMD_JOURNAL_FACILITY;
2752  }
2753 #endif
2754  bool dblog = toBool("enabledblog");
2755  LogLevel_t level = GetLogLevel();
2756  if (level == LOG_UNKNOWN)
2758 
2759  LOG(VB_GENERAL, LOG_CRIT,
2760  QString("%1 version: %2 [%3] www.mythtv.org")
2761  .arg(QCoreApplication::applicationName())
2763  LOG(VB_GENERAL, LOG_CRIT, QString("Qt version: compile: %1, runtime: %2")
2764  .arg(QT_VERSION_STR).arg(qVersion()));
2765  LOG(VB_GENERAL, LOG_INFO, QString("%1 (%2)")
2766  .arg(QSysInfo::prettyProductName()).arg(QSysInfo::currentCpuArchitecture()));
2767  LOG(VB_GENERAL, LOG_NOTICE,
2768  QString("Enabled verbose msgs: %1").arg(verboseString));
2769 
2770  QString logfile = GetLogFilePath();
2771  bool propagate = !logfile.isEmpty();
2772 
2773  if (toBool("daemon"))
2774  quiet = std::max(quiet, 1);
2775 
2776  logStart(logfile, progress, quiet, facility, level, dblog, propagate);
2777  qInstallMessageHandler([](QtMsgType /*unused*/, const QMessageLogContext& /*unused*/, const QString &Msg)
2778  { LOG(VB_GENERAL, LOG_INFO, "Qt: " + Msg); });
2779 
2780  return GENERIC_EXIT_OK;
2781 }
2782 
2788 {
2789  if (m_verbose)
2790  std::cerr << "Applying settings override" << std::endl;
2791 
2792  QMap<QString, QString> override = GetSettingsOverride();
2793  if (!override.empty())
2794  {
2795  QMap<QString, QString>::iterator it;
2796  for (it = override.begin(); it != override.end(); ++it)
2797  {
2798  LOG(VB_GENERAL, LOG_NOTICE,
2799  QString("Setting '%1' being forced to '%2'")
2800  .arg(it.key()).arg(*it));
2801  gCoreContext->OverrideSettingForSession(it.key(), *it);
2802  }
2803  }
2804 }
2805 
2806 bool openPidfile(std::ofstream &pidfs, const QString &pidfile)
2807 {
2808  if (!pidfile.isEmpty())
2809  {
2810  pidfs.open(pidfile.toLatin1().constData());
2811  if (!pidfs)
2812  {
2813  std::cerr << "Could not open pid file: " << ENO_STR << std::endl;
2814  return false;
2815  }
2816  }
2817  return true;
2818 }
2819 
2822 bool setUser(const QString &username)
2823 {
2824  if (username.isEmpty())
2825  return true;
2826 
2827 #ifdef _WIN32
2828  cerr << "--user option is not supported on Windows" << endl;
2829  return false;
2830 #else // ! _WIN32
2831 #if defined(__linux__) || defined(__LINUX__)
2832  // Check the current dumpability of core dumps, which will be disabled
2833  // by setuid, so we can re-enable, if appropriate
2834  int dumpability = prctl(PR_GET_DUMPABLE);
2835 #endif
2836  struct passwd *user_info = getpwnam(username.toLocal8Bit().constData());
2837  const uid_t user_id = geteuid();
2838 
2839  if (user_id && (!user_info || user_id != user_info->pw_uid))
2840  {
2841  std::cerr << "You must be running as root to use the --user switch." << std::endl;
2842  return false;
2843  }
2844  if (user_info && user_id == user_info->pw_uid)
2845  {
2846  LOG(VB_GENERAL, LOG_WARNING,
2847  QString("Already running as '%1'").arg(username));
2848  }
2849  else if (!user_id && user_info)
2850  {
2851  if (setenv("HOME", user_info->pw_dir,1) == -1)
2852  {
2853  std::cerr << "Error setting home directory." << std::endl;
2854  return false;
2855  }
2856  if (setgid(user_info->pw_gid) == -1)
2857  {
2858  std::cerr << "Error setting effective group." << std::endl;
2859  return false;
2860  }
2861  if (initgroups(user_info->pw_name, user_info->pw_gid) == -1)
2862  {
2863  std::cerr << "Error setting groups." << std::endl;
2864  return false;
2865  }
2866  if (setuid(user_info->pw_uid) == -1)
2867  {
2868  std::cerr << "Error setting effective user." << std::endl;
2869  return false;
2870  }
2871 #if defined(__linux__) || defined(__LINUX__)
2872  if (dumpability && (prctl(PR_SET_DUMPABLE, dumpability) == -1))
2873  {
2874  LOG(VB_GENERAL, LOG_WARNING, "Unable to re-enable core file "
2875  "creation. Run without the --user argument to use "
2876  "shell-specified limits.");
2877  }
2878 #endif
2879  }
2880  else
2881  {
2882  std::cerr << QString("Invalid user '%1' specified with --user")
2883  .arg(username).toLocal8Bit().constData() << std::endl;
2884  return false;
2885  }
2886  return true;
2887 #endif // ! _WIN32
2888 }
2889 
2890 
2894 {
2895  std::ofstream pidfs;
2896  if (!openPidfile(pidfs, toString("pidfile")))
2898 
2899  if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
2900  LOG(VB_GENERAL, LOG_WARNING, "Unable to ignore SIGPIPE");
2901 
2902 #if CONFIG_DARWIN
2903  if (toBool("daemon"))
2904  {
2905  std::cerr << "Daemonizing is unavailable in OSX" << std::endl;
2906  LOG(VB_GENERAL, LOG_WARNING, "Unable to daemonize");
2907  }
2908 #else
2909  if (toBool("daemon") && (daemon(0, 1) < 0))
2910  {
2911  std::cerr << "Failed to daemonize: " << ENO_STR << std::endl;
2913  }
2914 #endif
2915 
2916  QString username = toString("username");
2917  if (!username.isEmpty() && !setUser(username))
2919 
2920  if (pidfs)
2921  {
2922  pidfs << getpid() << std::endl;
2923  pidfs.close();
2924  }
2925 
2926  return GENERIC_EXIT_OK;
2927 }
force
bool force
Definition: mythtv/programs/mythcommflag/main.cpp:74
MythCommandLineParser::addDisplay
void addDisplay(void)
Canned argument definition for -display.
Definition: mythcommandlineparser.cpp:2615
MythCommandLineParser::addGeometry
void addGeometry(void)
Canned argument definition for –geometry.
Definition: mythcommandlineparser.cpp:2494
setuid
#define setuid(x)
Definition: compat.h:264
strip_quotes
QByteArray strip_quotes(QByteArray val)
Definition: mythcommandlineparser.cpp:105
build_compdb.args
args
Definition: build_compdb.py:11
MythDate::toString
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:80
MythCommandLineParser::Result
Result
Definition: mythcommandlineparser.h:121
CommandLineArg::SetChild
CommandLineArg * SetChild(const QString &opt)
Set argument as parent of given child.
Definition: mythcommandlineparser.cpp:607
GENERIC_EXIT_OK
#define GENERIC_EXIT_OK
Exited with no error.
Definition: exitcodes.h:10
CommandLineArg::SetParent
CommandLineArg * SetParent(const QString &opt)
Set argument as child of given parent.
Definition: mythcommandlineparser.cpp:573
MythCommandLineParser::m_appname
QString m_appname
Definition: mythcommandlineparser.h:269
MythCommandLineParser::operator[]
QVariant operator[](const QString &name)
Returned stored QVariant for given argument, or default value if not used.
Definition: mythcommandlineparser.cpp:1937
MythCommandLineParser::allowPassthrough
void allowPassthrough(bool allow=true)
Specify that parser should allow a bare '–', and collect all subsequent text as a QString.
Definition: mythcommandlineparser.cpp:2384
CommandLineArg::AllowOneOf
static void AllowOneOf(const QList< CommandLineArg * > &args)
Mark a list of arguments as mutually exclusive.
Definition: mythcommandlineparser.cpp:834
MythCommandLineParser::toMap
QMap< QString, QString > toMap(const QString &key) const
Returns stored QVariant as a QMap, falling to default if not provided.
Definition: mythcommandlineparser.cpp:2287
MythCommandLineParser::Result::kOptVal
@ kOptVal
CommandLineArg::GetKeywordLength
int GetKeywordLength(void) const
Return length of full keyword string for use in determining indent of help text.
Definition: mythcommandlineparser.cpp:234
MythCommandLineParser::m_verbose
bool m_verbose
Definition: mythcommandlineparser.h:274
CommandLineArg::m_keywords
QStringList m_keywords
Definition: mythcommandlineparser.h:103
MythCommandLineParser::Result::kEmpty
@ kEmpty
CommandLineArg::GetHelpString
QString GetHelpString(int off, const QString &group="", bool force=false) const
Return string containing help text with desired offset.
Definition: mythcommandlineparser.cpp:260
MythCommandLineParser::addPlatform
void addPlatform(void)
Pass through the platform argument to Qt for GUI applications.
Definition: mythcommandlineparser.cpp:2626
MythCommandLineParser::~MythCommandLineParser
virtual ~MythCommandLineParser()
Definition: mythcommandlineparser.cpp:1175
MythCommandLineParser::Result::kPassthrough
@ kPassthrough
MythCoreContext::OverrideSettingForSession
void OverrideSettingForSession(const QString &key, const QString &value)
Definition: mythcorecontext.cpp:1346
MythCommandLineParser::toDouble
double toDouble(const QString &key) const
Returns stored QVariant as double floating point value, falling to default if not provided.
Definition: mythcommandlineparser.cpp:2170
progress
bool progress
Definition: mythtv/programs/mythcommflag/main.cpp:73
CommandLineArg::m_removedversion
QString m_removedversion
Definition: mythcommandlineparser.h:98
MythCommandLineParser::addPIDFile
void addPIDFile(void)
Canned argument definition for –pidfile.
Definition: mythcommandlineparser.cpp:2584
CommandLineArg::PrintVerbose
void PrintVerbose(void) const
Internal use.
Definition: mythcommandlineparser.cpp:1034
logStart
void logStart(const QString &logfile, bool progress, int quiet, int facility, LogLevel_t level, bool dblog, bool propagate, bool testHarness)
Entry point to start logging for the application.
Definition: logging.cpp:700
syslogGetFacility
int syslogGetFacility(const QString &facility)
Map a syslog facility name back to the enumerated value.
Definition: logging.cpp:787
setenv
#define setenv(x, y, z)
Definition: compat.h:158
MythCommandLineParser::addVersion
void addVersion(void)
Canned argument definition for –version.
Definition: mythcommandlineparser.cpp:2414
arg
arg(title).arg(filename).arg(doDelete))
CommandLineArg::m_removed
QString m_removed
Definition: mythcommandlineparser.h:97
CommandLineArg::SetRequires
CommandLineArg * SetRequires(const QString &opt)
Set argument as requiring given option.
Definition: mythcommandlineparser.cpp:666
MythCommandLineParser::ReconcileLinks
bool ReconcileLinks(void)
Replace dummy arguments used to define interdependency with pointers to their real counterparts.
Definition: mythcommandlineparser.cpp:1780
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
CommandLineArg::m_default
QVariant m_default
Definition: mythcommandlineparser.h:100
MythCommandLineParser::m_overridesImported
bool m_overridesImported
Definition: mythcommandlineparser.h:273
MythCommandLineParser::addWindowed
void addWindowed(void)
Canned argument definition for –windowed and -no-windowed.
Definition: mythcommandlineparser.cpp:2424
GENERIC_EXIT_INVALID_CMDLINE
#define GENERIC_EXIT_INVALID_CMDLINE
Command line parse error.
Definition: exitcodes.h:15
CommandLineArg::SetRequiredChild
CommandLineArg * SetRequiredChild(const QString &opt)
Set argument as parent of given child and mark as required.
Definition: mythcommandlineparser.cpp:624
MythCommandLineParser::m_optionedArgs
QMap< QString, CommandLineArg * > m_optionedArgs
Definition: mythcommandlineparser.h:270
MythCommandLineParser::m_namedArgs
QMap< QString, CommandLineArg * > m_namedArgs
Definition: mythcommandlineparser.h:271
MythCommandLineParser::GetHelpString
QString GetHelpString(void) const
Generate command line option help text.
Definition: mythcommandlineparser.cpp:1290
CommandLineArg::m_parents
QList< CommandLineArg * > m_parents
Definition: mythcommandlineparser.h:106
MythCommandLineParser::addRecording
void addRecording(void)
Canned argument definition for –chanid and –starttime.
Definition: mythcommandlineparser.cpp:2481
MythDate::current
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:10
MythCommandLineParser::Result::kArg
@ kArg
openPidfile
bool openPidfile(std::ofstream &pidfs, const QString &pidfile)
Definition: mythcommandlineparser.cpp:2806
tmp
static guint32 * tmp
Definition: goom_core.cpp:31
MythCommandLineParser::addLogging
void addLogging(const QString &defaultVerbosity="general", LogLevel_t defaultLogLevel=LOG_INFO)
Canned argument definition for all logging options, including –verbose, –logpath, –quiet,...
Definition: mythcommandlineparser.cpp:2518
mythversion.h
CommandLineArg::GetLongHelpString
QString GetLongHelpString(QString keyword) const
Return string containing extended help text.
Definition: mythcommandlineparser.cpp:334
CommandLineArg::SetRemoved
CommandLineArg * SetRemoved(QString remstr="", QString remver="")
Set option as removed.
Definition: mythcommandlineparser.cpp:710
CommandLineArg::m_stored
QVariant m_stored
Definition: mythcommandlineparser.h:101
CommandLineArg::SetParentOf
CommandLineArg * SetParentOf(const QString &opt)
Set argument as parent of given child.
Definition: mythcommandlineparser.cpp:556
CommandLineArg::m_blocks
QList< CommandLineArg * > m_blocks
Definition: mythcommandlineparser.h:110
verboseString
QString verboseString
Definition: logging.cpp:102
CommandLineArg::SetChildOf
CommandLineArg * SetChildOf(const QString &opt)
Set argument as child of given parent.
Definition: mythcommandlineparser.cpp:590
MythCommandLineParser::Parse
virtual bool Parse(int argc, const char *const *argv)
Loop through argv and populate arguments with values.
Definition: mythcommandlineparser.cpp:1435
MythCommandLineParser::add
CommandLineArg * add(const QString &arg, const QString &name, bool def, QString help, QString longhelp)
Definition: mythcommandlineparser.cpp:1651
wrapList
void wrapList(QStringList &list, int width)
Definition: mythmiscutil.cpp:961
mythdate.h
CommandLineArg::m_given
bool m_given
Definition: mythcommandlineparser.h:92
MythCommandLineParser::addMouse
void addMouse(void)
Canned argument definition for –mouse-cursor and –no-mouse-cursor.
Definition: mythcommandlineparser.cpp:2439
mythlogging.h
logLevelGetName
QString logLevelGetName(LogLevel_t level)
Map a log level enumerated value back to the name.
Definition: logging.cpp:837
CommandLineArg::m_deprecated
QString m_deprecated
Definition: mythcommandlineparser.h:96
MythDate::kFilename
@ kFilename
Default UTC, "yyyyMMddhhmmss".
Definition: mythdate.h:15
MythCommandLineParser::getOpt
Result getOpt(int argc, const char *const *argv, int &argpos, QString &opt, QByteArray &val)
Internal use.
Definition: mythcommandlineparser.cpp:1354
setUser
bool setUser(const QString &username)
Drop permissions to the specified user.
Definition: mythcommandlineparser.cpp:2822
MythCommandLineParser::Result::kInvalid
@ kInvalid
logfile
QString logfile
Definition: backendcontext.cpp:14
verboseMask
uint64_t verboseMask
Definition: logging.cpp:101
daemon
#define daemon(x, y)
Definition: compat.h:323
CommandLineArg::m_longhelp
QString m_longhelp
Definition: mythcommandlineparser.h:113
CommandLineArg::m_help
QString m_help
Definition: mythcommandlineparser.h:112
MythCommandLineParser::MythCommandLineParser
MythCommandLineParser(QString appname)
Default constructor for MythCommandLineArg class.
Definition: mythcommandlineparser.cpp:1163
logLevelGet
LogLevel_t logLevelGet(const QString &level)
Map a log level name back to the enumerated value.
Definition: logging.cpp:815
ENO_STR
#define ENO_STR
Definition: mythlogging.h:73
CommandLineArg::SetRequiredChildOf
CommandLineArg * SetRequiredChildOf(const QString &opt)
Set argument as child required by given parent.
Definition: mythcommandlineparser.cpp:645
CommandLineArg::Set
bool Set(const QString &opt)
Set option as provided on command line with no value.
Definition: mythcommandlineparser.cpp:440
MythCommandLineParser::GetArgs
QStringList GetArgs(void) const
Return list of additional values provided on the command line independent of any keyword.
Definition: mythcommandlineparser.cpp:1956
MythCommandLineParser::m_passthroughActive
bool m_passthroughActive
Definition: mythcommandlineparser.h:272
SIGPIPE
#define SIGPIPE
Definition: compat.h:220
MythCommandLineParser::PrintVersion
static void PrintVersion(void)
Print application version information.
Definition: mythcommandlineparser.cpp:1263
CommandLineArg::GetName
QString GetName(void) const
Definition: mythcommandlineparser.h:34
filename
QString filename
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:637
MythCommandLineParser::GetExtra
QMap< QString, QString > GetExtra(void) const
Return map of additional key/value pairs provided on the command line independent of any registered a...
Definition: mythcommandlineparser.cpp:1964
CommandLineArg::PrintDeprecatedWarning
void PrintDeprecatedWarning(QString &keyword) const
Internal use.
Definition: mythcommandlineparser.cpp:1140
CommandLineArg::m_type
QVariant::Type m_type
Definition: mythcommandlineparser.h:99
MythCommandLineParser::toUInt
uint toUInt(const QString &key) const
Returns stored QVariant as an unsigned integer, falling to default if not provided.
Definition: mythcommandlineparser.cpp:2116
CommandLineArg::m_requires
QList< CommandLineArg * > m_requires
Definition: mythcommandlineparser.h:108
f
QTextStream t & f
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:603
MythCommandLineParser::PrintHelp
void PrintHelp(void) const
Print command line option help.
Definition: mythcommandlineparser.cpp:1279
MythCommandLineParser::Daemonize
int Daemonize(void) const
Fork application into background, and detatch from terminal.
Definition: mythcommandlineparser.cpp:2893
quiet
int quiet
Definition: mythtv/programs/mythcommflag/main.cpp:72
uint
unsigned int uint
Definition: compat.h:141
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:60
pidfile
QString pidfile
Definition: backendcontext.cpp:13
GENERIC_EXIT_PERMISSIONS_ERROR
#define GENERIC_EXIT_PERMISSIONS_ERROR
File permissions error.
Definition: exitcodes.h:19
MythCommandLineParser::GetSyslogFacility
int GetSyslogFacility(void) const
Helper utility for logging interface to return syslog facility.
Definition: mythcommandlineparser.cpp:2666
MythCommandLineParser::ApplySettingsOverride
void ApplySettingsOverride(void)
Apply all overrides to the global context.
Definition: mythcommandlineparser.cpp:2787
QT_ENDL
#define QT_ENDL
Definition: mythcommandlineparser.cpp:68
MythCommandLineParser::GetSettingsOverride
QMap< QString, QString > GetSettingsOverride(void)
Return map of key/value pairs provided to override database options.
Definition: mythcommandlineparser.cpp:1983
CommandLineArg::GetPreferredKeyword
QString GetPreferredKeyword(void) const
Return the longest keyword for the argument.
Definition: mythcommandlineparser.cpp:919
GetMythSourcePath
const char * GetMythSourcePath()
Definition: mythcoreutil.cpp:318
CommandLineArg::TestLinks
bool TestLinks(void) const
Test all related arguments to make sure specified requirements are fulfilled.
Definition: mythcommandlineparser.cpp:941
CommandLineArg::SetBlocks
CommandLineArg * SetBlocks(const QString &opt)
Set argument as incompatible with given option.
Definition: mythcommandlineparser.cpp:683
MythDate::fromString
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
Definition: mythdate.cpp:30
nv_python_libs.vimeo.vimeo_api.user_info
def user_info(user, format="xml")
Definition: vimeo_api.py:515
verboseArgParse
int verboseArgParse(const QString &arg)
Parse the –verbose commandline argument and set the verbose level.
Definition: logging.cpp:963
CommandLineArg::CleanupLinks
void CleanupLinks(void)
Clear out references to other arguments in preparation for deletion.
Definition: mythcommandlineparser.cpp:1013
TERMWIDTH
#define TERMWIDTH
Definition: mythcommandlineparser.cpp:81
CommandLineArg::m_usedKeyword
QString m_usedKeyword
Definition: mythcommandlineparser.h:104
MYTH_BINARY_VERSION
#define MYTH_BINARY_VERSION
Update this whenever the plug-in ABI changes.
Definition: mythversion.h:15
CommandLineArg::PrintRemovedWarning
void PrintRemovedWarning(QString &keyword) const
Internal use.
Definition: mythcommandlineparser.cpp:1124
MythCommandLineParser::allowArgs
void allowArgs(bool allow=true)
Specify that parser should allow and collect values provided independent of any keyword.
Definition: mythcommandlineparser.cpp:2348
MYTH_PROTO_VERSION
#define MYTH_PROTO_VERSION
Increment this whenever the MythTV network protocol changes.
Definition: mythversion.h:47
CommandLineArg::m_requiredby
QList< CommandLineArg * > m_requiredby
Definition: mythcommandlineparser.h:109
mythmiscutil.h
MythCommandLineParser::toString
QString toString(const QString &key) const
Returns stored QVariant as a QString, falling to default if not provided.
Definition: mythcommandlineparser.cpp:2224
CommandLineArg::m_group
QString m_group
Definition: mythcommandlineparser.h:95
CommandLineArg::m_name
QString m_name
Definition: mythcommandlineparser.h:94
mythcorecontext.h
MythCommandLineParser::addHelp
void addHelp(void)
Canned argument definition for –help.
Definition: mythcommandlineparser.cpp:2401
MythCommandLineParser::SetValue
bool SetValue(const QString &key, const QVariant &value)
Set a new stored value for an existing argument definition, or spawn a new definition store value in.
Definition: mythcommandlineparser.cpp:2695
MythCommandLineParser::toBool
bool toBool(const QString &key) const
Returns stored QVariant as a boolean.
Definition: mythcommandlineparser.cpp:2067
MythCommandLineParser::GetLogLevel
LogLevel_t GetLogLevel(void) const
Helper utility for logging interface to filtering level.
Definition: mythcommandlineparser.cpp:2677
CommandLineArg
Definition for a single command line option.
Definition: mythcommandlineparser.h:21
MythCommandLineParser::toLongLong
long long toLongLong(const QString &key) const
Returns stored QVariant as a long integer, falling to default if not provided.
Definition: mythcommandlineparser.cpp:2143
MythDate::ISODate
@ ISODate
Default UTC.
Definition: mythdate.h:14
MythCommandLineParser::toStringList
QStringList toStringList(const QString &key, const QString &sep="") const
Returns stored QVariant as a QStringList, falling to default if not provided.
Definition: mythcommandlineparser.cpp:2255
MythCommandLineParser::NamedOptType
static const char * NamedOptType(Result type)
Definition: mythcommandlineparser.cpp:117
logging.h
CommandLineArg::SetGroup
CommandLineArg * SetGroup(const QString &group)
Definition: mythcommandlineparser.h:30
MythCommandLineParser::Result::kOptOnly
@ kOptOnly
build_compdb.help
help
Definition: build_compdb.py:10
MythCommandLineParser::addJob
void addJob(void)
Canned argument definition for –jobid.
Definition: mythcommandlineparser.cpp:2596
GENERIC_EXIT_DAEMONIZING_ERROR
#define GENERIC_EXIT_DAEMONIZING_ERROR
Error daemonizing or execl.
Definition: exitcodes.h:28
MythCommandLineParser::toSize
QSize toSize(const QString &key) const
Returns stored QVariant as a QSize value, falling to default if not provided.
Definition: mythcommandlineparser.cpp:2197
MythCommandLineParser::GetLogFilePath
QString GetLogFilePath(void)
Helper utility for logging interface to pull path from –logpath.
Definition: mythcommandlineparser.cpp:2635
GetMythSourceVersion
const char * GetMythSourceVersion()
Definition: mythcoreutil.cpp:313
CommandLineArg::m_converted
bool m_converted
Definition: mythcommandlineparser.h:93
MythCommandLineParser::ConfigureLogging
int ConfigureLogging(const QString &mask="general", bool progress=false)
Read in logging options and initialize the logging interface.
Definition: mythcommandlineparser.cpp:2718
MythCommandLineParser::addSettingsOverride
void addSettingsOverride(void)
Canned argument definition for –override-setting and –override-settings-file.
Definition: mythcommandlineparser.cpp:2465
CommandLineArg::SetDeprecated
CommandLineArg * SetDeprecated(QString depstr="")
Set option as deprecated.
Definition: mythcommandlineparser.cpp:700
MythCommandLineParser::GetHelpHeader
virtual QString GetHelpHeader(void) const
Definition: mythcommandlineparser.h:139
MythCommandLineParser::LoadArguments
virtual void LoadArguments(void)
Definition: mythcommandlineparser.h:135
CommandLineArg::CommandLineArg
CommandLineArg(const QString &name, QVariant::Type type, QVariant def, QString help, QString longhelp)
Default constructor for CommandLineArg class.
Definition: mythcommandlineparser.cpp:182
MythCommandLineParser::allowExtras
void allowExtras(bool allow=true)
Specify that parser should allow and collect additional key/value pairs not explicitly defined for pr...
Definition: mythcommandlineparser.cpp:2365
MythCommandLineParser::addUPnP
void addUPnP(void)
Canned argument definition for –noupnp.
Definition: mythcommandlineparser.cpp:2503
MythCommandLineParser::addDaemon
void addDaemon(void)
Canned argument definition for –daemon.
Definition: mythcommandlineparser.cpp:2453
geteuid
#define geteuid()
Definition: compat.h:263
exitcodes.h
MythCommandLineParser::toInt
int toInt(const QString &key) const
Returns stored QVariant as an integer, falling to default if not provided.
Definition: mythcommandlineparser.cpp:2089
CommandLineArg::m_children
QList< CommandLineArg * > m_children
Definition: mythcommandlineparser.h:107
ReferenceCounter::IncrRef
virtual int IncrRef(void)
Increments reference count.
Definition: referencecounter.cpp:101
MythCommandLineParser::addDVBv3
void addDVBv3(void)
Canned argument definition for –dvbv3.
Definition: mythcommandlineparser.cpp:2510
mythcommandlineparser.h
MythCommandLineParser::GetPassthrough
QString GetPassthrough(void) const
Return any text supplied on the command line after a bare '–'.
Definition: mythcommandlineparser.cpp:1971
MythCommandLineParser::Result::kEnd
@ kEnd
MythCommandLineParser::Result::kCombOptVal
@ kCombOptVal
GetTermWidth
int GetTermWidth(void)
returns terminal width, or 79 on error
Definition: mythcommandlineparser.cpp:91
MythCommandLineParser::toDateTime
QDateTime toDateTime(const QString &key) const
Returns stored QVariant as a QDateTime, falling to default if not provided.
Definition: mythcommandlineparser.cpp:2321
MythCommandLineParser::addInFile
void addInFile(bool addOutFile=false)
Canned argument definition for –infile and –outfile.
Definition: mythcommandlineparser.cpp:2606
CommandLineArg::Convert
void Convert(void)
Convert stored string value from QByteArray to QString.
Definition: mythcommandlineparser.cpp:862
ReferenceCounter
General purpose reference counter.
Definition: referencecounter.h:26
CommandLineArg::GetKeywordString
QString GetKeywordString(void) const
Return string containing all possible keyword triggers for this argument.
Definition: mythcommandlineparser.cpp:224