// Serve starts Goji using reasonable defaults.
func Serve() {
	if !flag.Parsed() {
		flag.Parse()
	}

	log.SetFlags(log.Flags() | log.Lmicroseconds)

	// Install our handler at the root of the standard net/http default mux.
	// This allows packages like expvar to continue working as expected.
	http.Handle("/", DefaultMux)

	listener := bind.Default()
	log.Println("Starting Goji on", listener.Addr())

	graceful.HandleSignals()
	bind.Ready()

	err := graceful.Serve(listener, http.DefaultServeMux)

	if err != nil {
		log.Fatal(err)
	}

	graceful.Wait()
}
Exemplo n.º 2
0
Arquivo: auth.go Projeto: romana/core
// Initialize constructs appropriate Credential structure based on
// provided data, which includes, in the following precedence (later
// superseding earlier):
// * In case of username/password auth:
//   1. As keys UsernameKey and PasswordKey in ~/.romana.yaml file
//   2. As environment variables whose names are UsernameKey and PasswordKey values
//   3. As --username and --password command-line flags.
//      If --username flag is specified but --password flag is omitted,
//      the user will be prompted for the password.
// Notes:
// 1. The first two precedence steps (~/.romana.yaml and environment variables)
//    are taken care by the config module (github.com/spf13/viper)
// 2. If flag.Parsed() is false at the time of this call, the command-line values are
//    ignored.
//
func (c *Credential) Initialize() error {
	username := config.GetString(UsernameKey)
	password := config.GetString(PasswordKey)
	if c.assumeFlagParsed || flag.Parsed() {
		if c.userFlag != "" {
			username = c.userFlag
			if c.passFlag == "" {
				// Ask for password
				var err error
				password, err = GetPasswd()
				if err != nil {
					return err
				}
			} else {
				password = c.passFlag
			}
		}
	}
	if username != "" {
		//
		c.Username = username
		c.Password = password
		c.Type = CredentialUsernamePassword
	} else {
		// For now, credential is None if not specified
		c.Type = CredentialNone
	}
	return nil
}
Exemplo n.º 3
0
func loadConfig() (*Config, error) {

	var configFlag string
	var versionFlag bool

	if !flag.Parsed() {
		flag.StringVar(&configFlag, "config", "",
			"JSON config or file:// path to JSON config file.")
		flag.BoolVar(&versionFlag, "version", false, "Show version identifier and quit.")
		flag.Parse()
	} else {
		// allows for safe configuration reload
		configFlag = flag.Lookup("config").Value.String()
	}
	if versionFlag {
		fmt.Printf("Version: %s\nGitHash: %s\n", Version, GitHash)
		os.Exit(0)
	}
	if configFlag == "" {
		configFlag = os.Getenv("CONTAINERBUDDY")
	}

	config, err := parseConfig(configFlag)
	if err != nil {
		return nil, err
	}
	return initializeConfig(config)
}
Exemplo n.º 4
0
// createNewFiles creates all the log files for severity from sev down to infoLog.
// l.mu is held.
func (l *loggingT) createNewFiles() error {
	l.mu.Lock()
	defer l.mu.Unlock()

	if !flag.Parsed() {
		return fmt.Errorf("ERROR: logging before flag.Parse: ")
	} else if l.toStderr {
		return nil
	}

	now := time.Now()
	// Files are created in decreasing severity order, so as soon as we find one
	// has already been created, we can stop.
	for s := fatalLog; s >= infoLog; s-- {
		if l.file[s] == nil {
			continue
		}

		if sb, ok := l.file[s].(*syncBuffer); ok {
			if err := sb.rotateFile(now); err != nil {
				return err
			}
		}
	}

	return nil
}
Exemplo n.º 5
0
// HandlerFunc returns the http handler func, which renders the
// template with the data.
func (p page) HandlerFunc() http.HandlerFunc {
	fn := func(w http.ResponseWriter, r *http.Request) {
		data, err := p.getTemplateData(w, r)
		if err != nil {
			glog.Errorf("error getting template data: %v\n", err)
			serveISE(w)
			return
		}
		err = p.tmpl.ExecuteTemplate(w, baseTemplate, data)
		if err != nil {
			glog.Errorf("error rendering template: %v\n", err)
			serveISE(w)
			return
		}
	}

	if !flag.Parsed() {
		flag.Parse()
	}
	if *authDisabled {
		glog.Infof("-disabled_auth is set, not checking credentials\n")
	} else {
		fn = googleauth.RequireLogin(fn)
	}
	return fn
}
Exemplo n.º 6
0
// Run runs the tests. It returns an exit code to pass to os.Exit.
func (m *M) Run() int {
	// TestMain may have already called flag.Parse.
	if !flag.Parsed() {
		flag.Parse()
	}

	parseCpuList()

	m.before()
	startAlarm()
	haveExamples = len(m.examples) > 0
	testRan, testOk := runTests(m.deps.MatchString, m.tests)
	exampleRan, exampleOk := runExamples(m.deps.MatchString, m.examples)
	if !testRan && !exampleRan && *matchBenchmarks == "" {
		fmt.Fprintln(os.Stderr, "testing: warning: no tests to run")
	}
	if !testOk || !exampleOk || !runBenchmarks(m.deps.MatchString, m.benchmarks) {
		fmt.Println("FAIL")
		m.after()
		return 1
	}

	fmt.Println("PASS")
	m.after()
	return 0
}
Exemplo n.º 7
0
func main() {
	flag.Parse()

	if !flag.Parsed() || filename == "" || socket == "" {
		flag.Usage()
		os.Exit(1)
	}

	f, err := os.Open(filename)
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()

	l, err := net.Listen("unix", socket)
	if err != nil {
		log.Fatal(err)
	}
	defer l.Close()

	var a net.Conn
	a, err = l.Accept()
	if err != nil {
		log.Fatal(err)
	}
	defer a.Close()

	listenConn := a.(*net.UnixConn)
	if err = fd.Put(listenConn, f); err != nil {
		log.Fatal(err)
	}
}
Exemplo n.º 8
0
func main() {
	flag.Parse()
	if !flag.Parsed() {
		fmt.Fprintf(os.Stderr, "Invalid command line!\n")
		flag.PrintDefaults()
		return
	}

	if len(flag.Args()) < 1 {
		fmt.Fprintf(os.Stderr, "No file is specified\n")
		flag.PrintDefaults()
		return
	}

	filename := flag.Arg(0)

	file, err := NewLogFile(filename)
	if err != nil {
		fmt.Fprintf(os.Stderr, "NewLogFile() failed! %s\n", err)
		panic(err)
	}
	defer file.Close()

	err = file.Monitor(*linesToPrint)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Monitor() failed! %s\n", err)
		panic(err)
	}

	shutdown := make(chan bool)
	<-shutdown
}
Exemplo n.º 9
0
// createNewFiles creates all the log files for severity from sev down to infoLog.
// l.mu is held.
func (l *loggingT) createNewFiles(sev severity) error {
	l.mu.Lock()
	defer l.mu.Unlock()

	if !flag.Parsed() {
		return fmt.Errorf("ERROR: logging before flag.Parse: ")
	} else if l.toStderr {
		return nil
	}

	now := time.Now()
	// Files are created in decreasing severity order, so as soon as we find one
	// has already been created, we can stop.
	for s := sev; s >= infoLog; s-- {
		var sb *syncBuffer
		if l.file[s] == nil {
			sb = &syncBuffer{
				logger: l,
				sev:    s,
			}
		} else {
			if v, ok := l.file[s].(*syncBuffer); ok {
				sb = v
			}
		}

		if err := sb.rotateFile(now); err != nil {
			return err
		}
		l.file[s] = sb
	}

	return nil
}
Exemplo n.º 10
0
// getFlags will define the variables that can be found in the command line (via the flags package)
func (c *GetConf) getFlags() error {
	// parse command line
	if flag.Parsed() {
		return errors.New("getconf.getFlags: flags already parsed")
	} else {
		//fl := flag.NewFlagSet("flag", flag.ContinueOnError)
		for _, v := range c.allOptions {
			if v.flagName == "" {
				v.flagName = strings.ToLower(v.name)
			}
			switch v.oType {
			case reflect.Int:
				flag.Int(v.flagName, 0, "")
			case reflect.Int64:
				flag.Int64(v.flagName, 0, "")
			case reflect.Float64:
				flag.Float64(v.flagName, 0, "")
			case reflect.Bool:
				flag.Bool(v.flagName, false, "")
			case reflect.String:
				flag.String(v.flagName, "", "")
			}
		}
	}
	return nil
}
Exemplo n.º 11
0
// getConfigFilename gets the absolute filename of the config file specified by
// the ConfigFilename flag, and whether it exists.
//
// If the (relative or absolute) ConfigFilename exists, then it is returned.
// If the ConfigFilename exists in a valid XDG path, then it is returned.
// If neither of those exist, the (relative or absolute) ConfigFilename is returned.
func getConfigFilename() (string, bool) {
	if !flag.Parsed() {
		flag.Parse()
	}

	cf := *configFilename
	if *configFilename == "" {
		cf = defaultConfigFilename
	}

	if filepath.IsAbs(cf) {
		// Absolute path specified; user knows what they want.
		_, err := os.Stat(cf)
		return cf, err == nil
	}

	absCF, err := filepath.Abs(cf)
	if err != nil {
		// syscall failure; treat as if file doesn't exist.
		return cf, false
	}
	if _, err := os.Stat(absCF); err == nil {
		// File exists on relative path.
		return absCF, true
	}

	if xdgCF, err := xdg.Config.Find(cf); err == nil {
		// File exists in an XDG directory.
		return xdgCF, true
	}

	// Default to relative path. This is probably what the user expects if
	// it wasn't found anywhere else.
	return absCF, false
}
Exemplo n.º 12
0
// New returns prepares the *app.App and then
// returns a new Tester. It also disables
// logging in the App, since the Tester does
// its own logging.
func New(r Reporter, a *app.App) *Tester {
	if !flag.Parsed() {
		flag.Parse()
	}
	if *remoteHost == "" {
		if gaeLocal != nil && *gaeLocal {
			h := gaeLocalHost
			remoteHost = &h
		} else if gaeRemote != nil && *gaeRemote {
			h := internal.AppEngineAppHost()
			if h == "" {
				panic(errors.New("no application found in app.yaml - please, specify one to run remote tests"))
			}
			remoteHost = &h
		}
	}
	if *remoteHost != "" {
		r.Log(fmt.Sprintf("using host %s", *remoteHost))
	}
	if err := a.Prepare(); err != nil {
		r.Fatal(fmt.Errorf("error preparing app: %s", err))
	}
	a.Logger = nil
	return &Tester{r, a}
}
Exemplo n.º 13
0
func init() {
	flag.StringVar(&hostname, "host", "localhost", "Mongo DB host details.")
	flag.StringVar(&defaultVersion, "version", "New International Version (UK)", "Default Bible version to use, if none provided in request.")
	flag.StringVar(&defaultBook, "book", "Romans", "Default book to open, if none provided in request.")
	flag.StringVar(&defaultChapter, "chapter", "5", "Default chapter to open, if none provided in request.")
	flag.IntVar(&port, "port", 8998, "Port on which to bind the Rhema server.")
	var templatePath string
	flag.StringVar(&templatePath, "template", path.Join(path.Dir(os.Args[0]), "rhema.html"), "Path to the template file to use in generating web pages.")
	flag.Parse()
	if !flag.Parsed() {
		panic("Arguments could not be parsed.")
	}
	dat, e := ioutil.ReadFile(templatePath)
	if e != nil {
		panic(e)
	}
	page, e = template.New("Rhema").Parse(string(dat))
	if e != nil {
		panic(e)
	}
	session, e := mgo.Dial(hostname)
	if e != nil {
		panic(e)
	}
	bible = session.DB("bible")
	http.HandleFunc("/", rhemaHandler)
}
Exemplo n.º 14
0
// RegisterTaskQ registers the TaskQ application and all its handler in the
// hive.
func RegisterTaskQ(h beehive.Hive, opts ...Option) error {
	if !flag.Parsed() {
		flag.Parse()
	}

	proto, err := NewProtoHandler(addr.Get(opts))
	if err != nil {
		return err
	}

	r := rate.Get(opts)
	taskq := h.NewApp("taskq", beehive.Persistent(repl.Get(opts)),
		beehive.OutRate(bucket.Rate(r), 2*r))
	taskq.Handle(Enque{}, EnQHandler{})
	taskq.Handle(Deque{}, DeQHandler{})
	taskq.Handle(Ack{}, AckHandler{})
	taskq.Handle(Timeout{}, TimeoutHandler{
		ExpDur: 60 * time.Second,
	})

	ah := &AckHTTPHandler{Hive: h}
	taskq.HandleHTTP("/{queue}/tasks/{id:[0-9]+}", ah).Methods("DELETE")
	dh := &DeQHTTPHandler{Hive: h}
	taskq.HandleHTTP("/{queue}/tasks/deque", dh).Methods("POST")
	eh := &EnQHTTPHandler{Hive: h}
	taskq.HandleHTTP("/{queue}/tasks", eh).Methods("POST")

	taskq.Detached(beehive.NewTimer(30*time.Second, func() {
		h.Emit(Timeout(time.Now()))
	}))
	taskq.Detached(proto)

	return nil
}
Exemplo n.º 15
0
func main() {
	// show usage and exit if
	//   -h or --help was passed
	//   the flags failed to parse
	//   there isn't a single arg left
	flag.Parse()
	if help || !flag.Parsed() || flag.NArg() != 1 {
		usage()
		os.Exit(1)
	}

	stringOfDigits := flag.Arg(0)
	barlength := getbarlength(stringOfDigits)
	if bar {
		fmt.Println(strings.Repeat("*", barlength))
	}
	for row := range bigDigits[0] {
		line := ""
		for column := range stringOfDigits {
			digit := stringOfDigits[column] - '0'
			if 0 <= digit && digit <= 9 {
				line += bigDigits[digit][row] + "  "
			} else {
				log.Fatal("invalid whole number")
			}
		}
		fmt.Println(line)
	}
	if bar {
		fmt.Println(strings.Repeat("*", barlength))
	}
}
Exemplo n.º 16
0
Arquivo: serve.go Projeto: gunosy/kami
// Serve starts kami with reasonable defaults.
// It works (exactly) like Goji, looking for Einhorn, the bind flag, GOJI_BIND...
func Serve() {
	if !flag.Parsed() {
		flag.Parse()
	}

	// Install our handler at the root of the standard net/http default mux.
	// This allows packages like expvar to continue working as expected.
	http.Handle("/", Handler())

	listener := bind.Default()
	log.Println("Starting kami on", listener.Addr())

	graceful.HandleSignals()
	bind.Ready()
	graceful.PreHook(func() { log.Printf("kami received signal, gracefully stopping") })
	graceful.PostHook(func() { log.Printf("kami stopped") })

	err := graceful.Serve(listener, http.DefaultServeMux)

	if err != nil {
		log.Fatal(err)
	}

	graceful.Wait()
}
Exemplo n.º 17
0
func init() {
	if flag.Parsed() {
		return
	}
	level := log.LogNone
	levels := strings.SplitN(*loglevel, "|", -1)
	for _, v := range levels {
		switch v {
		case "none":
			level = level | log.LogNone
			break
		case "error":
			level = level | log.LogError
		case "warning":
			level = level | log.LogWarning
		case "message":
			level = level | log.LogMessage
		case "debug":
			level = level | log.LogDebug
		case "all":
			level = log.LogAll
		default:
		}
	}
	if err := log.Init(*logfile, level); err != nil {
		log.Error(err)
	}
}
Exemplo n.º 18
0
func (s *Server) Serve() {
	if !flag.Parsed() {
		flag.Parse()
	}
	s.Init()
	log.Fatal(http.ListenAndServe(fmt.Sprintf(":%v", environment.Port()), http.HandlerFunc(s.PreServe)))
}
Exemplo n.º 19
0
// LoadApp parses the commandline arguments and loads the config
func LoadApp() (*App, error) {

	var configFlag string
	var versionFlag bool

	if !flag.Parsed() {
		flag.StringVar(&configFlag, "config", "",
			"JSON config or file:// path to JSON config file.")
		flag.BoolVar(&versionFlag, "version", false, "Show version identifier and quit.")
		flag.Parse()
	}
	if versionFlag {
		fmt.Printf("Version: %s\nGitHash: %s\n", Version, GitHash)
		os.Exit(0)
	}
	if configFlag == "" {
		configFlag = os.Getenv("CONTAINERPILOT")
	}

	os.Setenv("CONTAINERPILOT_PID", fmt.Sprintf("%v", os.Getpid()))
	app, err := NewApp(configFlag)
	if err != nil {
		return nil, err
	}
	return app, nil
}
Exemplo n.º 20
0
func DBCheck() {
	// It only makes sense to do the DB check if the admin credentials are provided.

	if !flag.Parsed() {
		log.Fatal("Package jackdb requires you to parse the flags, preferably in your 'main' package.")
	}

	if adminSettings.Password == "" || adminSettings.Username == "" {
		// The admin credentials are not set.
		return
	}

	// The following variables should never vary.
	adminSettings.Database = "postgres"
	adminSettings.Host = sttngs.Host

	// Does the User exist?
	if exists, err := roleExists(); err != nil {
		log.Fatal("DBCHECK: An error occurred while checking for the role: " + err.Error())
	} else if !exists {
		if err := roleCreate(); err != nil {
			log.Fatal("DBCHECK: An error occurred while creating the role: " + err.Error())
		}
	}

	// Does the DB exist?
	if exists, err := dbExists(); err != nil {
		log.Fatal("DBCHECK: An error occurred while checking for the DB: " + err.Error())
	} else if !exists {
		if err := dbCreate(); err != nil {
			log.Fatal("DBCHECK: An error occurred while creating the DB: " + err.Error())
		}
	}
}
Exemplo n.º 21
0
func main() {
	if !flag.Parsed() {
		flag.Parse()
	}

	router := mux.NewRouter()
	router.StrictSlash(true)
	for _, route := range routes {
		handler := http.Handler(http.HandlerFunc(route.HandlerFunc))
		switch route.Type {
		case "JSON":
			handler = handlers.ContentTypeHandler(handler, "application/json")
		case "":
			break
		default:
			log.Fatalf("invalid route type: %v", route.Type)
		}

		r := router.NewRoute()
		r.Name(route.Name).
			Path(route.Path).
			Methods(route.Methods).
			Handler(handler)
	}

	address := fmt.Sprintf(":%d", *port)
	handler := handlers.CombinedLoggingHandler(os.Stderr, router)
	log.Printf("Version: %s", version.DeploymentManagerVersion)
	log.Printf("Listening on port %d...", *port)
	log.Fatal(http.ListenAndServe(address, handler))
}
Exemplo n.º 22
0
// Like Serve, but enables TLS using the given config.
func ServeTLS(config *tls.Config) {
	if !flag.Parsed() {
		flag.Parse()
	}

	ServeListener(tls.NewListener(bind.Default(), config))
}
Exemplo n.º 23
0
Arquivo: bmpic.go Projeto: ishawge/bmp
func GetAllArgs() []string {
	rv := make([]string, 0, 1000)
	f := os.Stdin // f is * osFile
	rdr := bufio.NewReader(f)
	alldone := false
	for {
		line, err := rdr.ReadString('\n')
		if err != nil {
			if err == io.EOF {
				alldone = true
			} else {
				log.Panicf("MDR: GetAllArgs read error")
			}
		}
		line = strings.TrimSpace(line)
		if len(line) > 0 {
			rv = append(rv, line)
		}
		if alldone {
			break
		}
	}
	if flag.Parsed() {
		args := flag.Args()
		for _, arg := range args {
			rv = append(rv, arg)
		}
	} else {
		fmt.Printf("Warning --> GetAllArgs: flags not parsed yet\n")
	}
	return rv
}
Exemplo n.º 24
0
// GetDSN returns a (command-line defined) connection string
func GetDSN() string {
	if !flag.Parsed() {
		flag.Parse()
		if *fDsn == "" {
			*fDsn = os.Getenv("DSN")
		}
	}

	var user, passw, sid string
	if !(fDsn == nil || *fDsn == "") {
		user, passw, sid = oracle.SplitDSN(*fDsn)
		//log.Printf("user=%q passw=%q sid=%q", user, passw, sid)
	}
	if user == "" && fUsername != nil && *fUsername != "" {
		user = *fUsername
	}
	if passw == "" && fPassword != nil && *fPassword != "" {
		passw = *fPassword
	}
	if sid == "" {
		if fSid != nil && *fSid != "" {
			sid = *fSid
		} else {
			sid = oracle.MakeDSN(*fHost, *fPort, "", *fServiceName)
		}
	}
	return user + "/" + passw + "@" + sid
}
Exemplo n.º 25
0
// Serve starts Goji using reasonable defaults.
func Serve() {
	if !flag.Parsed() {
		flag.Parse()
	}

	ServeListener(bind.Default())
}
Exemplo n.º 26
0
func main() {
	flag.Parse()
	if !flag.Parsed() {
		glog.Fatal("Unable to parse flags")
	}
	logrus.SetLevel(logrus.InfoLevel)
	numCpus := runtime.NumCPU()
	prev := runtime.GOMAXPROCS(numCpus)
	glog.WithField("num_cpu", numCpus).
		WithField("prev_maxprocs", prev).
		Info("Set max procs to num cpus")

	ps := new(store.Store)
	ps.Init(*postingDir)
	defer ps.Close()

	clog := commit.NewLogger(*mutationDir, "dgraph", 50<<20)
	clog.SyncEvery = 1
	clog.Init()
	defer clog.Close()

	posting.Init(ps, clog)

	http.HandleFunc("/query", queryHandler)
	glog.WithField("port", *port).Info("Listening for requests...")
	if err := http.ListenAndServe(":"+*port, nil); err != nil {
		x.Err(glog, err).Fatal("ListenAndServe")
	}
}
Exemplo n.º 27
0
//CreateClientFromFlags function parses the command line arguments
func CreateClientFromFlags() (*ChatClient, error) {
	var c = &ChatClient{}
	var host string

	flag.StringVar(&c.Username, "user", "Goof", "Your username")
	flag.StringVar(&host, "host", "localhost", "The host you want to connect to")

	flag.Parse()
	if c.Username == "Goof" {
		fmt.Println("Enter your Goof ID: ")
		fmt.Scanln(&c.Username)
	}
	if !flag.Parsed() {
		return c, errors.New("Unable to create user from commandline flags. Please try again")
	}

	// Check for the structure of the flag to see if we can make any educated guesses for them
	if len(host) != 0 {

		if strings.HasPrefix(host, ":") { // Begins with a colon means :3410 (just port)
			c.Address = DefaultHost + host
		} else if strings.Contains(host, ":") { // Contains a colon means host:port
			c.Address = host
		} else { // Otherwise, it's just a host
			c.Address = net.JoinHostPort(host, strconv.Itoa(DefaultPort))
		}

	} else {
		c.Address = net.JoinHostPort(DefaultHost, strconv.Itoa(DefaultPort)) // Default to our default port and host
	}

	return c, nil
}
Exemplo n.º 28
0
// GetFromFlags returns the logger defined by the command-line flags. This
// function runs flag.Parse() if it has not been run yet.
func GetFromFlags() log.Logger {
	if logger != nil {
		return logger
	}
	if !flag.Parsed() {
		flag.Parse()
	}

	threshold := getLevelFromName(*thresholdName)
	thresholdName = nil

	out := getStream(*logToStderr)
	logToStderr = nil

	flushThreshold := getLevelFromName(*flushThresholdName)
	flushThresholdName = nil

	if flushThreshold == log.None {
		logger = golog.New(out, threshold)
	} else {
		logger = buflog.New(out, threshold, flushThreshold)
	}

	return logger
}
Exemplo n.º 29
0
Arquivo: main.go Projeto: scds/eimbu
func main() {
	if !flag.Parsed() {
		flag.Parse()
	}
	var regexHandler = NewHttpHandlerRegexMatcher()

	http.Handle("/", http.StripPrefix(*prefix, regexHandler))

	regexHandler.Handle("/test", HttpHandlerRestHandler{5})
	regexHandler.Handle("/test/", HttpHandlerRestHandler{5})
	regexHandler.Handle("/test/{id}", HttpHandlerRestHandler{5})

	regexHandler.Handle("/ses/{request}", oauthFlowHandler{})

	var socket = *socket

	os.Remove(socket)

	oldUmask := syscall.Umask(000)
	l, err := net.Listen("unix", socket)
	syscall.Umask(oldUmask)
	if err != nil {
		panic(err)
	}

	panic(fcgi.Serve(l, http.DefaultServeMux))
}
Exemplo n.º 30
0
func main() {
	var rootDir, folder string
	var err error

	flag.StringVar(&rootDir, "root", os.ExpandEnv("$HOME/Maildir"), "path to maildir")
	flag.StringVar(&folder, "folder", "", "maildir folder name to put email (empty for inbox)")
	flag.StringVar(&cache.path, "cache", os.ExpandEnv("$HOME/.cache/maildir-put.cache"),
		"path to store message-ids to drop duplicate messages")
	flag.BoolVar(&cache.useRedis, "redis", false, "use redis for cache storage")
	flag.StringVar(&cache.redisOptions.Addr, "redis-addr", "127.0.0.1:6379", "redis address")
	flag.Int64Var(&cache.redisOptions.DB, "redis-db", 0, "redis base")
	flag.StringVar(&cache.redisOptions.Password, "redis-password", "", "redis password")

	if flag.Parse(); !flag.Parsed() {
		flag.PrintDefaults()
		os.Exit(1)
	}

	if err = cache.OpenCache(); err != nil {
		log.Fatalf("Can't open cache: %s", err.Error())
	}

	if hostname, err = os.Hostname(); err != nil {
		log.Fatalf("Can't get hostname: %s", err.Error())
	}

	md, err := maildir.New(rootDir, true)
	if err != nil {
		log.Fatalf("Can't open maildir: %s", err.Error())
	}

	for _, subfolder := range strings.Split(folder, "/") {
		if subfolder != "" {
			md, err = md.Child(subfolder, true)
			if err != nil {
				log.Fatalf("Can't open maildir: %s", err.Error())
			}
		}
	}

	dec := json.NewDecoder(os.Stdin)
	for {
		msg := new(Message)
		err = dec.Decode(msg)
		if err == nil {
			err = msg.Process(md)
		}

		if err == io.EOF {
			break
		} else if err != nil {
			log.Printf("Cannot read input message: %s", err.Error())
		}
	}

	if err = cache.Dump(); err != nil {
		log.Printf("warning: can't dump cache: %s", err.Error())
	}
}