func (self *interaction) Pager(text string) (err error) { pipe := make(chan io.WriteCloser, 1) prepare := func(cmd *exec.Cmd) (err error) { cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr p, err := cmd.StdinPipe() if err != nil { return errors.Decorated(err) } pipe <- p return } run := func(cmd *exec.Cmd) (err error) { p := <-pipe p.Write([]byte(text)) err = p.Close() if err != nil { return errors.Decorated(err) } return } err = exec.Command(prepare, run, "less", "-R") return }
func xclip(name string, selection string) (err error) { pipe := make(chan io.WriteCloser, 1) prepare := func(cmd *exec.Cmd) (err error) { p, err := cmd.StdinPipe() if err != nil { return errors.Decorated(err) } pipe <- p return } run := func(cmd *exec.Cmd) (err error) { p := <-pipe p.Write([]byte(name)) err = p.Close() if err != nil { return errors.Decorated(err) } return } err = exec.Command(prepare, run, "xclip", "-selection", selection) return }
// Spawn a given command. // - prepare() is called after the command creation but before actually starting it // - run() is called while the command is running and before waiting for its completion func Command(prepare func(cmd *Cmd) error, run func(cmd *Cmd) error, command string, arguments ...string) (err error) { cmd := exec.Command(command, arguments...) if prepare != nil { err = prepare((*Cmd)(cmd)) if err != nil { return } } err = cmd.Start() if err != nil { return errors.Decorated(err) } if run != nil { err = run((*Cmd)(cmd)) if err != nil { return } } err = cmd.Wait() if err != nil { return errors.Decorated(err) } return }
func (self *interaction) ReadPassword(text string) (result string, err error) { command, err := self.config.Eval("", "password", "command", os.Getenv) if err != nil { return } env := func(name string) string { switch name { case "TEXT": return text } return "" } arguments, err := self.config.Eval("", "password", "arguments", env) if err != nil { return } buffer := &bytes.Buffer{} type barrierData struct { n int64 err error } barrier := make(chan barrierData) prepare := func(cmd *exec.Cmd) (err error) { out, err := cmd.StdoutPipe() if err != nil { return errors.Decorated(err) } go func() { n, err := buffer.ReadFrom(out) barrier <- barrierData{n, err} }() return } resulter := make(chan string, 1) run := func(cmd *exec.Cmd) (err error) { data := <-barrier if data.err != nil { return errors.Decorated(err) } // the last character is a \n -- ignore it resulter <- string(buffer.Bytes()[:data.n-1]) return } err = exec.Command(prepare, run, "bash", "-c", fmt.Sprintf("%s %s", command, arguments)) if err != nil { return } result = <-resulter return }
func (self *config) ListConfigFiles() (result []string, err error) { xdg, err := self.Xdg() if err != nil { return } config_path, err := xdg.ConfigHome() if err != nil { return } config, err := os.Open(config_path) if err != nil { err = errors.Decorated(err) return } names, err := config.Readdirnames(0) if err != nil { err = errors.Decorated(err) return } result = make([]string, 0, len(names)-1) for _, name := range names { if name != "config.rc" && strings.HasSuffix(name, ".rc") { result = append(result, name) } } return }
func displayMenu(config core.Config, srv server.Server, list []string) (err error) { command, err := config.Eval("", "menu", "command", os.Getenv) if err != nil { return } arguments, err := config.Eval("", "menu", "arguments", nil) if err != nil { return } barrier := make(chan error) pipe := make(chan io.WriteCloser, 1) prepare := func(cmd *exec.Cmd) (err error) { p, err := cmd.StdinPipe() if err != nil { return errors.Decorated(err) } out, err := cmd.StdoutPipe() if err != nil { return errors.Decorated(err) } mmi, err := ui.Ui(srv, config) if err != nil { return } go clipboard(mmi, out, barrier) pipe <- p return } run := func(cmd *exec.Cmd) (err error) { p := <-pipe for _, entry := range list { p.Write([]byte(entry + "\n")) } err = p.Close() if err != nil { return errors.Decorated(err) } e := <-barrier if e != io.EOF { err = errors.Decorated(e) } return } err = exec.Command(prepare, run, "bash", "-c", fmt.Sprintf("%s %s", command, arguments)) return }
func (self *vault) save(config core.Config) (err error) { outstream, err := self.out() if err != nil { return errors.Decorated(err) } defer outstream.Close() cipher, err := config.Eval("", "vault", "openssl.cipher", os.Getenv) if err != nil { return err } pipe := make(chan io.WriteCloser, 1) prepare := func(cmd *exec.Cmd) (err error) { cmd.Env = append(os.Environ(), fmt.Sprintf("VAULT_MASTER=%s", self.master)) cmd.Stdout = outstream p, err := cmd.StdinPipe() if err != nil { return errors.Decorated(err) } pipe <- p return } run := func(cmd *exec.Cmd) (err error) { p := <-pipe for _, k := range self.data { code := k.Encoded() n, err := p.Write([]byte(code)) if err != nil { return errors.Decorated(err) } if n < len(code) { return errors.Newf("Incomplete write") } } err = p.Close() if err != nil { return errors.Decorated(err) } return } err = exec.Command(prepare, run, "openssl", cipher, "-a", "-pass", "env:VAULT_MASTER") return }
func (self *httpChannelClient) Ping(info string, reply *string) (err error) { err = self.client.Call("Gate.Ping", info, reply) if err != nil { err = errors.Decorated(err) } return }
func (self *httpChannelClient) SetMaster(master string, reply *bool) (err error) { err = self.client.Call("Gate.SetMaster", master, reply) if err != nil { err = errors.Decorated(err) } return }
func (self *httpChannelClient) Set(args server.SetArgs, reply *string) (err error) { err = self.client.Call("Gate.Set", args, reply) if err != nil { err = errors.Decorated(err) } return }
func (self *httpChannelClient) Save(force bool, reply *bool) (err error) { err = self.client.Call("Gate.Save", force, reply) if err != nil { err = errors.Decorated(err) } return }
func (self *httpChannelClient) Merge(args server.MergeArgs, reply *bool) (err error) { err = self.client.Call("Gate.Merge", args, reply) if err != nil { err = errors.Decorated(err) } return }
func (self *httpChannelClient) List(filter string, reply *[]string) (err error) { err = self.client.Call("Gate.List", filter, reply) if err != nil { err = errors.Decorated(err) } return }
func (self *httpChannelClient) Get(name string, reply *string) (err error) { err = self.client.Call("Gate.Get", name, reply) if err != nil { err = errors.Decorated(err) } return }
func (self *httpChannelClient) IsOpen(thenClose bool, reply *bool) (err error) { err = self.client.Call("Gate.IsOpen", thenClose, reply) if err != nil { err = errors.Decorated(err) } return }
func (self *httpChannelClient) Stop(status int, reply *bool) (err error) { err = self.client.Call("Gate.Stop", status, reply) if err != nil { err = errors.Decorated(err) } return }
func (self *httpChannelClient) Unset(key string, reply *bool) (err error) { err = self.client.Call("Gate.Unset", key, reply) if err != nil { err = errors.Decorated(err) } return }
func proxy(config core.Config) (result server.Server, err error) { result = _proxy if result == nil { s, err := serverimpl.Proxy(config, startServer) if err != nil { return } var isopen bool err = s.IsOpen(false, &isopen) if err != nil { err = errors.Decorated(err) return } if !isopen { err = openVault(s, config) if err != nil { return } } result = s _proxy = result } return }
func (self *properties) storeProperties(out io.Writer) (err error) { if err != nil { return errors.Decorated(err) } for property, value := range self.properties { if value != "" { _, err = out.Write([]byte(fmt.Sprintf("%s = %s\n", property, value))) if err != nil { return errors.Decorated(err) } } } return }
func (self *vault) Open(master string, config core.Config) (err error) { instream, err := self.in() if err != nil { return errors.Decorated(err) } defer instream.Close() cipher, err := config.Eval("", "vault", "openssl.cipher", os.Getenv) if err != nil { return } barrier := make(chan error) prepare := func(cmd *exec.Cmd) (err error) { cmd.Env = append(os.Environ(), fmt.Sprintf("VAULT_MASTER=%s", master)) cmd.Stdin = instream out, err := cmd.StdoutPipe() if err != nil { return errors.Decorated(err) } go self.decode(self, out, barrier) return } run := func(cmd *exec.Cmd) (err error) { e := <-barrier if e != io.EOF { err = errors.Decorated(e) } return } err = exec.Command(prepare, run, "openssl", cipher, "-d", "-a", "-pass", "env:VAULT_MASTER") if err != nil { return } self.master = master self.open = true return }
func decode_group_int(dec *regexp.Regexp, data string, name string, match []int) (result int64, err error) { s := decode_group(dec, data, name, match) result, err = strconv.ParseInt(s, 10, 64) if err != nil { return 0, errors.Decorated(err) } return }
func (self *generator) New() (result string, err error) { in, err := os.Open("/dev/random") if err != nil { return "", errors.Decorated(err) } defer in.Close() return self.generated(in) }
func startServer() (err error) { pipe := make(chan io.WriteCloser, 1) prepare := func(cmd *exec.Cmd) (err error) { p, err := cmd.StdinPipe() if err != nil { return errors.Decorated(err) } pipe <- p return } run := func(cmd *exec.Cmd) (err error) { p := <-pipe dir := dirname() var exe string if dir == "" { exe, err = osexec.LookPath("server") if err != nil { return errors.Decorated(err) } } else { exe = fmt.Sprintf("%s/server", dir) } var rc string if len(os.Args) > 1 { rc = os.Args[1] } p.Write([]byte(fmt.Sprintf("#!/bin/bash\n%s \"%s\" > /tmp/server-%s.log 2>&1 & disown\n", exe, rc, time.Now().Format("20060102150405")))) err = p.Close() if err != nil { return errors.Decorated(err) } return } err = exec.Command(prepare, run, "at", "now") if err != nil { return } return }
func (self *httpChannelServer) Stop(status int, reply *bool) (err error) { err = self.server.Stop(status, reply) if err != nil { return } err = self.listener.Close() if err != nil { return errors.Decorated(err) } return }
func (self *proxy) StoreProperties(out io.Writer) (err error) { if self.countProperties() > 0 { _, err = out.Write([]byte("[proxy]\n")) if err != nil { return errors.Decorated(err) } err = self.storeProperties(out) } return }
func (self *httpChannelClient) Connect() (err error) { host, port := networkConfig(self.config) endpoint := fmt.Sprintf("%s:%d", host, port) client, err := rpc.DialHTTP("tcp", endpoint) if err != nil { e := self.startFunc() if e != nil { err = errors.Decorated(e) return } for delay := 100 * time.Millisecond; err != nil && delay <= 3*time.Second; delay *= 2 { // if the server just started, maybe it needs time to settle time.Sleep(delay) client, err = rpc.DialHTTP("tcp", endpoint) } } if err != nil { err = errors.Decorated(err) return } self.client = client return }
// Get the list of passwords from the server, displays a list and puts // the corresponding password in xclip func Menu(config core.Config) (err error) { srv, err := proxy(config) if err != nil { return } var list []string err = srv.List(".*", &list) if err != nil { return errors.Decorated(err) } if len(list) > 0 { err = displayMenu(config, srv, list) } return }
func checkdir(dirname string) (result string, err error) { result = dirname info, err := os.Stat(dirname) if err == nil { if !info.IsDir() { err = errors.Newf("%s is not a directory", dirname) } } else { err = os.MkdirAll(dirname, os.ModeDir|0700) if err != nil { err = errors.Decorated(err) } } return }
func (self *httpChannelServer) Bind() (err error) { rpc.RegisterName("Gate", self) rpc.HandleHTTP() host, port := networkConfig(self.config) endpoint := fmt.Sprintf("%s:%s", host, port) self.listener, err = net.Listen("tcp", endpoint) if err != nil { err = errors.Decorated(err) return } go http.Serve(self.listener, self.handler) return }
func (self generator_mix) extend_pass(in io.Reader, pass string) (result string, err error) { data := make([]byte, 0, 3) n, err := in.Read(data) if err != nil { return "", errors.Decorated(err) } if n < 3 { return "", errors.New("not enough data") } b1 := data[0] b2 := data[1] b := byte(int((b1&0x7f)<<8+b2) % len(self.ingredient)) i := int(data[2]) % (len(pass) + 1) result = string(append(append(append(make([]byte, 0, len(pass)+1), pass[:i]...), b), pass[i:]...)) return }