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