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 // linux
47 #endif // not _WIN32
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 // MythTV headers
72 #include "mythcommandlineparser.h"
73 #include "mythcorecontext.h"
74 #include "exitcodes.h"
75 #include "mythconfig.h"
76 #include "mythlogging.h"
77 #include "mythversion.h"
78 #include "logging.h"
79 #include "mythmiscutil.h"
80 #include "mythdate.h"
81 
82 static constexpr int k_defaultWidth = 79;
83 
87 static int GetTermWidth(void)
88 {
89 #if defined(_WIN32) || defined(Q_OS_ANDROID)
90  return k_defaultWidth;
91 #else
92  struct winsize ws {};
93 
94  if (ioctl(0, TIOCGWINSZ, &ws) != 0)
95  return k_defaultWidth;
96 
97  return static_cast<int>(ws.ws_col);
98 #endif
99 }
100 
101 static QByteArray strip_quotes(const QByteArray& array)
102 {
103  return ((array.startsWith('"') && array.endsWith('"') ) ||
104  (array.startsWith('\'') && array.endsWith('\''))
105  ) ? array.mid(1, array.size() - 2) : array;
106 }
107 
108 static void wrapList(QStringList &list, int width)
109 {
110  // Set a minimum width of 5 to prevent a crash; if this is triggered,
111  // something has gone seriously wrong and the result won't really be usable
112  width = std::max(width, 5);
113 
114  for (int i = 0; i < list.size(); i++)
115  {
116  QString string = list.at(i);
117 
118  if( string.size() <= width )
119  continue;
120 
121  QString left = string.left(width);
122  bool inserted = false;
123 
124  while( !inserted && !left.endsWith(" " ))
125  {
126  if( string.mid(left.size(), 1) == " " )
127  {
128  list.replace(i, left);
129  list.insert(i+1, string.mid(left.size()).trimmed());
130  inserted = true;
131  }
132  else
133  {
134  left.chop(1);
135  if( !left.contains(" ") )
136  {
137  // Line is too long, just hyphenate it
138  list.replace(i, left + "-");
139  list.insert(i+1, string.mid(left.size()));
140  inserted = true;
141  }
142  }
143  }
144 
145  if( !inserted )
146  {
147  left.chop(1);
148  list.replace(i, left);
149  list.insert(i+1, string.mid(left.size()).trimmed());
150  }
151  }
152 }
153 
158 QStringList MythCommandLineParser::MythSplitCommandString(const QString &line)
159 {
160  QStringList fields;
164  enum states {
165  START,
166  INTEXT,
167  INSQUOTE,
168  INDQUOTE,
169  ESCTEXT,
170  ESCSQUOTE,
171  ESCDQUOTE,
172  };
173  states state = START;
174  int tokenStart = -1;
175 
176  for (int i = 0; i < line.size(); i++)
177  {
178  const QChar c = line.at(i);
179 
180  switch (state) {
181  case START:
182  tokenStart = i;
183  if (c.isSpace()) break;
184  if (c == '\'') state = INSQUOTE;
185  else if (c == '\"') state = INDQUOTE;
186  else if (c == '\\') state = ESCTEXT;
187  else state = INTEXT;
188  break;
189  case INTEXT:
190  if (c.isSpace()) {
191  fields += line.mid(tokenStart, i - tokenStart);
192  state = START;
193  break;
194  }
195  else if (c == '\'') state = INSQUOTE;
196  else if (c == '\"') state = INDQUOTE;
197  else if (c == '\\') state = ESCTEXT;
198  break;
199  case INSQUOTE:
200  if (c == '\'') state = INTEXT;
201  else if (c == '\\') state = ESCSQUOTE;
202  break;
203  case INDQUOTE:
204  if (c == '\"') state = INTEXT;
205  else if (c == '\\') state = ESCDQUOTE;
206  break;
207  case ESCTEXT: state = INTEXT; break;
208  case ESCSQUOTE: state = INSQUOTE; break;
209  case ESCDQUOTE: state = INDQUOTE; break;
210  }
211  }
212 
213  if (state != START)
214  fields += line.mid(tokenStart);
215  return fields;
216 }
217 
222 {
223  switch (type)
224  {
225  case Result::kEnd:
226  return "kEnd";
227 
228  case Result::kEmpty:
229  return "kEmpty";
230 
231  case Result::kOptOnly:
232  return "kOptOnly";
233 
234  case Result::kOptVal:
235  return "kOptVal";
236 
237  case Result::kCombOptVal:
238  return "kCombOptVal";
239 
240  case Result::kArg:
241  return "kArg";
242 
244  return "kPassthrough";
245 
246  case Result::kInvalid:
247  return "kInvalid";
248  }
249  return "kUnknown";
250 }
251 
286 CommandLineArg::CommandLineArg(const QString& name, QMetaType::Type type,
287  QVariant def, QString help, QString longhelp) :
288  ReferenceCounter(QString("CommandLineArg:%1").arg(name)),
289  m_name(name), m_type(type), m_default(std::move(def)),
290  m_help(std::move(help)), m_longhelp(std::move(longhelp))
291 {
292  if ((m_type != QMetaType::QString) && (m_type != QMetaType::QStringList) &&
293  (m_type != QMetaType::QVariantMap))
294  m_converted = true;
295 }
296 
303 CommandLineArg::CommandLineArg(const QString& name, QMetaType::Type type, QVariant def)
304  : ReferenceCounter(QString("CommandLineArg:%1").arg(name)),
305  m_name(name), m_type(type), m_default(std::move(def))
306 {
307  if ((m_type != QMetaType::QString) && (m_type != QMetaType::QStringList) &&
308  (m_type != QMetaType::QVariantMap))
309  m_converted = true;
310 }
311 
319 CommandLineArg::CommandLineArg(const QString& name) :
320  ReferenceCounter(QString("CommandLineArg:%1").arg(name)),
321  m_name(name)
322 {
323 }
324 
329 {
330  // this may cause problems if the terminal is too narrow, or if too
331  // many keywords for the same argument are used
332  return m_keywords.join(" OR ");
333 }
334 
339 {
340  int len = GetKeywordString().length();
341 
342  QList<CommandLineArg*>::const_iterator i1;
343  for (i1 = m_parents.begin(); i1 != m_parents.end(); ++i1)
344  len = std::max(len, (*i1)->GetKeywordLength()+2);
345 
346  return len;
347 }
348 
364 QString CommandLineArg::GetHelpString(int off, const QString& group, bool force) const
365 {
366  QString helpstr;
367  QTextStream msg(&helpstr, QIODevice::WriteOnly);
368  int termwidth = GetTermWidth();
369  if (termwidth < off)
370  {
371  if (off > 70)
372  {
373  // developer has configured some absurdly long command line
374  // arguments, but we still need to do something
375  termwidth = off+40;
376  }
377  else
378  {
379  // user is running uselessly narrow console, use a sane console
380  // width instead
381  termwidth = k_defaultWidth;
382  }
383  }
384 
385  if (m_help.isEmpty() && !force)
386  // only print if there is a short help to print
387  return helpstr;
388 
389  if ((m_group != group) && !force)
390  // only print if looping over the correct group
391  return helpstr;
392 
393  if (!m_parents.isEmpty() && !force)
394  {
395  // only print if an independent option, not subject
396  // to a parent option
397  return helpstr;
398  }
399 
400  if (!m_deprecated.isEmpty())
401  // option is marked as deprecated, do not show
402  return helpstr;
403 
404  if (!m_removed.isEmpty())
405  // option is marked as removed, do not show
406  return helpstr;
407 
408  QString pad;
409  pad.fill(' ', off);
410 
411  // print the first line with the available keywords
412  QStringList hlist = m_help.split('\n');
413  wrapList(hlist, termwidth-off);
414  if (!m_parents.isEmpty())
415  msg << " ";
416  msg << GetKeywordString().leftJustified(off, ' ')
417  << hlist.takeFirst() << QT_ENDL;
418 
419  // print remaining lines with necessary padding
420  for (const auto & line : qAsConst(hlist))
421  msg << pad << line << QT_ENDL;
422 
423  // loop through any child arguments to print underneath
424  for (auto * arg : qAsConst(m_children))
425  msg << arg->GetHelpString(off, group, true);
426 
427  msg.flush();
428  return helpstr;
429 }
430 
438 QString CommandLineArg::GetLongHelpString(QString keyword) const
439 {
440  QString helpstr;
441  QTextStream msg(&helpstr, QIODevice::WriteOnly);
442  int termwidth = GetTermWidth();
443 
444  // help called for an argument that is not me, this should not happen
445  if (!m_keywords.contains(keyword))
446  return helpstr;
447 
448  // argument has been marked as removed, so warn user of such
449  if (!m_removed.isEmpty())
450  {
451  PrintRemovedWarning(keyword);
452  // argument has been marked as deprecated, so warn user of such
453  }
454  else if (!m_deprecated.isEmpty())
455  {
456  PrintDeprecatedWarning(keyword);
457  }
458 
459  msg << "Option: " << keyword << QT_ENDL << QT_ENDL;
460 
461  bool first = true;
462 
463  // print all related keywords, padding for multiples
464  for (const auto & word : qAsConst(m_keywords))
465  {
466  if (word != keyword)
467  {
468  if (first)
469  {
470  msg << "Aliases: " << word << QT_ENDL;
471  first = false;
472  }
473  else
474  msg << " " << word << QT_ENDL;
475  }
476  }
477 
478  // print type and default for the stored value
479 #if QT_VERSION < QT_VERSION_CHECK(5,15,0)
480  msg << "Type: " << QMetaType::typeName(m_type) << QT_ENDL;
481 #else
482  msg << "Type: " << QMetaType(m_type).name() << QT_ENDL;
483 #endif
484  if (m_default.canConvert<QString>())
485  msg << "Default: " << m_default.toString() << QT_ENDL;
486 
487  QStringList help;
488  if (m_longhelp.isEmpty())
489  help = m_help.split("\n");
490  else
491  help = m_longhelp.split("\n");
492  wrapList(help, termwidth-13);
493 
494  // print description, wrapping and padding as necessary
495  msg << "Description: " << help.takeFirst() << QT_ENDL;
496  for (const auto & line : qAsConst(help))
497  msg << " " << line << QT_ENDL;
498 
499  QList<CommandLineArg*>::const_iterator i2;
500 
501  // loop through the four relation types and print
502  if (!m_parents.isEmpty())
503  {
504  msg << QT_ENDL << "Can be used in combination with:" << QT_ENDL;
505  for (auto * parent : qAsConst(m_parents))
506  msg << " " << parent->GetPreferredKeyword()
507  .toLocal8Bit().constData();
508  msg << QT_ENDL;
509  }
510 
511  if (!m_children.isEmpty())
512  {
513  msg << QT_ENDL << "Allows the use of:" << QT_ENDL;
514  for (i2 = m_children.constBegin(); i2 != m_children.constEnd(); ++i2)
515  msg << " " << (*i2)->GetPreferredKeyword()
516  .toLocal8Bit().constData();
517  msg << QT_ENDL;
518  }
519 
520  if (!m_requires.isEmpty())
521  {
522  msg << QT_ENDL << "Requires the use of:" << QT_ENDL;
523  for (i2 = m_requires.constBegin(); i2 != m_requires.constEnd(); ++i2)
524  msg << " " << (*i2)->GetPreferredKeyword()
525  .toLocal8Bit().constData();
526  msg << QT_ENDL;
527  }
528 
529  if (!m_blocks.isEmpty())
530  {
531  msg << QT_ENDL << "Prevents the use of:" << QT_ENDL;
532  for (i2 = m_blocks.constBegin(); i2 != m_blocks.constEnd(); ++i2)
533  msg << " " << (*i2)->GetPreferredKeyword()
534  .toLocal8Bit().constData();
535  msg << QT_ENDL;
536  }
537 
538  msg.flush();
539  return helpstr;
540 }
541 
548 bool CommandLineArg::Set(const QString& opt)
549 {
550  m_usedKeyword = opt;
551 
552  switch (m_type)
553  {
554  case QMetaType::Bool:
555  m_stored = QVariant(!m_default.toBool());
556  break;
557 
558  case QMetaType::Int:
559  if (m_stored.isNull())
560  m_stored = QVariant(1);
561  else
562  m_stored = QVariant(m_stored.toInt() + 1);
563  break;
564 
565  case QMetaType::QString:
567  break;
568 
569  default:
570  std::cerr << "Command line option did not receive value:" << std::endl
571  << " " << opt.toLocal8Bit().constData() << std::endl;
572  return false;
573  }
574 
575  m_given = true;
576  return true;
577 }
578 
581 bool CommandLineArg::Set(const QString& opt, const QByteArray& val)
582 {
583  QVariantList vlist;
584  QList<QByteArray> blist;
585  QVariantMap vmap;
586  m_usedKeyword = opt;
587 
588  switch (m_type)
589  {
590  case QMetaType::Bool:
591  std::cerr << "Boolean type options do not accept values:" << std::endl
592  << " " << opt.toLocal8Bit().constData() << std::endl;
593  return false;
594 
595  case QMetaType::QString:
596  m_stored = QVariant(val);
597  break;
598 
599  case QMetaType::Int:
600  m_stored = QVariant(val.toInt());
601  break;
602 
603  case QMetaType::UInt:
604  m_stored = QVariant(val.toUInt());
605  break;
606 
607  case QMetaType::LongLong:
608  m_stored = QVariant(val.toLongLong());
609  break;
610 
611  case QMetaType::Double:
612  m_stored = QVariant(val.toDouble());
613  break;
614 
615  case QMetaType::QDateTime:
616  m_stored = QVariant(MythDate::fromString(QString(val)));
617  break;
618 
619  case QMetaType::QStringList:
620  if (!m_stored.isNull())
621  vlist = m_stored.toList();
622  vlist << val;
623  m_stored = QVariant(vlist);
624  break;
625 
626  case QMetaType::QVariantMap:
627  if (!val.contains('='))
628  {
629  std::cerr << "Command line option did not get expected "
630  << "key/value pair" << std::endl;
631  return false;
632  }
633 
634  blist = val.split('=');
635 
636  if (!m_stored.isNull())
637  vmap = m_stored.toMap();
638  vmap[QString(strip_quotes(blist[0]))] = QVariant(strip_quotes(blist[1]));
639  m_stored = QVariant(vmap);
640  break;
641 
642  case QMetaType::QSize:
643  if (!val.contains('x'))
644  {
645  std::cerr << "Command line option did not get expected "
646  << "XxY pair" << std::endl;
647  return false;
648  }
649 
650  blist = val.split('x');
651  m_stored = QVariant(QSize(blist[0].toInt(), blist[1].toInt()));
652  break;
653 
654  default:
655  m_stored = QVariant(val);
656  }
657 
658  m_given = true;
659  return true;
660 }
661 
665 {
666  m_children << new CommandLineArg(opt);
667  return this;
668 }
669 
673 {
674  for (const auto& opt : qAsConst(opts))
675  m_children << new CommandLineArg(opt);
676  return this;
677 }
678 
682 {
683  m_parents << new CommandLineArg(opt);
684  return this;
685 }
686 
690 {
691  for (const auto& opt : qAsConst(opts))
692  m_parents << new CommandLineArg(opt);
693  return this;
694 }
695 
699 {
700  m_parents << new CommandLineArg(opt);
701  return this;
702 }
703 
707 {
708  for (const auto& opt : qAsConst(opts))
709  m_parents << new CommandLineArg(opt);
710  return this;
711 }
712 
716 {
717  m_children << new CommandLineArg(opt);
718  return this;
719 }
720 
724 {
725  for (const auto& opt : qAsConst(opts))
726  m_children << new CommandLineArg(opt);
727  return this;
728 }
729 
733 {
734  m_children << new CommandLineArg(opt);
735  m_requires << new CommandLineArg(opt);
736  return this;
737 }
738 
742 {
743  for (const auto& opt : qAsConst(opts))
744  {
745  m_children << new CommandLineArg(opt);
746  m_requires << new CommandLineArg(opt);
747  }
748  return this;
749 }
750 
754 {
755  m_parents << new CommandLineArg(opt);
756  m_requiredby << new CommandLineArg(opt);
757  return this;
758 }
759 
763 {
764  for (const auto& opt : qAsConst(opts))
765  {
766  m_parents << new CommandLineArg(opt);
767  m_requiredby << new CommandLineArg(opt);
768  }
769  return this;
770 }
771 
775 {
776  m_requires << new CommandLineArg(opt);
777  return this;
778 }
779 
783 {
784  for (const auto& opt : qAsConst(opts))
785  m_requires << new CommandLineArg(opt);
786  return this;
787 }
788 
792 {
793  m_blocks << new CommandLineArg(opt);
794  return this;
795 }
796 
800 {
801  for (const auto& opt : qAsConst(opts))
802  m_blocks << new CommandLineArg(opt);
803  return this;
804 }
805 
809 {
810  if (depstr.isEmpty())
811  depstr = "and will be removed in a future version.";
812  m_deprecated = depstr;
813  return this;
814 }
815 
818 CommandLineArg* CommandLineArg::SetRemoved(QString remstr, QString remver)
819 {
820  if (remstr.isEmpty())
821  remstr = "and is no longer available in this version.";
822  m_removed = remstr;
823  m_removedversion = std::move(remver);
824  return this;
825 }
826 
832 void CommandLineArg::SetParentOf(CommandLineArg *other, bool forward)
833 {
834  bool replaced = false;
835  other->IncrRef();
836 
837  for (int i = 0; i < m_children.size(); i++)
838  {
839  if (m_children[i]->m_name == other->m_name)
840  {
841  m_children[i]->DecrRef();
842  m_children.replace(i, other);
843  replaced = true;
844  break;
845  }
846  }
847 
848  if (!replaced)
849  m_children << other;
850 
851  if (forward)
852  other->SetChildOf(this, false);
853 }
854 
860 void CommandLineArg::SetChildOf(CommandLineArg *other, bool forward)
861 {
862  bool replaced = false;
863  other->IncrRef();
864 
865  for (int i = 0; i < m_parents.size(); i++)
866  {
867  if (m_parents[i]->m_name == other->m_name)
868  {
869  m_parents[i]->DecrRef();
870  m_parents.replace(i, other);
871  replaced = true;
872  break;
873  }
874  }
875 
876  if (!replaced)
877  m_parents << other;
878 
879  if (forward)
880  other->SetParentOf(this, false);
881 }
882 
888 void CommandLineArg::SetRequires(CommandLineArg *other, bool /*forward*/)
889 {
890  bool replaced = false;
891  other->IncrRef();
892 
893  for (int i = 0; i < m_requires.size(); i++)
894  {
895  if (m_requires[i]->m_name == other->m_name)
896  {
897  m_requires[i]->DecrRef();
898  m_requires.replace(i, other);
899  replaced = true;
900  break;
901  }
902  }
903 
904  if (!replaced)
905  m_requires << other;
906 
907 // requirements need not be reciprocal
908 // if (forward)
909 // other->SetRequires(this, false);
910 }
911 
917 void CommandLineArg::SetBlocks(CommandLineArg *other, bool forward)
918 {
919  bool replaced = false;
920  other->IncrRef();
921 
922  for (int i = 0; i < m_blocks.size(); i++)
923  {
924  if (m_blocks[i]->m_name == other->m_name)
925  {
926  m_blocks[i]->DecrRef();
927  m_blocks.replace(i, other);
928  replaced = true;
929  break;
930  }
931  }
932 
933  if (!replaced)
934  m_blocks << other;
935 
936  if (forward)
937  other->SetBlocks(this, false);
938 }
939 
942 void CommandLineArg::AllowOneOf(const QList<CommandLineArg*>& args)
943 {
944  // TODO: blocks do not get set properly if multiple dummy arguments
945  // are provided. since this method will not have access to the
946  // argument list, this issue will have to be resolved later in
947  // ReconcileLinks().
948 
949  // loop through all but the last entry
950  for (auto i1 = args.cbegin(); i1 != args.cend()-1; ++i1)
951  {
952  // loop through the next to the last entry
953  // and block use with the current
954  for (auto i2 = i1+1; i2 != args.cend(); ++i2)
955  {
956  (*i1)->SetBlocks(*i2);
957  }
958 
959  if ((*i1)->m_type == QMetaType::UnknownType)
960  (*i1)->DecrRef();
961  }
962 }
963 
971 {
972  if (!QCoreApplication::instance())
973  // QApplication not available, no sense doing anything yet
974  return;
975 
976  if (m_converted)
977  // already run, abort
978  return;
979 
980  if (!m_given)
981  {
982  // nothing to work on, abort
983  m_converted = true;
984  return;
985  }
986 
987 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
988  auto storedType = static_cast<QMetaType::Type>(m_stored.type());
989 #else
990  auto storedType = m_stored.typeId();
991 #endif
992  if (m_type == QMetaType::QString)
993  {
994  if (storedType == QMetaType::QByteArray)
995  {
996  m_stored = QString::fromLocal8Bit(m_stored.toByteArray());
997  }
998  // else
999  // not sure why this isnt a bytearray, but ignore it and
1000  // set it as converted
1001  }
1002  else if (m_type == QMetaType::QStringList)
1003  {
1004  if (storedType == QMetaType::QVariantList)
1005  {
1006  QVariantList vlist = m_stored.toList();
1007  QStringList slist;
1008  for (const auto& item : qAsConst(vlist))
1009  slist << QString::fromLocal8Bit(item.toByteArray());
1010  m_stored = QVariant(slist);
1011  }
1012  }
1013  else if (m_type == QMetaType::QVariantMap)
1014  {
1015  QVariantMap vmap = m_stored.toMap();
1016  // NOLINTNEXTLINE(modernize-loop-convert)
1017  for (auto iter = vmap.begin(); iter != vmap.end(); ++iter)
1018  (*iter) = QString::fromLocal8Bit(iter->toByteArray());
1019  }
1020  else
1021  return;
1022 
1023  m_converted = true;
1024 }
1025 
1026 
1033 {
1034  QStringList::const_iterator it;
1035  QString preferred;
1036  int len = 0;
1037 
1038  for (it = m_keywords.constBegin(); it != m_keywords.constEnd(); ++it)
1039  {
1040  int len2 = (*it).size();
1041  if (len2 > len)
1042  {
1043  preferred = *it;
1044  len = len2;
1045  }
1046  }
1047 
1048  return preferred;
1049 }
1050 
1055 {
1056  if (!m_given)
1057  return true; // not in use, no need for checks
1058 
1059  QList<CommandLineArg*>::const_iterator i;
1060 
1061  bool passes = false;
1062  for (i = m_parents.constBegin(); i != m_parents.constEnd(); ++i)
1063  {
1064  // one of these must have been defined
1065  if ((*i)->m_given)
1066  {
1067  passes = true;
1068  break;
1069  }
1070  }
1071  if (!passes && !m_parents.isEmpty())
1072  {
1073  std::cerr << "ERROR: " << m_usedKeyword.toLocal8Bit().constData()
1074  << " requires at least one of the following arguments" << std::endl;
1075  for (i = m_parents.constBegin(); i != m_parents.constEnd(); ++i)
1076  std::cerr << " "
1077  << (*i)->GetPreferredKeyword().toLocal8Bit().constData();
1078  std::cerr << std::endl << std::endl;
1079  return false;
1080  }
1081 
1082  // we dont care about children
1083 
1084  for (i = m_requires.constBegin(); i != m_requires.constEnd(); ++i)
1085  {
1086  // all of these must have been defined
1087  if (!(*i)->m_given)
1088  {
1089  std::cerr << "ERROR: " << m_usedKeyword.toLocal8Bit().constData()
1090  << " requires all of the following be defined as well"
1091  << std::endl;
1092  for (i = m_requires.constBegin(); i != m_requires.constEnd(); ++i)
1093  {
1094  std::cerr << " "
1095  << (*i)->GetPreferredKeyword().toLocal8Bit()
1096  .constData();
1097  }
1098  std::cerr << std::endl << std::endl;
1099  return false;
1100  }
1101  }
1102 
1103  for (i = m_blocks.constBegin(); i != m_blocks.constEnd(); ++i)
1104  {
1105  // none of these can be defined
1106  if ((*i)->m_given)
1107  {
1108  std::cerr << "ERROR: " << m_usedKeyword.toLocal8Bit().constData()
1109  << " requires that none of the following be defined" << std::endl;
1110  for (i = m_blocks.constBegin(); i != m_blocks.constEnd(); ++i)
1111  {
1112  std::cerr << " "
1113  << (*i)->GetPreferredKeyword().toLocal8Bit()
1114  .constData();
1115  }
1116  std::cerr << std::endl << std::endl;
1117  return false;
1118  }
1119  }
1120 
1121  return true;
1122 }
1123 
1127 {
1128  // clear out interdependent pointers in preparation for deletion
1129  while (!m_parents.isEmpty())
1130  m_parents.takeFirst()->DecrRef();
1131 
1132  while (!m_children.isEmpty())
1133  m_children.takeFirst()->DecrRef();
1134 
1135  while (!m_blocks.isEmpty())
1136  m_blocks.takeFirst()->DecrRef();
1137 
1138  while (!m_requires.isEmpty())
1139  m_requires.takeFirst()->DecrRef();
1140 
1141  while (!m_requiredby.isEmpty())
1142  m_requiredby.takeFirst()->DecrRef();
1143 }
1144 
1148 {
1149  if (!m_given)
1150  return;
1151 
1152  std::cerr << " " << m_name.leftJustified(30).toLocal8Bit().constData();
1153 
1154  QSize tmpsize;
1155  QMap<QString, QVariant> tmpmap;
1156  QMap<QString, QVariant>::const_iterator it;
1157  QVariantList vlist;
1158  bool first = true;
1159 
1160  switch (m_type)
1161  {
1162  case QMetaType::Bool:
1163  std::cerr << (m_stored.toBool() ? "True" : "False") << std::endl;
1164  break;
1165 
1166  case QMetaType::Int:
1167  std::cerr << m_stored.toInt() << std::endl;
1168  break;
1169 
1170  case QMetaType::UInt:
1171  std::cerr << m_stored.toUInt() << std::endl;
1172  break;
1173 
1174  case QMetaType::LongLong:
1175  std::cerr << m_stored.toLongLong() << std::endl;
1176  break;
1177 
1178  case QMetaType::Double:
1179  std::cerr << m_stored.toDouble() << std::endl;
1180  break;
1181 
1182  case QMetaType::QSize:
1183  tmpsize = m_stored.toSize();
1184  std::cerr << "x=" << tmpsize.width()
1185  << " y=" << tmpsize.height()
1186  << std::endl;
1187  break;
1188 
1189  case QMetaType::QString:
1190  std::cerr << '"' << m_stored.toByteArray().constData()
1191  << '"' << std::endl;
1192  break;
1193 
1194  case QMetaType::QStringList:
1195  vlist = m_stored.toList();
1196  std::cerr << '"' << vlist.takeFirst().toByteArray().constData() << '"';
1197  for (const auto& str : qAsConst(vlist))
1198  {
1199  std::cerr << ", \""
1200  << str.constData()
1201  << '"';
1202  }
1203  std::cerr << std::endl;
1204  break;
1205 
1206  case QMetaType::QVariantMap:
1207  tmpmap = m_stored.toMap();
1208  for (it = tmpmap.cbegin(); it != tmpmap.cend(); ++it)
1209  {
1210  if (first)
1211  first = false;
1212  else
1213  std::cerr << QString("").leftJustified(32)
1214  .toLocal8Bit().constData();
1215 
1216  std::cerr << it.key().toLocal8Bit().constData()
1217  << '='
1218  << it->toByteArray().constData()
1219  << std::endl;
1220  }
1221 
1222  break;
1223 
1224  case QMetaType::QDateTime:
1225  std::cerr << m_stored.toDateTime().toString(Qt::ISODate)
1226  .toLocal8Bit().constData()
1227  << std::endl;
1228  break;
1229 
1230  default:
1231  std::cerr << std::endl;
1232  }
1233 }
1234 
1237 void CommandLineArg::PrintRemovedWarning(QString &keyword) const
1238 {
1239  QString warn = QString("%1 has been removed").arg(keyword);
1240  if (!m_removedversion.isEmpty())
1241  warn += QString(" as of MythTV %1").arg(m_removedversion);
1242 
1243  std::cerr << QString("****************************************************\n"
1244  " WARNING: %1\n"
1245  " %2\n"
1246  "****************************************************\n\n")
1247  .arg(warn, m_removed)
1248  .toLocal8Bit().constData();
1249 }
1250 
1253 void CommandLineArg::PrintDeprecatedWarning(QString &keyword) const
1254 {
1255  std::cerr << QString("****************************************************\n"
1256  " WARNING: %1 has been deprecated\n"
1257  " %2\n"
1258  "****************************************************\n\n")
1259  .arg(keyword, m_deprecated)
1260  .toLocal8Bit().constData();
1261 }
1262 
1277  : m_appname(std::move(appname))
1278 {
1279  if (qEnvironmentVariableIsSet("VERBOSE_PARSER"))
1280  {
1281  std::cerr << "MythCommandLineParser is now operating verbosely." << std::endl;
1282  m_verbose = true;
1283  }
1284 
1286 }
1287 
1289 {
1290  QMap<QString, CommandLineArg*>::iterator i;
1291 
1292  i = m_namedArgs.begin();
1293  while (i != m_namedArgs.end())
1294  {
1295  (*i)->CleanupLinks();
1296  (*i)->DecrRef();
1297  i = m_namedArgs.erase(i);
1298  }
1299 
1300  i = m_optionedArgs.begin();
1301  while (i != m_optionedArgs.end())
1302  {
1303  (*i)->DecrRef();
1304  i = m_optionedArgs.erase(i);
1305  }
1306 }
1307 
1342  const QString& name, QMetaType::Type type, QVariant def,
1343  QString help, QString longhelp)
1344 {
1345  CommandLineArg *arg = nullptr;
1346 
1347  if (m_namedArgs.contains(name))
1348  arg = m_namedArgs[name];
1349  else
1350  {
1351  arg = new CommandLineArg(name, type, std::move(def), std::move(help), std::move(longhelp));
1352  m_namedArgs.insert(name, arg);
1353  }
1354 
1355  for (const auto & str : qAsConst(arglist))
1356  {
1357  if (!m_optionedArgs.contains(str))
1358  {
1359  arg->AddKeyword(str);
1360  if (m_verbose)
1361  {
1362  std::cerr << "Adding " << str.toLocal8Bit().constData()
1363  << " as taking type '"
1364 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
1365  << QVariant::typeToName(static_cast<int>(type))
1366 #else
1367  << QMetaType(type).name()
1368 #endif
1369  << "'" << std::endl;
1370  }
1371  arg->IncrRef();
1372  m_optionedArgs.insert(str, arg);
1373  }
1374  }
1375 
1376  return arg;
1377 }
1378 
1382 {
1383  std::cout << "Please attach all output as a file in bug reports." << std::endl;
1384  std::cout << "MythTV Version : " << GetMythSourceVersion() << std::endl;
1385  std::cout << "MythTV Branch : " << GetMythSourcePath() << std::endl;
1386  std::cout << "Network Protocol : " << MYTH_PROTO_VERSION << std::endl;
1387  std::cout << "Library API : " << MYTH_BINARY_VERSION << std::endl;
1388  std::cout << "QT Version : " << QT_VERSION_STR << std::endl;
1389 #ifdef MYTH_BUILD_CONFIG
1390  std::cout << "Options compiled in:" <<std::endl;
1391  std::cout << MYTH_BUILD_CONFIG << std::endl;
1392 #endif
1393 }
1394 
1398 {
1399  QString help = GetHelpString();
1400  std::cerr << help.toLocal8Bit().constData();
1401 }
1402 
1409 {
1410  QString helpstr;
1411  QTextStream msg(&helpstr, QIODevice::WriteOnly);
1412 
1413  QString versionStr = QString("%1 version: %2 [%3] www.mythtv.org")
1415  msg << versionStr << QT_ENDL;
1416 
1417  if (toString("showhelp").isEmpty())
1418  {
1419  // build generic help text
1420 
1421  QString descr = GetHelpHeader();
1422  if (descr.size() > 0)
1423  msg << QT_ENDL << descr << QT_ENDL << QT_ENDL;
1424 
1425  // loop through registered arguments to populate list of groups
1426  QStringList groups("");
1427  int maxlen = 0;
1428  for (auto * cmdarg : qAsConst(m_namedArgs))
1429  {
1430  maxlen = std::max(cmdarg->GetKeywordLength(), maxlen);
1431  if (!groups.contains(cmdarg->m_group))
1432  groups << cmdarg->m_group;
1433  }
1434 
1435  // loop through list of groups and print help string for each
1436  // arguments will filter themselves if they are not in the group
1437  maxlen += 4;
1438  for (const auto & group : qAsConst(groups))
1439  {
1440  if (group.isEmpty())
1441  msg << "Misc. Options:" << QT_ENDL;
1442  else
1443  msg << group.toLocal8Bit().constData() << " Options:" << QT_ENDL;
1444 
1445  for (auto * cmdarg : qAsConst(m_namedArgs))
1446  msg << cmdarg->GetHelpString(maxlen, group);
1447  msg << QT_ENDL;
1448  }
1449  }
1450  else
1451  {
1452  // build help for a specific argument
1453  QString optstr = "-" + toString("showhelp");
1454  if (!m_optionedArgs.contains(optstr))
1455  {
1456  optstr = "-" + optstr;
1457  if (!m_optionedArgs.contains(optstr))
1458  return QString("Could not find option matching '%1'\n")
1459  .arg(toString("showhelp"));
1460  }
1461 
1462  if (m_optionedArgs[optstr] != nullptr)
1463  msg << m_optionedArgs[optstr]->GetLongHelpString(optstr);
1464  }
1465 
1466  msg.flush();
1467  return helpstr;
1468 }
1469 
1473  int &argpos, QString &opt, QByteArray &val)
1474 {
1475  opt.clear();
1476  val.clear();
1477 
1478  if (argpos >= argc)
1479  // this shouldnt happen, return and exit
1480  return Result::kEnd;
1481 
1482  QByteArray tmp(argv[argpos]);
1483  if (tmp.isEmpty())
1484  // string is empty, return and loop
1485  return Result::kEmpty;
1486 
1487  if (m_passthroughActive)
1488  {
1489  // pass through has been activated
1490  val = tmp;
1491  return Result::kArg;
1492  }
1493 
1494  if (tmp.startsWith('-') && tmp.size() > 1)
1495  {
1496  if (tmp == "--")
1497  {
1498  // all options beyond this will be passed as a single string
1499  m_passthroughActive = true;
1500  return Result::kPassthrough;
1501  }
1502 
1503  if (tmp.contains('='))
1504  {
1505  // option contains '=', split
1506  QList<QByteArray> blist = tmp.split('=');
1507 
1508  if (blist.size() != 2)
1509  {
1510  // more than one '=' in option, this is not handled
1511  opt = QString(tmp);
1512  return Result::kInvalid;
1513  }
1514 
1515  opt = QString(strip_quotes(blist[0]));
1516  val = strip_quotes(blist[1]);
1517  return Result::kCombOptVal;
1518  }
1519 
1520  opt = QString(tmp);
1521 
1522  if (argpos+1 >= argc)
1523  // end of input, option only
1524  return Result::kOptOnly;
1525 
1526  tmp = QByteArray(argv[++argpos]);
1527  if (tmp.isEmpty())
1528  // empty string, option only
1529  return Result::kOptOnly;
1530 
1531  if (tmp.startsWith("-") && tmp.size() > 1)
1532  {
1533  // no value found for option, backtrack
1534  argpos--;
1535  return Result::kOptOnly;
1536  }
1537 
1538  val = tmp;
1539  return Result::kOptVal;
1540  }
1541 
1542  // input is not an option string, return as arg
1543  val = tmp;
1544  return Result::kArg;
1545 }
1546 
1553 bool MythCommandLineParser::Parse(int argc, const char * const * argv)
1554 {
1555  Result res = Result::kEnd;
1556  QString opt;
1557  QByteArray val;
1558  CommandLineArg *argdef = nullptr;
1559 
1560  // reconnect interdependencies between command line options
1561  if (!ReconcileLinks())
1562  return false;
1563 
1564  // loop through command line arguments until all are spent
1565  for (int argpos = 1; argpos < argc; ++argpos)
1566  {
1567 
1568  // pull next option
1569  res = getOpt(argc, argv, argpos, opt, val);
1570 
1571  if (m_verbose)
1572  {
1573  std::cerr << "res: " << NamedOptType(res) << std::endl
1574  << "opt: " << opt.toLocal8Bit().constData() << std::endl
1575  << "val: " << val.constData() << std::endl << std::endl;
1576  }
1577 
1578  // '--' found on command line, enable passthrough mode
1579  if (res == Result::kPassthrough && !m_namedArgs.contains("_passthrough"))
1580  {
1581  std::cerr << "Received '--' but passthrough has not been enabled" << std::endl;
1582  SetValue("showhelp", "");
1583  return false;
1584  }
1585 
1586  // end of options found, terminate loop
1587  if (res == Result::kEnd)
1588  break;
1589 
1590  // GetOpt pulled an empty option, this shouldnt happen by ignore
1591  // it and continue
1592  if (res == Result::kEmpty)
1593  continue;
1594 
1595  // more than one equal found in key/value pair, fault out
1596  if (res == Result::kInvalid)
1597  {
1598  std::cerr << "Invalid option received:" << std::endl << " "
1599  << opt.toLocal8Bit().constData();
1600  SetValue("showhelp", "");
1601  return false;
1602  }
1603 
1604  // passthrough is active, so add the data to the stringlist
1605  if (m_passthroughActive)
1606  {
1607  m_namedArgs["_passthrough"]->Set("", val);
1608  continue;
1609  }
1610 
1611  // argument with no preceeding '-' encountered, add to stringlist
1612  if (res == Result::kArg)
1613  {
1614  if (!m_namedArgs.contains("_args"))
1615  {
1616  std::cerr << "Received '"
1617  << val.constData()
1618  << "' but unassociated arguments have not been enabled"
1619  << std::endl;
1620  SetValue("showhelp", "");
1621  return false;
1622  }
1623 
1624  m_namedArgs["_args"]->Set("", val);
1625  continue;
1626  }
1627 
1628  // this line should not be passed once arguments have started collecting
1629  if (toBool("_args"))
1630  {
1631  std::cerr << "Command line arguments received out of sequence"
1632  << std::endl;
1633  SetValue("showhelp", "");
1634  return false;
1635  }
1636 
1637 #ifdef Q_OS_DARWIN
1638  if (opt.startsWith("-psn_"))
1639  {
1640  std::cerr << "Ignoring Process Serial Number from command line"
1641  << std::endl;
1642  continue;
1643  }
1644 #endif
1645 
1646  if (!m_optionedArgs.contains(opt))
1647  {
1648  // argument is unhandled, check if parser allows arbitrary input
1649  if (m_namedArgs.contains("_extra"))
1650  {
1651  // arbitrary allowed, specify general collection pool
1652  argdef = m_namedArgs["_extra"];
1653  QByteArray tmp = opt.toLocal8Bit();
1654  tmp += '=';
1655  tmp += val;
1656  val = tmp;
1657  res = Result::kOptVal;
1658  }
1659  else
1660  {
1661  // arbitrary not allowed, fault out
1662  std::cerr << "Unhandled option given on command line:" << std::endl
1663  << " " << opt.toLocal8Bit().constData() << std::endl;
1664  SetValue("showhelp", "");
1665  return false;
1666  }
1667  }
1668  else
1669  argdef = m_optionedArgs[opt];
1670 
1671  // argument has been marked as removed, warn user and fail
1672  if (!argdef->m_removed.isEmpty())
1673  {
1674  argdef->PrintRemovedWarning(opt);
1675  SetValue("showhelp", "");
1676  return false;
1677  }
1678 
1679  // argument has been marked as deprecated, warn user
1680  if (!argdef->m_deprecated.isEmpty())
1681  argdef->PrintDeprecatedWarning(opt);
1682 
1683  if (m_verbose)
1684  std::cerr << "name: " << argdef->GetName().toLocal8Bit().constData()
1685  << std::endl;
1686 
1687  // argument is keyword only, no value
1688  if (res == Result::kOptOnly)
1689  {
1690  if (!argdef->Set(opt))
1691  {
1692  SetValue("showhelp", "");
1693  return false;
1694  }
1695  }
1696  // argument has keyword and value
1697  else if ((res == Result::kOptVal) || (res == Result::kCombOptVal))
1698  {
1699  if (!argdef->Set(opt, val))
1700  {
1701  // if option and value were combined with a '=', abort directly
1702  // otherwise, attempt processing them independenly
1703  if ((res == Result::kCombOptVal) || !argdef->Set(opt))
1704  {
1705  SetValue("showhelp", "");
1706  return false;
1707  }
1708  // drop back an iteration so the unused value will get
1709  // processed a second time as a keyword-less argument
1710  --argpos;
1711  }
1712  }
1713  else
1714  {
1715  SetValue("showhelp", "");
1716  return false; // this should not occur
1717  }
1718 
1719  if (m_verbose)
1720  std::cerr << "value: " << argdef->m_stored.toString().toLocal8Bit().constData()
1721  << std::endl;
1722  }
1723 
1724  if (m_verbose)
1725  {
1726  std::cerr << "Processed option list:" << std::endl;
1727  for (auto * cmdarg : qAsConst(m_namedArgs))
1728  cmdarg->PrintVerbose();
1729 
1730  if (m_namedArgs.contains("_args"))
1731  {
1732  std::cerr << std::endl << "Extra argument list:" << std::endl;
1733  QStringList slist = toStringList("_args");
1734  for (const auto& lopt : qAsConst(slist))
1735  std::cerr << " " << (lopt).toLocal8Bit().constData() << std::endl;
1736  }
1737 
1738  if (m_namedArgs.contains("_passthrough"))
1739  {
1740  std::cerr << std::endl << "Passthrough string:" << std::endl;
1741  std::cerr << " " << GetPassthrough().toLocal8Bit().constData() << std::endl;
1742  }
1743 
1744  std::cerr << std::endl;
1745  }
1746 
1747  // make sure all interdependencies are fulfilled
1748  for (auto * cmdarg : qAsConst(m_namedArgs))
1749  {
1750  if (!cmdarg->TestLinks())
1751  {
1752  QString keyword = cmdarg->m_usedKeyword;
1753  if (keyword.startsWith('-'))
1754  {
1755  if (keyword.startsWith("--"))
1756  keyword.remove(0,2);
1757  else
1758  keyword.remove(0,1);
1759  }
1760 
1761  SetValue("showhelp", keyword);
1762  return false;
1763  }
1764  }
1765 
1766  return true;
1767 }
1768 
1769 CommandLineArg* MythCommandLineParser::add(const QString& arg, const QString& name, bool def,
1770  QString help, QString longhelp)
1771 {
1772  return add(QStringList(arg), name, QMetaType::Bool, QVariant(def), std::move(help), std::move(longhelp));
1773 }
1774 
1775 CommandLineArg* MythCommandLineParser::add(const QString& arg, const QString& name, int def,
1776  QString help, QString longhelp)
1777 {
1778  return add(QStringList(arg), name, QMetaType::Int, QVariant(def), std::move(help), std::move(longhelp));
1779 }
1780 
1781 CommandLineArg* MythCommandLineParser::add(const QString& arg, const QString& name, uint def,
1782  QString help, QString longhelp)
1783 {
1784  return add(QStringList(arg), name, QMetaType::UInt, QVariant(def), std::move(help), std::move(longhelp));
1785 }
1786 
1787 CommandLineArg* MythCommandLineParser::add(const QString& arg, const QString& name, long long def,
1788  QString help, QString longhelp)
1789 {
1790  return add(QStringList(arg), name, QMetaType::LongLong, QVariant(def), std::move(help), std::move(longhelp));
1791 }
1792 
1793 CommandLineArg* MythCommandLineParser::add(const QString& arg, const QString& name, double def,
1794  QString help, QString longhelp)
1795 {
1796  return add(QStringList(arg), name, QMetaType::Double, QVariant(def), std::move(help), std::move(longhelp));
1797 }
1798 
1799 CommandLineArg* MythCommandLineParser::add(const QString& arg, const QString& name, const char *def,
1800  QString help, QString longhelp)
1801 {
1802  return add(QStringList(arg), name, QMetaType::QString, QVariant(def), std::move(help), std::move(longhelp));
1803 }
1804 
1805 CommandLineArg* MythCommandLineParser::add(const QString& arg, const QString& name, const QString& def,
1806  QString help, QString longhelp)
1807 {
1808  return add(QStringList(arg), name, QMetaType::QString, QVariant(def), std::move(help), std::move(longhelp));
1809 }
1810 
1811 CommandLineArg* MythCommandLineParser::add(const QString& arg, const QString& name, QSize def,
1812  QString help, QString longhelp)
1813 {
1814  return add(QStringList(arg), name, QMetaType::QSize, QVariant(def), std::move(help), std::move(longhelp));
1815 }
1816 
1817 CommandLineArg* MythCommandLineParser::add(const QString& arg, const QString& name, const QDateTime& def,
1818  QString help, QString longhelp)
1819 {
1820  return add(QStringList(arg), name, QMetaType::QDateTime, QVariant(def), std::move(help), std::move(longhelp));
1821 }
1822 
1823 CommandLineArg* MythCommandLineParser::add(const QString& arg, const QString& name, QMetaType::Type type,
1824  QString help, QString longhelp)
1825 {
1826  return add(QStringList(arg), name, type,
1827 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
1828  QVariant(static_cast<QVariant::Type>(type)),
1829 #else
1830  QVariant(QMetaType(type)),
1831 #endif
1832  std::move(help), std::move(longhelp));
1833 }
1834 
1835 CommandLineArg* MythCommandLineParser::add(const QString& arg, const QString& name,
1836  QMetaType::Type type,
1837  QVariant def, QString help, QString longhelp)
1838 {
1839  return add(QStringList(arg), name, type, std::move(def), std::move(help), std::move(longhelp));
1840 }
1841 
1842 CommandLineArg* MythCommandLineParser::add(QStringList arglist, const QString& name, bool def,
1843  QString help, QString longhelp)
1844 {
1845  return add(std::move(arglist), name, QMetaType::Bool, QVariant(def), std::move(help), std::move(longhelp));
1846 }
1847 
1848 CommandLineArg* MythCommandLineParser::add(QStringList arglist, const QString& name, int def,
1849  QString help, QString longhelp)
1850 {
1851  return add(std::move(arglist), name, QMetaType::Int, QVariant(def), std::move(help), std::move(longhelp));
1852 }
1853 
1854 CommandLineArg* MythCommandLineParser::add(QStringList arglist, const QString& name, uint def,
1855  QString help, QString longhelp)
1856 {
1857  return add(std::move(arglist), name, QMetaType::UInt, QVariant(def), std::move(help), std::move(longhelp));
1858 }
1859 
1860 CommandLineArg* MythCommandLineParser::add(QStringList arglist, const QString& name, long long def,
1861  QString help, QString longhelp)
1862 {
1863  return add(std::move(arglist), name, QMetaType::LongLong, QVariant(def), std::move(help), std::move(longhelp));
1864 }
1865 
1866 CommandLineArg* MythCommandLineParser::add(QStringList arglist, const QString& name, double def,
1867  QString help, QString longhelp)
1868 {
1869  return add(std::move(arglist), name, QMetaType::Double, QVariant(def), std::move(help), std::move(longhelp));
1870 }
1871 
1872 CommandLineArg* MythCommandLineParser::add(QStringList arglist, const QString& name, const char *def,
1873  QString help, QString longhelp)
1874 {
1875  return add(std::move(arglist), name, QMetaType::QString, QVariant(def), std::move(help), std::move(longhelp));
1876 }
1877 
1878 CommandLineArg* MythCommandLineParser::add(QStringList arglist, const QString& name, const QString& def,
1879  QString help, QString longhelp)
1880 {
1881  return add(std::move(arglist), name, QMetaType::QString, QVariant(def), std::move(help), std::move(longhelp));
1882 }
1883 
1884 CommandLineArg* MythCommandLineParser::add(QStringList arglist, const QString& name, QSize def,
1885  QString help, QString longhelp)
1886 {
1887  return add(std::move(arglist), name, QMetaType::QSize, QVariant(def), std::move(help), std::move(longhelp));
1888 }
1889 
1890 CommandLineArg* MythCommandLineParser::add(QStringList arglist, const QString& name, const QDateTime& def,
1891  QString help, QString longhelp)
1892 {
1893  return add(std::move(arglist), name, QMetaType::QDateTime, QVariant(def), std::move(help), std::move(longhelp));
1894 }
1895 
1896 CommandLineArg* MythCommandLineParser::add(QStringList arglist, const QString& name,
1897  QMetaType::Type type,
1898  QString help, QString longhelp)
1899 {
1900  return add(std::move(arglist), name, type,
1901 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
1902  QVariant(static_cast<QVariant::Type>(type)),
1903 #else
1904  QVariant(QMetaType(type)),
1905 #endif
1906  std::move(help), std::move(longhelp));
1907 }
1908 
1913 {
1914  if (m_verbose)
1915  std::cerr << "Reconciling links for option interdependencies." << std::endl;
1916 
1917  QMap<QString,CommandLineArg*>::iterator args_it;
1918  for (args_it = m_namedArgs.begin(); args_it != m_namedArgs.end(); ++args_it)
1919  {
1920  QList<CommandLineArg*> links = (*args_it)->m_parents;
1921  QList<CommandLineArg*>::iterator links_it;
1922  for (links_it = links.begin(); links_it != links.end(); ++links_it)
1923  {
1924  if ((*links_it)->m_type != QMetaType::UnknownType)
1925  continue; // already handled
1926 
1927  if (!m_namedArgs.contains((*links_it)->m_name))
1928  {
1929  // not found
1930  std::cerr << "ERROR: could not reconcile linked argument." << std::endl
1931  << " '" << (*args_it)->m_name.toLocal8Bit().constData()
1932  << "' could not find '"
1933  << (*links_it)->m_name.toLocal8Bit().constData()
1934  << "'." << std::endl
1935  << " Please resolve dependency and recompile." << std::endl;
1936  return false;
1937  }
1938 
1939  // replace linked argument
1940  if (m_verbose)
1941  {
1942  std::cerr << QString(" Setting %1 as child of %2")
1943  .arg((*args_it)->m_name, (*links_it)->m_name)
1944  .toLocal8Bit().constData()
1945  << std::endl;
1946  }
1947  (*args_it)->SetChildOf(m_namedArgs[(*links_it)->m_name]);
1948  }
1949 
1950  links = (*args_it)->m_children;
1951  for (links_it = links.begin(); links_it != links.end(); ++links_it)
1952  {
1953  if ((*links_it)->m_type != QMetaType::UnknownType)
1954  continue; // already handled
1955 
1956  if (!m_namedArgs.contains((*links_it)->m_name))
1957  {
1958  // not found
1959  std::cerr << "ERROR: could not reconcile linked argument." << std::endl
1960  << " '" << (*args_it)->m_name.toLocal8Bit().constData()
1961  << "' could not find '"
1962  << (*links_it)->m_name.toLocal8Bit().constData()
1963  << "'." << std::endl
1964  << " Please resolve dependency and recompile." << std::endl;
1965  return false;
1966  }
1967 
1968  // replace linked argument
1969  if (m_verbose)
1970  {
1971  std::cerr << QString(" Setting %1 as parent of %2")
1972  .arg((*args_it)->m_name, (*links_it)->m_name)
1973  .toLocal8Bit().constData()
1974  << std::endl;
1975  }
1976  (*args_it)->SetParentOf(m_namedArgs[(*links_it)->m_name]);
1977  }
1978 
1979  links = (*args_it)->m_requires;
1980  for (links_it = links.begin(); links_it != links.end(); ++links_it)
1981  {
1982  if ((*links_it)->m_type != QMetaType::UnknownType)
1983  continue; // already handled
1984 
1985  if (!m_namedArgs.contains((*links_it)->m_name))
1986  {
1987  // not found
1988  std::cerr << "ERROR: could not reconcile linked argument." << std::endl
1989  << " '" << (*args_it)->m_name.toLocal8Bit().constData()
1990  << "' could not find '"
1991  << (*links_it)->m_name.toLocal8Bit().constData()
1992  << "'." << std::endl
1993  << " Please resolve dependency and recompile." << std::endl;
1994  return false;
1995  }
1996 
1997  // replace linked argument
1998  if (m_verbose)
1999  {
2000  std::cerr << QString(" Setting %1 as requiring %2")
2001  .arg((*args_it)->m_name, (*links_it)->m_name)
2002  .toLocal8Bit().constData()
2003  << std::endl;
2004  }
2005  (*args_it)->SetRequires(m_namedArgs[(*links_it)->m_name]);
2006  }
2007 
2008  QList<CommandLineArg*>::iterator req_it =
2009  (*args_it)->m_requiredby.begin();
2010  while (req_it != (*args_it)->m_requiredby.end())
2011  {
2012  if ((*req_it)->m_type == QMetaType::UnknownType)
2013  {
2014  // if its not an invalid, it shouldnt be here anyway
2015  if (m_namedArgs.contains((*req_it)->m_name))
2016  {
2017  m_namedArgs[(*req_it)->m_name]->SetRequires(*args_it);
2018  if (m_verbose)
2019  {
2020  std::cerr << QString(" Setting %1 as blocking %2")
2021  .arg((*args_it)->m_name,
2022  (*req_it)->m_name)
2023  .toLocal8Bit().constData()
2024  << std::endl;
2025  }
2026  }
2027  }
2028 
2029  (*req_it)->DecrRef();
2030  req_it = (*args_it)->m_requiredby.erase(req_it);
2031  }
2032 
2033  QList<CommandLineArg*>::iterator block_it =
2034  (*args_it)->m_blocks.begin();
2035  while (block_it != (*args_it)->m_blocks.end())
2036  {
2037  if ((*block_it)->m_type != QMetaType::UnknownType)
2038  {
2039  ++block_it;
2040  continue; // already handled
2041  }
2042 
2043  if (!m_namedArgs.contains((*block_it)->m_name))
2044  {
2045  (*block_it)->DecrRef();
2046  block_it = (*args_it)->m_blocks.erase(block_it);
2047  continue; // if it doesnt exist, it cant block this command
2048  }
2049 
2050  // replace linked argument
2051  if (m_verbose)
2052  {
2053  std::cerr << QString(" Setting %1 as blocking %2")
2054  .arg((*args_it)->m_name, (*block_it)->m_name)
2055  .toLocal8Bit().constData()
2056  << std::endl;
2057  }
2058  (*args_it)->SetBlocks(m_namedArgs[(*block_it)->m_name]);
2059  ++block_it;
2060  }
2061  }
2062 
2063  return true;
2064 }
2065 
2069 QVariant MythCommandLineParser::operator[](const QString &name)
2070 {
2071  QVariant var("");
2072  if (!m_namedArgs.contains(name))
2073  return var;
2074 
2075  CommandLineArg *arg = m_namedArgs[name];
2076 
2077  if (arg->m_given)
2078  var = arg->m_stored;
2079  else
2080  var = arg->m_default;
2081 
2082  return var;
2083 }
2084 
2088 QStringList MythCommandLineParser::GetArgs(void) const
2089 {
2090  return toStringList("_args");
2091 }
2092 
2096 QMap<QString,QString> MythCommandLineParser::GetExtra(void) const
2097 {
2098  return toMap("_extra");
2099 }
2100 
2104 {
2105  return toStringList("_passthrough").join(" ");
2106 }
2107 
2116 {
2117  QMap<QString,QString> smap = toMap("overridesettings");
2118 
2119  if (!m_overridesImported)
2120  {
2121  if (toBool("overridesettingsfile"))
2122  {
2123  QString filename = toString("overridesettingsfile");
2124  if (!filename.isEmpty())
2125  {
2126  QFile f(filename);
2127  if (f.open(QIODevice::ReadOnly))
2128  {
2129  QTextStream in(&f);
2130  while (!in.atEnd()) {
2131  QString line = in.readLine().trimmed();
2132 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
2133  QStringList tokens = line.split("=",
2134  QString::SkipEmptyParts);
2135 #else
2136  QStringList tokens = line.split("=",
2137  Qt::SkipEmptyParts);
2138 #endif
2139  if (tokens.size() == 2)
2140  {
2141  tokens[0].remove(QRegularExpression("^[\"']"));
2142  tokens[0].remove(QRegularExpression("[\"']$"));
2143  tokens[1].remove(QRegularExpression("^[\"']"));
2144  tokens[1].remove(QRegularExpression("[\"']$"));
2145  if (!tokens[0].isEmpty())
2146  smap[tokens[0]] = tokens[1];
2147  }
2148  }
2149  }
2150  else
2151  {
2152  QByteArray tmp = filename.toLatin1();
2153  std::cerr << "Failed to open the override settings file: '"
2154  << tmp.constData() << "'" << std::endl;
2155  }
2156  }
2157  }
2158 
2159  if (toBool("windowed"))
2160  smap["RunFrontendInWindow"] = "1";
2161  else if (toBool("notwindowed"))
2162  smap["RunFrontendInWindow"] = "0";
2163 
2164  if (toBool("mousecursor"))
2165  smap["HideMouseCursor"] = "0";
2166  else if (toBool("nomousecursor"))
2167  smap["HideMouseCursor"] = "1";
2168 
2169  m_overridesImported = true;
2170 
2171  if (!smap.isEmpty())
2172  {
2173  QVariantMap vmap;
2174  for (auto it = smap.cbegin(); it != smap.cend(); ++it)
2175  vmap[it.key()] = QVariant(it.value());
2176 
2177  m_namedArgs["overridesettings"]->Set(QVariant(vmap));
2178  }
2179  }
2180 
2181  if (m_verbose)
2182  {
2183  std::cerr << "Option Overrides:" << std::endl;
2184  QMap<QString, QString>::const_iterator it;
2185  for (it = smap.constBegin(); it != smap.constEnd(); ++it)
2186  std::cerr << QString(" %1 - %2").arg(it.key(), 30).arg(*it)
2187  .toLocal8Bit().constData() << std::endl;
2188  }
2189 
2190  return smap;
2191 }
2192 
2199 bool MythCommandLineParser::toBool(const QString& key) const
2200 {
2201  if (!m_namedArgs.contains(key))
2202  return false;
2203 
2204  CommandLineArg *arg = m_namedArgs[key];
2205  if (arg == nullptr)
2206  return false;
2207 
2208  if (arg->m_type == QMetaType::Bool)
2209  {
2210  if (arg->m_given)
2211  return arg->m_stored.toBool();
2212  return arg->m_default.toBool();
2213  }
2214 
2215  return arg->m_given;
2216 }
2217 
2221 int MythCommandLineParser::toInt(const QString& key) const
2222 {
2223  int val = 0;
2224  if (!m_namedArgs.contains(key))
2225  return val;
2226 
2227  CommandLineArg *arg = m_namedArgs[key];
2228  if (arg == nullptr)
2229  return val;
2230 
2231  if (arg->m_given)
2232  {
2233  if (arg->m_stored.canConvert<int>())
2234  val = arg->m_stored.toInt();
2235  }
2236  else
2237  {
2238  if (arg->m_default.canConvert<int>())
2239  val = arg->m_default.toInt();
2240  }
2241 
2242  return val;
2243 }
2244 
2248 uint MythCommandLineParser::toUInt(const QString& key) const
2249 {
2250  uint val = 0;
2251  if (!m_namedArgs.contains(key))
2252  return val;
2253 
2254  CommandLineArg *arg = m_namedArgs[key];
2255  if (arg == nullptr)
2256  return val;
2257 
2258  if (arg->m_given)
2259  {
2260  if (arg->m_stored.canConvert<uint>())
2261  val = arg->m_stored.toUInt();
2262  }
2263  else
2264  {
2265  if (arg->m_default.canConvert<uint>())
2266  val = arg->m_default.toUInt();
2267  }
2268 
2269  return val;
2270 }
2271 
2275 long long MythCommandLineParser::toLongLong(const QString& key) const
2276 {
2277  long long val = 0;
2278  if (!m_namedArgs.contains(key))
2279  return val;
2280 
2281  CommandLineArg *arg = m_namedArgs[key];
2282  if (arg == nullptr)
2283  return val;
2284 
2285  if (arg->m_given)
2286  {
2287  if (arg->m_stored.canConvert<long long>())
2288  val = arg->m_stored.toLongLong();
2289  }
2290  else
2291  {
2292  if (arg->m_default.canConvert<long long>())
2293  val = arg->m_default.toLongLong();
2294  }
2295 
2296  return val;
2297 }
2298 
2302 double MythCommandLineParser::toDouble(const QString& key) const
2303 {
2304  double val = 0.0;
2305  if (!m_namedArgs.contains(key))
2306  return val;
2307 
2308  CommandLineArg *arg = m_namedArgs[key];
2309  if (arg == nullptr)
2310  return val;
2311 
2312  if (arg->m_given)
2313  {
2314  if (arg->m_stored.canConvert<double>())
2315  val = arg->m_stored.toDouble();
2316  }
2317  else
2318  {
2319  if (arg->m_default.canConvert<double>())
2320  val = arg->m_default.toDouble();
2321  }
2322 
2323  return val;
2324 }
2325 
2329 QSize MythCommandLineParser::toSize(const QString& key) const
2330 {
2331  QSize val(0,0);
2332  if (!m_namedArgs.contains(key))
2333  return val;
2334 
2335  CommandLineArg *arg = m_namedArgs[key];
2336  if (arg == nullptr)
2337  return val;
2338 
2339  if (arg->m_given)
2340  {
2341  if (arg->m_stored.canConvert<QSize>())
2342  val = arg->m_stored.toSize();
2343  }
2344  else
2345  {
2346  if (arg->m_default.canConvert<QSize>())
2347  val = arg->m_default.toSize();
2348  }
2349 
2350  return val;
2351 }
2352 
2356 QString MythCommandLineParser::toString(const QString& key) const
2357 {
2358  QString val("");
2359  if (!m_namedArgs.contains(key))
2360  return val;
2361 
2362  CommandLineArg *arg = m_namedArgs[key];
2363  if (arg == nullptr)
2364  return val;
2365 
2366  if (arg->m_given)
2367  {
2368  if (!arg->m_converted)
2369  arg->Convert();
2370 
2371  if (arg->m_stored.canConvert<QString>())
2372  val = arg->m_stored.toString();
2373  }
2374  else
2375  {
2376  if (arg->m_default.canConvert<QString>())
2377  val = arg->m_default.toString();
2378  }
2379 
2380  return val;
2381 }
2382 
2387 QStringList MythCommandLineParser::toStringList(const QString& key, const QString& sep) const
2388 {
2389  QVariant varval;
2390  QStringList val;
2391  if (!m_namedArgs.contains(key))
2392  return val;
2393 
2394  CommandLineArg *arg = m_namedArgs[key];
2395  if (arg == nullptr)
2396  return val;
2397 
2398  if (arg->m_given)
2399  {
2400  if (!arg->m_converted)
2401  arg->Convert();
2402 
2403  varval = arg->m_stored;
2404  }
2405  else
2406  varval = arg->m_default;
2407 
2408  if (arg->m_type == QMetaType::QString && !sep.isEmpty())
2409  val = varval.toString().split(sep);
2410  else if (varval.canConvert<QStringList>())
2411  val = varval.toStringList();
2412 
2413  return val;
2414 }
2415 
2419 QMap<QString,QString> MythCommandLineParser::toMap(const QString& key) const
2420 {
2421  QMap<QString, QString> val;
2422  QMap<QString, QVariant> tmp;
2423  if (!m_namedArgs.contains(key))
2424  return val;
2425 
2426  CommandLineArg *arg = m_namedArgs[key];
2427  if (arg == nullptr)
2428  return val;
2429 
2430  if (arg->m_given)
2431  {
2432  if (!arg->m_converted)
2433  arg->Convert();
2434 
2435  if (arg->m_stored.canConvert<QMap<QString, QVariant>>())
2436  tmp = arg->m_stored.toMap();
2437  }
2438  else
2439  {
2440  if (arg->m_default.canConvert<QMap<QString, QVariant>>())
2441  tmp = arg->m_default.toMap();
2442  }
2443 
2444  for (auto i = tmp.cbegin(); i != tmp.cend(); ++i)
2445  val[i.key()] = i.value().toString();
2446 
2447  return val;
2448 }
2449 
2453 QDateTime MythCommandLineParser::toDateTime(const QString& key) const
2454 {
2455  QDateTime val;
2456  if (!m_namedArgs.contains(key))
2457  return val;
2458 
2459  CommandLineArg *arg = m_namedArgs[key];
2460  if (arg == nullptr)
2461  return val;
2462 
2463  if (arg->m_given)
2464  {
2465  if (arg->m_stored.canConvert<QDateTime>())
2466  val = arg->m_stored.toDateTime();
2467  }
2468  else
2469  {
2470  if (arg->m_default.canConvert<QDateTime>())
2471  val = arg->m_default.toDateTime();
2472  }
2473 
2474  return val;
2475 }
2476 
2481 {
2482  if (m_namedArgs.contains("_args"))
2483  {
2484  if (!allow)
2485  m_namedArgs.remove("_args");
2486  }
2487  else if (!allow)
2488  return;
2489 
2490  auto *arg = new CommandLineArg("_args", QMetaType::QStringList, QStringList());
2491  m_namedArgs["_args"] = arg;
2492 }
2493 
2498 {
2499  if (m_namedArgs.contains("_extra"))
2500  {
2501  if (!allow)
2502  m_namedArgs.remove("_extra");
2503  }
2504  else if (!allow)
2505  return;
2506 
2507  QMap<QString,QVariant> vmap;
2508  auto *arg = new CommandLineArg("_extra", QMetaType::QVariantMap, vmap);
2509 
2510  m_namedArgs["_extra"] = arg;
2511 }
2512 
2517 {
2518  if (m_namedArgs.contains("_passthrough"))
2519  {
2520  if (!allow)
2521  m_namedArgs.remove("_passthrough");
2522  }
2523  else if (!allow)
2524  return;
2525 
2526  auto *arg = new CommandLineArg("_passthrough",
2527  QMetaType::QStringList, QStringList());
2528  m_namedArgs["_passthrough"] = arg;
2529 }
2530 
2534 {
2535  add(QStringList{"-h", "--help", "--usage"},
2536  "showhelp", "", "Display this help printout, or give detailed "
2537  "information of selected option.",
2538  "Displays a list of all commands available for use with "
2539  "this application. If another option is provided as an "
2540  "argument, it will provide detailed information on that "
2541  "option.");
2542 }
2543 
2547 {
2548  add("--version", "showversion", false, "Display version information.",
2549  "Display informtion about build, including:\n"
2550  " version, branch, protocol, library API, Qt "
2551  "and compiled options.");
2552 }
2553 
2557 {
2558  add(QStringList{"-nw", "--no-windowed"},
2559  "notwindowed", false,
2560  "Prevent application from running in a window.", "")
2561  ->SetBlocks("windowed")
2562  ->SetGroup("User Interface");
2563 
2564  add(QStringList{"-w", "--windowed"}, "windowed",
2565  false, "Force application to run in a window.", "")
2566  ->SetGroup("User Interface");
2567 }
2568 
2572 {
2573  add("--mouse-cursor", "mousecursor", false,
2574  "Force visibility of the mouse cursor.", "")
2575  ->SetBlocks("nomousecursor")
2576  ->SetGroup("User Interface");
2577 
2578  add("--no-mouse-cursor", "nomousecursor", false,
2579  "Force the mouse cursor to be hidden.", "")
2580  ->SetGroup("User Interface");
2581 }
2582 
2586 {
2587  add(QStringList{"-d", "--daemon"}, "daemon", false,
2588  "Fork application into background after startup.",
2589  "Fork application into background, detatching from "
2590  "the local terminal.\nOften used with: "
2591  " --logpath --pidfile --user");
2592 }
2593 
2598 {
2599  add(QStringList{"-O", "--override-setting"},
2600  "overridesettings", QMetaType::QVariantMap,
2601  "Override a single setting defined by a key=value pair.",
2602  "Override a single setting from the database using "
2603  "options defined as one or more key=value pairs\n"
2604  "Multiple can be defined by multiple uses of the "
2605  "-O option.");
2606  add("--override-settings-file", "overridesettingsfile", "",
2607  "Define a file of key=value pairs to be "
2608  "loaded for setting overrides.", "");
2609 }
2610 
2614 {
2615  add("--chanid", "chanid", 0U,
2616  "Specify chanid of recording to operate on.", "")
2617  ->SetRequires("starttime");
2618 
2619  add("--starttime", "starttime", QDateTime(),
2620  "Specify start time of recording to operate on.", "")
2621  ->SetRequires("chanid");
2622 }
2623 
2627 {
2628  add(QStringList{"-geometry", "--geometry"}, "geometry",
2629  "", "Specify window size and position (WxH[+X+Y])", "")
2630  ->SetGroup("User Interface");
2631 }
2632 
2636 {
2637  add("--noupnp", "noupnp", false, "Disable use of UPnP.", "");
2638 }
2639 
2643 {
2644  add("--dvbv3", "dvbv3", false, "Use legacy DVBv3 API.", "");
2645 }
2646 
2651  const QString &defaultVerbosity, LogLevel_t defaultLogLevel)
2652 {
2653  defaultLogLevel =
2654  ((defaultLogLevel >= LOG_UNKNOWN) || (defaultLogLevel <= LOG_ANY)) ?
2655  LOG_INFO : defaultLogLevel;
2656 
2657  QString logLevelStr = logLevelGetName(defaultLogLevel);
2658 
2659  add(QStringList{"-v", "--verbose"}, "verbose",
2660  defaultVerbosity,
2661  "Specify log filtering. Use '-v help' for level info.", "")
2662  ->SetGroup("Logging");
2663  add("-V", "verboseint", 0LL, "",
2664  "This option is intended for internal use only.\n"
2665  "This option takes an unsigned value corresponding "
2666  "to the bitwise log verbosity operator.")
2667  ->SetGroup("Logging");
2668  add("--logpath", "logpath", "",
2669  "Writes logging messages to a file in the directory logpath with "
2670  "filenames in the format: applicationName.date.pid.log.\n"
2671  "This is typically used in combination with --daemon, and if used "
2672  "in combination with --pidfile, this can be used with log "
2673  "rotators, using the HUP call to inform MythTV to reload the "
2674  "file", "")
2675  ->SetGroup("Logging");
2676  add(QStringList{"-q", "--quiet"}, "quiet", 0,
2677  "Don't log to the console (-q). Don't log anywhere (-q -q)", "")
2678  ->SetGroup("Logging");
2679  add("--loglevel", "loglevel", logLevelStr,
2680  QString(
2681  "Set the logging level. All log messages at lower levels will be "
2682  "discarded.\n"
2683  "In descending order: emerg, alert, crit, err, warning, notice, "
2684  "info, debug\ndefaults to ") + logLevelStr, "")
2685  ->SetGroup("Logging");
2686  add("--syslog", "syslog", "none",
2687  "Set the syslog logging facility.\nSet to \"none\" to disable, "
2688  "defaults to none.", "")
2689  ->SetGroup("Logging");
2690 #if CONFIG_SYSTEMD_JOURNAL
2691  add("--systemd-journal", "systemd-journal", "false",
2692  "Use systemd-journal instead of syslog.", "")
2693  ->SetBlocks(QStringList()
2694  << "syslog"
2695  )
2696  ->SetGroup("Logging");
2697 #endif
2698  add("--nodblog", "nodblog", false, "Disable database logging.", "")
2699  ->SetGroup("Logging")
2700  ->SetDeprecated("this is now the default, see --enable-dblog");
2701  add("--enable-dblog", "enabledblog", false, "Enable logging to database.", "")
2702  ->SetGroup("Logging");
2703 
2704  add(QStringList{"-l", "--logfile"},
2705  "logfile", "", "", "")
2706  ->SetGroup("Logging")
2707  ->SetRemoved("This option has been removed as part of "
2708  "rewrite of the logging interface. Please update your init "
2709  "scripts to use --syslog to interface with your system's "
2710  "existing system logging daemon, or --logpath to specify a "
2711  "dirctory for MythTV to write its logs to.", "0.25");
2712 }
2713 
2717 {
2718  add(QStringList{"-p", "--pidfile"}, "pidfile", "",
2719  "Write PID of application to filename.",
2720  "Write the PID of the currently running process as a single "
2721  "line to this file. Used for init scripts to know what "
2722  "process to terminate, and with log rotators "
2723  "to send a HUP signal to process to have it re-open files.");
2724 }
2725 
2729 {
2730  add(QStringList{"-j", "--jobid"}, "jobid", 0, "",
2731  "Intended for internal use only, specify the JobID to match "
2732  "up with in the database for additional information and the "
2733  "ability to update runtime status in the database.");
2734 }
2735 
2739 {
2740  add("--infile", "infile", "", "Input file URI", "");
2741  if (addOutFile)
2742  add("--outfile", "outfile", "", "Output file URI", "");
2743 }
2744 
2748 {
2749 #ifdef USING_X11
2750  add(QStringList{"-display", "--display"}, "display", "",
2751  "Qt (QPA) X11 connection name when using xcb (X11) platform plugin", "")
2752  ->SetGroup("Qt");
2753 #endif
2754 }
2755 
2759 {
2760  add(QStringList{"-platform", "--platform"}, "platform", "", "Qt (QPA) platform argument",
2761  "Qt platform argument that is passed through to Qt")
2762  ->SetGroup("Qt");
2763 }
2764 
2768 {
2769  QString logfile = toString("logpath");
2770  pid_t pid = getpid();
2771 
2772  if (logfile.isEmpty())
2773  return logfile;
2774 
2775  QFileInfo finfo(logfile);
2776  if (!finfo.isDir())
2777  {
2778  LOG(VB_GENERAL, LOG_ERR,
2779  QString("%1 is not a directory, disabling logfiles")
2780  .arg(logfile));
2781  return QString();
2782  }
2783 
2784  QString logdir = finfo.filePath();
2785  logfile = QCoreApplication::applicationName() + "." +
2787  QString(".%1").arg(pid) + ".log";
2788 
2789  SetValue("logdir", logdir);
2790  SetValue("logfile", logfile);
2791  SetValue("filepath", QFileInfo(QDir(logdir), logfile).filePath());
2792 
2793  return toString("filepath");
2794 }
2795 
2799 {
2800  QString setting = toString("syslog").toLower();
2801  if (setting == "none")
2802  return -2;
2803 
2804  return syslogGetFacility(setting);
2805 }
2806 
2810 {
2811  QString setting = toString("loglevel");
2812  if (setting.isEmpty())
2813  return LOG_INFO;
2814 
2815  LogLevel_t level = logLevelGet(setting);
2816  if (level == LOG_UNKNOWN)
2817  std::cerr << "Unknown log level: " << setting.toLocal8Bit().constData()
2818  << std::endl;
2819 
2820  return level;
2821 }
2822 
2827 bool MythCommandLineParser::SetValue(const QString &key, const QVariant& value)
2828 {
2829  CommandLineArg *arg = nullptr;
2830 
2831  if (!m_namedArgs.contains(key))
2832  {
2833  const QVariant& val(value);
2834 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
2835  auto type = static_cast<QMetaType::Type>(val.type());
2836 #else
2837  auto type = static_cast<QMetaType::Type>(val.typeId());
2838 #endif
2839  arg = new CommandLineArg(key, type, val);
2840  m_namedArgs.insert(key, arg);
2841  }
2842  else
2843  {
2844  arg = m_namedArgs[key];
2845 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
2846  auto type = static_cast<QMetaType::Type>(value.type());
2847 #else
2848  auto type = value.typeId();
2849 #endif
2850  if (arg->m_type != type)
2851  return false;
2852  }
2853 
2854  arg->Set(value);
2855  return true;
2856 }
2857 
2861 {
2862  int err = 0;
2863 
2864  // Setup the defaults
2865  verboseString = "";
2866  verboseMask = 0;
2867  verboseArgParse(mask);
2868 
2869  if (toBool("verbose"))
2870  {
2871  if ((err = verboseArgParse(toString("verbose"))) != 0)
2872  return err;
2873  }
2874  else if (toBool("verboseint"))
2875  verboseMask = static_cast<uint64_t>(toLongLong("verboseint"));
2876 
2877  verboseMask |= VB_STDIO|VB_FLUSH;
2878 
2879  int quiet = toInt("quiet");
2880  if (std::max(quiet, static_cast<int>(progress)) > 1)
2881  {
2882  verboseMask = VB_NONE|VB_FLUSH;
2883  verboseArgParse("none");
2884  }
2885 
2886  int facility = GetSyslogFacility();
2887 #if CONFIG_SYSTEMD_JOURNAL
2888  bool journal = toBool("systemd-journal");
2889  if (journal)
2890  {
2891  if (facility >= 0)
2893  facility = SYSTEMD_JOURNAL_FACILITY;
2894  }
2895 #endif
2896  bool dblog = toBool("enabledblog");
2897  LogLevel_t level = GetLogLevel();
2898  if (level == LOG_UNKNOWN)
2900 
2901  LOG(VB_GENERAL, LOG_CRIT,
2902  QString("%1 version: %2 [%3] www.mythtv.org")
2903  .arg(QCoreApplication::applicationName(),
2905  LOG(VB_GENERAL, LOG_CRIT, QString("Qt version: compile: %1, runtime: %2")
2906  .arg(QT_VERSION_STR, qVersion()));
2907  LOG(VB_GENERAL, LOG_INFO, QString("%1 (%2)")
2908  .arg(QSysInfo::prettyProductName(), QSysInfo::currentCpuArchitecture()));
2909  LOG(VB_GENERAL, LOG_NOTICE,
2910  QString("Enabled verbose msgs: %1").arg(verboseString));
2911 
2912  QString logfile = GetLogFilePath();
2913  bool propagate = !logfile.isEmpty();
2914 
2915  if (toBool("daemon"))
2916  quiet = std::max(quiet, 1);
2917 
2918  logStart(logfile, progress, quiet, facility, level, dblog, propagate);
2919  qInstallMessageHandler([](QtMsgType /*unused*/, const QMessageLogContext& /*unused*/, const QString &Msg)
2920  { LOG(VB_GENERAL, LOG_INFO, "Qt: " + Msg); });
2921 
2922  return GENERIC_EXIT_OK;
2923 }
2924 
2930 {
2931  if (m_verbose)
2932  std::cerr << "Applying settings override" << std::endl;
2933 
2934  QMap<QString, QString> override = GetSettingsOverride();
2935  if (!override.empty())
2936  {
2937  QMap<QString, QString>::iterator it;
2938  for (it = override.begin(); it != override.end(); ++it)
2939  {
2940  LOG(VB_GENERAL, LOG_NOTICE,
2941  QString("Setting '%1' being forced to '%2'")
2942  .arg(it.key(), *it));
2943  gCoreContext->OverrideSettingForSession(it.key(), *it);
2944  }
2945  }
2946 }
2947 
2948 static bool openPidfile(std::ofstream &pidfs, const QString &pidfile)
2949 {
2950  if (!pidfile.isEmpty())
2951  {
2952  pidfs.open(pidfile.toLatin1().constData());
2953  if (!pidfs)
2954  {
2955  std::cerr << "Could not open pid file: " << ENO_STR << std::endl;
2956  return false;
2957  }
2958  }
2959  return true;
2960 }
2961 
2964 static bool setUser(const QString &username)
2965 {
2966  if (username.isEmpty())
2967  return true;
2968 
2969 #ifdef _WIN32
2970  std::cerr << "--user option is not supported on Windows" << std::endl;
2971  return false;
2972 #else // ! _WIN32
2973 #if defined(__linux__) || defined(__LINUX__)
2974  // Check the current dumpability of core dumps, which will be disabled
2975  // by setuid, so we can re-enable, if appropriate
2976  int dumpability = prctl(PR_GET_DUMPABLE);
2977 #endif
2978  struct passwd *user_info = getpwnam(username.toLocal8Bit().constData());
2979  const uid_t user_id = geteuid();
2980 
2981  if (user_id && (!user_info || user_id != user_info->pw_uid))
2982  {
2983  std::cerr << "You must be running as root to use the --user switch." << std::endl;
2984  return false;
2985  }
2986  if (user_info && user_id == user_info->pw_uid)
2987  {
2988  LOG(VB_GENERAL, LOG_WARNING,
2989  QString("Already running as '%1'").arg(username));
2990  }
2991  else if (!user_id && user_info)
2992  {
2993  if (setenv("HOME", user_info->pw_dir,1) == -1)
2994  {
2995  std::cerr << "Error setting home directory." << std::endl;
2996  return false;
2997  }
2998  if (setgid(user_info->pw_gid) == -1)
2999  {
3000  std::cerr << "Error setting effective group." << std::endl;
3001  return false;
3002  }
3003  if (initgroups(user_info->pw_name, user_info->pw_gid) == -1)
3004  {
3005  std::cerr << "Error setting groups." << std::endl;
3006  return false;
3007  }
3008  if (setuid(user_info->pw_uid) == -1)
3009  {
3010  std::cerr << "Error setting effective user." << std::endl;
3011  return false;
3012  }
3013 #if defined(__linux__) || defined(__LINUX__)
3014  if (dumpability && (prctl(PR_SET_DUMPABLE, dumpability) == -1))
3015  {
3016  LOG(VB_GENERAL, LOG_WARNING, "Unable to re-enable core file "
3017  "creation. Run without the --user argument to use "
3018  "shell-specified limits.");
3019  }
3020 #endif
3021  }
3022  else
3023  {
3024  std::cerr << QString("Invalid user '%1' specified with --user")
3025  .arg(username).toLocal8Bit().constData() << std::endl;
3026  return false;
3027  }
3028  return true;
3029 #endif // ! _WIN32
3030 }
3031 
3032 
3036 {
3037  std::ofstream pidfs;
3038  if (!openPidfile(pidfs, toString("pidfile")))
3040 
3041  if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
3042  LOG(VB_GENERAL, LOG_WARNING, "Unable to ignore SIGPIPE");
3043 
3044 #ifdef Q_OS_DARWIN
3045  if (toBool("daemon"))
3046  {
3047  std::cerr << "Daemonizing is unavailable in OSX" << std::endl;
3048  LOG(VB_GENERAL, LOG_WARNING, "Unable to daemonize");
3049  }
3050 #else
3051  if (toBool("daemon") && (daemon(0, 1) < 0))
3052  {
3053  std::cerr << "Failed to daemonize: " << ENO_STR << std::endl;
3055  }
3056 #endif
3057 
3058  QString username = toString("username");
3059  if (!username.isEmpty() && !setUser(username))
3061 
3062  if (pidfs)
3063  {
3064  pidfs << getpid() << std::endl;
3065  pidfs.close();
3066  }
3067 
3068  return GENERIC_EXIT_OK;
3069 }
pidfile
QString pidfile
Definition: mythjobqueue.cpp:44
MythCommandLineParser::addDisplay
void addDisplay(void)
Canned argument definition for -display.
Definition: mythcommandlineparser.cpp:2747
MythCommandLineParser::addGeometry
void addGeometry(void)
Canned argument definition for –geometry.
Definition: mythcommandlineparser.cpp:2626
setuid
#define setuid(x)
Definition: compat.h:181
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:85
MythCommandLineParser::Result
Result
Definition: mythcommandlineparser.h:121
CommandLineArg::SetChild
CommandLineArg * SetChild(const QString &opt)
Set argument as parent of given child.
Definition: mythcommandlineparser.cpp:715
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:681
MythCommandLineParser::m_appname
QString m_appname
Definition: mythcommandlineparser.h:271
MythCommandLineParser::operator[]
QVariant operator[](const QString &name)
Returned stored QVariant for given argument, or default value if not used.
Definition: mythcommandlineparser.cpp:2069
openPidfile
static bool openPidfile(std::ofstream &pidfs, const QString &pidfile)
Definition: mythcommandlineparser.cpp:2948
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:2516
CommandLineArg::AllowOneOf
static void AllowOneOf(const QList< CommandLineArg * > &args)
Mark a list of arguments as mutually exclusive.
Definition: mythcommandlineparser.cpp:942
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:2419
MythCommandLineParser::Result::kOptVal
@ kOptVal
CommandLineArg::CommandLineArg
CommandLineArg(const QString &name, QMetaType::Type type, QVariant def, QString help, QString longhelp)
Default constructor for CommandLineArg class.
Definition: mythcommandlineparser.cpp:286
CommandLineArg::GetKeywordLength
int GetKeywordLength(void) const
Return length of full keyword string for use in determining indent of help text.
Definition: mythcommandlineparser.cpp:338
MythCommandLineParser::m_verbose
bool m_verbose
Definition: mythcommandlineparser.h:276
progress
bool progress
Definition: mythcommflag.cpp:69
k_defaultWidth
static constexpr int k_defaultWidth
Definition: mythcommandlineparser.cpp:82
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:364
MythCommandLineParser::addPlatform
void addPlatform(void)
Pass through the platform argument to Qt for GUI applications.
Definition: mythcommandlineparser.cpp:2758
MythCommandLineParser::~MythCommandLineParser
virtual ~MythCommandLineParser()
Definition: mythcommandlineparser.cpp:1288
MythCommandLineParser::Result::kPassthrough
@ kPassthrough
MythCoreContext::OverrideSettingForSession
void OverrideSettingForSession(const QString &key, const QString &value)
Definition: mythcorecontext.cpp:1360
GetTermWidth
static int GetTermWidth(void)
returns terminal width, or 79 on error
Definition: mythcommandlineparser.cpp:87
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:2302
CommandLineArg::m_removedversion
QString m_removedversion
Definition: mythcommandlineparser.h:98
GetMythSourceVersion
const char * GetMythSourceVersion()
Definition: mythversion.cpp:5
MythCommandLineParser::addPIDFile
void addPIDFile(void)
Canned argument definition for –pidfile.
Definition: mythcommandlineparser.cpp:2716
CommandLineArg::PrintVerbose
void PrintVerbose(void) const
Internal use.
Definition: mythcommandlineparser.cpp:1147
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:682
syslogGetFacility
int syslogGetFacility(const QString &facility)
Map a syslog facility name back to the enumerated value.
Definition: logging.cpp:769
setenv
#define setenv(x, y, z)
Definition: compat.h:87
MythCommandLineParser::addVersion
void addVersion(void)
Canned argument definition for –version.
Definition: mythcommandlineparser.cpp:2546
CommandLineArg::m_removed
QString m_removed
Definition: mythcommandlineparser.h:97
quiet
int quiet
Definition: mythcommflag.cpp:68
CommandLineArg::SetRequires
CommandLineArg * SetRequires(const QString &opt)
Set argument as requiring given option.
Definition: mythcommandlineparser.cpp:774
MythCommandLineParser::ReconcileLinks
bool ReconcileLinks(void)
Replace dummy arguments used to define interdependency with pointers to their real counterparts.
Definition: mythcommandlineparser.cpp:1912
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
wrapList
static void wrapList(QStringList &list, int width)
Definition: mythcommandlineparser.cpp:108
CommandLineArg::m_default
QVariant m_default
Definition: mythcommandlineparser.h:100
MythCommandLineParser::m_overridesImported
bool m_overridesImported
Definition: mythcommandlineparser.h:275
logfile
QString logfile
Definition: mythjobqueue.cpp:45
MythCommandLineParser::addWindowed
void addWindowed(void)
Canned argument definition for –windowed and -no-windowed.
Definition: mythcommandlineparser.cpp:2556
force
bool force
Definition: mythcommflag.cpp:70
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:732
MythCommandLineParser::m_optionedArgs
QMap< QString, CommandLineArg * > m_optionedArgs
Definition: mythcommandlineparser.h:272
MythCommandLineParser::m_namedArgs
QMap< QString, CommandLineArg * > m_namedArgs
Definition: mythcommandlineparser.h:273
MythCommandLineParser::GetHelpString
QString GetHelpString(void) const
Generate command line option help text.
Definition: mythcommandlineparser.cpp:1408
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:2613
MythDate::current
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:15
MythCommandLineParser::Result::kArg
@ kArg
tmp
static guint32 * tmp
Definition: goom_core.cpp:32
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:2650
mythversion.h
CommandLineArg::GetLongHelpString
QString GetLongHelpString(QString keyword) const
Return string containing extended help text.
Definition: mythcommandlineparser.cpp:438
CommandLineArg::SetRemoved
CommandLineArg * SetRemoved(QString remstr="", QString remver="")
Set option as removed.
Definition: mythcommandlineparser.cpp:818
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:664
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:698
MythCommandLineParser::Parse
virtual bool Parse(int argc, const char *const *argv)
Loop through argv and populate arguments with values.
Definition: mythcommandlineparser.cpp:1553
MythCommandLineParser::add
CommandLineArg * add(const QString &arg, const QString &name, bool def, QString help, QString longhelp)
Definition: mythcommandlineparser.cpp:1769
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:2571
mythlogging.h
logLevelGetName
QString logLevelGetName(LogLevel_t level)
Map a log level enumerated value back to the name.
Definition: logging.cpp:818
CommandLineArg::m_deprecated
QString m_deprecated
Definition: mythcommandlineparser.h:96
MythDate::kFilename
@ kFilename
Default UTC, "yyyyMMddhhmmss".
Definition: mythdate.h:18
MythCommandLineParser::getOpt
Result getOpt(int argc, const char *const *argv, int &argpos, QString &opt, QByteArray &val)
Internal use.
Definition: mythcommandlineparser.cpp:1472
MythCommandLineParser::Result::kInvalid
@ kInvalid
verboseMask
uint64_t verboseMask
Definition: logging.cpp:101
daemon
#define daemon(x, y)
Definition: compat.h:186
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:1276
logLevelGet
LogLevel_t logLevelGet(const QString &level)
Map a log level name back to the enumerated value.
Definition: logging.cpp:796
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:753
CommandLineArg::Set
bool Set(const QString &opt)
Set option as provided on command line with no value.
Definition: mythcommandlineparser.cpp:548
MythCommandLineParser::GetArgs
QStringList GetArgs(void) const
Return list of additional values provided on the command line independent of any keyword.
Definition: mythcommandlineparser.cpp:2088
MythCommandLineParser::m_passthroughActive
bool m_passthroughActive
Definition: mythcommandlineparser.h:274
SIGPIPE
#define SIGPIPE
Definition: compat.h:137
MythCommandLineParser::PrintVersion
static void PrintVersion(void)
Print application version information.
Definition: mythcommandlineparser.cpp:1381
CommandLineArg::GetName
QString GetName(void) const
Definition: mythcommandlineparser.h:34
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:2096
CommandLineArg::PrintDeprecatedWarning
void PrintDeprecatedWarning(QString &keyword) const
Internal use.
Definition: mythcommandlineparser.cpp:1253
MythCommandLineParser::toUInt
uint toUInt(const QString &key) const
Returns stored QVariant as an unsigned integer, falling to default if not provided.
Definition: mythcommandlineparser.cpp:2248
CommandLineArg::m_requires
QList< CommandLineArg * > m_requires
Definition: mythcommandlineparser.h:108
MythCommandLineParser::PrintHelp
void PrintHelp(void) const
Print command line option help.
Definition: mythcommandlineparser.cpp:1397
MythCommandLineParser::Daemonize
int Daemonize(void) const
Fork application into background, and detatch from terminal.
Definition: mythcommandlineparser.cpp:3035
MythCommandLineParser::MythSplitCommandString
static QStringList MythSplitCommandString(const QString &line)
Parse a string into separate tokens.
Definition: mythcommandlineparser.cpp:158
uint
unsigned int uint
Definition: compat.h:79
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:61
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:2798
MythCommandLineParser::ApplySettingsOverride
void ApplySettingsOverride(void)
Apply all overrides to the global context.
Definition: mythcommandlineparser.cpp:2929
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:2115
CommandLineArg::GetPreferredKeyword
QString GetPreferredKeyword(void) const
Return the longest keyword for the argument.
Definition: mythcommandlineparser.cpp:1032
CommandLineArg::TestLinks
bool TestLinks(void) const
Test all related arguments to make sure specified requirements are fulfilled.
Definition: mythcommandlineparser.cpp:1054
CommandLineArg::SetBlocks
CommandLineArg * SetBlocks(const QString &opt)
Set argument as incompatible with given option.
Definition: mythcommandlineparser.cpp:791
GetMythSourcePath
const char * GetMythSourcePath()
Definition: mythversion.cpp:10
MythDate::fromString
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
Definition: mythdate.cpp:35
nv_python_libs.vimeo.vimeo_api.user_info
def user_info(user, format="xml")
Definition: vimeo_api.py:517
strip_quotes
static QByteArray strip_quotes(const QByteArray &array)
Definition: mythcommandlineparser.cpp:101
verboseArgParse
int verboseArgParse(const QString &arg)
Parse the –verbose commandline argument and set the verbose level.
Definition: logging.cpp:944
CommandLineArg::m_type
QMetaType::Type m_type
Definition: mythcommandlineparser.h:99
CommandLineArg::CleanupLinks
void CleanupLinks(void)
Clear out references to other arguments in preparation for deletion.
Definition: mythcommandlineparser.cpp:1126
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:1237
MythCommandLineParser::allowArgs
void allowArgs(bool allow=true)
Specify that parser should allow and collect values provided independent of any keyword.
Definition: mythcommandlineparser.cpp:2480
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:2356
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:2533
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:2827
MythCommandLineParser::toBool
bool toBool(const QString &key) const
Returns stored QVariant as a boolean.
Definition: mythcommandlineparser.cpp:2199
MythCommandLineParser::GetLogLevel
LogLevel_t GetLogLevel(void) const
Helper utility for logging interface to filtering level.
Definition: mythcommandlineparser.cpp:2809
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:2275
std
Definition: mythchrono.h:23
MythDate::ISODate
@ ISODate
Default UTC.
Definition: mythdate.h:17
CommandLineArg::AddKeyword
void AddKeyword(const QString &keyword)
Definition: mythcommandlineparser.h:32
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:2387
MythCommandLineParser::NamedOptType
static const char * NamedOptType(Result type)
Definition: mythcommandlineparser.cpp:221
logging.h
setUser
static bool setUser(const QString &username)
Drop permissions to the specified user.
Definition: mythcommandlineparser.cpp:2964
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:2728
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:2329
MythCommandLineParser::GetLogFilePath
QString GetLogFilePath(void)
Helper utility for logging interface to pull path from –logpath.
Definition: mythcommandlineparser.cpp:2767
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:2860
MythCommandLineParser::addSettingsOverride
void addSettingsOverride(void)
Canned argument definition for –override-setting and –override-settings-file.
Definition: mythcommandlineparser.cpp:2597
CommandLineArg::SetDeprecated
CommandLineArg * SetDeprecated(QString depstr="")
Set option as deprecated.
Definition: mythcommandlineparser.cpp:808
MythCommandLineParser::GetHelpHeader
virtual QString GetHelpHeader(void) const
Definition: mythcommandlineparser.h:141
MythCommandLineParser::LoadArguments
virtual void LoadArguments(void)
Definition: mythcommandlineparser.h:137
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:2497
MythCommandLineParser::addUPnP
void addUPnP(void)
Canned argument definition for –noupnp.
Definition: mythcommandlineparser.cpp:2635
MythCommandLineParser::addDaemon
void addDaemon(void)
Canned argument definition for –daemon.
Definition: mythcommandlineparser.cpp:2585
geteuid
#define geteuid()
Definition: compat.h:180
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:2221
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:2642
build_compdb.filename
filename
Definition: build_compdb.py:21
START
#define START
Definition: freesat_huffman.cpp:3
mythcommandlineparser.h
MythCommandLineParser::GetPassthrough
QString GetPassthrough(void) const
Return any text supplied on the command line after a bare '–'.
Definition: mythcommandlineparser.cpp:2103
MythCommandLineParser::Result::kEnd
@ kEnd
MythCommandLineParser::Result::kCombOptVal
@ kCombOptVal
MythCommandLineParser::toDateTime
QDateTime toDateTime(const QString &key) const
Returns stored QVariant as a QDateTime, falling to default if not provided.
Definition: mythcommandlineparser.cpp:2453
MythCommandLineParser::addInFile
void addInFile(bool addOutFile=false)
Canned argument definition for –infile and –outfile.
Definition: mythcommandlineparser.cpp:2738
CommandLineArg::Convert
void Convert(void)
Convert stored string value from QByteArray to QString.
Definition: mythcommandlineparser.cpp:970
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:328