<commit_before>package main

import (
	"crypto/tls"
	"flag"
	slog "log"
	"net/http"
	"os"
	"strings"

	"github.com/dcu/mongodb_exporter/collector"
	"github.com/dcu/mongodb_exporter/shared"

	"github.com/golang/glog"
	"github.com/prometheus/client_golang/prometheus"
)

func mongodbDefaultUri() string {
	if u := os.Getenv("MONGODB_URL"); u != "" {
		return u
	}
	return "mongodb://localhost:27017"
}

var (
	listenAddressFlag = flag.String("web.listen-address", ":9001", "Address on which to expose metrics and web interface.")
	metricsPathFlag   = flag.String("web.metrics-path", "/metrics", "Path under which to expose metrics.")
	webTlsCert        = flag.String("web.tls-cert", "", "Path to PEM file that conains the certificate (and opionally also the private key in PEM format).\n"+
		"    \tThis should include the whole certificate chain.\n"+
		"    \tIf provided: The web socket will be a HTTPS socket.\n"+
		"    \tIf not provided: Only HTTP.")
	webTlsPrivateKey = flag.String("web.tls-private-key", "", "Path to PEM file that conains the private key (if not contained in web.tls-cert file).")
	webTlsClientCa   = flag.String("web.tls-client-ca", "", "Path to PEM file that conains the CAs that are trused for client connections.\n"+
		"    \tIf provided: Connecting clients should present a certificate signed by one of this CAs.\n"+
		"    \tIf not provided: Every client will be accepted.")

	mongodbURIFlag = flag.String("mongodb.uri", mongodbDefaultUri(), "Mongodb URI, format: [mongodb://][user:pass@]host1[:port1][,host2[:port2],...][/database][?options]")
	mongodbTlsCert = flag.String("mongodb.tls-cert", "", "Path to PEM file that conains the certificate (and opionally also the private key in PEM format).\n"+
		"    \tThis should include the whole certificate chain.\n"+
		"    \tIf provided: The connection will be opened via TLS to the MongoDB server.")
	mongodbTlsPrivateKey = flag.String("mongodb.tls-private-key", "", "Path to PEM file that conains the private key (if not contained in mongodb.tls-cert file).")
	mongodbTlsCa         = flag.String("mongodb.tls-ca", "", "Path to PEM file that conains the CAs that are trused for server connections.\n"+
		"    \tIf provided: MongoDB servers connecting to should present a certificate signed by one of this CAs.\n"+
		"    \tIf not provided: System default CAs are used.")
	mongodbTlsDisableHostnameValidation = flag.Bool("mongodb.tls-disable-hostname-validation", false, "Do hostname validation for server connection.")
	enabledGroupsFlag                   = flag.String("groups.enabled", "asserts,durability,background_flushing,connections,extra_info,global_lock,index_counters,network,op_counters,op_counters_repl,memory,locks,metrics", "Comma-separated list of groups to use, for more info see: docs.mongodb.org/manual/reference/command/serverStatus/")
	authUserFlag                        = flag.String("auth.user", "", "Username for basic auth.")
	authPassFlag                        = flag.String("auth.pass", "", "Password for basic auth.")
)

type basicAuthHandler struct {
	handler  http.HandlerFunc
	user     string
	password string
}

func (h *basicAuthHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	user, password, ok := r.BasicAuth()
	if !ok || password != h.password || user != h.user {
		w.Header().Set("WWW-Authenticate", "Basic realm=\"metrics\"")
		http.Error(w, "Invalid username or password", http.StatusUnauthorized)
		return
	}
	h.handler(w, r)
	return
}

func hasUserAndPassword() bool {
	return *authUserFlag != "" && *authPassFlag != ""
}

func prometheusHandler() http.Handler {
	handler := prometheus.Handler()
	if hasUserAndPassword() {
		handler = &basicAuthHandler{
			handler:  prometheus.Handler().ServeHTTP,
			user:     *authUserFlag,
			password: *authPassFlag,
		}
	}

	return handler
}

func startWebServer() {
	handler := prometheusHandler()

	registerCollector()

	http.Handle(*metricsPathFlag, handler)

	server := &http.Server{
		Addr:     *listenAddressFlag,
		ErrorLog: createHttpServerLogWrapper(),
	}

	var err error
	if len(*webTlsCert) > 0 {
		clientValidation := "no"
		if len(*webTlsClientCa) > 0 && len(*webTlsCert) > 0 {
			certificates, err := shared.LoadCertificatesFrom(*webTlsClientCa)
			if err != nil {
				glog.Fatalf("Couldn't load client CAs from %s. Got: %s", *webTlsClientCa, err)
			}
			server.TLSConfig = &tls.Config{
				ClientCAs:  certificates,
				ClientAuth: tls.RequireAndVerifyClientCert,
			}
			clientValidation = "yes"
		}
		targetTlsPrivateKey := *webTlsPrivateKey
		if len(targetTlsPrivateKey) <= 0 {
			targetTlsPrivateKey = *webTlsCert
		}
		glog.Infof("Listening on %s (scheme=HTTPS, secured=TLS, clientValidation=%s)\n", server.Addr, clientValidation)
		err = server.ListenAndServeTLS(*webTlsCert, targetTlsPrivateKey)
	} else {
		glog.Infof("Listening on %s (scheme=HTTP, secured=no, clientValidation=no)\n", server.Addr)
		err = server.ListenAndServe()
	}

	if err != nil {
		panic(err)
	}
}

func registerCollector() {
	mongodbCollector := collector.NewMongodbCollector(collector.MongodbCollectorOpts{
		URI:                   *mongodbURIFlag,
		TLSCertificateFile:    *mongodbTlsCert,
		TLSPrivateKeyFile:     *mongodbTlsPrivateKey,
		TLSCaFile:             *mongodbTlsCa,
		TLSHostnameValidation: !(*mongodbTlsDisableHostnameValidation),
	})
	prometheus.MustRegister(mongodbCollector)
}

type bufferedLogWriter struct {
	buf []byte
}

func (w *bufferedLogWriter) Write(p []byte) (n int, err error) {
	glog.Info(strings.TrimSpace(strings.Replace(string(p), "\n", " ", -1)))
	return len(p), nil
}

func createHttpServerLogWrapper() *slog.Logger {
	return slog.New(&bufferedLogWriter{}, "", 0)
}

func main() {
	flag.Parse()
	shared.ParseEnabledGroups(*enabledGroupsFlag)

	startWebServer()
}
<commit_msg>Switched back to fmt.Printf for listening message<commit_after>package main

import (
	"crypto/tls"
	"flag"
	"fmt"
	slog "log"
	"net/http"
	"os"
	"strings"

	"github.com/dcu/mongodb_exporter/collector"
	"github.com/dcu/mongodb_exporter/shared"

	"github.com/golang/glog"
	"github.com/prometheus/client_golang/prometheus"
)

func mongodbDefaultUri() string {
	if u := os.Getenv("MONGODB_URL"); u != "" {
		return u
	}
	return "mongodb://localhost:27017"
}

var (
	listenAddressFlag = flag.String("web.listen-address", ":9001", "Address on which to expose metrics and web interface.")
	metricsPathFlag   = flag.String("web.metrics-path", "/metrics", "Path under which to expose metrics.")
	webTlsCert        = flag.String("web.tls-cert", "", "Path to PEM file that conains the certificate (and opionally also the private key in PEM format).\n"+
		"    \tThis should include the whole certificate chain.\n"+
		"    \tIf provided: The web socket will be a HTTPS socket.\n"+
		"    \tIf not provided: Only HTTP.")
	webTlsPrivateKey = flag.String("web.tls-private-key", "", "Path to PEM file that conains the private key (if not contained in web.tls-cert file).")
	webTlsClientCa   = flag.String("web.tls-client-ca", "", "Path to PEM file that conains the CAs that are trused for client connections.\n"+
		"    \tIf provided: Connecting clients should present a certificate signed by one of this CAs.\n"+
		"    \tIf not provided: Every client will be accepted.")

	mongodbURIFlag = flag.String("mongodb.uri", mongodbDefaultUri(), "Mongodb URI, format: [mongodb://][user:pass@]host1[:port1][,host2[:port2],...][/database][?options]")
	mongodbTlsCert = flag.String("mongodb.tls-cert", "", "Path to PEM file that conains the certificate (and opionally also the private key in PEM format).\n"+
		"    \tThis should include the whole certificate chain.\n"+
		"    \tIf provided: The connection will be opened via TLS to the MongoDB server.")
	mongodbTlsPrivateKey = flag.String("mongodb.tls-private-key", "", "Path to PEM file that conains the private key (if not contained in mongodb.tls-cert file).")
	mongodbTlsCa         = flag.String("mongodb.tls-ca", "", "Path to PEM file that conains the CAs that are trused for server connections.\n"+
		"    \tIf provided: MongoDB servers connecting to should present a certificate signed by one of this CAs.\n"+
		"    \tIf not provided: System default CAs are used.")
	mongodbTlsDisableHostnameValidation = flag.Bool("mongodb.tls-disable-hostname-validation", false, "Do hostname validation for server connection.")
	enabledGroupsFlag                   = flag.String("groups.enabled", "asserts,durability,background_flushing,connections,extra_info,global_lock,index_counters,network,op_counters,op_counters_repl,memory,locks,metrics", "Comma-separated list of groups to use, for more info see: docs.mongodb.org/manual/reference/command/serverStatus/")
	authUserFlag                        = flag.String("auth.user", "", "Username for basic auth.")
	authPassFlag                        = flag.String("auth.pass", "", "Password for basic auth.")
)

type basicAuthHandler struct {
	handler  http.HandlerFunc
	user     string
	password string
}

func (h *basicAuthHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	user, password, ok := r.BasicAuth()
	if !ok || password != h.password || user != h.user {
		w.Header().Set("WWW-Authenticate", "Basic realm=\"metrics\"")
		http.Error(w, "Invalid username or password", http.StatusUnauthorized)
		return
	}
	h.handler(w, r)
	return
}

func hasUserAndPassword() bool {
	return *authUserFlag != "" && *authPassFlag != ""
}

func prometheusHandler() http.Handler {
	handler := prometheus.Handler()
	if hasUserAndPassword() {
		handler = &basicAuthHandler{
			handler:  prometheus.Handler().ServeHTTP,
			user:     *authUserFlag,
			password: *authPassFlag,
		}
	}

	return handler
}

func startWebServer() {
	handler := prometheusHandler()

	registerCollector()

	http.Handle(*metricsPathFlag, handler)

	server := &http.Server{
		Addr:     *listenAddressFlag,
		ErrorLog: createHttpServerLogWrapper(),
	}

	var err error
	if len(*webTlsCert) > 0 {
		clientValidation := "no"
		if len(*webTlsClientCa) > 0 && len(*webTlsCert) > 0 {
			certificates, err := shared.LoadCertificatesFrom(*webTlsClientCa)
			if err != nil {
				glog.Fatalf("Couldn't load client CAs from %s. Got: %s", *webTlsClientCa, err)
			}
			server.TLSConfig = &tls.Config{
				ClientCAs:  certificates,
				ClientAuth: tls.RequireAndVerifyClientCert,
			}
			clientValidation = "yes"
		}
		targetTlsPrivateKey := *webTlsPrivateKey
		if len(targetTlsPrivateKey) <= 0 {
			targetTlsPrivateKey = *webTlsCert
		}
		fmt.Printf("Listening on %s (scheme=HTTPS, secured=TLS, clientValidation=%s)\n", server.Addr, clientValidation)
		err = server.ListenAndServeTLS(*webTlsCert, targetTlsPrivateKey)
	} else {
		fmt.Printf("Listening on %s (scheme=HTTP, secured=no, clientValidation=no)\n", server.Addr)
		err = server.ListenAndServe()
	}

	if err != nil {
		panic(err)
	}
}

func registerCollector() {
	mongodbCollector := collector.NewMongodbCollector(collector.MongodbCollectorOpts{
		URI:                   *mongodbURIFlag,
		TLSCertificateFile:    *mongodbTlsCert,
		TLSPrivateKeyFile:     *mongodbTlsPrivateKey,
		TLSCaFile:             *mongodbTlsCa,
		TLSHostnameValidation: !(*mongodbTlsDisableHostnameValidation),
	})
	prometheus.MustRegister(mongodbCollector)
}

