MythTV  master
mythmiscutil.cpp
Go to the documentation of this file.
1 #ifdef _WIN32
2  #include <sys/stat.h>
3 #endif
4 
5 #include "mythmiscutil.h"
6 
7 // C++ headers
8 #include <array>
9 #include <cerrno>
10 #include <cstdlib>
11 #include <ctime>
12 #include <iostream>
13 
14 // POSIX
15 #include <unistd.h>
16 #include <fcntl.h>
17 #include <sched.h>
18 
19 // System specific C headers
20 #include "compat.h"
21 #include <QtGlobal>
22 
23 #ifdef __linux__
24 #include <sys/vfs.h>
25 #include <sys/sysinfo.h>
26 #include <sys/stat.h> // for umask, chmod
27 #endif
28 
29 #ifdef Q_OS_DARWIN
30 #include <mach/mach.h>
31 #endif
32 
33 #ifdef BSD
34 #include <sys/mount.h> // for struct statfs
35 #include <sys/sysctl.h>
36 #include <sys/stat.h> // for umask, chmod
37 #endif
38 
39 // Qt headers
40 #include <QReadWriteLock>
41 #include <QNetworkProxy>
42 #include <QStringList>
43 #include <QDataStream>
44 #include <QUdpSocket>
45 #include <QFileInfo>
46 #include <QFile>
47 #include <QDir>
48 #include <QUrl>
49 #include <QHostAddress>
50 #include <QRegularExpression>
51 #include <QRegularExpressionMatchIterator>
52 
53 // Myth headers
54 #include "mythcorecontext.h"
55 #include "exitcodes.h"
56 #include "mythlogging.h"
57 #include "mythsocket.h"
58 #include "mythcoreutil.h"
59 #include "mythsystemlegacy.h"
60 
61 
66 bool getUptime(std::chrono::seconds &uptime)
67 {
68 #ifdef __linux__
69  struct sysinfo sinfo {};
70  if (sysinfo(&sinfo) == -1)
71  {
72  LOG(VB_GENERAL, LOG_ERR, "sysinfo() error");
73  return false;
74  }
75  uptime = std::chrono::seconds(sinfo.uptime);
76 
77 #elif defined(__FreeBSD__) || defined(Q_OS_DARWIN)
78 
79  std::array<int,2> mib { CTL_KERN, KERN_BOOTTIME };
80  struct timeval bootTime;
81  size_t len;
82 
83  // Uptime is calculated. Get this machine's boot time
84  // and subtract it from the current machine time
85  len = sizeof(bootTime);
86  if (sysctl(mib.data(), 2, &bootTime, &len, nullptr, 0) == -1)
87  {
88  LOG(VB_GENERAL, LOG_ERR, "sysctl() error");
89  return false;
90  }
91  uptime = std::chrono::seconds(time(nullptr) - bootTime.tv_sec);
92 #elif defined(_WIN32)
93  uptime = std::chrono::seconds(::GetTickCount() / 1000);
94 #else
95  // Hmmm. Not Linux, not FreeBSD or Darwin. What else is there :-)
96  LOG(VB_GENERAL, LOG_NOTICE, "Unknown platform. How do I get the uptime?");
97  return false;
98 #endif
99 
100  return true;
101 }
102 
109 bool getMemStats([[maybe_unused]] int &totalMB,
110  [[maybe_unused]] int &freeMB,
111  [[maybe_unused]] int &totalVM,
112  [[maybe_unused]] int &freeVM)
113 {
114 #ifdef __linux__
115  static constexpr size_t MB { 1024LL * 1024 };
116  struct sysinfo sinfo {};
117  if (sysinfo(&sinfo) == -1)
118  {
119  LOG(VB_GENERAL, LOG_ERR,
120  "getMemStats(): Error, sysinfo() call failed.");
121  return false;
122  }
123 
124  totalMB = (int)((sinfo.totalram * sinfo.mem_unit)/MB);
125  freeMB = (int)((sinfo.freeram * sinfo.mem_unit)/MB);
126  totalVM = (int)((sinfo.totalswap * sinfo.mem_unit)/MB);
127  freeVM = (int)((sinfo.freeswap * sinfo.mem_unit)/MB);
128  return true;
129 #elif defined(Q_OS_DARWIN)
130  mach_port_t mp;
131  mach_msg_type_number_t count;
132  vm_size_t pageSize;
133  vm_statistics_data_t s;
134 
135  mp = mach_host_self();
136 
137  // VM page size
138  if (host_page_size(mp, &pageSize) != KERN_SUCCESS)
139  pageSize = 4096; // If we can't look it up, 4K is a good guess
140 
141  count = HOST_VM_INFO_COUNT;
142  if (host_statistics(mp, HOST_VM_INFO,
143  (host_info_t)&s, &count) != KERN_SUCCESS)
144  {
145  LOG(VB_GENERAL, LOG_ERR, "getMemStats(): Error, "
146  "failed to get virtual memory statistics.");
147  return false;
148  }
149 
150  pageSize >>= 10; // This gives usages in KB
151  totalMB = (s.active_count + s.inactive_count +
152  s.wire_count + s.free_count) * pageSize / 1024;
153  freeMB = s.free_count * pageSize / 1024;
154 
155 
156  // This is a real hack. I have not found a way to ask the kernel how much
157  // swap it is using, and the dynamic_pager daemon doesn't even seem to be
158  // able to report what filesystem it is using for the swapfiles. So, we do:
159  int64_t total, used, free;
160  free = getDiskSpace("/private/var/vm", total, used);
161  totalVM = (int)(total >> 10);
162  freeVM = (int)(free >> 10);
163  return true;
164 #else
165  return false;
166 #endif
167 }
168 
176 {
177 #if !defined(_WIN32) && !defined(Q_OS_ANDROID)
178  loadArray loads {};
179  if (getloadavg(loads.data(), loads.size()) != -1)
180  return loads;
181 #endif
182  return {-1, -1, -1};
183 }
184 
199 bool ping(const QString &host, std::chrono::milliseconds timeout)
200 {
201 #ifdef _WIN32
202  QString cmd = QString("%systemroot%\\system32\\ping.exe -w %1 -n 1 %2>NUL")
203  .arg(timeout.count()) .arg(host);
204 
207 #else
208  QString addrstr =
210  QHostAddress addr = QHostAddress(addrstr);
211 #if defined(__FreeBSD__) || defined(Q_OS_DARWIN)
212  QString timeoutparam("-t");
213 #else
214  // Linux, NetBSD, OpenBSD
215  QString timeoutparam("-w");
216 #endif // UNIX-like
217  QString pingcmd =
218  addr.protocol() == QAbstractSocket::IPv6Protocol ? "ping6" : "ping";
219  QString cmd = QString("%1 %2 %3 -c 1 %4 >/dev/null 2>&1")
220  .arg(pingcmd, timeoutparam,
221  QString::number(duration_cast<std::chrono::seconds>(timeout).count()),
222  host);
223 
226 #endif // _WIN32
227 }
228 
232 bool telnet(const QString &host, int port)
233 {
234  auto *s = new MythSocket();
235 
236  bool connected = s->ConnectToHost(host, port);
237  s->DecrRef();
238 
239  return connected;
240 }
241 
263 long long MythFile::copy(QFile &dst, QFile &src, uint block_size)
264 {
265  uint buflen = (block_size < 1024) ? (16 * 1024) : block_size;
266  char *buf = new char[buflen];
267  bool odst = false;
268  bool osrc = false;
269 
270  if (!buf)
271  return -1LL;
272 
273  if (!dst.isWritable() && !dst.isOpen())
274  {
275  odst = dst.open(QIODevice::Unbuffered |
276  QIODevice::WriteOnly |
277  QIODevice::Truncate);
278  }
279 
280  if (!src.isReadable() && !src.isOpen())
281  osrc = src.open(QIODevice::Unbuffered|QIODevice::ReadOnly);
282 
283  bool ok = dst.isWritable() && src.isReadable();
284  long long total_bytes = 0LL;
285  while (ok)
286  {
287  long long off = 0;
288  long long rlen = src.read(buf, buflen);
289  if (rlen<0)
290  {
291  LOG(VB_GENERAL, LOG_ERR, "read error");
292  ok = false;
293  break;
294  }
295  if (rlen==0)
296  break;
297 
298  total_bytes += rlen;
299 
300  while ((rlen-off>0) && ok)
301  {
302  long long wlen = dst.write(buf + off, rlen - off);
303  if (wlen>=0)
304  off+= wlen;
305  if (wlen<0)
306  {
307  LOG(VB_GENERAL, LOG_ERR, "write error");
308  ok = false;
309  }
310  }
311  }
312  delete[] buf;
313 
314  if (odst)
315  dst.close();
316 
317  if (osrc)
318  src.close();
319 
320  return (ok) ? total_bytes : -1LL;
321 }
322 
323 QString createTempFile(QString name_template, bool dir)
324 {
325  int ret = -1;
326 
327 #ifdef _WIN32
328  char temppath[MAX_PATH] = ".";
329  char tempfilename[MAX_PATH] = "";
330  // if GetTempPath fails, use current dir
331  GetTempPathA(MAX_PATH, temppath);
332  if (GetTempFileNameA(temppath, "mth", 0, tempfilename))
333  {
334  if (dir)
335  {
336  // GetTempFileNameA creates the file, so delete it before mkdir
337  unlink(tempfilename);
338  ret = mkdir(tempfilename);
339  }
340  else
341  ret = open(tempfilename, O_CREAT | O_RDWR, S_IREAD | S_IWRITE);
342  }
343  QString tmpFileName(tempfilename);
344 #else
345  QByteArray safe_name_template = name_template.toLatin1();
346  const char *tmp = safe_name_template.constData();
347  char *ctemplate = strdup(tmp);
348 
349  if (dir)
350  {
351  ret = (mkdtemp(ctemplate)) ? 0 : -1;
352  }
353  else
354  {
355  mode_t cur_umask = umask(S_IRWXO | S_IRWXG);
356  ret = mkstemp(ctemplate);
357  umask(cur_umask);
358  }
359 
360  QString tmpFileName(ctemplate);
361  free(ctemplate);
362 #endif
363 
364  if (ret == -1)
365  {
366  LOG(VB_GENERAL, LOG_ERR, QString("createTempFile(%1), Error ")
367  .arg(name_template) + ENO);
368  return name_template;
369  }
370 
371  if (!dir && (ret >= 0))
372  close(ret);
373 
374  return tmpFileName;
375 }
376 
395 bool makeFileAccessible(const QString& filename)
396 {
397  QByteArray fname = filename.toLatin1();
398  int ret = chmod(fname.constData(), 0666);
399  if (ret == -1)
400  {
401  LOG(VB_GENERAL, LOG_ERR, QString("Unable to change permissions on file. (%1)").arg(filename));
402  return false;
403  }
404  return true;
405 }
406 
410 QString getResponse(const QString &query, const QString &def)
411 {
412  QByteArray tmp = query.toLocal8Bit();
413  std::cout << tmp.constData();
414 
415  tmp = def.toLocal8Bit();
416  if (!def.isEmpty())
417  std::cout << " [" << tmp.constData() << "] ";
418  else
419  std::cout << " ";
420 
421  if (!isatty(fileno(stdin)) || !isatty(fileno(stdout)))
422  {
423  std::cout << std::endl << "[console is not interactive, using default '"
424  << tmp.constData() << "']" << std::endl;
425  return def;
426  }
427 
428  QTextStream stream(stdin);
429  QString qresponse = stream.readLine();
430 
431  if (qresponse.isEmpty())
432  qresponse = def;
433 
434  return qresponse;
435 }
436 
440 int intResponse(const QString &query, int def)
441 {
442  QString str_resp = getResponse(query, QString("%1").arg(def));
443  if (str_resp.isEmpty())
444  return def;
445  bool ok = false;
446  int resp = str_resp.toInt(&ok);
447  return (ok ? resp : def);
448 }
449 
450 
451 QString getSymlinkTarget(const QString &start_file,
452  QStringList *intermediaries,
453  unsigned maxLinks)
454 {
455 #if 0
456  LOG(VB_GENERAL, LOG_DEBUG,
457  QString("getSymlinkTarget('%1', 0x%2, %3)")
458  .arg(start_file).arg((uint64_t)intermediaries,0,16)
459  .arg(maxLinks));
460 #endif
461 
462  QString link;
463  QString cur_file = start_file;
464  QFileInfo fi(cur_file);
465 
466  if (intermediaries)
467  {
468  intermediaries->clear();
469  intermediaries->push_back(start_file);
470  }
471 
472  for (uint i = 0; (i <= maxLinks) && fi.isSymLink() &&
473  !(link = fi.symLinkTarget()).isEmpty(); i++)
474  {
475  cur_file = (link[0] == '/') ?
476  link : // absolute link
477  fi.absoluteDir().absolutePath() + "/" + link; // relative link
478 
479  if (intermediaries && !intermediaries->contains(cur_file))
480  intermediaries->push_back(cur_file);
481 
482  fi = QFileInfo(cur_file);
483  }
484 
485 #if 0
486  if (intermediaries)
487  {
488  for (uint i = 0; i < intermediaries->size(); i++)
489  {
490  LOG(VB_GENERAL, LOG_DEBUG, QString(" inter%1: %2")
491  .arg(i).arg((*intermediaries)[i]));
492  }
493  }
494 
495  LOG(VB_GENERAL, LOG_DEBUG,
496  QString("getSymlinkTarget() -> '%1'")
497  .arg((!fi.isSymLink()) ? cur_file : QString()));
498 #endif
499 
500  return (!fi.isSymLink()) ? cur_file : QString();
501 }
502 
503 bool IsMACAddress(const QString& MAC)
504 {
505  QStringList tokens = MAC.split(':');
506  if (tokens.size() != 6)
507  {
508  LOG(VB_NETWORK, LOG_ERR,
509  QString("IsMACAddress(%1) = false, doesn't have 6 parts").arg(MAC));
510  return false;
511  }
512 
513  for (int y = 0; y < 6; y++)
514  {
515  if (tokens[y].isEmpty())
516  {
517  LOG(VB_NETWORK, LOG_ERR,
518  QString("IsMACAddress(%1) = false, part #%2 is empty.")
519  .arg(MAC).arg(y));
520  return false;
521  }
522 
523  bool ok = false;
524  int value = tokens[y].toInt(&ok, 16);
525  if (!ok)
526  {
527  LOG(VB_NETWORK, LOG_ERR,
528  QString("IsMACAddress(%1) = false, unable to "
529  "convert part '%2' to integer.")
530  .arg(MAC, tokens[y]));
531  return false;
532  }
533 
534  if (value > 255)
535  {
536  LOG(VB_NETWORK, LOG_ERR,
537  QString("IsMACAddress(%1) = false, part #%2 "
538  "evaluates to %3 which is higher than 255.")
539  .arg(MAC).arg(y).arg(value));
540  return false;
541  }
542  }
543 
544  LOG(VB_NETWORK, LOG_DEBUG, QString("IsMACAddress(%1) = true").arg(MAC));
545  return true;
546 }
547 
548 QString FileHash(const QString& filename)
549 {
550  QFile file(filename);
551  QFileInfo fileinfo(file);
552  qint64 initialsize = fileinfo.size();
553  quint64 hash = 0;
554 
555  if (initialsize == 0)
556  return {"NULL"};
557 
558  if (file.open(QIODevice::ReadOnly))
559  hash = initialsize;
560  else
561  {
562  LOG(VB_GENERAL, LOG_ERR,
563  "Error: Unable to open selected file, missing read permissions?");
564  return {"NULL"};
565  }
566 
567  file.seek(0);
568  QDataStream stream(&file);
569  stream.setByteOrder(QDataStream::LittleEndian);
570  for (quint64 tmp = 0, i = 0; i < 65536/sizeof(tmp); i++)
571  {
572  stream >> tmp;
573  hash += tmp;
574  }
575 
576  file.seek(initialsize - 65536);
577  for (quint64 tmp = 0, i = 0; i < 65536/sizeof(tmp); i++)
578  {
579  stream >> tmp;
580  hash += tmp;
581  }
582 
583  file.close();
584 
585  QString output = QString("%1").arg(hash, 0, 16);
586  return output;
587 }
588 
589 bool WakeOnLAN(const QString& MAC)
590 {
591  std::vector<char> msg(6, static_cast<char>(0xFF));
592  std::array<char,6> macaddr {};
593  QStringList tokens = MAC.split(':');
594 
595  if (tokens.size() != 6)
596  {
597  LOG(VB_GENERAL, LOG_ERR,
598  QString( "WakeOnLan(%1): Incorrect MAC length").arg(MAC));
599  return false;
600  }
601 
602  for (int y = 0; y < 6; y++)
603  {
604  bool ok = false;
605  macaddr[y] = tokens[y].toInt(&ok, 16);
606 
607  if (!ok)
608  {
609  LOG(VB_GENERAL, LOG_ERR,
610  QString( "WakeOnLan(%1): Invalid MAC address").arg(MAC));
611  return false;
612  }
613  }
614 
615  msg.reserve(1024);
616  for (int x = 0; x < 16; x++)
617  msg.insert(msg.end(), macaddr.cbegin(), macaddr.cend());
618 
619  LOG(VB_NETWORK, LOG_INFO,
620  QString("WakeOnLan(): Sending WOL packet to %1").arg(MAC));
621 
622  QUdpSocket udp_socket;
623  qlonglong msglen = msg.size();
624  return udp_socket.writeDatagram(
625  msg.data(), msglen, QHostAddress::Broadcast, 32767) == msglen;
626 }
627 
628 // Wake up either by command or by MAC address
629 // return true = success
630 bool MythWakeup(const QString &wakeUpCommand, uint flags, std::chrono::seconds timeout)
631 {
632  if (!IsMACAddress(wakeUpCommand))
633  return myth_system(wakeUpCommand, flags, timeout) == 0U;
634 
635  return WakeOnLAN(wakeUpCommand);
636 }
637 
639 {
640 #ifdef _WIN32
641  return false;
642 #else
643 
644 #if defined(Q_OS_DARWIN) || defined(__FreeBSD__) || defined(__OpenBSD__)
645  const char *command = "ps -ax | grep -i pulseaudio | grep -v grep > /dev/null";
646 #else
647  const char *command = "ps ch -C pulseaudio -o pid > /dev/null";
648 #endif
649  // Do NOT use kMSProcessEvents here, it will cause deadlock
650  uint res = myth_system(command, kMSDontBlockInputDevs |
652  return (res == GENERIC_EXIT_OK);
653 #endif // _WIN32
654 }
655 
656 bool myth_nice(int val)
657 {
658  errno = 0;
659  int ret = nice(val);
660 
661  if ((-1 == ret) && (0 != errno) && (val >= 0))
662  {
663  LOG(VB_GENERAL, LOG_ERR, "Failed to nice process" + ENO);
664  return false;
665  }
666 
667  return true;
668 }
669 
670 void myth_yield(void)
671 {
672 #ifdef _POSIX_PRIORITY_SCHEDULING
673  if (sched_yield()<0)
674  usleep(5000);
675 #else
676  usleep(5000);
677 #endif
678 }
679 
697 #if defined(__linux__) && ( defined(__i386__) || defined(__ppc__) || \
698  defined(__x86_64__) || defined(__ia64__) )
699 
700 #include <cstdio>
701 #include <getopt.h>
702 #include <sys/ptrace.h>
703 #include <sys/syscall.h>
704 #if __has_include(<linux/ioprio.h>)
705 // Starting with kernel 6.5.0, the following include uses the C++
706 // reserved keyword "class" as a variable name. Fortunately we can
707 // redefine it without any ill effects.
708 #define class class2
709 #include <linux/ioprio.h>
710 #undef class
711 #else
712 static constexpr int8_t IOPRIO_BITS { 16 };
713 static constexpr int8_t IOPRIO_CLASS_SHIFT { 13 };
714 static constexpr int IOPRIO_PRIO_MASK { (1UL << IOPRIO_CLASS_SHIFT) - 1 };
715 static constexpr int IOPRIO_PRIO_CLASS(int mask)
716  { return mask >> IOPRIO_CLASS_SHIFT; };
717 static constexpr int IOPRIO_PRIO_DATA(int mask)
718  { return mask & IOPRIO_PRIO_MASK; };
719 static constexpr int IOPRIO_PRIO_VALUE(int pclass, int data)
720  { return (pclass << IOPRIO_CLASS_SHIFT) | data; };
721 
722 enum { IOPRIO_CLASS_NONE,IOPRIO_CLASS_RT,IOPRIO_CLASS_BE,IOPRIO_CLASS_IDLE, };
723 enum { IOPRIO_WHO_PROCESS = 1, IOPRIO_WHO_PGRP, IOPRIO_WHO_USER, };
724 #endif // has_include(<linux/ioprio.h>)
725 
726 bool myth_ioprio(int val)
727 {
728  int new_ioclass = (val < 0) ? IOPRIO_CLASS_RT :
729  (val > 7) ? IOPRIO_CLASS_IDLE : IOPRIO_CLASS_BE;
730  int new_iodata = (new_ioclass == IOPRIO_CLASS_BE) ? val : 0;
731  int new_ioprio = IOPRIO_PRIO_VALUE(new_ioclass, new_iodata);
732 
733  int pid = getpid();
734  int old_ioprio = syscall(SYS_ioprio_get, IOPRIO_WHO_PROCESS, pid);
735  if (old_ioprio == new_ioprio)
736  return true;
737 
738  int ret = syscall(SYS_ioprio_set, IOPRIO_WHO_PROCESS, pid, new_ioprio);
739 
740  if (-1 == ret && EPERM == errno && IOPRIO_CLASS_BE != new_ioclass)
741  {
742  new_iodata = (new_ioclass == IOPRIO_CLASS_RT) ? 0 : 7;
743  new_ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, new_iodata);
744  ret = syscall(SYS_ioprio_set, IOPRIO_WHO_PROCESS, pid, new_ioprio);
745  }
746 
747  return 0 == ret;
748 }
749 
750 #else
751 
752 bool myth_ioprio(int) { return true; }
753 
754 #endif
755 
756 bool MythRemoveDirectory(QDir &aDir)
757 {
758  if (!aDir.exists())//QDir::NoDotAndDotDot
759  return false;
760 
761  QFileInfoList entries = aDir.entryInfoList(QDir::NoDotAndDotDot |
762  QDir::Dirs | QDir::Files);
763  int count = entries.size();
764  bool has_err = false;
765 
766  for (int idx = 0; idx < count && !has_err; idx++)
767  {
768  QFileInfo entryInfo = entries[idx];
769  QString path = entryInfo.absoluteFilePath();
770  if (entryInfo.isDir())
771  {
772  QDir dir(path);
773  has_err = MythRemoveDirectory(dir);
774  }
775  else
776  {
777  QFile file(path);
778  if (!file.remove())
779  has_err = true;
780  }
781  }
782 
783  if (!has_err && !aDir.rmdir(aDir.absolutePath()))
784  has_err = true;
785 
786  return(has_err);
787 }
788 
800 void setHttpProxy(void)
801 {
802  QString LOC = "setHttpProxy() - ";
803 
804  // Set http proxy for the application if specified in environment variable
805  QString var(qEnvironmentVariable("http_proxy"));
806  if (var.isEmpty())
807  var = qEnvironmentVariable("HTTP_PROXY"); // Sadly, some OS envs are case sensitive
808  if (!var.isEmpty())
809  {
810  if (!var.startsWith("http://")) // i.e. just a host name
811  var.prepend("http://");
812 
813  QUrl url = QUrl(var, QUrl::TolerantMode);
814  QString host = url.host();
815  int port = url.port();
816 
817  if (port == -1) // Parsing error
818  {
819  port = 0; // The default when creating a QNetworkProxy
820 
821  if (telnet(host, 1080)) // Socks?
822  port = 1080;
823  if (telnet(host, 3128)) // Squid
824  port = 3128;
825  if (telnet(host, 8080)) // MS ISA
826  port = 8080;
827 
828  LOG(VB_NETWORK, LOG_INFO, LOC +
829  QString("assuming port %1 on host %2") .arg(port).arg(host));
830  url.setPort(port);
831  }
832  else if (!ping(host, 1s))
833  {
834  LOG(VB_GENERAL, LOG_ERR, LOC +
835  QString("cannot locate host %1").arg(host) +
836  "\n\t\t\tPlease check HTTP_PROXY environment variable!");
837  }
838  else if (!telnet(host,port))
839  {
840  LOG(VB_GENERAL, LOG_ERR, LOC +
841  QString("%1:%2 - cannot connect!").arg(host).arg(port) +
842  "\n\t\t\tPlease check HTTP_PROXY environment variable!");
843  }
844 
845 #if 0
846  LOG(VB_NETWORK, LOG_DEBUG, LOC + QString("using http://%1:%2@%3:%4")
847  .arg(url.userName()).arg(url.password())
848  .arg(host).arg(port));
849 #endif
850  QNetworkProxy p =
851  QNetworkProxy(QNetworkProxy::HttpCachingProxy,
852  host, port, url.userName(), url.password());
853  QNetworkProxy::setApplicationProxy(p);
854  return;
855  }
856 
857  LOG(VB_NETWORK, LOG_DEBUG, LOC + "no HTTP_PROXY environment var.");
858 
859  // Use Qt to look for user proxy settings stored by the OS or browser:
860 
861  QList<QNetworkProxy> proxies;
862  QNetworkProxyQuery query(QUrl("http://www.mythtv.org"));
863 
864  proxies = QNetworkProxyFactory::systemProxyForQuery(query);
865 
866  for (const auto& p : std::as_const(proxies))
867  {
868  QString host = p.hostName();
869  int port = p.port();
870 
871  if (p.type() == QNetworkProxy::NoProxy)
872  continue;
873 
874  if (!telnet(host, port))
875  {
876  LOG(VB_NETWORK, LOG_ERR, LOC +
877  "failed to contact proxy host " + host);
878  continue;
879  }
880 
881  LOG(VB_NETWORK, LOG_INFO, LOC + QString("using proxy host %1:%2")
882  .arg(host).arg(port));
883  QNetworkProxy::setApplicationProxy(p);
884 
885  // Allow sub-commands to use this proxy
886  // via myth_system(command), by setting HTTP_PROXY
887  QString url;
888 
889  if (!p.user().isEmpty())
890  {
891  url = "http://%1:%2@%3:%4",
892  url = url.arg(p.user(), p.password());
893  }
894  else
895  {
896  url = "http://%1:%2";
897  }
898 
899  url = url.arg(p.hostName()).arg(p.port());
900  setenv("HTTP_PROXY", url.toLatin1(), 1);
901  setenv("http_proxy", url.toLatin1(), 0);
902 
903  return;
904  }
905 
906  LOG(VB_NETWORK, LOG_ERR, LOC + "failed to find a network proxy");
907 }
908 
909 /* vim: set expandtab tabstop=4 shiftwidth=4: */
ENO
#define ENO
This can be appended to the LOG args with "+".
Definition: mythlogging.h:73
hardwareprofile.smolt.timeout
float timeout
Definition: smolt.py:102
setHttpProxy
void setHttpProxy(void)
Get network proxy settings from OS, and use for [Q]Http[Comms].
Definition: mythmiscutil.cpp:800
kMSDontBlockInputDevs
@ kMSDontBlockInputDevs
avoid blocking LIRC & Joystick Menu
Definition: mythsystem.h:36
getDiskSpace
int64_t getDiskSpace(const QString &file_on_disk, int64_t &total, int64_t &used)
Definition: mythcoreutil.cpp:33
myth_ioprio
bool myth_ioprio(int)
Allows setting the I/O priority of the current process/thread.
Definition: mythmiscutil.cpp:752
mythcoreutil.h
getLoadAvgs
loadArray getLoadAvgs(void)
Returns the system load averages.
Definition: mythmiscutil.cpp:175
getMemStats
bool getMemStats([[maybe_unused]] int &totalMB, [[maybe_unused]] int &freeMB, [[maybe_unused]] int &totalVM, [[maybe_unused]] int &freeVM)
Definition: mythmiscutil.cpp:109
LOC
#define LOC
Definition: audioconvert.cpp:41
setenv
#define setenv(x, y, z)
Definition: compat.h:89
getSymlinkTarget
QString getSymlinkTarget(const QString &start_file, QStringList *intermediaries, unsigned maxLinks)
Definition: mythmiscutil.cpp:451
WakeOnLAN
bool WakeOnLAN(const QString &MAC)
Definition: mythmiscutil.cpp:589
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
build_compdb.file
file
Definition: build_compdb.py:55
myth_system
uint myth_system(const QString &command, uint flags, std::chrono::seconds timeout)
Definition: mythsystemlegacy.cpp:506
GENERIC_EXIT_OK
@ GENERIC_EXIT_OK
Exited with no error.
Definition: exitcodes.h:11
telnet
bool telnet(const QString &host, int port)
Can we talk to port on host?
Definition: mythmiscutil.cpp:232
getloadavg
#define getloadavg(x, y)
Definition: compat.h:191
close
#define close
Definition: compat.h:43
tmp
static guint32 * tmp
Definition: goom_core.cpp:26
mythsystemlegacy.h
IsPulseAudioRunning
bool IsPulseAudioRunning(void)
Is A/V Sync destruction daemon is running on this host?
Definition: mythmiscutil.cpp:638
MythSocket
Class for communcating between myth backends and frontends.
Definition: mythsocket.h:25
MythRemoveDirectory
bool MythRemoveDirectory(QDir &aDir)
Definition: mythmiscutil.cpp:756
mythlogging.h
MythFile::copy
MBASE_PUBLIC long long copy(QFile &dst, QFile &src, uint block_size=0)
Copies src file to dst file.
Definition: mythmiscutil.cpp:263
hardwareprofile.config.p
p
Definition: config.py:33
compat.h
createTempFile
QString createTempFile(QString name_template, bool dir)
Definition: mythmiscutil.cpp:323
getResponse
QString getResponse(const QString &query, const QString &def)
In an interactive shell, prompt the user to input a string.
Definition: mythmiscutil.cpp:410
MythWakeup
bool MythWakeup(const QString &wakeUpCommand, uint flags, std::chrono::seconds timeout)
Definition: mythmiscutil.cpp:630
loadArray
std::array< double, 3 > loadArray
Definition: mythmiscutil.h:22
hardwareprofile.distros.mythtv_data.main.stdout
stdout
Definition: main.py:87
uint
unsigned int uint
Definition: compat.h:81
getUptime
bool getUptime(std::chrono::seconds &uptime)
Definition: mythmiscutil.cpp:66
MythCoreContext::resolveAddress
static QString resolveAddress(const QString &host, ResolveType type=ResolveAny, bool keepscope=false)
if host is an IP address, it will be returned or resolved otherwise.
Definition: mythcorecontext.cpp:1192
block_size
unsigned int block_size
Definition: freesurround.cpp:48
ping
bool ping(const QString &host, std::chrono::milliseconds timeout)
Can we ping host within timeout seconds?
Definition: mythmiscutil.cpp:199
mythmiscutil.h
makeFileAccessible
bool makeFileAccessible(const QString &filename)
Definition: mythmiscutil.cpp:395
mythcorecontext.h
intResponse
int intResponse(const QString &query, int def)
In an interactive shell, prompt the user to input a number.
Definition: mythmiscutil.cpp:440
kMSProcessEvents
@ kMSProcessEvents
process events while waiting
Definition: mythsystem.h:39
nice
#define nice(x)
Definition: compat.h:122
myth_nice
bool myth_nice(int val)
Definition: mythmiscutil.cpp:656
mythburn.temppath
string temppath
Definition: mythburn.py:161
kMSDontDisableDrawing
@ kMSDontDisableDrawing
avoid disabling UI drawing
Definition: mythsystem.h:37
exitcodes.h
build_compdb.filename
filename
Definition: build_compdb.py:21
FileHash
QString FileHash(const QString &filename)
Definition: mythmiscutil.cpp:548
IsMACAddress
bool IsMACAddress(const QString &MAC)
Definition: mythmiscutil.cpp:503
mythsocket.h
hardwareprofile.smolt.proxies
proxies
Definition: smolt.py:103
output
#define output
Definition: synaesthesia.cpp:220
MythCoreContext::ResolveAny
@ ResolveAny
Definition: mythcorecontext.h:211
myth_yield
void myth_yield(void)
Definition: mythmiscutil.cpp:670