launcher_linux.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #include "platform/linux/launcher_linux.h"
  8. #include "core/crash_reports.h"
  9. #include "core/update_checker.h"
  10. #include "webview/platform/linux/webview_linux_webkitgtk.h"
  11. #include <QtWidgets/QApplication>
  12. #include <glib/glib.hpp>
  13. using namespace gi::repository;
  14. namespace Platform {
  15. Launcher::Launcher(int argc, char *argv[])
  16. : Core::Launcher(argc, argv) {
  17. }
  18. int Launcher::exec() {
  19. for (auto i = arguments().begin(), e = arguments().end(); i != e; ++i) {
  20. if (*i == u"-webviewhelper"_q && std::distance(i, e) > 1) {
  21. Webview::WebKitGTK::SetSocketPath((i + 1)->toStdString());
  22. return Webview::WebKitGTK::Exec();
  23. }
  24. }
  25. return Core::Launcher::exec();
  26. }
  27. bool Launcher::launchUpdater(UpdaterLaunch action) {
  28. if (cExeName().isEmpty()) {
  29. return false;
  30. }
  31. const auto justRelaunch = action == UpdaterLaunch::JustRelaunch;
  32. if (action == UpdaterLaunch::PerformUpdate) {
  33. _updating = true;
  34. }
  35. std::vector<std::string> argumentsList;
  36. // What we are launching.
  37. const auto launching = justRelaunch
  38. ? (cExeDir() + cExeName())
  39. : cWriteProtected()
  40. ? GLib::find_program_in_path("run0")
  41. ? u"run0"_q
  42. : u"pkexec"_q
  43. : (cExeDir() + u"Updater"_q);
  44. argumentsList.push_back(launching.toStdString());
  45. if (justRelaunch) {
  46. // argv[0] that is passed to what we are launching.
  47. // It should be added explicitly in case of FILE_AND_ARGV_ZERO_.
  48. const auto argv0 = !arguments().isEmpty()
  49. ? arguments().first()
  50. : launching;
  51. argumentsList.push_back(argv0.toStdString());
  52. } else if (cWriteProtected()) {
  53. // Elevated process that run0/pkexec should launch.
  54. const auto elevated = cWorkingDir() + u"tupdates/temp/Updater"_q;
  55. argumentsList.push_back(elevated.toStdString());
  56. }
  57. if (Logs::DebugEnabled()) {
  58. argumentsList.push_back("-debug");
  59. }
  60. if (justRelaunch) {
  61. if (cLaunchMode() == LaunchModeAutoStart) {
  62. argumentsList.push_back("-autostart");
  63. }
  64. if (cStartInTray()) {
  65. argumentsList.push_back("-startintray");
  66. }
  67. if (cDataFile() != u"data"_q) {
  68. argumentsList.push_back("-key");
  69. argumentsList.push_back(cDataFile().toStdString());
  70. }
  71. if (!_updating) {
  72. argumentsList.push_back("-noupdate");
  73. argumentsList.push_back("-tosettings");
  74. }
  75. if (customWorkingDir()) {
  76. argumentsList.push_back("-workdir");
  77. argumentsList.push_back(cWorkingDir().toStdString());
  78. }
  79. } else {
  80. // Don't relaunch Telegram.
  81. argumentsList.push_back("-justupdate");
  82. argumentsList.push_back("-workpath");
  83. argumentsList.push_back(cWorkingDir().toStdString());
  84. argumentsList.push_back("-exename");
  85. argumentsList.push_back(cExeName().toStdString());
  86. argumentsList.push_back("-exepath");
  87. argumentsList.push_back(cExeDir().toStdString());
  88. if (cWriteProtected()) {
  89. argumentsList.push_back("-writeprotected");
  90. }
  91. }
  92. Logs::closeMain();
  93. CrashReports::Finish();
  94. int waitStatus = 0;
  95. if (justRelaunch) {
  96. return GLib::spawn_async(
  97. initialWorkingDir().toStdString(),
  98. argumentsList,
  99. {},
  100. GLib::SpawnFlags::FILE_AND_ARGV_ZERO_,
  101. nullptr,
  102. nullptr,
  103. nullptr);
  104. } else if (!GLib::spawn_sync(
  105. argumentsList,
  106. {},
  107. // if the spawn is sync, working directory is not set
  108. // and GLib::SpawnFlags::LEAVE_DESCRIPTORS_OPEN_ is set,
  109. // it goes through an optimized code path
  110. GLib::SpawnFlags::SEARCH_PATH_
  111. | GLib::SpawnFlags::LEAVE_DESCRIPTORS_OPEN_,
  112. nullptr,
  113. nullptr,
  114. nullptr,
  115. &waitStatus,
  116. nullptr) || !g_spawn_check_exit_status(waitStatus, nullptr)) {
  117. return false;
  118. }
  119. return launchUpdater(UpdaterLaunch::JustRelaunch);
  120. }
  121. } // namespace