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