type bufferedLogWriter struct {
	buf []byte
}

func (w *bufferedLogWriter) Write(p []byte) (n int, err error) {
	glog.Info(strings.TrimSpace(strings.Replace(string(p), "\n", " ", -1)))
	return len(p), nil
}

func createHttpServerLogWrapper() *slog.Logger {
	return slog.New(&bufferedLogWriter{}, "", 0)
}

func main() {
	flag.Parse()
	shared.ParseEnabledGroups(*enabledGroupsFlag)

	startWebServer()
}
<|endoftext|>


<commit_before>package netsec

import (
	"atlantis/supervisor/containers/serialize"
	"errors"
	"log"
	"sync"
)

type NetworkSecurity struct {
	sync.Mutex
	SaveFile   string                        // where to save state
	DeniedIPs  map[string]bool               // list of denied IPs. map for easy existence check
	IPGroups   map[string][]string           // group name -> list of infrastructure IPs to blanket deny
	Containers map[string]*ContainerSecurity // container id -> ContainerSecurity
}

func New(saveFile string) *NetworkSecurity {
	return &NetworkSecurity{
		Mutex:      sync.Mutex{},
		SaveFile:   saveFile,
		DeniedIPs:  map[string]bool{},
		IPGroups:   map[string][]string{},
		Containers: map[string]*ContainerSecurity{},
	}
}

func (n *NetworkSecurity) save() {
	// save state
	serialize.SaveAll(serialize.SaveDefinition{
		n.SaveFile,
		n,
	})
}

func (n *NetworkSecurity) UpdateIPGroup(name string, ips []string) error {
	n.Lock()
	defer n.Unlock()

	if err := delConnTrackRule(); err != nil {
		return err
	}

	current, exists := n.IPGroups[name]
	toRemove := []string{}
	if exists {
		// figure out what is being removed
		incomingMap := map[string]bool{}
		for _, ip := range ips {
			incomingMap[ip] = true
		}
		for _, ip := range current {
			if !incomingMap[ip] {
				toRemove = append(toRemove, ip)
			}
		}
	}
	// add blanket deny rule for new IPs
	newIPs := []string{}
	for _, ip := range ips {
		if n.DeniedIPs[ip] {
			// already exists
			continue
		}
		if err := n.rejectIP(ip); err != nil {
			return err
		}
		n.DeniedIPs[ip] = true
		newIPs = append(newIPs, ip)
	}
	// remove blanket deny rule for removed IPs
	for _, ip := range toRemove {
		if !n.DeniedIPs[ip] {
			// already removed
			continue
		}
		n.allowIP(ip)
		delete(n.DeniedIPs, ip)
	}
	// add/remove forward rules for new IPs for everything that uses the name
	for _, contSec := range n.Containers {
		ports, exists := contSec.SecurityGroups[name]
		if !exists {
			// this container does not use this ip group
			continue
		}
		for _, port := range ports {
			// add new ips
			for _, ip := range newIPs {
				contSec.allowPort(ip, port)
			}
			// remove old ips
			for _, ip := range toRemove {
				contSec.rejectPort(ip, port)
			}
		}
	}
	// update ipGroups
	n.IPGroups[name] = ips
	n.save()

	return addConnTrackRule()
}

func (n *NetworkSecurity) DeleteIPGroup(name string) error {
	if err := n.UpdateIPGroup(name, []string{}); err != nil {
		return err
	}
	n.Lock()
	defer n.Unlock()
	delete(n.IPGroups, name)
	n.save()
	return nil
}

func (n *NetworkSecurity) AddContainerSecurity(id string, pid int, sgs map[string][]uint16) error {
	n.Lock()
	defer n.Unlock()
	log.Println("[netsec] add container security: "+id)
	if _, exists := n.Containers[id]; exists {
		// we already have security set up for this id. don't do it and return an error.
		log.Println("[netsec] -- not adding, already existed for: "+id)
		return errors.New("Container " + id + " already has Network Security set up.")
	}
	// make sure all groups exist
	for group, _ := range sgs {
		_, exists := n.IPGroups[group]
		if !exists {
			log.Println("[netsec] -- not adding group "+group+" doesn't exist for: "+id)
			return errors.New("IP Group " + group + " does not exist")
		}
	}

	// fetch network info
	contSec, err := NewContainerSecurity(id, pid, sgs)
	if err != nil {
		return err
	}
	contSec.addMark()

	// add forward rules
	for group, ports := range sgs {
		for _, port := range ports {
			ips := n.IPGroups[group]
			for _, ip := range ips {
				if err := contSec.allowPort(ip, port); err != nil {
					defer n.RemoveContainerSecurity(id) // cleanup created references when we error out
					return err
				}
			}
		}
	}
	n.Containers[id] = contSec
	n.save()
	log.Println("[netsec] -- added "+id)
	return nil
}

func (n *NetworkSecurity) RemoveContainerSecurity(id string) error {
	n.Lock()
	defer n.Unlock()
	log.Println("[netsec] remove container security: "+id)
	contSec, exists := n.Containers[id]
	if !exists {
		log.Println("[netsec] -- not removing, none existed for: "+id)
		// no container security here, nothing to remove
		return nil
	}

	contSec.delMark()
	// remove forward rules
	for group, ports := range contSec.SecurityGroups {
		for _, port := range ports {
			ips := n.IPGroups[group]
			for _, ip := range ips {
				contSec.rejectPort(ip, port)
			}
		}
	}
	delete(n.Containers, id)
	n.save()
	log.Println("[netsec] -- removed "+id)
	return nil
}

func delConnTrackRule() error {
	_, err := executeCommand("iptables", "-D", "FORWARD", "-o", "docker0", "-m", "conntrack", "--ctstate", "RELATED,ESTABLISHED", "-j", "ACCEPT")
	return err
}

func addConnTrackRule() error {
	_, err := executeCommand("iptables", "-I", "FORWARD", "-o", "docker0", "-m", "conntrack", "--ctstate", "RELATED,ESTABLISHED", "-j", "ACCEPT")
	return err
}

func (n *NetworkSecurity) forwardRule(action, ip string) error {
	_, err := executeCommand("iptables", action, "FORWARD", "-d", ip, "-j", "REJECT")
	return err
}

func (n *NetworkSecurity) rejectIP(ip string) error {
	return n.forwardRule("-I", ip)
}

func (n *NetworkSecurity) allowIP(ip string) error {
	return n.forwardRule("-D", ip)
}
<commit_msg>Add denies on docker0, instead of blanket denies in FORWARD chains.<commit_after>package netsec

import (
	"atlantis/supervisor/containers/serialize"
	"errors"
	"log"
	"sync"
)

type NetworkSecurity struct {
	sync.Mutex
	SaveFile   string                        // where to save state
	DeniedIPs  map[string]bool               // list of denied IPs. map for easy existence check
	IPGroups   map[string][]string           // group name -> list of infrastructure IPs to blanket deny
	Containers map[string]*ContainerSecurity // container id -> ContainerSecurity
}

func New(saveFile string) *NetworkSecurity {
	return &NetworkSecurity{
		Mutex:      sync.Mutex{},
		SaveFile:   saveFile,
		DeniedIPs:  map[string]bool{},
		IPGroups:   map[string][]string{},
		Containers: map[string]*ContainerSecurity{},
	}
}

func (n *NetworkSecurity) save() {
	// save state
	serialize.SaveAll(serialize.SaveDefinition{
		n.SaveFile,
		n,
	})
}

func (n *NetworkSecurity) UpdateIPGroup(name string, ips []string) error {
	n.Lock()
	defer n.Unlock()

	if err := delConnTrackRule(); err != nil {
		return err
	}

	current, exists := n.IPGroups[name]
	toRemove := []string{}
	if exists {
		// figure out what is being removed
		incomingMap := map[string]bool{}
		for _, ip := range ips {
			incomingMap[ip] = true
		}
		for _, ip := range current {
			if !incomingMap[ip] {
				toRemove = append(toRemove, ip)
			}
		}
	}
	// add blanket deny rule for new IPs
	newIPs := []string{}
	for _, ip := range ips {
		if n.DeniedIPs[ip] {
			// already exists
			continue
		}
		if err := n.rejectIP(ip); err != nil {
			return err
		}
		n.DeniedIPs[ip] = true
		newIPs = append(newIPs, ip)
	}
	// remove blanket deny rule for removed IPs
	for _, ip := range toRemove {
		if !n.DeniedIPs[ip] {
			// already removed
			continue
		}
		n.allowIP(ip)
		delete(n.DeniedIPs, ip)
	}
	// add/remove forward rules for new IPs for everything that uses the name
	for _, contSec := range n.Containers {
		ports, exists := contSec.SecurityGroups[name]
		if !exists {
			// this container does not use this ip group
			continue
		}
		for _, port := range ports {
			// add new ips
			for _, ip := range newIPs {
				contSec.allowPort(ip, port)
			}
			// remove old ips
			for _, ip := range toRemove {
				contSec.rejectPort(ip, port)
			}
		}
	}
	// update ipGroups
	n.IPGroups[name] = ips
	n.save()

	return addConnTrackRule()
}

func (n *NetworkSecurity) DeleteIPGroup(name string) error {
	if err := n.UpdateIPGroup(name, []string{}); err != nil {
		return err
	}
	n.Lock()
	defer n.Unlock()
	delete(n.IPGroups, name)
	n.save()
	return nil
}

func (n *NetworkSecurity) AddContainerSecurity(id string, pid int, sgs map[string][]uint16) error {
	n.Lock()
	defer n.Unlock()
	log.Println("[netsec] add container security: "+id)
	if _, exists := n.Containers[id]; exists {
		// we already have security set up for this id. don't do it and return an error.
		log.Println("[netsec] -- not adding, already existed for: "+id)
		return errors.New("Container " + id + " already has Network Security set up.")
	}
	// make sure all groups exist
	for group, _ := range sgs {
		_, exists := n.IPGroups[group]
		if !exists {
			log.Println("[netsec] -- not adding group "+group+" doesn't exist for: "+id)
			return errors.New("IP Group " + group + " does not exist")
		}
	}

	// fetch network info
	contSec, err := NewContainerSecurity(id, pid, sgs)
	if err != nil {
		return err
	}
	contSec.addMark()

	// add forward rules
	for group, ports := range sgs {
		for _, port := range ports {
			ips := n.IPGroups[group]
			for _, ip := range ips {
				if err := contSec.allowPort(ip, port); err != nil {
					defer n.RemoveContainerSecurity(id) // cleanup created references when we error out
					return err
				}
			}
		}
	}
	n.Containers[id] = contSec
	n.save()
	log.Println("[netsec] -- added "+id)
	return nil
}

func (n *NetworkSecurity) RemoveContainerSecurity(id string) error {
	n.Lock()
	defer n.Unlock()
	log.Println("[netsec] remove container security: "+id)
	contSec, exists := n.Containers[id]
	if !exists {
		log.Println("[netsec] -- not removing, none existed for: "+id)
		// no container security here, nothing to remove
		return nil
	}

	contSec.delMark()
	// remove forward rules
	for group, ports := range contSec.SecurityGroups {
		for _, port := range ports {
			ips := n.IPGroups[group]
			for _, ip := range ips {
				contSec.rejectPort(ip, port)
			}
		}
	}
	delete(n.Containers, id)
	n.save()
	log.Println("[netsec] -- removed "+id)
	return nil
}

func delConnTrackRule() error {
	_, err := executeCommand("iptables", "-D", "FORWARD", "-o", "docker0", "-m", "conntrack", "--ctstate", "RELATED,ESTABLISHED", "-j", "ACCEPT")
	return err
}

func addConnTrackRule() error {
	_, err := executeCommand("iptables", "-I", "FORWARD", "-o", "docker0", "-m", "conntrack", "--ctstate", "RELATED,ESTABLISHED", "-j", "ACCEPT")
	return err
}

