# HG changeset patch # User Guido Berhoerster # Date 1603718155 -3600 # Node ID 3fe1614de42c757fa9db02e40fc426672deb7db8 # Parent eec31eb2d21a8baed52c0833725e1812bc71e774 Split off sievemgr command into separate repository diff -r eec31eb2d21a -r 3fe1614de42c README --- a/README Sat Oct 17 22:40:57 2020 +0200 +++ b/README Mon Oct 26 14:15:55 2020 +0100 @@ -9,9 +9,6 @@ the SCRAM-SHA-1 SASL mechanism. Additional SASL authentication mechanisms can be provided by consumers. -A command-line ManageSieve client called sievemgr is included and provides an -example of how the package may be used. - Usage ----- diff -r eec31eb2d21a -r 3fe1614de42c cmd/sievemgr/activate.go --- a/cmd/sievemgr/activate.go Sat Oct 17 22:40:57 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ -// Copyright (C) 2020 Guido Berhoerster -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -package main - -import ( - "net" -) - -func init() { - cmdActivate.Flag.StringVar(&username, "u", "", "Set the username") - cmdActivate.Flag.StringVar(&passwordFilename, "P", "", - "Set the name of the password file") -} - -var cmdActivate = &command{ - UsageLine: "activate [options] host[:port] name", - Run: runActivate, -} - -var cmdDeactivate = &command{ - UsageLine: "deactivate [options] host[:port]", - Run: runActivate, -} - -func runActivate(cmd *command, args []string) error { - if (cmd.Name() == "activate" && len(args) != 2) || - (cmd.Name() == "deactivate" && len(args) != 1) { - return usageError("invalid number of arguments") - } - - host, port, err := parseHostPort(args[0]) - if err != nil { - return err - } - - var scriptName string - if len(args) > 1 { - scriptName = args[1] - } - - username, password, err := usernamePassword(host, port, username, - passwordFilename) - if err != nil { - return err - } - - c, err := dialPlainAuth(net.JoinHostPort(host, port), username, - password) - if err != nil { - return err - } - defer c.Logout() - - if err := c.ActivateScript(scriptName); err != nil { - return err - } - - return nil -} diff -r eec31eb2d21a -r 3fe1614de42c cmd/sievemgr/command.go --- a/cmd/sievemgr/command.go Sat Oct 17 22:40:57 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -// Copyright (C) 2020 Guido Berhoerster -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -package main - -import ( - "flag" - "fmt" - "strings" -) - -type command struct { - UsageLine string - Flag flag.FlagSet - Run func(cmd *command, args []string) error -} - -func (c *command) Usage() { - fmt.Fprintf(flag.CommandLine.Output(), "usage:\n %s %s\n", - flag.CommandLine.Name(), c.UsageLine) - fmt.Fprintln(flag.CommandLine.Output(), "options:") - c.Flag.PrintDefaults() -} - -func (c *command) Name() string { - return strings.SplitN(strings.Trim(c.UsageLine, " "), " ", 2)[0] -} diff -r eec31eb2d21a -r 3fe1614de42c cmd/sievemgr/common.go --- a/cmd/sievemgr/common.go Sat Oct 17 22:40:57 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,192 +0,0 @@ -// Copyright (C) 2020 Guido Berhoerster -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -package main - -import ( - "bufio" - "crypto/tls" - "errors" - "fmt" - "io" - "io/ioutil" - "net" - "os" - "os/user" - "runtime" - "strings" - - "go.guido-berhoerster.org/managesieve" - "golang.org/x/crypto/ssh/terminal" -) - -var errTooBig = errors.New("too big") - -func parseHostPort(s string) (string, string, error) { - var host string - host, port, err := net.SplitHostPort(s) - if err != nil { - // error may be due to a missing port but there is no usable - // error value to test for, thus try again with a port added - var tmpErr error - host, _, tmpErr = net.SplitHostPort(s + ":4190") - if tmpErr != nil { - return "", "", err - } - } - if port == "" { - // no port given, try to look up a SRV record for given domain - // and fall back to the domain and port 4190 - services, err := managesieve.LookupService(host) - if err != nil { - return "", "", err - } - host, port, err = net.SplitHostPort(services[0]) - if err != nil { - return "", "", err - } - } - return host, port, nil -} - -func readPassword() (string, error) { - var tty *os.File - var fd int - var w io.Writer - if runtime.GOOS == "windows" { - fd = int(os.Stdin.Fd()) - w = os.Stdout - } else { - var err error - tty, err = os.OpenFile("/dev/tty", os.O_RDWR, 0666) - if err != nil { - return "", err - } - defer tty.Close() - fd = int(tty.Fd()) - w = tty - } - - io.WriteString(w, "Password: ") - rawPassword, err := terminal.ReadPassword(fd) - io.WriteString(w, "\n") - if err != nil { - return "", fmt.Errorf("failed to read password: %s", err) - } - password := string(rawPassword) - if password == "" { - return "", fmt.Errorf("invalid password") - } - return password, nil -} - -func readPasswordFile(filename string) (string, error) { - f, err := os.Open(filename) - if err != nil { - return "", err - } - defer f.Close() - scanner := bufio.NewScanner(f) - if !scanner.Scan() { - err := scanner.Err() - if err == nil { - err = fmt.Errorf("failed to read from %q: unexpected EOF", - filename) - } - return "", err - } - password := scanner.Text() - if password == "" { - return "", fmt.Errorf("invalid password") - } - return password, nil -} - -func usernamePassword(host, port, username, passwordFile string) (string, string, error) { - // fall back to the system username - if username == "" { - u, err := user.Current() - if err != nil { - return "", "", - fmt.Errorf("failed to obtain username: %s", err) - } - username = u.Username - } - - var password string - var err error - if passwordFile != "" { - password, err = readPasswordFile(passwordFilename) - } else { - password, err = readPassword() - } - if err != nil { - return "", "", err - } - - return username, password, nil -} - -func dialPlainAuth(hostport, username, password string) (*managesieve.Client, error) { - c, err := managesieve.Dial(hostport) - if err != nil { - return nil, fmt.Errorf("failed to connect: %s", err) - } - - host, _, _ := net.SplitHostPort(hostport) - // switch to a TLS connection except for localhost - if host != "localhost" && host != "127.0.0.1" && host != "::1" { - tlsConf := &tls.Config{ - ServerName: host, - InsecureSkipVerify: skipCertVerify, - } - if err := c.StartTLS(tlsConf); err != nil { - return nil, - fmt.Errorf("failed to start TLS connection: %s", - err) - } - } - - auth := managesieve.PlainAuth("", username, password, host) - if err := c.Authenticate(auth); err != nil { - return nil, fmt.Errorf("failed to authenticate user %s: %s", - username, err) - } - - return c, nil -} - -func readLimitedString(r io.Reader, n int64) (string, error) { - var s strings.Builder - _, err := io.CopyN(&s, r, n) - if err == nil { - // check for EOF - _, err = io.CopyN(ioutil.Discard, r, 1) - if err == nil { - return s.String(), errTooBig - } - } - if err != io.EOF { - return s.String(), err - } - - return s.String(), nil -} diff -r eec31eb2d21a -r 3fe1614de42c cmd/sievemgr/delete.go --- a/cmd/sievemgr/delete.go Sat Oct 17 22:40:57 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -// Copyright (C) 2020 Guido Berhoerster -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -package main - -import ( - "net" -) - -func init() { - cmdDelete.Flag.StringVar(&username, "u", "", "Set the username") - cmdDelete.Flag.StringVar(&passwordFilename, "P", "", - "Set the name of the password file") -} - -var cmdDelete = &command{ - UsageLine: "delete [options] host[:port] name", - Run: runDelete, -} - -func runDelete(cmd *command, args []string) error { - if len(args) != 2 { - return usageError("invalid number of arguments") - } - - host, port, err := parseHostPort(args[0]) - if err != nil { - return err - } - - scriptName := args[1] - - username, password, err := usernamePassword(host, port, username, - passwordFilename) - if err != nil { - return err - } - - c, err := dialPlainAuth(net.JoinHostPort(host, port), username, - password) - if err != nil { - return err - } - defer c.Logout() - - if err := c.DeleteScript(scriptName); err != nil { - return err - } - - return nil -} diff -r eec31eb2d21a -r 3fe1614de42c cmd/sievemgr/get.go --- a/cmd/sievemgr/get.go Sat Oct 17 22:40:57 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -// Copyright (C) 2020 Guido Berhoerster -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -package main - -import ( - "net" - "os" -) - -func init() { - cmdGet.Flag.StringVar(&username, "u", "", "Set the username") - cmdGet.Flag.StringVar(&passwordFilename, "P", "", - "Set the name of the password file") -} - -var cmdGet = &command{ - UsageLine: "get [options] host[:port] name", - Run: runGet, -} - -func runGet(cmd *command, args []string) error { - if len(args) != 2 { - return usageError("invalid number of arguments") - } - - host, port, err := parseHostPort(args[0]) - if err != nil { - return err - } - - scriptName := args[1] - - username, password, err := usernamePassword(host, port, username, - passwordFilename) - if err != nil { - return err - } - - c, err := dialPlainAuth(net.JoinHostPort(host, port), username, - password) - if err != nil { - return err - } - defer c.Logout() - - script, err := c.GetScript(scriptName) - if err != nil { - return err - } - os.Stdout.WriteString(script) - - return nil -} diff -r eec31eb2d21a -r 3fe1614de42c cmd/sievemgr/info.go --- a/cmd/sievemgr/info.go Sat Oct 17 22:40:57 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,84 +0,0 @@ -// Copyright (C) 2020 Guido Berhoerster -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -package main - -import ( - "fmt" - "net" -) - -func init() { - cmdInfo.Flag.StringVar(&username, "u", "", "Set the username") - cmdInfo.Flag.StringVar(&passwordFilename, "P", "", - "Set the name of the password file") -} - -var cmdInfo = &command{ - UsageLine: "info [options] host[:port]", - Run: runInfo, -} - -func runInfo(cmd *command, args []string) error { - if len(args) != 1 { - return usageError("invalid number of arguments") - } - - host, port, err := parseHostPort(args[0]) - if err != nil { - return err - } - - username, password, err := usernamePassword(host, port, username, - passwordFilename) - if err != nil { - return err - } - - c, err := dialPlainAuth(net.JoinHostPort(host, port), username, - password) - if err != nil { - return err - } - defer c.Logout() - - fmt.Println(net.JoinHostPort(host, port)) - if c.SupportsRFC5804() { - fmt.Println("RFC5804 supported") - } - if c.SupportsTLS() { - fmt.Println("STARTTLS supported") - } - fmt.Printf("SASL mechanisms:\n") - for _, m := range c.SASLMechanisms() { - fmt.Printf(" %s\n", m) - } - fmt.Printf("Extensions:\n") - for _, e := range c.Extensions() { - fmt.Printf(" %s\n", e) - } - fmt.Printf("Notification methods:\n") - for _, m := range c.NotifyMethods() { - fmt.Printf(" %s\n", m) - } - - return nil -} diff -r eec31eb2d21a -r 3fe1614de42c cmd/sievemgr/list.go --- a/cmd/sievemgr/list.go Sat Oct 17 22:40:57 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,77 +0,0 @@ -// Copyright (C) 2020 Guido Berhoerster -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -package main - -import ( - "fmt" - "net" -) - -func init() { - cmdList.Flag.StringVar(&username, "u", "", "Set the username") - cmdList.Flag.StringVar(&passwordFilename, "P", "", - "Set the name of the password file") -} - -var cmdList = &command{ - UsageLine: "list [options] host[:port]", - Run: runList, -} - -func runList(cmd *command, args []string) error { - if len(args) != 1 { - return usageError("invalid number of arguments") - } - - host, port, err := parseHostPort(args[0]) - if err != nil { - return err - } - - username, password, err := usernamePassword(host, port, username, - passwordFilename) - if err != nil { - return err - } - - c, err := dialPlainAuth(net.JoinHostPort(host, port), username, - password) - if err != nil { - return err - } - defer c.Logout() - - scripts, active, _ := c.ListScripts() - if err != nil { - return err - } - fmt.Println("ACTIVE SCRIPT") - for _, script := range scripts { - isActive := "no" - if script == active { - isActive = "yes" - } - fmt.Printf("%-3s %s\n", isActive, script) - } - - return nil -} diff -r eec31eb2d21a -r 3fe1614de42c cmd/sievemgr/main.go --- a/cmd/sievemgr/main.go Sat Oct 17 22:40:57 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,116 +0,0 @@ -// Copyright (C) 2020 Guido Berhoerster -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -package main - -import ( - "errors" - "flag" - "fmt" - "os" -) - -const ( - exitSuccess = iota - exitFailure - exitUsage -) - -type usageError string - -func (e usageError) Error() string { - return string(e) -} - -var ( - skipCertVerify bool - username string - passwordFilename string -) - -var cmds = []*command{ - cmdList, - cmdPut, - cmdGet, - cmdActivate, - cmdDeactivate, - cmdDelete, - cmdInfo, -} - -func usage() { - fmt.Fprintf(flag.CommandLine.Output(), - "usage:\n %s [options] [subcommand [options] [arguments]]\n", - flag.CommandLine.Name()) - fmt.Fprintln(flag.CommandLine.Output(), "subcommands:") - for _, cmd := range cmds { - fmt.Fprintf(flag.CommandLine.Output(), " %s\n", cmd.Name()) - } - fmt.Fprintln(flag.CommandLine.Output(), "global options:") - flag.PrintDefaults() -} - -func main() { - flag.Usage = usage - flag.BoolVar(&skipCertVerify, "I", false, - "Skip TLS certificate verification") - flag.Parse() - if flag.NArg() == 0 { - fmt.Fprintln(flag.CommandLine.Output(), "missing subcommand") - usage() - os.Exit(exitUsage) - } - - name := flag.Arg(0) - var cmd *command - for _, c := range cmds { - if c.Name() == name { - cmd = c - break - } - } - if cmd == nil { - fmt.Fprintf(flag.CommandLine.Output(), - "unknown subcommand %q\n", name) - usage() - os.Exit(exitUsage) - } - - cmd.Flag.Init(cmd.Name(), flag.ExitOnError) - cmd.Flag.Usage = cmd.Usage - args := flag.Args() - if err := cmd.Flag.Parse(args[1:]); err != nil { - fmt.Fprintln(flag.CommandLine.Output(), err) - os.Exit(exitFailure) - } - - if err := cmd.Run(cmd, cmd.Flag.Args()); err != nil { - fmt.Fprintln(flag.CommandLine.Output(), err) - - var uerr usageError - if errors.As(err, &uerr) { - cmd.Usage() - os.Exit(exitUsage) - } - - os.Exit(exitFailure) - } -} diff -r eec31eb2d21a -r 3fe1614de42c cmd/sievemgr/put.go --- a/cmd/sievemgr/put.go Sat Oct 17 22:40:57 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -// Copyright (C) 2020 Guido Berhoerster -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -package main - -import ( - "fmt" - "io" - "net" - "os" - - "go.guido-berhoerster.org/managesieve" -) - -func init() { - cmdPut.Flag.StringVar(&username, "u", "", "Set the username") - cmdPut.Flag.StringVar(&passwordFilename, "P", "", - "Set the name of the password file") -} - -var cmdPut = &command{ - UsageLine: "put [options] host[:port] name [file]", - Run: runPut, -} - -func runPut(cmd *command, args []string) error { - var scriptName string - var r io.Reader = os.Stdin - var host, port string - var err error - switch len(args) { - case 3: // name and filename - scriptFile, err := os.Open(args[2]) - if err != nil { - return fmt.Errorf("failed to open script file: %s\n", - err) - } - defer scriptFile.Close() - r = scriptFile - fallthrough - case 2: // only name - host, port, err = parseHostPort(args[0]) - if err != nil { - return err - } - - scriptName = args[1] - default: - return usageError("invalid number of arguments") - } - - script, err := readLimitedString(r, managesieve.ReadLimit) - if err != nil { - return fmt.Errorf("failed to read script: %s\n", err) - } - - username, password, err := usernamePassword(host, port, username, - passwordFilename) - if err != nil { - return err - } - - c, err := dialPlainAuth(net.JoinHostPort(host, port), username, - password) - if err != nil { - return err - } - defer c.Logout() - - if err := c.PutScript(scriptName, script); err != nil { - return err - } - - return nil -}