OmniSciDB  04ee39c94c
CommandHistoryFile.h
Go to the documentation of this file.
1 /*
2  * Copyright 2019 OmniSci, Inc.
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 #ifndef COMMANDHISTORYFILE_H
18 #define COMMANDHISTORYFILE_H
19 
20 #include <iostream>
21 #include <string>
22 #include <utility>
23 
24 #include <pwd.h>
25 #include <sys/types.h>
26 #include <unistd.h>
27 
28 #include "Shared/ConfigResolve.h"
29 
30 inline constexpr char const* const getDefaultHistoryFilename() {
31  return ".omnisql_history";
32 }
33 
35  public:
36  auto getuid() const { return ::getuid(); }
37  auto const* getpwuid(decltype(::getuid()) uid) const { return ::getpwuid(uid); }
38 
39 #ifdef __APPLE__
40  auto const* getenv(char const* env_var_name) const { return ::getenv(env_var_name); }
41 #else
42  auto const* getenv(char const* env_var_name) const {
43  return ::secure_getenv(env_var_name);
44  }
45 #endif
46 };
47 
48 template <typename ENV_RESOLVER>
49 class CommandHistoryFileImpl : private ENV_RESOLVER {
50  public:
51  CommandHistoryFileImpl() : CommandHistoryFileImpl(resolveCommandFile()) {}
52  explicit CommandHistoryFileImpl(std::string command_file_name)
53  : command_file_name_(command_file_name) {}
54 
55  operator char const*() const { return command_file_name_.c_str(); }
56 
57  template <typename ER>
58  friend inline std::istream& operator>>(std::istream& i,
59  CommandHistoryFileImpl<ER>& cmd_file);
60  template <typename ER>
61  friend inline std::ostream& operator<<(std::ostream& o,
62  CommandHistoryFileImpl<ER> const& cmd_file);
63 
64  private:
65  auto resolveHomeDirectory() const {
66  auto* home_env = this->getenv("HOME");
67  if (home_env == nullptr) {
68  auto* passwd_entry = ENV_RESOLVER::getpwuid(ENV_RESOLVER::getuid());
69  if (passwd_entry != nullptr) {
70  home_env = passwd_entry->pw_dir;
71  }
72  }
73  return home_env;
74  }
75 
76  std::string const resolveCommandFile() const {
77  auto* home_dir = resolveHomeDirectory();
78  if (home_dir == nullptr) { // Just use default command history file name in current
79  // dir in this scenario
80  return std::string(getDefaultHistoryFilename());
81  }
82  return std::string(home_dir) + '/' + getDefaultHistoryFilename();
83  }
84 
85  private:
86  std::string command_file_name_;
87 };
88 
89 template <typename ENV_RESOLVER>
90 inline std::ostream& operator<<(std::ostream& o,
91  CommandHistoryFileImpl<ENV_RESOLVER> const& cmd_file) {
92  o << cmd_file.command_file_name_;
93  return o;
94 }
95 
96 template <typename ENV_RESOLVER>
97 inline std::istream& operator>>(std::istream& i,
99  i >> cmd_file.command_file_name_;
100  return i;
101 }
102 
104 
105 #endif
auto const * getenv(char const *env_var_name) const
constexpr char const *const getDefaultHistoryFilename()
std::ostream & operator<<(std::ostream &o, CommandHistoryFileImpl< ENV_RESOLVER > const &cmd_file)
std::istream & operator>>(std::istream &i, CommandHistoryFileImpl< ENV_RESOLVER > &cmd_file)
auto const * getpwuid(decltype(::getuid()) uid) const
std::string const resolveCommandFile() const
CommandHistoryFileImpl(std::string command_file_name)
auto resolveHomeDirectory() const