func (n *NetworkSecurity) forwardRule(action, ip string) error {
	_, err := executeCommand("iptables", action, "FORWARD", "-i", "docker0", "-d", ip, "-j", "REJECT")
	return err
}

func (n *NetworkSecurity) rejectIP(ip string) error {
	return n.forwardRule("-I", ip)
}

func (n *NetworkSecurity) allowIP(ip string) error {
	return n.forwardRule("-D", ip)
}
<|endoftext|>


<commit_before>package main

import (
    "bufio"
    "fmt"
    "os"
    "./src"
    //"strconv"
)

const EXIT = "exit";
const PROMPT = "> ";

func main() {
    fmt.Println("Welcome to Calculator! Type 'exit' to exit");
    reader := bufio.NewScanner(os.Stdin);
    fmt.Print(PROMPT);
    //op := src.NewCalculator();
    for reader.Scan() {
        line := reader.Text();
        if (line == EXIT) {
            break;
        }
        src.Read(line);
        fmt.Println(src.Read(line));
        fmt.Print(PROMPT);
        line = reader.Text();
    }
}
<commit_msg>cleaning up code<commit_after>package main

import (
    "bufio"
    "fmt"
    "os"
    "./src"
    //"strconv"
)

const EXIT = "exit";
const PROMPT = "> ";

func main() {
    fmt.Println("Welcome to Calculator! Type 'exit' to exit");
    reader := bufio.NewScanner(os.Stdin);
    fmt.Print(PROMPT);
    //op := src.NewCalculator();
    for reader.Scan() {
        line := reader.Text();
        if (line == EXIT) {
            break;
        }
        fmt.Println(src.Read(line));
        fmt.Print(PROMPT);
    }
}
<|endoftext|>


<commit_before>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package types2

import (
	"cmd/compile/internal/syntax"
	"sync"
)

// TODO(gri) Clean up Named struct below; specifically the fromRHS field (can we use underlying?).

// A Named represents a named (defined) type.
type Named struct {
	check      *Checker
	info       typeInfo    // for cycle detection
	obj        *TypeName   // corresponding declared object
	orig       *Named      // original, uninstantiated type
	fromRHS    Type        // type (on RHS of declaration) this *Named type is derived from (for cycle reporting)
	underlying Type        // possibly a *Named during setup; never a *Named once set up completely
	instance   *instance   // position information for lazy instantiation, or nil
	tparams    *TypeParams // type parameters, or nil
	targs      []Type      // type arguments (after instantiation), or nil
	methods    []*Func     // methods declared for this type (not the method set of this type); signatures are type-checked lazily

	resolve func(*Named) ([]*TypeName, Type, []*Func)
	once    sync.Once
}

// NewNamed returns a new named type for the given type name, underlying type, and associated methods.
// If the given type name obj doesn't have a type yet, its type is set to the returned named type.
// The underlying type must not be a *Named.
func NewNamed(obj *TypeName, underlying Type, methods []*Func) *Named {
	if _, ok := underlying.(*Named); ok {
		panic("underlying type must not be *Named")
	}
	return (*Checker)(nil).newNamed(obj, nil, underlying, nil, methods)
}

func (t *Named) load() *Named {
	// If t is an instantiated type, it derives its methods and tparams from its
	// base type. Since we expect type parameters and methods to be set after a
	// call to load, we must load the base and copy here.
	//
	// underlying is set when t is expanded.
	//
	// By convention, a type instance is loaded iff its tparams are set.
	if len(t.targs) > 0 && t.tparams == nil {
		t.orig.load()
		t.tparams = t.orig.tparams
		t.methods = t.orig.methods
	}
	if t.resolve == nil {
		return t
	}

	t.once.Do(func() {
		// TODO(mdempsky): Since we're passing t to resolve anyway
		// (necessary because types2 expects the receiver type for methods
		// on defined interface types to be the Named rather than the
		// underlying Interface), maybe it should just handle calling
		// SetTParams, SetUnderlying, and AddMethod instead?  Those
		// methods would need to support reentrant calls though.  It would
		// also make the API more future-proof towards further extensions
		// (like SetTParams).

		tparams, underlying, methods := t.resolve(t)

		switch underlying.(type) {
		case nil, *Named:
			panic("invalid underlying type")
		}

		t.tparams = bindTParams(tparams)
		t.underlying = underlying
		t.methods = methods
	})
	return t
}

// newNamed is like NewNamed but with a *Checker receiver and additional orig argument.
func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tparams *TypeParams, methods []*Func) *Named {
	typ := &Named{check: check, obj: obj, orig: orig, fromRHS: underlying, underlying: underlying, tparams: tparams, methods: methods}
	if typ.orig == nil {
		typ.orig = typ
	}
	if obj.typ == nil {
		obj.typ = typ
	}
	// Ensure that typ is always expanded, at which point the check field can be
	// nilled out.
	//
	// Note that currently we cannot nil out check inside typ.under(), because
	// it's possible that typ is expanded multiple times.
	//
	// TODO(gri): clean this up so that under is the only function mutating
	//            named types.
	if check != nil {
		check.later(func() {
			switch typ.under().(type) {
			case *Named:
				panic("unexpanded underlying type")
			}
			typ.check = nil
		})
	}
	return typ
}

// Obj returns the type name for the named type t.
func (t *Named) Obj() *TypeName { return t.obj }

// Orig returns the original generic type an instantiated type is derived from.
// If t is not an instantiated type, the result is t.
func (t *Named) Orig() *Named { return t.orig }

// TODO(gri) Come up with a better representation and API to distinguish
//           between parameterized instantiated and non-instantiated types.

// TParams returns the type parameters of the named type t, or nil.
// The result is non-nil for an (originally) parameterized type even if it is instantiated.
func (t *Named) TParams() *TypeParams { return t.load().tparams }

// SetTParams sets the type parameters of the named type t.
func (t *Named) SetTParams(tparams []*TypeName) { t.load().tparams = bindTParams(tparams) }

// TArgs returns the type arguments after instantiation of the named type t, or nil if not instantiated.
func (t *Named) TArgs() []Type { return t.targs }

// NumMethods returns the number of explicit methods whose receiver is named type t.
func (t *Named) NumMethods() int { return len(t.load().methods) }

// Method returns the i'th method of named type t for 0 <= i < t.NumMethods().
func (t *Named) Method(i int) *Func { return t.load().methods[i] }

// SetUnderlying sets the underlying type and marks t as complete.
func (t *Named) SetUnderlying(underlying Type) {
	if underlying == nil {
		panic("underlying type must not be nil")
	}
	if _, ok := underlying.(*Named); ok {
		panic("underlying type must not be *Named")
	}
	t.load().underlying = underlying
}

// AddMethod adds method m unless it is already in the method list.
func (t *Named) AddMethod(m *Func) {
	t.load()
	if i, _ := lookupMethod(t.methods, m.pkg, m.name); i < 0 {
		t.methods = append(t.methods, m)
	}
}

func (t *Named) Underlying() Type { return t.load().expand(nil).underlying }
func (t *Named) String() string   { return TypeString(t, nil) }

// ----------------------------------------------------------------------------
// Implementation

// under returns the expanded underlying type of n0; possibly by following
// forward chains of named types. If an underlying type is found, resolve
// the chain by setting the underlying type for each defined type in the
// chain before returning it. If no underlying type is found or a cycle
// is detected, the result is Typ[Invalid]. If a cycle is detected and
// n0.check != nil, the cycle is reported.
func (n0 *Named) under() Type {
	n0.expand(nil)

	u := n0.load().underlying

	if u == Typ[Invalid] {
		return u
	}

	// If the underlying type of a defined type is not a defined
	// (incl. instance) type, then that is the desired underlying
	// type.
	switch u.(type) {
	case nil:
		return Typ[Invalid]
	default:
		// common case
		return u
	case *Named:
		// handled below
	}

	if n0.check == nil {
		panic("Named.check == nil but type is incomplete")
	}

	// Invariant: after this point n0 as well as any named types in its
	// underlying chain should be set up when this function exits.
	check := n0.check

	// If we can't expand u at this point, it is invalid.
	n := asNamed(u)
	if n == nil {
		n0.underlying = Typ[Invalid]
		return n0.underlying
	}

	// Otherwise, follow the forward chain.
	seen := map[*Named]int{n0: 0}
	path := []Object{n0.obj}
	for {
		u = n.load().underlying
		if u == nil {
			u = Typ[Invalid]
			break
		}
		var n1 *Named
		switch u1 := u.(type) {
		case *Named:
			u1.expand(nil)
			n1 = u1
		}
		if n1 == nil {
			break // end of chain
		}

		seen[n] = len(seen)
		path = append(path, n.obj)
		n = n1

		if i, ok := seen[n]; ok {
			// cycle
			check.cycleError(path[i:])
			u = Typ[Invalid]
			break
		}
	}

	for n := range seen {
		// We should never have to update the underlying type of an imported type;
		// those underlying types should have been resolved during the import.
		// Also, doing so would lead to a race condition (was issue #31749).
		// Do this check always, not just in debug mode (it's cheap).
		if n.obj.pkg != check.pkg {
			panic("imported type with unresolved underlying type")
		}
		n.underlying = u
	}

	return u
}

func (n *Named) setUnderlying(typ Type) {
	if n != nil {
		n.underlying = typ
	}
}

// instance holds position information for use in lazy instantiation.
//
// TODO(rfindley): come up with a better name for this type, now that its usage
// has changed.
type instance struct {
	pos     syntax.Pos   // position of type instantiation; for error reporting only
	posList []syntax.Pos // position of each targ; for error reporting only
}

// expand ensures that the underlying type of n is instantiated.
// The underlying type will be Typ[Invalid] if there was an error.
func (n *Named) expand(typMap map[string]*Named) *Named {
	if n.instance != nil {
		// n must be loaded before instantiation, in order to have accurate
		// tparams. This is done implicitly by the call to n.TParams, but making it
		// explicit is harmless: load is idempotent.
		n.load()
		if typMap == nil {
			if n.check != nil {
				typMap = n.check.typMap
			} else {
				// If we're instantiating lazily, we might be outside the scope of a
				// type-checking pass. In that case we won't have a pre-existing
				// typMap, but don't want to create a duplicate of the current instance
				// in the process of expansion.
				h := instantiatedHash(n.orig, n.targs)
				typMap = map[string]*Named{h: n}
			}
		}

		inst := n.check.instantiate(n.instance.pos, n.orig.underlying, n.TParams().list(), n.targs, n.instance.posList, typMap)
		n.underlying = inst
		n.fromRHS = inst
		n.instance = nil
	}
	return n
}

// safeUnderlying returns the underlying of typ without expanding instances, to
// avoid infinite recursion.
//
// TODO(rfindley): eliminate this function or give it a better name.
func safeUnderlying(typ Type) Type {
	if t, _ := typ.(*Named); t != nil {
		return t.load().underlying
	}
	return typ.Underlying()
}
<commit_msg>cmd/compile/internal/types2: simplify Named.under<commit_after>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package types2

import (
	"cmd/compile/internal/syntax"
	"sync"
)

// TODO(gri) Clean up Named struct below; specifically the fromRHS field (can we use underlying?).

// A Named represents a named (defined) type.
type Named struct {
	check      *Checker
	info       typeInfo    // for cycle detection
	obj        *TypeName   // corresponding declared object
	orig       *Named      // original, uninstantiated type
	fromRHS    Type        // type (on RHS of declaration) this *Named type is derived from (for cycle reporting)
	underlying Type        // possibly a *Named during setup; never a *Named once set up completely
	instance   *instance   // position information for lazy instantiation, or nil
	tparams    *TypeParams // type parameters, or nil
	targs      []Type      // type arguments (after instantiation), or nil
	methods    []*Func     // methods declared for this type (not the method set of this type); signatures are type-checked lazily

	resolve func(*Named) ([]*TypeName, Type, []*Func)
	once    sync.Once
}

