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 }