kranewl

A wlroots-based dynamic Wayland compositor, written in C++, configurable with Lua
git clone git://git.deurzen.net/kranewl
Log | Files | Refs | LICENSE

options.cc (3537B)


      1 #include <version.hh>
      2 
      3 #include <kranewl/conf/options.hh>
      4 
      5 #include <cassert>
      6 #include <cstdlib>
      7 #include <iostream>
      8 #include <optional>
      9 extern "C" {
     10 #include <sys/stat.h>
     11 #include <unistd.h>
     12 }
     13 
     14 static const std::string CONFIG_FILE = "kranewlrc.lua";
     15 static const std::string DEFAULT_CONFIG = "/etc/kranewl/" + CONFIG_FILE;
     16 static const std::string USAGE = "usage: kranewl [...options]\n\n"
     17     "options: \n"
     18     "  -a <autostart_file> Path to an executable autostart file.\n"
     19     "  -c <config_file>    Path to a configuration file.\n"
     20     "  -e <env_file>       Path to file with environment variables.\n"
     21     "  -v                  Prints the version.\n"
     22     "  -h                  Prints this message.";
     23 
     24 static std::string
     25 default_user_path(std::string const& path) noexcept
     26 {
     27     if (const char* prefix = std::getenv("XDG_CONFIG_HOME"))
     28         return std::string{prefix}
     29             + std::string{"/kranewl/"}
     30             + path;
     31     else
     32         return std::string{std::getenv("HOME")}
     33             + std::string{"/.config/kranewl/"}
     34             + path;
     35 }
     36 
     37 static bool
     38 assert_permissions(std::string const& path, int mode) noexcept
     39 {
     40     struct stat s;
     41     return stat(path.c_str(), &s) == 0
     42         && S_ISREG(s.st_mode)
     43         && !access(path.c_str(), mode);
     44 }
     45 
     46 static std::string const&
     47 resolve_config_path(std::string& path) noexcept
     48 {
     49     if (!path.empty())
     50         if (assert_permissions(path, R_OK))
     51             return path;
     52 
     53     path.assign(default_user_path(CONFIG_FILE));
     54     if (assert_permissions(path, R_OK))
     55         return path;
     56 
     57     return DEFAULT_CONFIG;
     58 }
     59 
     60 static std::optional<std::string>
     61 resolve_env_path(std::string& path) noexcept
     62 {
     63     if (!path.empty())
     64         if (assert_permissions(path, R_OK))
     65             return path;
     66 
     67     path.assign(default_user_path("env"));
     68     if (assert_permissions(path, R_OK))
     69         return path;
     70 
     71     return {};
     72 }
     73 
     74 static std::optional<std::string>
     75 resolve_rules_path(std::string& path) noexcept
     76 {
     77     if (!path.empty())
     78         if (assert_permissions(path, R_OK))
     79             return path;
     80 
     81     path.assign(default_user_path("rules"));
     82     if (assert_permissions(path, R_OK))
     83         return {path};
     84 
     85     return {};
     86 }
     87 
     88 static std::optional<std::string>
     89 resolve_autostart_path(std::string& path) noexcept
     90 {
     91     const int mode = R_OK | X_OK;
     92 
     93     if (!path.empty())
     94         if (assert_permissions(path, mode))
     95             return {path};
     96 
     97     path.assign(default_user_path("autostart"));
     98     if (assert_permissions(path, mode))
     99         return {path};
    100 
    101     return {};
    102 }
    103 
    104 Options
    105 parse_options(int argc, char** argv) noexcept
    106 {
    107     std::string autostart_path, config_path, env_path, rules_path;
    108     int opt;
    109 
    110     while ((opt = getopt(argc, argv, "h?va:c:e:r:")) != -1) {
    111         switch (opt) {
    112         case 'a':
    113             autostart_path = optarg;
    114             break;
    115 
    116         case 'c':
    117             config_path = optarg;
    118             break;
    119 
    120         case 'e':
    121             env_path = optarg;
    122             break;
    123 
    124         case 'r':
    125             rules_path = optarg;
    126             break;
    127 
    128         case 'v':
    129             std::cout << VERSION << std::endl;
    130             std::exit(EXIT_SUCCESS);
    131             break;
    132 
    133         case '?':
    134         case 'h':
    135         default:
    136             std::cout << USAGE << std::endl;
    137             std::exit(EXIT_SUCCESS);
    138             break;
    139         }
    140     }
    141 
    142     return Options(
    143         std::move(resolve_config_path(config_path)),
    144         resolve_env_path(env_path),
    145         resolve_rules_path(rules_path),
    146         resolve_autostart_path(autostart_path)
    147     );
    148 }