// NewNamed returns a new named type for the given type name, underlying type, and associated methods.
// If the given type name obj doesn't have a type yet, its type is set to the returned named type.
// The underlying type must not be a *Named.
func NewNamed(obj *TypeName, underlying Type, methods []*Func) *Named {
	if _, ok := underlying.(*Named); ok {
		panic("underlying type must not be *Named")
	}
	return (*Checker)(nil).newNamed(obj, nil, underlying, nil, methods)
}

func (t *Named) load() *Named {
	// If t is an instantiated type, it derives its methods and tparams from its
	// base type. Since we expect type parameters and methods to be set after a
	// call to load, we must load the base and copy here.
	//
	// underlying is set when t is expanded.
	//
	// By convention, a type instance is loaded iff its tparams are set.
	if len(t.targs) > 0 && t.tparams == nil {
		t.orig.load()
		t.tparams = t.orig.tparams
		t.methods = t.orig.methods
	}
	if t.resolve == nil {
		return t
	}

	t.once.Do(func() {
		// TODO(mdempsky): Since we're passing t to resolve anyway
		// (necessary because types2 expects the receiver type for methods
		// on defined interface types to be the Named rather than the
		// underlying Interface), maybe it should just handle calling
		// SetTParams, SetUnderlying, and AddMethod instead?  Those
		// methods would need to support reentrant calls though.  It would
		// also make the API more future-proof towards further extensions
		// (like SetTParams).

		tparams, underlying, methods := t.resolve(t)

		switch underlying.(type) {
		case nil, *Named:
			panic("invalid underlying type")
		}

		t.tparams = bindTParams(tparams)
		t.underlying = underlying
		t.methods = methods
	})
	return t
}

// newNamed is like NewNamed but with a *Checker receiver and additional orig argument.
func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tparams *TypeParams, methods []*Func) *Named {
	typ := &Named{check: check, obj: obj, orig: orig, fromRHS: underlying, underlying: underlying, tparams: tparams, methods: methods}
	if typ.orig == nil {
		typ.orig = typ
	}
	if obj.typ == nil {
		obj.typ = typ
	}
	// Ensure that typ is always expanded, at which point the check field can be
	// nilled out.
	//
	// Note that currently we cannot nil out check inside typ.under(), because
	// it's possible that typ is expanded multiple times.
	//
	// TODO(gri): clean this up so that under is the only function mutating
	//            named types.
	if check != nil {
		check.later(func() {
			switch typ.under().(type) {
			case *Named:
				panic("unexpanded underlying type")
			}
			typ.check = nil
		})
	}
	return typ
}

// Obj returns the type name for the named type t.
func (t *Named) Obj() *TypeName { return t.obj }

// Orig returns the original generic type an instantiated type is derived from.
// If t is not an instantiated type, the result is t.
func (t *Named) Orig() *Named { return t.orig }

// TODO(gri) Come up with a better representation and API to distinguish
//           between parameterized instantiated and non-instantiated types.

// TParams returns the type parameters of the named type t, or nil.
// The result is non-nil for an (originally) parameterized type even if it is instantiated.
func (t *Named) TParams() *TypeParams { return t.load().tparams }

// SetTParams sets the type parameters of the named type t.
func (t *Named) SetTParams(tparams []*TypeName) { t.load().tparams = bindTParams(tparams) }

// TArgs returns the type arguments after instantiation of the named type t, or nil if not instantiated.
func (t *Named) TArgs() []Type { return t.targs }

// NumMethods returns the number of explicit methods whose receiver is named type t.
func (t *Named) NumMethods() int { return len(t.load().methods) }

// Method returns the i'th method of named type t for 0 <= i < t.NumMethods().
func (t *Named) Method(i int) *Func { return t.load().methods[i] }

// SetUnderlying sets the underlying type and marks t as complete.
func (t *Named) SetUnderlying(underlying Type) {
	if underlying == nil {
		panic("underlying type must not be nil")
	}
	if _, ok := underlying.(*Named); ok {
		panic("underlying type must not be *Named")
	}
	t.load().underlying = underlying
}

// AddMethod adds method m unless it is already in the method list.
func (t *Named) AddMethod(m *Func) {
	t.load()
	if i, _ := lookupMethod(t.methods, m.pkg, m.name); i < 0 {
		t.methods = append(t.methods, m)
	}
}

func (t *Named) Underlying() Type { return t.load().expand(nil).underlying }
func (t *Named) String() string   { return TypeString(t, nil) }

// ----------------------------------------------------------------------------
// Implementation

// under returns the expanded underlying type of n0; possibly by following
// forward chains of named types. If an underlying type is found, resolve
// the chain by setting the underlying type for each defined type in the
// chain before returning it. If no underlying type is found or a cycle
// is detected, the result is Typ[Invalid]. If a cycle is detected and
// n0.check != nil, the cycle is reported.
func (n0 *Named) under() Type {
	u := n0.Underlying()

	// If the underlying type of a defined type is not a defined
	// (incl. instance) type, then that is the desired underlying
	// type.
	var n1 *Named
	switch u1 := u.(type) {
	case nil:
		return Typ[Invalid]
	default:
		// common case
		return u
	case *Named:
		// handled below
		n1 = u1
	}

	if n0.check == nil {
		panic("Named.check == nil but type is incomplete")
	}

	// Invariant: after this point n0 as well as any named types in its
	// underlying chain should be set up when this function exits.
	check := n0.check
	n := n0

	seen := make(map[*Named]int) // types that need their underlying resolved
	var path []Object            // objects encountered, for cycle reporting

loop:
	for {
		seen[n] = len(seen)
		path = append(path, n.obj)
		n = n1
		if i, ok := seen[n]; ok {
			// cycle
			check.cycleError(path[i:])
			u = Typ[Invalid]
			break
		}
		u = n.Underlying()
		switch u1 := u.(type) {
		case nil:
			u = Typ[Invalid]
			break loop
		default:
			break loop
		case *Named:
			// Continue collecting *Named types in the chain.
			n1 = u1
		}
	}

	for n := range seen {
		// We should never have to update the underlying type of an imported type;
		// those underlying types should have been resolved during the import.
		// Also, doing so would lead to a race condition (was issue #31749).
		// Do this check always, not just in debug mode (it's cheap).
		if n.obj.pkg != check.pkg {
			panic("imported type with unresolved underlying type")
		}
		n.underlying = u
	}

	return u
}

func (n *Named) setUnderlying(typ Type) {
	if n != nil {
		n.underlying = typ
	}
}

// instance holds position information for use in lazy instantiation.
//
// TODO(rfindley): come up with a better name for this type, now that its usage
// has changed.
type instance struct {
	pos     syntax.Pos   // position of type instantiation; for error reporting only
	posList []syntax.Pos // position of each targ; for error reporting only
}

// expand ensures that the underlying type of n is instantiated.
// The underlying type will be Typ[Invalid] if there was an error.
func (n *Named) expand(typMap map[string]*Named) *Named {
	if n.instance != nil {
		// n must be loaded before instantiation, in order to have accurate
		// tparams. This is done implicitly by the call to n.TParams, but making it
		// explicit is harmless: load is idempotent.
		n.load()
		if typMap == nil {
			if n.check != nil {
				typMap = n.check.typMap
			} else {
				// If we're instantiating lazily, we might be outside the scope of a
				// type-checking pass. In that case we won't have a pre-existing
				// typMap, but don't want to create a duplicate of the current instance
				// in the process of expansion.
				h := instantiatedHash(n.orig, n.targs)
				typMap = map[string]*Named{h: n}
			}
		}

		inst := n.check.instantiate(n.instance.pos, n.orig.underlying, n.TParams().list(), n.targs, n.instance.posList, typMap)
		n.underlying = inst
		n.fromRHS = inst
		n.instance = nil
	}
	return n
}

// safeUnderlying returns the underlying of typ without expanding instances, to
// avoid infinite recursion.
//
// TODO(rfindley): eliminate this function or give it a better name.
func safeUnderlying(typ Type) Type {
	if t, _ := typ.(*Named); t != nil {
		return t.load().underlying
	}
	return typ.Underlying()
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"

	"github.com/hashicorp/consul-template/util"
	multierror "github.com/hashicorp/go-multierror"
)

// Runner responsible rendering Templates and invoking Commands.
type Runner struct {
	// outStream and errStream are the io.Writer streams where the runner will
	// write information. These streams can be set using the SetOutStream()
	// and SetErrStream() functions.
	outStream, errStream io.Writer

	// configTemplates, templates, and dependencies are internally calculated
	// caches of all the data this Runner knows about.
	configTemplates []*ConfigTemplate
	templates       []*Template
	dependencies    []util.Dependency

	// templateConfigTemplateMap is a map of each template to the ConfigTemplates
	// that made it.
	templateConfigTemplateMap map[string][]*ConfigTemplate

	// dependencyDataMap is a map of each dependency to its data.
	dependencyDataReceivedMap map[string]struct{}
	dependencyDataMap         map[string]interface{}
}

// NewRunner accepts a slice of ConfigTemplates and returns a pointer to the new
// Runner and any error that occurred during creation.
func NewRunner(configTemplates []*ConfigTemplate) (*Runner, error) {
	runner := &Runner{configTemplates: configTemplates}
	if err := runner.init(); err != nil {
		return nil, err
	}

	return runner, nil
}

// SetOutStream accepts an io.Writer and sets the internal outStream for this
// Runner.
func (r *Runner) SetOutStream(s io.Writer) {
	r.outStream = s
}

// SetErrStream accepts an io.Writer and sets the internal outStream for this
// Runner.
func (r *Runner) SetErrStream(s io.Writer) {
	r.errStream = s
}

// Receive accepts a Dependency and data for that Dependency. This data is
// cached on the Runner. This data is then used to determine if a Template
// is "renderable" (i.e. all its Dependencies have been downloaded at least
// once).
func (r *Runner) Receive(dependency util.Dependency, data interface{}) {
	r.dependencyDataReceivedMap[dependency.HashCode()] = struct{}{}
	r.dependencyDataMap[dependency.HashCode()] = data
}

// Dependencies returns the unique slice of Dependency in the Runner
func (r *Runner) Dependencies() []util.Dependency {
	return r.dependencies
}

// RunAll iterates over each template in this Runner and conditionally executes
// the template rendering and command execution.
//
// The template is rendered atomicly. If and only if the template render
// completes successfully, the optional commands will be executed, if given.
// Please note that all templates are rendered **and then** any commands are
// executed.
//
// If the dry flag is given, the template will be rendered to the outStream,
// which defaults to os.Stdout. In dry mode, commands are never executed.
func (r *Runner) RunAll(dry bool) error {
	var commands []string

	for _, template := range r.templates {
		// If the template is not ready to be rendered, just return
		if !r.canRender(template) {
			return nil
		}

		for _, ctemplate := range r.configTemplatesFor(template) {
			// Render the template, taking dry mode into account
			rendered, err := r.render(template, ctemplate.Destination, dry)
			if err != nil {
				return err
			}

			// If the template was rendered (changed) and we are not in dry-run mode,
			// aggregate commands, ignoring previously known commands
			if rendered && !dry {
				if ctemplate.Command != "" && !exists(ctemplate.Command, commands) {
					commands = append(commands, ctemplate.Command)
				}
			}
		}
	}

	// Execute each command in sequence, collecting any errors that occur - this
	// ensures all commands execute at least once
	var errs []error
	for _, command := range commands {
		if err := r.execute(command); err != nil {
			errs = append(errs, err)
		}
	}

	// If any errors were returned, convert them to an ErrorList for human
	// readability
	if len(errs) != 0 {
		var result *multierror.Error

		for _, err := range errs {
			result = multierror.Append(result, err)
		}
		return result.ErrorOrNil()
	}

	return nil
}

