changeset 2:3fe1614de42c

Split off sievemgr command into separate repository
author Guido Berhoerster <guido+managesieve@berhoerster.name>
date Mon, 26 Oct 2020 14:15:55 +0100
parents eec31eb2d21a
children 8413916df2be
files README cmd/sievemgr/activate.go cmd/sievemgr/command.go cmd/sievemgr/common.go cmd/sievemgr/delete.go cmd/sievemgr/get.go cmd/sievemgr/info.go cmd/sievemgr/list.go cmd/sievemgr/main.go cmd/sievemgr/put.go
diffstat 10 files changed, 0 insertions(+), 829 deletions(-) [+]
line wrap: on
line diff
--- 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
 -----
 
--- 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 <guido+managesieve@berhoerster.name>
-//
-// 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
-}
--- 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 <guido+managesieve@berhoerster.name>
-//
-// 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]
-}
--- 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 <guido+managesieve@berhoerster.name>
-//
-// 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
-}
--- 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 <guido+managesieve@berhoerster.name>
-//
-// 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
-}
--- 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 <guido+managesieve@berhoerster.name>
-//
-// 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
-}
--- 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 <guido+managesieve@berhoerster.name>
-//
-// 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
-}
--- 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 <guido+managesieve@berhoerster.name>
-//
-// 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
-}
--- 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 <guido+managesieve@berhoerster.name>
-//
-// 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)
-	}
-}
--- 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 <guido+managesieve@berhoerster.name>
-//
-// 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
-}