func timedExit() {
	time.Sleep(15 * time.Second)
	log.LogError("Smtpd clean shutdown timed out, forcing exit")
	os.Exit(0)
}
timedExit is called as a goroutine during shutdown, it will force an exit after 15 seconds
package main
import (
	"flag"
	"fmt"
	golog "log"
	"os"
	"os/signal"
	"runtime"
	"syscall"
	"time"
	"github.com/gleez/smtpd/config"
	"github.com/gleez/smtpd/data"
	"github.com/gleez/smtpd/log"
	"github.com/gleez/smtpd/smtpd"
	"github.com/gleez/smtpd/web"
)
var (
	VERSION    = "1.1"
	BUILD_DATE = "undefined"
	help       = flag.Bool("help", false, "Displays this help")
	pidfile    = flag.String("pidfile", "none", "Write our PID into the specified file")
	logfile    = flag.String("logfile", "stderr", "Write out log into the specified file")
	configfile = flag.String("config", "/etc/smtpd.conf", "Path to the configuration file")
	startTime = time.Now()
	logf *os.File
	smtpServer *smtpd.Server
)
func main() {
	flag.Parse()
	runtime.GOMAXPROCS(runtime.NumCPU())
	if *help {
		flag.Usage()
		return
	}
	err := config.LoadConfig(*configfile)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Failed to parse config: %v\n", err)
		os.Exit(1)
	}
	sigChan := make(chan os.Signal)
	signal.Notify(sigChan, syscall.SIGHUP, syscall.SIGTERM)
	go signalProcessor(sigChan)
	level, _ := config.Config.String("logging", "level")
	log.SetLogLevel(level)
	if *logfile != "stderr" {
		if *logfile == "stdout" {
			golog.SetOutput(os.Stdout)
		} else {
			err := openLogFile()
			if err != nil {
				fmt.Fprintf(os.Stderr, "%v", err)
				os.Exit(1)
			}
			defer closeLogFile()
			os.Stdout.Close()
			os.Stderr.Close()  
			os.Stdin.Close()
			os.Stdout = logf
			os.Stderr = logf
		}
	}
	log.LogInfo("Smtpd %v (%v) starting...", VERSION, BUILD_DATE)
	if *pidfile != "none" {
		pidf, err := os.Create(*pidfile)
		if err != nil {
			log.LogError("Failed to create %v: %v", *pidfile, err)
			os.Exit(1)
		}
		defer pidf.Close()
		fmt.Fprintf(pidf, "%v\n", os.Getpid())
	}
	ds := data.NewDataStore()
	web.Initialize(config.GetWebConfig(), ds)
	go web.Start()
	smtpServer = smtpd.NewSmtpServer(config.GetSmtpConfig(), ds)
	smtpServer.Start()
	smtpServer.Drain()
}
func openLogFile() error {
	var err error
	logf, err = os.OpenFile(*logfile, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666)
	if err != nil {
		return fmt.Errorf("Failed to create %v: %v\n", *logfile, err)
	}
	golog.SetOutput(logf)
	log.LogTrace("Opened new logfile")
	return nil
}
func closeLogFile() error {
	log.LogTrace("Closing logfile")
	return logf.Close()
}
func signalProcessor(c <-chan os.Signal) {
	for {
		sig := <-c
		switch sig {
		case syscall.SIGHUP:
			if logf != nil {
				log.LogInfo("Recieved SIGHUP, cycling logfile")
				closeLogFile()
				openLogFile()
			} else {
				log.LogInfo("Ignoring SIGHUP, logfile not configured")
			}
		case syscall.SIGTERM:
			log.LogInfo("Received SIGTERM, shutting down")
			go timedExit()
			web.Stop()
			if smtpServer != nil {
				smtpServer.Stop()
			} else {
				log.LogError("smtpServer was nil during shutdown")
			}
		}
	}
}