// init() creates the Runner's underlying data structures and returns an error
// if any problems occur.
func (r *Runner) init() error {
	if len(r.configTemplates) == 0 {
		r.configTemplates = make([]*ConfigTemplate, 0)
	}

	templatesMap := make(map[string]*Template)
	dependenciesMap := make(map[string]util.Dependency)

	r.templateConfigTemplateMap = make(map[string][]*ConfigTemplate)

	// Process all Template first, so we can return errors
	for _, configTemplate := range r.configTemplates {
		template := &Template{Path: configTemplate.Source}
		if _, ok := templatesMap[template.HashCode()]; !ok {
			template, err := NewTemplate(configTemplate.Source)
			if err != nil {
				return err
			}
			templatesMap[template.HashCode()] = template
		}

		if len(r.templateConfigTemplateMap[template.HashCode()]) == 0 {
			r.templateConfigTemplateMap[template.HashCode()] = make([]*ConfigTemplate, 0, 1)
		}
		r.templateConfigTemplateMap[template.HashCode()] = append(r.templateConfigTemplateMap[template.HashCode()], configTemplate)
	}

	// For each Template, setup the mappings for O(1) lookups
	for _, template := range templatesMap {
		for _, dep := range template.Dependencies() {
			if _, ok := dependenciesMap[dep.HashCode()]; !ok {
				dependenciesMap[dep.HashCode()] = dep
			}
		}
	}

	// Calculate the list of Templates
	r.templates = make([]*Template, 0, len(templatesMap))
	for _, template := range templatesMap {
		r.templates = append(r.templates, template)
	}

	// Calculate the list of Dependency
	r.dependencies = make([]util.Dependency, 0, len(dependenciesMap))
	for _, dependency := range dependenciesMap {
		r.dependencies = append(r.dependencies, dependency)
	}

	r.dependencyDataReceivedMap = make(map[string]struct{})
	r.dependencyDataMap = make(map[string]interface{})
	r.outStream = os.Stdout

	return nil
}

// canRender accepts a Template and returns true if and only if all of the
// Dependencies of that template have data in the Runner.
func (r *Runner) canRender(template *Template) bool {
	for _, dependency := range template.Dependencies() {
		if !r.receivedData(dependency) {
			return false
		}
	}

	return true
}

// Render accepts a Template and a destinations. This will return an error if
// the Template is not ready to be rendered. You can check if a Template is
// renderable using canRender().
//
// If the template has changed on disk, this method return true.
//
// If the template already exists and has the same contents as the "would-be"
// template, no action is taken. In this scenario, the render function returns
// false, indicating no template change has occurred.
func (r *Runner) render(template *Template, destination string, dry bool) (bool, error) {
	if !r.canRender(template) {
		return false, fmt.Errorf("runner: template data not ready")
	}

	context, err := r.templateContextFor(template)
	if err != nil {
		return false, err
	}

	contents, err := template.Execute(context)
	if err != nil {
		return false, err
	}

	existingContents, err := ioutil.ReadFile(destination)
	if err != nil && !os.IsNotExist(err) {
		return false, err
	}

	if bytes.Equal(contents, existingContents) {
		return false, nil
	}

	if dry {
		fmt.Fprintf(r.outStream, "> %s\n%s", destination, contents)
	} else {
		if err := r.atomicWrite(destination, contents); err != nil {
			return false, err
		}
	}

	return true, nil
}

// execute accepts a command string and runs that command string on the current
// system.
func (r *Runner) execute(command string) error {
	var shell, flag string
	if runtime.GOOS == "windows" {
		shell, flag = "cmd", "/C"
	} else {
		shell, flag = "/bin/sh", "-c"
	}

	// Create an invoke the command
	cmd := exec.Command(shell, flag, command)
	cmd.Stdout = r.outStream
	cmd.Stderr = r.errStream
	return cmd.Run()
}

// receivedData returns true if the Runner has ever received data for the given
// dependency and false otherwise.
func (r *Runner) receivedData(dependency util.Dependency) bool {
	_, ok := r.dependencyDataReceivedMap[dependency.HashCode()]
	return ok
}

// data returns the data for the given dependency.
func (r *Runner) data(dependency util.Dependency) interface{} {
	return r.dependencyDataMap[dependency.HashCode()]
}

// ConfigTemplateFor returns the ConfigTemplate for the given Template
func (r *Runner) configTemplatesFor(template *Template) []*ConfigTemplate {
	return r.templateConfigTemplateMap[template.HashCode()]
}

// templateContextFor creates and returns a new TemplateContext for the given
// Template, iterating through all the Template's Dependencies and appending
// them where appropriate in the TemplateContext.
//
// If an unknown Dependency.(type) is encountered, an error is returned.
func (r *Runner) templateContextFor(template *Template) (*TemplateContext, error) {
	context := &TemplateContext{
		File:        make(map[string]string),
		KeyPrefixes: make(map[string][]*util.KeyPair),
		Keys:        make(map[string]string),
		Nodes:       make(map[string][]*util.Node),
		Services:    make(map[string][]*util.Service),
	}

	for _, dependency := range template.Dependencies() {
		data := r.data(dependency)

		switch dependency := dependency.(type) {
		case *util.FileDependency:
			context.File[dependency.Key()] = data.(string)
		case *util.KeyPrefixDependency:
			context.KeyPrefixes[dependency.Key()] = data.([]*util.KeyPair)
		case *util.KeyDependency:
			context.Keys[dependency.Key()] = data.(string)
		case *util.NodesDependency:
			context.Nodes[dependency.Key()] = data.([]*util.Node)
		case *util.ServiceDependency:
			context.Services[dependency.Key()] = data.([]*util.Service)
		default:
			return nil, fmt.Errorf("unknown dependency type %+v", dependency)
		}
	}

	return context, nil
}

// atomicWrite accepts a destination path and the template contents. It writes
// the template contents to a TempFile on disk, returning if any errors occur.
//
// If the parent destination directory does not exist, it will be created
// automatically with permissions 0755. To use a different permission, create
// the directory first or use `chmod` in a Command.
//
// If the destination path exists, all attempts will be made to preserve the
// existing file permissions. If those permissions cannot be read, an error is
// returned. If the file does not exist, it will be created automatically with
// permissions 0644. To use a different permission, create the destination file
// first or use `chmod` in a Command.
//
// If no errors occur, the Tempfile is "renamed" (moved) to the destination
// path.
func (r *Runner) atomicWrite(path string, contents []byte) error {
	var mode os.FileMode

	// If the current file exists, get permissions so we can preserve them
	stat, err := os.Stat(path)
	if err != nil {
		if os.IsNotExist(err) {
			mode = 0644
		} else {
			return err
		}
	} else {
		mode = stat.Mode()
	}

	parent := filepath.Dir(path)
	if _, err := os.Stat(parent); os.IsNotExist(err) {
		if err := os.MkdirAll(parent, 0755); err != nil {
			return err
		}
	}

	f, err := ioutil.TempFile(parent, "")
	if err != nil {
		return err
	}
	defer os.Remove(f.Name())

	if _, err := f.Write(contents); err != nil {
		return err
	}

	if err := f.Sync(); err != nil {
		return err
	}

	if err := f.Close(); err != nil {
		return err
	}

	if err := os.Chmod(f.Name(), mode); err != nil {
		return err
	}

	// Remove the file if we are running on Windows. There is a bug in Go on
	// Windows such that Go uses MoveFile which raises an exception if the file
	// already exists.
	//
	// See: http://grokbase.com/t/gg/golang-nuts/13aab5f210/go-nuts-atomic-replacement-of-files-on-windows
	// for more information.
	if runtime.GOOS == "windows" {
		if err := os.Remove(path); err != nil {
			return err
		}
	}

	if err := os.Rename(f.Name(), path); err != nil {
		return err
	}

	return nil
}

// Checks if a value exists in an array
func exists(needle string, haystack []string) bool {
	needle = strings.TrimSpace(needle)
	for _, value := range haystack {
		if needle == strings.TrimSpace(value) {
			return true
		}
	}

	return false
}
<commit_msg>Parse CatalogServices in the Runner<commit_after>package main

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"

	"github.com/hashicorp/consul-template/util"
	multierror "github.com/hashicorp/go-multierror"
)

// Runner responsible rendering Templates and invoking Commands.
type Runner struct {
	// outStream and errStream are the io.Writer streams where the runner will
	// write information. These streams can be set using the SetOutStream()
	// and SetErrStream() functions.
	outStream, errStream io.Writer

	// configTemplates, templates, and dependencies are internally calculated
	// caches of all the data this Runner knows about.
	configTemplates []*ConfigTemplate
	templates       []*Template
	dependencies    []util.Dependency

	// templateConfigTemplateMap is a map of each template to the ConfigTemplates
	// that made it.
	templateConfigTemplateMap map[string][]*ConfigTemplate

	// dependencyDataMap is a map of each dependency to its data.
	dependencyDataReceivedMap map[string]struct{}
	dependencyDataMap         map[string]interface{}
}

// NewRunner accepts a slice of ConfigTemplates and returns a pointer to the new
// Runner and any error that occurred during creation.
func NewRunner(configTemplates []*ConfigTemplate) (*Runner, error) {
	runner := &Runner{configTemplates: configTemplates}
	if err := runner.init(); err != nil {
		return nil, err
	}

	return runner, nil
}

// SetOutStream accepts an io.Writer and sets the internal outStream for this
// Runner.
func (r *Runner) SetOutStream(s io.Writer) {
	r.outStream = s
}

// SetErrStream accepts an io.Writer and sets the internal outStream for this
// Runner.
func (r *Runner) SetErrStream(s io.Writer) {
	r.errStream = s
}

// Receive accepts a Dependency and data for that Dependency. This data is
// cached on the Runner. This data is then used to determine if a Template
// is "renderable" (i.e. all its Dependencies have been downloaded at least
// once).
func (r *Runner) Receive(dependency util.Dependency, data interface{}) {
	r.dependencyDataReceivedMap[dependency.HashCode()] = struct{}{}
	r.dependencyDataMap[dependency.HashCode()] = data
}

// Dependencies returns the unique slice of Dependency in the Runner
func (r *Runner) Dependencies() []util.Dependency {
	return r.dependencies
}

// RunAll iterates over each template in this Runner and conditionally executes
// the template rendering and command execution.
//
// The template is rendered atomicly. If and only if the template render
// completes successfully, the optional commands will be executed, if given.
// Please note that all templates are rendered **and then** any commands are
// executed.
//
// If the dry flag is given, the template will be rendered to the outStream,
// which defaults to os.Stdout. In dry mode, commands are never executed.
func (r *Runner) RunAll(dry bool) error {
	var commands []string

	for _, template := range r.templates {
		// If the template is not ready to be rendered, just return
		if !r.canRender(template) {
			return nil
		}

		for _, ctemplate := range r.configTemplatesFor(template) {
			// Render the template, taking dry mode into account
			rendered, err := r.render(template, ctemplate.Destination, dry)
			if err != nil {
				return err
			}

			// If the template was rendered (changed) and we are not in dry-run mode,
			// aggregate commands, ignoring previously known commands
			if rendered && !dry {
				if ctemplate.Command != "" && !exists(ctemplate.Command, commands) {
					commands = append(commands, ctemplate.Command)
				}
			}
		}
	}

	// Execute each command in sequence, collecting any errors that occur - this
	// ensures all commands execute at least once
	var errs []error
	for _, command := range commands {
		if err := r.execute(command); err != nil {
			errs = append(errs, err)
		}
	}

	// If any errors were returned, convert them to an ErrorList for human
	// readability
	if len(errs) != 0 {
		var result *multierror.Error

		for _, err := range errs {
			result = multierror.Append(result, err)
		}
		return result.ErrorOrNil()
	}

	return nil
}

