PageRenderTime 56ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/src/service/main/CmdlineParser.cpp

https://gitlab.com/github-cloud-corporation/cynara
C++ | 212 lines | 170 code | 20 blank | 22 comment | 15 complexity | 45ac2688ba4b0a3002bb4814255e6f86 MD5 | raw file
  1. /*
  2. * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /**
  17. * @file src/service/main/CmdlineParser.cpp
  18. * @author Pawel Wieczorek <p.wieczorek2@samsung.com>
  19. * @version 1.0
  20. * @brief Helper namespace for Cynara's command-line options parsing
  21. */
  22. #include <cstdlib>
  23. #include <getopt.h>
  24. #include <grp.h>
  25. #include <iostream>
  26. #include <pwd.h>
  27. #include <sstream>
  28. #include "CmdlineParser.h"
  29. namespace Cynara {
  30. namespace CmdlineParser {
  31. std::ostream &operator<<(std::ostream &os, CmdlineOpt opt) {
  32. return os << static_cast<char>(opt);
  33. }
  34. struct CmdLineOptions handleCmdlineOptions(int argc, char * const *argv) {
  35. const std::string execName(argv[0]);
  36. std::stringstream shortOpts;
  37. shortOpts << ":"
  38. << CmdlineOpt::Help
  39. << CmdlineOpt::Version
  40. << CmdlineOpt::Daemon
  41. << CmdlineOpt::Mask << ":"
  42. << CmdlineOpt::User << ":"
  43. << CmdlineOpt::Group << ":";
  44. const struct option longOpts[] = {
  45. { "help", no_argument, NULL, CmdlineOpt::Help },
  46. { "version", no_argument, NULL, CmdlineOpt::Version },
  47. { "daemon", no_argument, NULL, CmdlineOpt::Daemon },
  48. { "mask", required_argument, NULL, CmdlineOpt::Mask },
  49. { "user", required_argument, NULL, CmdlineOpt::User },
  50. { "group", required_argument, NULL, CmdlineOpt::Group },
  51. { NULL, 0, NULL, 0 }
  52. };
  53. struct CmdLineOptions ret = {.m_error = false,
  54. .m_exit = false,
  55. .m_daemon = false,
  56. .m_mask = static_cast<mode_t>(-1),
  57. .m_uid = static_cast<uid_t>(-1),
  58. .m_gid = static_cast<gid_t>(-1) };
  59. optind = 0; // On entry to `getopt', zero means this is the first call; initialize.
  60. int opt;
  61. while ((opt = getopt_long(argc, argv, shortOpts.str().c_str(), longOpts, nullptr)) != -1) {
  62. switch (opt) {
  63. case CmdlineOpt::Help:
  64. printHelp(execName);
  65. ret.m_error = false;
  66. ret.m_exit = true;
  67. return ret;
  68. case CmdlineOpt::Version:
  69. printVersion();
  70. ret.m_error = false;
  71. ret.m_exit = true;
  72. return ret;
  73. case CmdlineOpt::Daemon:
  74. ret.m_daemon = true;
  75. break;
  76. case CmdlineOpt::Mask:
  77. ret.m_mask = getMask(optarg);
  78. if (ret.m_mask == static_cast<mode_t>(-1)) {
  79. printInvalidParam(execName, optarg);
  80. ret.m_error = true;
  81. ret.m_exit = true;
  82. return ret;
  83. }
  84. break;
  85. case CmdlineOpt::User:
  86. ret.m_uid = getUid(optarg);
  87. if (ret.m_uid == static_cast<uid_t>(-1)) {
  88. printInvalidParam(execName, optarg);
  89. ret.m_error = true;
  90. ret.m_exit = true;
  91. return ret;
  92. }
  93. break;
  94. case CmdlineOpt::Group:
  95. ret.m_gid = getGid(optarg);
  96. if (ret.m_gid == static_cast<gid_t>(-1)) {
  97. printInvalidParam(execName, optarg);
  98. ret.m_error = true;
  99. ret.m_exit = true;
  100. return ret;
  101. }
  102. break;
  103. case ':': // Missing argument
  104. ret.m_error = true;
  105. ret.m_exit = true;
  106. switch (optopt) {
  107. case CmdlineOpt::Mask:
  108. case CmdlineOpt::User:
  109. case CmdlineOpt::Group:
  110. printMissingArgument(execName, argv[optind - 1]);
  111. return ret;
  112. }
  113. //intentional fall to Unknown option
  114. case '?': // Unknown option
  115. default:
  116. printUnknownOption(execName, argv[optind - 1]);
  117. ret.m_error = true;
  118. ret.m_exit = true;
  119. return ret;
  120. }
  121. }
  122. return ret;
  123. }
  124. void printHelp(const std::string &execName) {
  125. std::cout << "Usage: " << execName << " [OPTIONS]" << std::endl << std::endl;
  126. std::cout << "Information mode options [program exits after printing information]:" << std::endl;
  127. std::cout << " -V, --version print version of " << execName << " and exit"
  128. << std::endl;
  129. std::cout << " -h, --help print this help message and exit" << std::endl;
  130. std::cout << "Normal work mode options:" << std::endl;
  131. std::cout << " -d, --daemon daemonize "
  132. "[by default " << execName << " does not daemonize]" << std::endl;
  133. std::cout << " -m, --mask=MASK set umask to MASK "
  134. "[by default no umask is set]" << std::endl;
  135. std::cout << " -u, --user=USER change user to USER "
  136. "[by default uid is not changed]" << std::endl;
  137. std::cout << " -g, --group=GROUP change group to GROUP "
  138. "[by default gid is not changed]" << std::endl;
  139. }
  140. void printVersion(void) {
  141. std::cout << std::string(CYNARA_VERSION) << std::endl;
  142. }
  143. void printUnknownOption(const std::string &execName, const std::string &option) {
  144. std::cerr << "Unknown option: " << option << std::endl;
  145. printHelp(execName);
  146. }
  147. void printInvalidParam(const std::string &execName, const std::string &param) {
  148. std::cerr << "Invalid param: " << param << std::endl;
  149. printHelp(execName);
  150. }
  151. void printMissingArgument(const std::string &execName, const std::string &option) {
  152. std::cerr << "Missing argument for option: " << option << std::endl;
  153. printHelp(execName);
  154. }
  155. mode_t getMask(const char *mask) {
  156. mode_t ret = static_cast<mode_t>(-1);
  157. if (!mask)
  158. return ret;
  159. try {
  160. ret = static_cast<mode_t>(std::stoi(mask, 0, 0));
  161. } catch (...) {
  162. }
  163. return ret;
  164. }
  165. uid_t getUid(const char *user) {
  166. uid_t ret = static_cast<uid_t>(-1);
  167. if (!user)
  168. return ret;
  169. try {
  170. ret = static_cast<uid_t>(std::stoi(user));
  171. } catch (...) {
  172. struct passwd *pwd = getpwnam(user);
  173. if (pwd)
  174. ret = pwd->pw_uid;
  175. }
  176. return ret;
  177. }
  178. gid_t getGid(const char *group) {
  179. gid_t ret = static_cast<gid_t>(-1);
  180. if (!group)
  181. return ret;
  182. try {
  183. ret = static_cast<gid_t>(std::stoi(group));
  184. } catch (...) {
  185. struct group *grp = getgrnam(group);
  186. if (grp)
  187. ret = grp->gr_gid;
  188. }
  189. return ret;
  190. }
  191. } /* namespace CmdlineOpts */
  192. } /* namespace Cynara */