1 /*
2  * GTK-based application grid
3  * Copyright (c) 2021 Piotr Miller
4  * e-mail: nwg.piotr@gmail.com
5  * Website: http://nwg.pl
6  * Project: https://github.com/nwg-piotr/nwg-launchers
7  * License: GPL3
8  * */
9 
10 #include <fstream>
11 #include <string_view>
12 #include <vector>
13 
14 #include "nwg_tools.h"
15 #include "nwg_exceptions.h"
16 #include "nwgconfig.h"
17 
18 const char* const HELP_MESSAGE = "\
19 GTK application grid: nwggrid " VERSION_STR " (c) 2021 Piotr Miller, Sergey Smirnykh & Contributors \n\n\
20 Usage:\n\
21     nwggrid -client      sends -SIGUSR1 to nwggrid-server, requires nwggrid-server running\n\
22     nwggrid [ARGS...]    launches nwggrid-server -oneshot ARGS...\n\n\
23 \
24 See also:\n\
25     nwggrid-server -h\n";
26 
main(int argc,char * argv[])27 int main(int argc, char* argv[]) {
28     try {
29         using namespace std::string_view_literals;
30 
31         if (argc >= 2) {
32             std::string_view argv1{ argv[1] };
33 
34             if (argv1 == "-h"sv) {
35                 Log::plain(HELP_MESSAGE);
36                 return EXIT_SUCCESS;
37             }
38 
39             if (argv1 == "-client"sv) {
40                 auto pid_file = get_pid_file("nwggrid-server.pid");
41                 Log::info("Using pid file ", pid_file);
42                 Log::info("Running in client mode");
43                 if (argc != 2) {
44                     Log::warn("Arguments after '-client' must be passed to nwggrid-server");
45                 }
46                 auto pid = get_instance_pid(pid_file.c_str());
47                 if (!pid) {
48                     throw std::runtime_error{ "nwggrid-server is not running" };
49                 }
50                 if (kill(*pid, SIGUSR1) != 0) {
51                     throw std::runtime_error{ "failed to send SIGUSR1 to the pid" };
52                 }
53                 Log::plain("Success");
54                 return EXIT_SUCCESS;
55             }
56         }
57         char path[] = INSTALL_PREFIX_STR "/bin/nwggrid-server";
58         char oneshot[] = "-oneshot";
59         auto arguments = new char*[argc + 2];
60         arguments[0] = path;
61         for (int i = 1; i < argc; ++i) {
62             arguments[i] = strdup(argv[i]);
63             if (!arguments[i]) {
64                 int err = errno;
65                 // totally unnecessary cleanup, but why not?
66                 for (int j = 0; j < i; ++j) {
67                     free(arguments[j]);
68                 }
69                 throw std::runtime_error{ error_description(err) };
70             }
71         }
72         arguments[argc] = oneshot;
73         arguments[argc + 1] = (char*)NULL;
74 
75         auto r = execv(
76             INSTALL_PREFIX_STR "/bin/nwggrid-server",
77             arguments
78         );
79         if (r == -1) {
80             throw ErrnoException{ errno };
81         }
82         return EXIT_SUCCESS;
83     } catch (const Glib::Error& err) {
84         // Glib::ustring performs conversion with respect to locale settings
85         // it might throw (and it does [on my machine])
86         // so let's try our best
87         auto ustr = err.what();
88         try {
89             Log::error(ustr);
90         } catch (const Glib::ConvertError& err) {
91             Log::plain("[message conversion failed]");
92             Log::error(std::string_view{ ustr.data(), ustr.bytes() });
93         } catch (...) {
94             Log::error("Failed to print error message due to unknown error");
95         }
96     } catch (const std::exception& err) {
97         Log::error(err.what());
98     }
99     return EXIT_FAILURE;
100 }
101