// init() creates the Runner's underlying data structures and returns an error
// if any problems occur.
func (r *Runner) init() error {
	if len(r.configTemplates) == 0 {
		r.configTemplates = make([]*ConfigTemplate, 0)
	}

	templatesMap := make(map[string]*Template)
	dependenciesMap := make(map[string]util.Dependency)

	r.templateConfigTemplateMap = make(map[string][]*ConfigTemplate)

	// Process all Template first, so we can return errors
	for _, configTemplate := range r.configTemplates {
		template := &Template{Path: configTemplate.Source}
		if _, ok := templatesMap[template.HashCode()]; !ok {
			template, err := NewTemplate(configTemplate.Source)
			if err != nil {
				return err
			}
			templatesMap[template.HashCode()] = template
		}

		if len(r.templateConfigTemplateMap[template.HashCode()]) == 0 {
			r.templateConfigTemplateMap[template.HashCode()] = make([]*ConfigTemplate, 0, 1)
		}
		r.templateConfigTemplateMap[template.HashCode()] = append(r.templateConfigTemplateMap[template.HashCode()], configTemplate)
	}

	// For each Template, setup the mappings for O(1) lookups
	for _, template := range templatesMap {
		for _, dep := range template.Dependencies() {
			if _, ok := dependenciesMap[dep.HashCode()]; !ok {
				dependenciesMap[dep.HashCode()] = dep
			}
		}
	}

	// Calculate the list of Templates
	r.templates = make([]*Template, 0, len(templatesMap))
	for _, template := range templatesMap {
		r.templates = append(r.templates, template)
	}

	// Calculate the list of Dependency
	r.dependencies = make([]util.Dependency, 0, len(dependenciesMap))
	for _, dependency := range dependenciesMap {
		r.dependencies = append(r.dependencies, dependency)
	}

	r.dependencyDataReceivedMap = make(map[string]struct{})
	r.dependencyDataMap = make(map[string]interface{})
	r.outStream = os.Stdout

	return nil
}

// canRender accepts a Template and returns true if and only if all of the
// Dependencies of that template have data in the Runner.
func (r *Runner) canRender(template *Template) bool {
	for _, dependency := range template.Dependencies() {
		if !r.receivedData(dependency) {
			return false
		}
	}

	return true
}

// Render accepts a Template and a destinations. This will return an error if
// the Template is not ready to be rendered. You can check if a Template is
// renderable using canRender().
//
// If the template has changed on disk, this method return true.
//
// If the template already exists and has the same contents as the "would-be"
// template, no action is taken. In this scenario, the render function returns
// false, indicating no template change has occurred.
func (r *Runner) render(template *Template, destination string, dry bool) (bool, error) {
	if !r.canRender(template) {
		return false, fmt.Errorf("runner: template data not ready")
	}

	context, err := r.templateContextFor(template)
	if err != nil {
		return false, err
	}

	contents, err := template.Execute(context)
	if err != nil {
		return false, err
	}

	existingContents, err := ioutil.ReadFile(destination)
	if err != nil && !os.IsNotExist(err) {
		return false, err
	}

	if bytes.Equal(contents, existingContents) {
		return false, nil
	}

	if dry {
		fmt.Fprintf(r.outStream, "> %s\n%s", destination, contents)
	} else {
		if err := r.atomicWrite(destination, contents); err != nil {
			return false, err
		}
	}

	return true, nil
}

// execute accepts a command string and runs that command string on the current
// system.
func (r *Runner) execute(command string) error {
	var shell, flag string
	if runtime.GOOS == "windows" {
		shell, flag = "cmd", "/C"
	} else {
		shell, flag = "/bin/sh", "-c"
	}

	// Create an invoke the command
	cmd := exec.Command(shell, flag, command)
	cmd.Stdout = r.outStream
	cmd.Stderr = r.errStream
	return cmd.Run()
}

// receivedData returns true if the Runner has ever received data for the given
// dependency and false otherwise.
func (r *Runner) receivedData(dependency util.Dependency) bool {
	_, ok := r.dependencyDataReceivedMap[dependency.HashCode()]
	return ok
}

// data returns the data for the given dependency.
func (r *Runner) data(dependency util.Dependency) interface{} {
	return r.dependencyDataMap[dependency.HashCode()]
}

// ConfigTemplateFor returns the ConfigTemplate for the given Template
func (r *Runner) configTemplatesFor(template *Template) []*ConfigTemplate {
	return r.templateConfigTemplateMap[template.HashCode()]
}

// templateContextFor creates and returns a new TemplateContext for the given
// Template, iterating through all the Template's Dependencies and appending
// them where appropriate in the TemplateContext.
//
// If an unknown Dependency.(type) is encountered, an error is returned.
func (r *Runner) templateContextFor(template *Template) (*TemplateContext, error) {
	context := &TemplateContext{
		CatalogServices: make(map[string][]*util.CatalogService),
		File:            make(map[string]string),
		KeyPrefixes:     make(map[string][]*util.KeyPair),
		Keys:            make(map[string]string),
		Nodes:           make(map[string][]*util.Node),
		Services:        make(map[string][]*util.Service),
	}

	for _, dependency := range template.Dependencies() {
		data := r.data(dependency)

		switch dependency := dependency.(type) {
		case *util.CatalogServicesDependency:
			context.CatalogServices[dependency.Key()] = data.([]*util.CatalogService)
		case *util.FileDependency:
			context.File[dependency.Key()] = data.(string)
		case *util.KeyPrefixDependency:
			context.KeyPrefixes[dependency.Key()] = data.([]*util.KeyPair)
		case *util.KeyDependency:
			context.Keys[dependency.Key()] = data.(string)
		case *util.NodesDependency:
			context.Nodes[dependency.Key()] = data.([]*util.Node)
		case *util.ServiceDependency:
			context.Services[dependency.Key()] = data.([]*util.Service)
		default:
			return nil, fmt.Errorf("unknown dependency type %+v", dependency)
		}
	}

	return context, nil
}

// atomicWrite accepts a destination path and the template contents. It writes
// the template contents to a TempFile on disk, returning if any errors occur.
//
// If the parent destination directory does not exist, it will be created
// automatically with permissions 0755. To use a different permission, create
// the directory first or use `chmod` in a Command.
//
// If the destination path exists, all attempts will be made to preserve the
// existing file permissions. If those permissions cannot be read, an error is
// returned. If the file does not exist, it will be created automatically with
// permissions 0644. To use a different permission, create the destination file
// first or use `chmod` in a Command.
//
// If no errors occur, the Tempfile is "renamed" (moved) to the destination
// path.
func (r *Runner) atomicWrite(path string, contents []byte) error {
	var mode os.FileMode

	// If the current file exists, get permissions so we can preserve them
	stat, err := os.Stat(path)
	if err != nil {
		if os.IsNotExist(err) {
			mode = 0644
		} else {
			return err
		}
	} else {
		mode = stat.Mode()
	}

	parent := filepath.Dir(path)
	if _, err := os.Stat(parent); os.IsNotExist(err) {
		if err := os.MkdirAll(parent, 0755); err != nil {
			return err
		}
	}

	f, err := ioutil.TempFile(parent, "")
	if err != nil {
		return err
	}
	defer os.Remove(f.Name())

	if _, err := f.Write(contents); err != nil {
		return err
	}

	if err := f.Sync(); err != nil {
		return err
	}

	if err := f.Close(); err != nil {
		return err
	}

	if err := os.Chmod(f.Name(), mode); err != nil {
		return err
	}

	// Remove the file if we are running on Windows. There is a bug in Go on
	// Windows such that Go uses MoveFile which raises an exception if the file
	// already exists.
	//
	// See: http://grokbase.com/t/gg/golang-nuts/13aab5f210/go-nuts-atomic-replacement-of-files-on-windows
	// for more information.
	if runtime.GOOS == "windows" {
		if err := os.Remove(path); err != nil {
			return err
		}
	}

	if err := os.Rename(f.Name(), path); err != nil {
		return err
	}

	return nil
}

// Checks if a value exists in an array
func exists(needle string, haystack []string) bool {
	needle = strings.TrimSpace(needle)
	for _, value := range haystack {
		if needle == strings.TrimSpace(value) {
			return true
		}
	}

	return false
}
<|endoftext|>


<commit_before>package main

import (
    "os"
    "fmt"
    "net/http"
    "github.com/gorilla/mux"
)

func lookHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Println("enter lookHandler")
	direction := mux.Vars(r)["direction"]
	err := bot.Look(direction)
	if err != nil {
		w.WriteHeader(500)
		panic(err)
	}
	w.WriteHeader(200)
}

func moveHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Println("enter moveHandler")
	direction := mux.Vars(r)["direction"]
	err := bot.Move(direction)
	if err != nil {
		w.WriteHeader(500)
		panic(err)
	}
	w.WriteHeader(200)
}

func ledHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Println("enter ledHandler")
	color := mux.Vars(r)["color"]

	var err error
	if r.Method == "POST" {
		err = bot.LedOn(color)
	} else if r.Method == "DELETE" {
		err = bot.LedOff(color)
	}

	if err != nil {
		w.WriteHeader(500)
		panic(err)
	}
	w.WriteHeader(200)
}

func errorHandler() {
	fmt.Println("enter errorHandler")
	if r := recover(); r != nil {
		fmt.Println(r)
	}
	os.Exit(1)
}
<commit_msg>removed panic and return 500 in case of i2c write failure<commit_after>package main

import (
    "os"
    "fmt"
    "net/http"
    "github.com/gorilla/mux"
)

func lookHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Println("enter lookHandler")
	direction := mux.Vars(r)["direction"]
	err := bot.Look(direction)
    statusCode := 200
	if err != nil {
		statusCode = 500
	}
	w.WriteHeader(statusCode)
}

func moveHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Println("enter moveHandler")
	direction := mux.Vars(r)["direction"]
	err := bot.Move(direction)
    statusCode := 200
	if err != nil {
		statusCode = 500
	}
	w.WriteHeader(statusCode)
}

func ledHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Println("enter ledHandler")
	color := mux.Vars(r)["color"]
	var err error
	if r.Method == "POST" {
		err = bot.LedOn(color)
	} else if r.Method == "DELETE" {
		err = bot.LedOff(color)
	}
    statusCode := 200
	if err != nil {
		statusCode = 500
	}
	w.WriteHeader(statusCode)
}

func distanceHandler(w http.ResponseWriter, r *http.Request) {
    w.WriteHeader(204)
}

func statusHandler(w http.ResponseWriter, r *http.Request) {
    w.WriteHeader(204)
}

func errorHandler() {
	fmt.Println("enter errorHandler")
	if r := recover(); r != nil {
		fmt.Println(r)
	}
	os.Exit(1)
}
<|endoftext|>


<commit_before>// Copyright 2017 Vector Creations Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package sqlite3

import (
	"context"
	"database/sql"
	"encoding/json"
	"errors"
	"strconv"
	"sync"

	"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
	"github.com/matrix-org/dendrite/internal/sqlutil"
	"github.com/matrix-org/dendrite/userapi/api"
	"github.com/matrix-org/gomatrixserverlib"
	"golang.org/x/crypto/bcrypt"
	// Import the sqlite3 database driver.
)

// Database represents an account database
type Database struct {
	db *sql.DB
	sqlutil.PartitionOffsetStatements
	accounts     accountsStatements
	profiles     profilesStatements
	accountDatas accountDataStatements
	threepids    threepidStatements
	serverName   gomatrixserverlib.ServerName

	createAccountMu sync.Mutex
}

// NewDatabase creates a new accounts and profiles database
func NewDatabase(dataSourceName string, serverName gomatrixserverlib.ServerName) (*Database, error) {
	var db *sql.DB
	var err error
	cs, err := sqlutil.ParseFileURI(dataSourceName)
	if err != nil {
		return nil, err
	}
	if db, err = sqlutil.Open(sqlutil.SQLiteDriverName(), cs, nil); err != nil {
		return nil, err
	}
	partitions := sqlutil.PartitionOffsetStatements{}
	if err = partitions.Prepare(db, "account"); err != nil {
		return nil, err
	}
	a := accountsStatements{}
	if err = a.prepare(db, serverName); err != nil {
		return nil, err
	}
	p := profilesStatements{}
	if err = p.prepare(db); err != nil {
		return nil, err
	}
	ac := accountDataStatements{}
	if err = ac.prepare(db); err != nil {
		return nil, err
	}
	t := threepidStatements{}
	if err = t.prepare(db); err != nil {
		return nil, err
	}
	return &Database{db, partitions, a, p, ac, t, serverName, sync.Mutex{}}, nil
}

// GetAccountByPassword returns the account associated with the given localpart and password.
// Returns sql.ErrNoRows if no account exists which matches the given localpart.
func (d *Database) GetAccountByPassword(
	ctx context.Context, localpart, plaintextPassword string,
) (*api.Account, error) {
	hash, err := d.accounts.selectPasswordHash(ctx, localpart)
	if err != nil {
		return nil, err
	}
	if err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(plaintextPassword)); err != nil {
		return nil, err
	}
	return d.accounts.selectAccountByLocalpart(ctx, localpart)
}

