trace_processor_shell: Persist cmdline history

Change-Id: If7e950beb1cbfdd184df9cbfdcc3a5f1cfdd804f
diff --git a/src/trace_processor/trace_processor_shell.cc b/src/trace_processor/trace_processor_shell.cc
index 2ee3e27..ed2d11f 100644
--- a/src/trace_processor/trace_processor_shell.cc
+++ b/src/trace_processor/trace_processor_shell.cc
@@ -38,6 +38,8 @@
 
 #if PERFETTO_BUILDFLAG(PERFETTO_STANDALONE_BUILD)
 #include <linenoise.h>
+#include <pwd.h>
+#include <sys/types.h>
 #endif
 
 #if PERFETTO_HAS_SIGNAL_H()
@@ -52,13 +54,54 @@
 
 #if PERFETTO_BUILDFLAG(PERFETTO_STANDALONE_BUILD)
 
+bool EnsureDir(const std::string& path) {
+  return mkdir(path.c_str(), 0755) != -1 || errno == EEXIST;
+}
+
+bool EnsureFile(const std::string& path) {
+  return base::OpenFile(path, O_RDONLY | O_CREAT).get() != -1;
+}
+
+std::string GetConfigPath() {
+  const char* homedir = getenv("HOME");
+  if (homedir == nullptr)
+    homedir = getpwuid(getuid())->pw_dir;
+  if (homedir == nullptr)
+    return "";
+  return std::string(homedir) + "/.config";
+}
+
+std::string GetPerfettoPath() {
+  std::string config = GetConfigPath();
+  if (config == "")
+    return "";
+  return config + "/perfetto";
+}
+
+std::string GetHistoryPath() {
+  std::string perfetto = GetPerfettoPath();
+  if (perfetto == "")
+    return "";
+  return perfetto + "/.trace_processor_shell_history";
+}
+
 void SetupLineEditor() {
   linenoiseSetMultiLine(true);
   linenoiseHistorySetMaxLen(1000);
+
+  bool success = GetHistoryPath() != "";
+  success = success && EnsureDir(GetConfigPath());
+  success = success && EnsureDir(GetPerfettoPath());
+  success = success && EnsureFile(GetHistoryPath());
+  success = success && linenoiseHistoryLoad(GetHistoryPath().c_str()) != -1;
+  if (!success) {
+    PERFETTO_PLOG("Could not load history from %s", GetHistoryPath().c_str());
+  }
 }
 
 void FreeLine(char* line) {
   linenoiseHistoryAdd(line);
+  linenoiseHistorySave(GetHistoryPath().c_str());
   linenoiseFree(line);
 }