package main import ( "bufio" "io" "io/ioutil" "log" "os" "os/user" "path" "strings" ) type HistoryFile struct { Dir string History *BashHistory FileHandle *os.File } type Tmpfile struct { Dir string FileHandle *os.File } type BashHistory struct { Old map[string]int Tmp []string } func (tempfile *Tmpfile) WriteFresh(historyfile *HistoryFile, makebackup bool) { defer os.RemoveAll(tempfile.Dir) defer tempfile.FileHandle.Close() if makebackup { historyfile.Makebackup() } if err := historyfile.FileHandle.Truncate(0); err != nil { log.Fatalf("h.trunc: %s\n", err) } if _, err := historyfile.FileHandle.Seek(0, 0); err != nil { log.Fatalf("writefresh h.Seek(): %s\n", err) } if _, err := tempfile.FileHandle.Seek(0, 0); err != nil { log.Fatalf("t.Seek(): %s\n", err) } if _, err := io.Copy(historyfile.FileHandle, tempfile.FileHandle); err != nil { log.Fatalf("tmp io.copy: %s\n", err) } } func (tempfile *Tmpfile) SaveTmp(h *BashHistory) (wrote int) { for key, val := range h.Old { h.Tmp[val] = key } wrote = 0 for _, key := range h.Tmp { if len(key) > 0 { if _, err := tempfile.FileHandle.WriteString(key + "\n"); err != nil { log.Fatalf("Error writing line %d value %s : %s \n", wrote, key, err) } wrote++ } } return wrote } func (historyfile *HistoryFile) Makebackup() { if _, err := historyfile.FileHandle.Seek(0, 0); err != nil { log.Fatalf("makebackup Seek(): %s\n", err) } backup, err := os.Create(historyfile.FileHandle.Name() + ".old") if err != nil { log.Fatalf("makebackup os.Create() .old: %s\n", err) } if _, err := io.Copy(backup, historyfile.FileHandle); err != nil { log.Fatalf("makebackup io.Copy(): %s\n", err) } backup.Close() } func (historyfile *HistoryFile) ReadHistory() { if historyfile.FileHandle == nil { historyfile.Open() } historyfile.History = new(BashHistory) historyfile.History.Old = make(map[string]int) scanner := bufio.NewScanner(historyfile.FileHandle) var nr = 0 for scanner.Scan() { line := strings.TrimSpace(scanner.Text()) historyfile.History.Old[line] = nr nr++ } historyfile.History.Tmp = make([]string, nr) delete(historyfile.History.Old, "") } func (historyfile *HistoryFile) Open() { h, err := os.OpenFile(path.Join(historyfile.Dir, ".bash_history"), os.O_RDWR, 0600) if err != nil { log.Fatalf("historyfile Open(): %s\n", err) } historyfile.FileHandle = h } func NewBashHistoryFile() *HistoryFile { u, err := user.Current() if err != nil { log.Fatalf("NewBashHistoryFile() user.Current(): %s\n ", err) } historyfile := new(HistoryFile) historyfile.Dir = u.HomeDir return historyfile } func NewBashHistoryTmpFile() *Tmpfile { tmpdir, err := ioutil.TempDir(os.TempDir(), "hipa") if err != nil { log.Fatalf("NewBashHistoryTmpFile() TempDir(): %s\n ", err) } tmpfile, err := ioutil.TempFile(tmpdir, "hipa") if err != nil { log.Fatalf("NewBashHistoryTmpFile() TempDir(): %s\n ", err) } tempfile := new(Tmpfile) tempfile.Dir = tmpdir tempfile.FileHandle = tmpfile return tempfile }