// GetProfileByLocalpart returns the profile associated with the given localpart.
// Returns sql.ErrNoRows if no profile exists which matches the given localpart.
func (d *Database) GetProfileByLocalpart(
	ctx context.Context, localpart string,
) (*authtypes.Profile, error) {
	return d.profiles.selectProfileByLocalpart(ctx, localpart)
}

// SetAvatarURL updates the avatar URL of the profile associated with the given
// localpart. Returns an error if something went wrong with the SQL query
func (d *Database) SetAvatarURL(
	ctx context.Context, localpart string, avatarURL string,
) error {
	return d.profiles.setAvatarURL(ctx, localpart, avatarURL)
}

// SetDisplayName updates the display name of the profile associated with the given
// localpart. Returns an error if something went wrong with the SQL query
func (d *Database) SetDisplayName(
	ctx context.Context, localpart string, displayName string,
) error {
	return d.profiles.setDisplayName(ctx, localpart, displayName)
}

// CreateGuestAccount makes a new guest account and creates an empty profile
// for this account.
func (d *Database) CreateGuestAccount(ctx context.Context) (acc *api.Account, err error) {
	// We need to lock so we sequentially create numeric localparts. If we don't, two calls to
	// this function will cause the same number to be selected and one will fail with 'database is locked'
	// when the first txn upgrades to a write txn. We also need to lock the account creation else we can
	// race with CreateAccount
	// We know we'll be the only process since this is sqlite ;) so a lock here will be all that is needed.
	d.createAccountMu.Lock()
	defer d.createAccountMu.Unlock()
	err = sqlutil.WithTransaction(d.db, func(txn *sql.Tx) error {
		var numLocalpart int64
		numLocalpart, err = d.accounts.selectNewNumericLocalpart(ctx, txn)
		if err != nil {
			return err
		}
		localpart := strconv.FormatInt(numLocalpart, 10)
		acc, err = d.createAccount(ctx, txn, localpart, "", "")
		return err
	})
	return acc, err
}

// CreateAccount makes a new account with the given login name and password, and creates an empty profile
// for this account. If no password is supplied, the account will be a passwordless account. If the
// account already exists, it will return nil, ErrUserExists.
func (d *Database) CreateAccount(
	ctx context.Context, localpart, plaintextPassword, appserviceID string,
) (acc *api.Account, err error) {
	// Create one account at a time else we can get 'database is locked'.
	d.createAccountMu.Lock()
	defer d.createAccountMu.Unlock()
	err = sqlutil.WithTransaction(d.db, func(txn *sql.Tx) error {
		acc, err = d.createAccount(ctx, txn, localpart, plaintextPassword, appserviceID)
		return err
	})
	return
}

func (d *Database) createAccount(
	ctx context.Context, txn *sql.Tx, localpart, plaintextPassword, appserviceID string,
) (*api.Account, error) {
	var err error
	// Generate a password hash if this is not a password-less user
	hash := ""
	if plaintextPassword != "" {
		hash, err = hashPassword(plaintextPassword)
		if err != nil {
			return nil, err
		}
	}
	if err := d.profiles.insertProfile(ctx, txn, localpart); err != nil {
		if isConstraintError(err) {
			return nil, sqlutil.ErrUserExists
		}
		return nil, err
	}

	if err := d.accountDatas.insertAccountData(ctx, txn, localpart, "", "m.push_rules", json.RawMessage(`{
		"global": {
			"content": [],
			"override": [],
			"room": [],
			"sender": [],
			"underride": []
		}
	}`)); err != nil {
		return nil, err
	}
	return d.accounts.insertAccount(ctx, txn, localpart, hash, appserviceID)
}

// SaveAccountData saves new account data for a given user and a given room.
// If the account data is not specific to a room, the room ID should be an empty string
// If an account data already exists for a given set (user, room, data type), it will
// update the corresponding row with the new content
// Returns a SQL error if there was an issue with the insertion/update
func (d *Database) SaveAccountData(
	ctx context.Context, localpart, roomID, dataType string, content json.RawMessage,
) error {
	return sqlutil.WithTransaction(d.db, func(txn *sql.Tx) error {
		return d.accountDatas.insertAccountData(ctx, txn, localpart, roomID, dataType, content)
	})
}

// GetAccountData returns account data related to a given localpart
// If no account data could be found, returns an empty arrays
// Returns an error if there was an issue with the retrieval
func (d *Database) GetAccountData(ctx context.Context, localpart string) (
	global map[string]json.RawMessage,
	rooms map[string]map[string]json.RawMessage,
	err error,
) {
	return d.accountDatas.selectAccountData(ctx, localpart)
}

// GetAccountDataByType returns account data matching a given
// localpart, room ID and type.
// If no account data could be found, returns nil
// Returns an error if there was an issue with the retrieval
func (d *Database) GetAccountDataByType(
	ctx context.Context, localpart, roomID, dataType string,
) (data json.RawMessage, err error) {
	return d.accountDatas.selectAccountDataByType(
		ctx, localpart, roomID, dataType,
	)
}

// GetNewNumericLocalpart generates and returns a new unused numeric localpart
func (d *Database) GetNewNumericLocalpart(
	ctx context.Context,
) (int64, error) {
	return d.accounts.selectNewNumericLocalpart(ctx, nil)
}

func hashPassword(plaintext string) (hash string, err error) {
	hashBytes, err := bcrypt.GenerateFromPassword([]byte(plaintext), bcrypt.DefaultCost)
	return string(hashBytes), err
}

// Err3PIDInUse is the error returned when trying to save an association involving
// a third-party identifier which is already associated to a local user.
var Err3PIDInUse = errors.New("This third-party identifier is already in use")

// SaveThreePIDAssociation saves the association between a third party identifier
// and a local Matrix user (identified by the user's ID's local part).
// If the third-party identifier is already part of an association, returns Err3PIDInUse.
// Returns an error if there was a problem talking to the database.
func (d *Database) SaveThreePIDAssociation(
	ctx context.Context, threepid, localpart, medium string,
) (err error) {
	return sqlutil.WithTransaction(d.db, func(txn *sql.Tx) error {
		user, err := d.threepids.selectLocalpartForThreePID(
			ctx, txn, threepid, medium,
		)
		if err != nil {
			return err
		}

		if len(user) > 0 {
			return Err3PIDInUse
		}

		return d.threepids.insertThreePID(ctx, txn, threepid, medium, localpart)
	})
}

// RemoveThreePIDAssociation removes the association involving a given third-party
// identifier.
// If no association exists involving this third-party identifier, returns nothing.
// If there was a problem talking to the database, returns an error.
func (d *Database) RemoveThreePIDAssociation(
	ctx context.Context, threepid string, medium string,
) (err error) {
	return d.threepids.deleteThreePID(ctx, threepid, medium)
}

// GetLocalpartForThreePID looks up the localpart associated with a given third-party
// identifier.
// If no association involves the given third-party idenfitier, returns an empty
// string.
// Returns an error if there was a problem talking to the database.
func (d *Database) GetLocalpartForThreePID(
	ctx context.Context, threepid string, medium string,
) (localpart string, err error) {
	return d.threepids.selectLocalpartForThreePID(ctx, nil, threepid, medium)
}

// GetThreePIDsForLocalpart looks up the third-party identifiers associated with
// a given local user.
// If no association is known for this user, returns an empty slice.
// Returns an error if there was an issue talking to the database.
func (d *Database) GetThreePIDsForLocalpart(
	ctx context.Context, localpart string,
) (threepids []authtypes.ThreePID, err error) {
	return d.threepids.selectThreePIDsForLocalpart(ctx, localpart)
}

// CheckAccountAvailability checks if the username/localpart is already present
// in the database.
// If the DB returns sql.ErrNoRows the Localpart isn't taken.
func (d *Database) CheckAccountAvailability(ctx context.Context, localpart string) (bool, error) {
	_, err := d.accounts.selectAccountByLocalpart(ctx, localpart)
	if err == sql.ErrNoRows {
		return true, nil
	}
	return false, err
}

// GetAccountByLocalpart returns the account associated with the given localpart.
// This function assumes the request is authenticated or the account data is used only internally.
// Returns sql.ErrNoRows if no account exists which matches the given localpart.
func (d *Database) GetAccountByLocalpart(ctx context.Context, localpart string,
) (*api.Account, error) {
	return d.accounts.selectAccountByLocalpart(ctx, localpart)
}
<commit_msg>Protect User API SQLite calls with mutexes (#1201)<commit_after>// Copyright 2017 Vector Creations Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package sqlite3

import (
	"context"
	"database/sql"
	"encoding/json"
	"errors"
	"strconv"
	"sync"

	"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
	"github.com/matrix-org/dendrite/internal/sqlutil"
	"github.com/matrix-org/dendrite/userapi/api"
	"github.com/matrix-org/gomatrixserverlib"
	"golang.org/x/crypto/bcrypt"
	// Import the sqlite3 database driver.
)

// Database represents an account database
type Database struct {
	db *sql.DB
	sqlutil.PartitionOffsetStatements
	accounts     accountsStatements
	profiles     profilesStatements
	accountDatas accountDataStatements
	threepids    threepidStatements
	serverName   gomatrixserverlib.ServerName

	accountsMu     sync.Mutex
	profilesMu     sync.Mutex
	accountDatasMu sync.Mutex
	threepidsMu    sync.Mutex
}

// NewDatabase creates a new accounts and profiles database
func NewDatabase(dataSourceName string, serverName gomatrixserverlib.ServerName) (*Database, error) {
	var db *sql.DB
	var err error
	cs, err := sqlutil.ParseFileURI(dataSourceName)
	if err != nil {
		return nil, err
	}
	if db, err = sqlutil.Open(sqlutil.SQLiteDriverName(), cs, nil); err != nil {
		return nil, err
	}
	partitions := sqlutil.PartitionOffsetStatements{}
	if err = partitions.Prepare(db, "account"); err != nil {
		return nil, err
	}
	a := accountsStatements{}
	if err = a.prepare(db, serverName); err != nil {
		return nil, err
	}
	p := profilesStatements{}
	if err = p.prepare(db); err != nil {
		return nil, err
	}
	ac := accountDataStatements{}
	if err = ac.prepare(db); err != nil {
		return nil, err
	}
	t := threepidStatements{}
	if err = t.prepare(db); err != nil {
		return nil, err
	}
	return &Database{
		db:                        db,
		PartitionOffsetStatements: partitions,
		accounts:                  a,
		profiles:                  p,
		accountDatas:              ac,
		threepids:                 t,
		serverName:                serverName,
	}, nil
}

// GetAccountByPassword returns the account associated with the given localpart and password.
// Returns sql.ErrNoRows if no account exists which matches the given localpart.
func (d *Database) GetAccountByPassword(
	ctx context.Context, localpart, plaintextPassword string,
) (*api.Account, error) {
	hash, err := d.accounts.selectPasswordHash(ctx, localpart)
	if err != nil {
		return nil, err
	}
	if err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(plaintextPassword)); err != nil {
		return nil, err
	}
	return d.accounts.selectAccountByLocalpart(ctx, localpart)
}

// GetProfileByLocalpart returns the profile associated with the given localpart.
// Returns sql.ErrNoRows if no profile exists which matches the given localpart.
func (d *Database) GetProfileByLocalpart(
	ctx context.Context, localpart string,
) (*authtypes.Profile, error) {
	return d.profiles.selectProfileByLocalpart(ctx, localpart)
}

// SetAvatarURL updates the avatar URL of the profile associated with the given
// localpart. Returns an error if something went wrong with the SQL query
func (d *Database) SetAvatarURL(
	ctx context.Context, localpart string, avatarURL string,
) error {
	d.profilesMu.Lock()
	defer d.profilesMu.Unlock()
	return d.profiles.setAvatarURL(ctx, localpart, avatarURL)
}

