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