// SetDisplayName updates the display name of the profile associated with the given
// localpart. Returns an error if something went wrong with the SQL query
func (d *Database) SetDisplayName(
	ctx context.Context, localpart string, displayName string,
) error {
	d.profilesMu.Lock()
	defer d.profilesMu.Unlock()
	return d.profiles.setDisplayName(ctx, localpart, displayName)
}

// CreateGuestAccount makes a new guest account and creates an empty profile
// for this account.
func (d *Database) CreateGuestAccount(ctx context.Context) (acc *api.Account, err error) {
	// We need to lock so we sequentially create numeric localparts. If we don't, two calls to
	// this function will cause the same number to be selected and one will fail with 'database is locked'
	// when the first txn upgrades to a write txn. We also need to lock the account creation else we can
	// race with CreateAccount
	// We know we'll be the only process since this is sqlite ;) so a lock here will be all that is needed.
	d.profilesMu.Lock()
	d.accountDatasMu.Lock()
	d.accountsMu.Lock()
	defer d.profilesMu.Unlock()
	defer d.accountDatasMu.Unlock()
	defer d.accountsMu.Unlock()
	err = sqlutil.WithTransaction(d.db, func(txn *sql.Tx) error {
		var numLocalpart int64
		numLocalpart, err = d.accounts.selectNewNumericLocalpart(ctx, txn)
		if err != nil {
			return err
		}
		localpart := strconv.FormatInt(numLocalpart, 10)
		acc, err = d.createAccount(ctx, txn, localpart, "", "")
		return err
	})
	return acc, err
}

// CreateAccount makes a new account with the given login name and password, and creates an empty profile
// for this account. If no password is supplied, the account will be a passwordless account. If the
// account already exists, it will return nil, ErrUserExists.
func (d *Database) CreateAccount(
	ctx context.Context, localpart, plaintextPassword, appserviceID string,
) (acc *api.Account, err error) {
	// Create one account at a time else we can get 'database is locked'.
	d.profilesMu.Lock()
	d.accountDatasMu.Lock()
	d.accountsMu.Lock()
	defer d.profilesMu.Unlock()
	defer d.accountDatasMu.Unlock()
	defer d.accountsMu.Unlock()
	err = sqlutil.WithTransaction(d.db, func(txn *sql.Tx) error {
		acc, err = d.createAccount(ctx, txn, localpart, plaintextPassword, appserviceID)
		return err
	})
	return
}

// WARNING! This function assumes that the relevant mutexes have already
// been taken out by the caller (e.g. CreateAccount or CreateGuestAccount).
func (d *Database) createAccount(
	ctx context.Context, txn *sql.Tx, localpart, plaintextPassword, appserviceID string,
) (*api.Account, error) {
	var err error
	// Generate a password hash if this is not a password-less user
	hash := ""
	if plaintextPassword != "" {
		hash, err = hashPassword(plaintextPassword)
		if err != nil {
			return nil, err
		}
	}
	if err := d.profiles.insertProfile(ctx, txn, localpart); err != nil {
		if isConstraintError(err) {
			return nil, sqlutil.ErrUserExists
		}
		return nil, err
	}

	if err := d.accountDatas.insertAccountData(ctx, txn, localpart, "", "m.push_rules", json.RawMessage(`{
		"global": {
			"content": [],
			"override": [],
			"room": [],
			"sender": [],
			"underride": []
		}
	}`)); err != nil {
		return nil, err
	}
	return d.accounts.insertAccount(ctx, txn, localpart, hash, appserviceID)
}

// SaveAccountData saves new account data for a given user and a given room.
// If the account data is not specific to a room, the room ID should be an empty string
// If an account data already exists for a given set (user, room, data type), it will
// update the corresponding row with the new content
// Returns a SQL error if there was an issue with the insertion/update
func (d *Database) SaveAccountData(
	ctx context.Context, localpart, roomID, dataType string, content json.RawMessage,
) error {
	d.accountDatasMu.Lock()
	defer d.accountDatasMu.Unlock()
	return sqlutil.WithTransaction(d.db, func(txn *sql.Tx) error {
		return d.accountDatas.insertAccountData(ctx, txn, localpart, roomID, dataType, content)
	})
}

// GetAccountData returns account data related to a given localpart
// If no account data could be found, returns an empty arrays
// Returns an error if there was an issue with the retrieval
func (d *Database) GetAccountData(ctx context.Context, localpart string) (
	global map[string]json.RawMessage,
	rooms map[string]map[string]json.RawMessage,
	err error,
) {
	return d.accountDatas.selectAccountData(ctx, localpart)
}

// GetAccountDataByType returns account data matching a given
// localpart, room ID and type.
// If no account data could be found, returns nil
// Returns an error if there was an issue with the retrieval
func (d *Database) GetAccountDataByType(
	ctx context.Context, localpart, roomID, dataType string,
) (data json.RawMessage, err error) {
	return d.accountDatas.selectAccountDataByType(
		ctx, localpart, roomID, dataType,
	)
}

// GetNewNumericLocalpart generates and returns a new unused numeric localpart
func (d *Database) GetNewNumericLocalpart(
	ctx context.Context,
) (int64, error) {
	return d.accounts.selectNewNumericLocalpart(ctx, nil)
}

func hashPassword(plaintext string) (hash string, err error) {
	hashBytes, err := bcrypt.GenerateFromPassword([]byte(plaintext), bcrypt.DefaultCost)
	return string(hashBytes), err
}

// Err3PIDInUse is the error returned when trying to save an association involving
// a third-party identifier which is already associated to a local user.
var Err3PIDInUse = errors.New("This third-party identifier is already in use")

// SaveThreePIDAssociation saves the association between a third party identifier
// and a local Matrix user (identified by the user's ID's local part).
// If the third-party identifier is already part of an association, returns Err3PIDInUse.
// Returns an error if there was a problem talking to the database.
func (d *Database) SaveThreePIDAssociation(
	ctx context.Context, threepid, localpart, medium string,
) (err error) {
	d.threepidsMu.Lock()
	defer d.threepidsMu.Unlock()
	return sqlutil.WithTransaction(d.db, func(txn *sql.Tx) error {
		user, err := d.threepids.selectLocalpartForThreePID(
			ctx, txn, threepid, medium,
		)
		if err != nil {
			return err
		}

		if len(user) > 0 {
			return Err3PIDInUse
		}

		return d.threepids.insertThreePID(ctx, txn, threepid, medium, localpart)
	})
}

// RemoveThreePIDAssociation removes the association involving a given third-party
// identifier.
// If no association exists involving this third-party identifier, returns nothing.
// If there was a problem talking to the database, returns an error.
func (d *Database) RemoveThreePIDAssociation(
	ctx context.Context, threepid string, medium string,
) (err error) {
	d.threepidsMu.Lock()
	defer d.threepidsMu.Unlock()
	return d.threepids.deleteThreePID(ctx, threepid, medium)
}

// GetLocalpartForThreePID looks up the localpart associated with a given third-party
// identifier.
// If no association involves the given third-party idenfitier, returns an empty
// string.
// Returns an error if there was a problem talking to the database.
func (d *Database) GetLocalpartForThreePID(
	ctx context.Context, threepid string, medium string,
) (localpart string, err error) {
	return d.threepids.selectLocalpartForThreePID(ctx, nil, threepid, medium)
}

// GetThreePIDsForLocalpart looks up the third-party identifiers associated with
// a given local user.
// If no association is known for this user, returns an empty slice.
// Returns an error if there was an issue talking to the database.
func (d *Database) GetThreePIDsForLocalpart(
	ctx context.Context, localpart string,
) (threepids []authtypes.ThreePID, err error) {
	return d.threepids.selectThreePIDsForLocalpart(ctx, localpart)
}

// CheckAccountAvailability checks if the username/localpart is already present
// in the database.
// If the DB returns sql.ErrNoRows the Localpart isn't taken.
func (d *Database) CheckAccountAvailability(ctx context.Context, localpart string) (bool, error) {
	_, err := d.accounts.selectAccountByLocalpart(ctx, localpart)
	if err == sql.ErrNoRows {
		return true, nil
	}
	return false, err
}

// GetAccountByLocalpart returns the account associated with the given localpart.
// This function assumes the request is authenticated or the account data is used only internally.
// Returns sql.ErrNoRows if no account exists which matches the given localpart.
func (d *Database) GetAccountByLocalpart(ctx context.Context, localpart string,
) (*api.Account, error) {
	return d.accounts.selectAccountByLocalpart(ctx, localpart)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"
	"path/filepath"

	"github.com/layeh/gumble/gumble"
	"github.com/layeh/gumble/gumble_ffmpeg"
	"github.com/layeh/gumble/gumbleutil"
	_ "github.com/layeh/gumble/opus"
)

func main() {
	files := make(map[string]string)
	var stream *gumble_ffmpeg.Stream

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage of %s: [flags] [audio files...]\n", os.Args[0])
		flag.PrintDefaults()
	}

	gumbleutil.Main(func(client *gumble.Client) {
		stream = gumble_ffmpeg.New(client)

		client.Attach(gumbleutil.AutoBitrate)

		for _, file := range flag.Args() {
			key := filepath.Base(file)
			files[key] = file
		}
	}, gumbleutil.Listener{
		// Connect event
		Connect: func(e *gumble.ConnectEvent) {
			fmt.Printf("audio player loaded! (%d files)\n", len(files))
		},

		// Text message event
		TextMessage: func(e *gumble.TextMessageEvent) {
			if e.Sender == nil {
				return
			}
			file, ok := files[e.Message]
			if !ok {
				return
			}
			stream.Source = gumble_ffmpeg.SourceFile(file)
			if err := stream.Play(); err != nil {
				fmt.Printf("%s\n", err)
			} else {
				fmt.Printf("Playing %s\n", file)
			}
		},
	})
}
<commit_msg>fix mumble-audio-player example<commit_after>package main

import (
	"flag"
	"fmt"
	"os"
	"path/filepath"

	"github.com/layeh/gumble/gumble"
	"github.com/layeh/gumble/gumbleffmpeg"
	"github.com/layeh/gumble/gumbleutil"
	_ "github.com/layeh/gumble/opus"
)

func main() {
	files := make(map[string]string)
	var stream *gumbleffmpeg.Stream

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage of %s: [flags] [audio files...]\n", os.Args[0])
		flag.PrintDefaults()
	}

	gumbleutil.Main(func(client *gumble.Client) {
		client.Attach(gumbleutil.AutoBitrate)

		for _, file := range flag.Args() {
			key := filepath.Base(file)
			files[key] = file
		}
	}, gumbleutil.Listener{
		// Connect event
		Connect: func(e *gumble.ConnectEvent) {
			fmt.Printf("audio player loaded! (%d files)\n", len(files))
		},

		// Text message event
		TextMessage: func(e *gumble.TextMessageEvent) {
			if e.Sender == nil {
				return
			}
			file, ok := files[e.Message]
			if !ok {
				return
			}
			if stream != nil && stream.State() == gumbleffmpeg.StatePlaying {
				return
			}
			stream = gumbleffmpeg.New(e.Client, gumbleffmpeg.SourceFile(file))
			if err := stream.Play(); err != nil {
				fmt.Printf("%s\n", err)
			} else {
				fmt.Printf("Playing %s\n", file)
			}
		},
	})
}
<|endoftext|>


<commit_before>/*
Copyright 2011 Google Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package osutil

import (
	"exec"
	"runtime"
	"os"
)

func OpenURL(url string) os.Error {
	if runtime.GOOS == "windows" {
		return exec.Command("cmd.exe", "/C", "start "+url).Run()
	}

	if runtime.GOOS == "darwin" {
		return exec.Command("open", url).Run()
	}

	return exec.Command("xdg-open", url).Run()
}
<commit_msg>update to Go 1<commit_after>/*
Copyright 2011 Google Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package osutil

import (
	"os/exec"
	"runtime"
)

func OpenURL(url string) error {
	if runtime.GOOS == "windows" {
		return exec.Command("cmd.exe", "/C", "start "+url).Run()
	}

	if runtime.GOOS == "darwin" {
		return exec.Command("open", url).Run()
	}

	return exec.Command("xdg-open", url).Run()
}
<|endoftext|>