<commit_before>package navmesh

import (
	"container/heap"
	. "github.com/spate/vectormath"
	"math"
)

const LARGE_NUMBER = 999999

// Triangle Heap
type WeightedTriangle struct {
	id     int32 // triangle id
	weight float32
}

type TriangleHeap struct {
	triangles []WeightedTriangle
}

func (th *TriangleHeap) Len() int {
	return len(th.triangles)
}

func (th *TriangleHeap) Less(i, j int) bool {
	return th.triangles[i].weight > th.triangles[j].weight
}

func (th *TriangleHeap) Swap(i, j int) {
	th.triangles[i], th.triangles[j] = th.triangles[j], th.triangles[i]
}

func (th *TriangleHeap) Push(x interface{}) {
	th.triangles = append(th.triangles, x.(WeightedTriangle))
}

func (th *TriangleHeap) Pop() interface{} {
	n := len(th.triangles)
	x := th.triangles[n-1]
	th.triangles = th.triangles[:n-1]
	return x
}

func (th *TriangleHeap) DecreaseKey(id int32, weight float32) {
	for k := range th.triangles {
		if th.triangles[k].id == id {
			heap.Remove(th, k)
			heap.Push(th, WeightedTriangle{id, weight})
			return
		}
	}
}

type Mesh struct {
	Vertices  []Point3   // vertices
	Triangles [][3]int32 // triangles
}

// Dijkstra
type Dijkstra struct {
	Matrix map[int32][]WeightedTriangle // all edge for nodes
}

// create neighbour matrix
func (d *Dijkstra) CreateMatrixFromMesh(mesh Mesh) {
	d.Matrix = make(map[int32][]WeightedTriangle)
	for i := 0; i < len(mesh.Triangles); i++ {
		for j := 0; j < len(mesh.Triangles); j++ {
			if i == j {
				continue
			}

			if len(intersect(mesh.Triangles[i], mesh.Triangles[j])) == 2 {
				x1 := (mesh.Vertices[mesh.Triangles[i][0]].X + mesh.Vertices[mesh.Triangles[i][1]].X + mesh.Vertices[mesh.Triangles[i][2]].X) / 3.0
				y1 := (mesh.Vertices[mesh.Triangles[i][0]].Y + mesh.Vertices[mesh.Triangles[i][1]].Y + mesh.Vertices[mesh.Triangles[i][2]].Y) / 3.0
				x2 := (mesh.Vertices[mesh.Triangles[j][0]].X + mesh.Vertices[mesh.Triangles[j][1]].X + mesh.Vertices[mesh.Triangles[j][2]].X) / 3.0
				y2 := (mesh.Vertices[mesh.Triangles[j][0]].Y + mesh.Vertices[mesh.Triangles[j][1]].Y + mesh.Vertices[mesh.Triangles[j][2]].Y) / 3.0
				weight := float32(math.Sqrt(float64((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1))))
				d.Matrix[int32(i)] = append(d.Matrix[int32(i)], WeightedTriangle{int32(j), weight})
			}
		}
	}
}

func intersect(a [3]int32, b [3]int32) []int32 {
	var inter []int32
	for i := range a {
		for j := range b {
			if a[i] == b[j] {
				inter = append(inter, a[i])
			}
		}
	}
	return inter
}

func (d *Dijkstra) Run(src_id int32) map[int32]int32 {
	defer func() {
		println("run ok")
	}()
	// triangle heap
	h := &TriangleHeap{}
	heap.Init(h)

	// min distance records
	dist := make(map[int32]float32)

	// previous map
	prev := make(map[int32]int32)

	// visit map
	visited := make(map[int32]bool)

	// set initial distance to a very large value
	for k := range d.Matrix {
		dist[k] = LARGE_NUMBER
		heap.Push(h, WeightedTriangle{k, LARGE_NUMBER})
	}

	// source vertex, the first vertex in Heap
	h.DecreaseKey(src_id, 0)
	dist[src_id] = 0.0

	for h.Len() > 0 { // for every un-visited vertex, try relaxing the path
		// pop the min element
		u := h.Pop().(WeightedTriangle)
		// current known shortest distance to u
		dist_u := dist[u.id]
		// mark the vertex as visited.
		visited[u.id] = true

		// for each neighbor v of u:
		for _, v := range d.Matrix[u.id] {
			alt := dist_u + v.weight // from src->u->v
			if alt < dist[v.id] {
				dist[v.id] = alt
				prev[v.id] = u.id
				h.DecreaseKey(v.id, alt)
			}
		}
	}
	return prev
}
<commit_msg>update<commit_after>package navmesh

import (
	"container/heap"
	. "github.com/spate/vectormath"
	"math"
)

const LARGE_NUMBER = 999999

// Triangle Heap
type WeightedTriangle struct {
	id     int32 // triangle id
	weight float32
}

type TriangleHeap struct {
	triangles []WeightedTriangle
}

func (th *TriangleHeap) Len() int {
	return len(th.triangles)
}

func (th *TriangleHeap) Less(i, j int) bool {
	return th.triangles[i].weight > th.triangles[j].weight
}

func (th *TriangleHeap) Swap(i, j int) {
	th.triangles[i], th.triangles[j] = th.triangles[j], th.triangles[i]
}

func (th *TriangleHeap) Push(x interface{}) {
	th.triangles = append(th.triangles, x.(WeightedTriangle))
}

func (th *TriangleHeap) Pop() interface{} {
	n := len(th.triangles)
	x := th.triangles[n-1]
	th.triangles = th.triangles[:n-1]
	return x
}

func (th *TriangleHeap) DecreaseKey(id int32, weight float32) {
	for k := range th.triangles {
		if th.triangles[k].id == id {
			heap.Remove(th, k)
			heap.Push(th, WeightedTriangle{id, weight})
			return
		}
	}
}

type Mesh struct {
	Vertices  []Point3   // vertices
	Triangles [][3]int32 // triangles
}

// Dijkstra
type Dijkstra struct {
	Matrix map[int32][]WeightedTriangle // all edge for nodes
}

// create neighbour matrix
func (d *Dijkstra) CreateMatrixFromMesh(mesh Mesh) {
	d.Matrix = make(map[int32][]WeightedTriangle)
	for i := 0; i < len(mesh.Triangles); i++ {
		for j := 0; j < len(mesh.Triangles); j++ {
			if i == j {
				continue
			}

			if len(intersect(mesh.Triangles[i], mesh.Triangles[j])) == 2 {
				x1 := (mesh.Vertices[mesh.Triangles[i][0]].X + mesh.Vertices[mesh.Triangles[i][1]].X + mesh.Vertices[mesh.Triangles[i][2]].X) / 3.0
				y1 := (mesh.Vertices[mesh.Triangles[i][0]].Y + mesh.Vertices[mesh.Triangles[i][1]].Y + mesh.Vertices[mesh.Triangles[i][2]].Y) / 3.0
				x2 := (mesh.Vertices[mesh.Triangles[j][0]].X + mesh.Vertices[mesh.Triangles[j][1]].X + mesh.Vertices[mesh.Triangles[j][2]].X) / 3.0
				y2 := (mesh.Vertices[mesh.Triangles[j][0]].Y + mesh.Vertices[mesh.Triangles[j][1]].Y + mesh.Vertices[mesh.Triangles[j][2]].Y) / 3.0
				weight := float32(math.Sqrt(float64((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1))))
				d.Matrix[int32(i)] = append(d.Matrix[int32(i)], WeightedTriangle{int32(j), weight})
			}
		}
	}
}

func intersect(a [3]int32, b [3]int32) []int32 {
	var inter []int32
	for i := range a {
		for j := range b {
			if a[i] == b[j] {
				inter = append(inter, a[i])
			}
		}
	}
	return inter
}

func (d *Dijkstra) Run(src_id int32) map[int32]int32 {
	defer func() {
		println("run ok")
	}()
	// triangle heap
	h := &TriangleHeap{}
	heap.Init(h)

	// min distance records
	dist := make(map[int32]float32)

	// previous map
	prev := make(map[int32]int32)

	// visit map
	visited := make(map[int32]bool)

	// set initial distance to a very large value
	for k := range d.Matrix {
		dist[k] = LARGE_NUMBER
		heap.Push(h, WeightedTriangle{k, LARGE_NUMBER})
	}

	// source vertex, the first vertex in Heap
	h.DecreaseKey(src_id, 0)
	dist[src_id] = 0.0

	for h.Len() > 0 { // for every un-visited vertex, try relaxing the path
		// pop the min element
		u := h.Pop().(WeightedTriangle)
		if visited[u.id] {
			continue
		}
		// current known shortest distance to u
		dist_u := dist[u.id]
		// mark the vertex as visited.
		visited[u.id] = true

		// for each neighbor v of u:
		for _, v := range d.Matrix[u.id] {
			alt := dist_u + v.weight // from src->u->v
			if alt < dist[v.id] {
				dist[v.id] = alt
				prev[v.id] = u.id
				h.DecreaseKey(v.id, alt)
			}
		}
	}
	return prev
}
<|endoftext|>


<commit_before>package canary

import (
	"fmt"
	"net/http"
	"net/http/httptest"
	"testing"
)

func TestGetManifest(t *testing.T) {
	handler := func(w http.ResponseWriter, r *http.Request) {
		data := `{
			"targets": [
				{
					"url": "http://www.canary.io",
					"name": "canary"
				}
			]
		}`

		fmt.Fprintf(w, data)
	}

	ts := httptest.NewServer(http.HandlerFunc(handler))
	defer ts.Close()

	m, err := GetManifest(ts.URL)
	if err != nil {
		t.Fatal(err)
	}

	if len(m.Targets) != 1 {
		t.Fatal("%d targets found, but expected 1", len(m.Targets))
	}

	target := m.Targets[0]
	if target.Name != "canary" {
		t.Fatal("expected name to be equal to 'canary', go %s", target.URL)
	}

	if target.URL != "http://www.canary.io" {
		t.Fatal("expected URL to be equal to 'http://www.canary.io', got %s", target.URL)
	}
}
<commit_msg>Update manifest_test to test the interval definiton on urls<commit_after>package canary

import (
	"fmt"
	"net/http"
	"net/http/httptest"
	"testing"
)

func TestGetManifestWithoutInterval(t *testing.T) {
	handler := func(w http.ResponseWriter, r *http.Request) {
		data := `{
			"targets": [
				{
					"url": "http://www.canary.io",
					"name": "canary"
				}
			]
		}`

		fmt.Fprintf(w, data)
	}

	ts := httptest.NewServer(http.HandlerFunc(handler))
	defer ts.Close()

	m, err := GetManifest(ts.URL)
	if err != nil {
		t.Fatal(err)
	}

	if len(m.Targets) != 1 {
		t.Fatal("%d targets found, but expected 1", len(m.Targets))
	}

	target := m.Targets[0]
	if target.Name != "canary" {
		t.Fatal("expected name to be equal to 'canary', go %s", target.URL)
	}

	if target.URL != "http://www.canary.io" {
		t.Fatal("expected URL to be equal to 'http://www.canary.io', got %s", target.URL)
	}

	if target.Interval != 0 {
		t.Fatal("expected Interval to be equal to zero when undefined in the manifest json, got %d", target.Interval)
	}
}

func TestGetManifestWithInterval(t *testing.T) {
	handler := func(w http.ResponseWriter, r *http.Request) {
		data := `{
			"targets": [
				{
					"url": "http://www.canary.io",
					"name": "canary",
					"interval": 2
				},
				{
					"url": "http://www.github.com",
					"name": "github",
					"interval": 4
				}
			]
		}`

		fmt.Fprintf(w, data)
	}

	ts := httptest.NewServer(http.HandlerFunc(handler))
	defer ts.Close()

	m, err := GetManifest(ts.URL)
	if err != nil {
		t.Fatal(err)
	}

	first_target := m.Targets[0]

	if first_target.Interval != 2 {
		t.Fatal("expected Interval on the first target to be equal to the manifest json definition of 2, got %d", first_target.Interval)
	}

	second_target := m.Targets[1]

	if second_target.Interval != 4 {
		t.Fatal("expected Interval on the second target to be equal to the manifest json definition of 4, got %d", second_target.Interval)
	}
}
<|endoftext|>


<commit_before>package phraseapp

import (
	"fmt"
	"net/http"

	"github.com/bgentry/speakeasy"
)

type DefaultParams Action
type Action map[string]map[string]interface{}

type AuthCredentials struct {
	Username string `cli:"opt --username desc='username used for authentication'"`
	Token    string `cli:"opt --token desc='token used for authentication'"`
	TFA      bool   `cli:"opt --tfa desc='use Two-Factor Authentication'"`
	Host     string `cli:"opt --host desc='Host to send Request to'"`
	Debug    bool   `cli:"opt --verbose desc='Verbose output'"`
}

var authC *AuthCredentials

func RegisterAuthCredentials(cmdAuth *AuthCredentials, defaultCredentials *AuthCredentials) {
	authC = new(AuthCredentials)

	if cmdAuth.Token != "" && authC.Token == "" && authC.Username == "" {
		authC.Token = cmdAuth.Token
	} else if cmdAuth.Username != "" && authC.Username == "" {
		authC.Username = cmdAuth.Username
	}

	if cmdAuth.TFA && authC.Username == "" {
		authC.TFA = cmdAuth.TFA
	}

	if cmdAuth.Debug == true || ((defaultCredentials != nil) && defaultCredentials.Debug == true) {
		EnableDebug()
	}

	if cmdAuth.Host != "" {
		authC.Host = cmdAuth.Host
	} else {
		if defaultCredentials != nil && defaultCredentials.Host != "" {
			authC.Host = defaultCredentials.Host
		}
	}

	if authC.Host == "" {
		authC.Host = "https://api.phraseapp.com"
	}

	notSet := authC.Token == "" && authC.Username == ""
	if notSet && defaultCredentials.Token != "" && defaultCredentials != nil {
		authC.Token = defaultCredentials.Token
	}
	if notSet && defaultCredentials != nil && defaultCredentials.Username != "" {
		authC.Username = defaultCredentials.Username
	}
}

func authenticate(req *http.Request) error {
	if authC == nil {
		return fmt.Errorf("no auth handler registered")
	}

	if err := authC.validate(); err != nil {
		return err
	}

	switch {
	case authC.Token != "":
		req.Header.Set("Authorization", "token "+authC.Token)
	case authC.Username != "":
		pwd, err := speakeasy.Ask("Password: ")
		if err != nil {
			return err
		}
		req.SetBasicAuth(authC.Username, pwd)

		if authC.TFA { // TFA only required for username+password based login.
			token, err := speakeasy.Ask("TFA-Token: ")
			if err != nil {
				return err
			}
			req.Header.Set("X-PhraseApp-OTP", token)
		}
	}

	return nil
}

func (ah *AuthCredentials) validate() error {
	switch {
	case ah.Username == "" && ah.Token == "":
		return fmt.Errorf("either username or token must be given")
	default:
		return nil
	}
}
<commit_msg>added support for env authentication with PHRASEAPP_AUTH_TOKEN, priority: cmd > env > defaults<commit_after>package phraseapp

import (
	"fmt"
	"net/http"

	"github.com/bgentry/speakeasy"
	"os"
)

type DefaultParams Action
type Action map[string]map[string]interface{}

type AuthCredentials struct {
	Username string `cli:"opt --username desc='username used for authentication'"`
	Token    string `cli:"opt --token desc='token used for authentication'"`
	TFA      bool   `cli:"opt --tfa desc='use Two-Factor Authentication'"`
	Host     string `cli:"opt --host desc='Host to send Request to'"`
	Debug    bool   `cli:"opt --verbose desc='Verbose output'"`
}

var authC *AuthCredentials

func RegisterAuthCredentials(cmdAuth *AuthCredentials, defaultCredentials *AuthCredentials) {
	authC = new(AuthCredentials)

	envToken := os.Getenv("PHRASEAPP_AUTH_TOKEN")

	if cmdAuth.Token != "" && authC.Token == "" && authC.Username == "" {
		authC.Token = cmdAuth.Token
	} else if cmdAuth.Username != "" && authC.Username == "" {
		authC.Username = cmdAuth.Username
	} else if envToken != "" && cmdAuth.Token == "" && cmdAuth.Username == "" && authC.Username == "" {
		authC.Token = envToken
	}

	if cmdAuth.TFA && authC.Username == "" {
		authC.TFA = cmdAuth.TFA
	}

	if cmdAuth.Debug == true || ((defaultCredentials != nil) && defaultCredentials.Debug == true) {
		EnableDebug()
	}

	if cmdAuth.Host != "" {
		authC.Host = cmdAuth.Host
	} else {
		if defaultCredentials != nil && defaultCredentials.Host != "" {
			authC.Host = defaultCredentials.Host
		}
	}

	if authC.Host == "" {
		authC.Host = "https://api.phraseapp.com"
	}

	notSet := authC.Token == "" && authC.Username == ""
	if notSet && defaultCredentials.Token != "" && defaultCredentials != nil {
		authC.Token = defaultCredentials.Token
	}
	if notSet && defaultCredentials != nil && defaultCredentials.Username != "" {
		authC.Username = defaultCredentials.Username
	}
}

func authenticate(req *http.Request) error {
	if authC == nil {
		return fmt.Errorf("no auth handler registered")
	}

	if err := authC.validate(); err != nil {
		return err
	}

	switch {
	case authC.Token != "":
		req.Header.Set("Authorization", "token "+authC.Token)
	case authC.Username != "":
		pwd, err := speakeasy.Ask("Password: ")
		if err != nil {
			return err
		}
		req.SetBasicAuth(authC.Username, pwd)

		if authC.TFA { // TFA only required for username+password based login.
			token, err := speakeasy.Ask("TFA-Token: ")
			if err != nil {
				return err
			}
			req.Header.Set("X-PhraseApp-OTP", token)
		}
	}

	return nil
}

func (ah *AuthCredentials) validate() error {
	switch {
	case ah.Username == "" && ah.Token == "":
		return fmt.Errorf("either username or token must be given")
	default:
		return nil
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 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 pixiecore

import (
	"errors"
	"fmt"
	"net"

	"go.universe.tf/netboot/dhcp4"
)

func (s *Server) serveDHCP(conn *dhcp4.Conn) error {
	for {
		pkt, intf, err := conn.RecvDHCP()
		if err != nil {
			return fmt.Errorf("Receiving DHCP packet: %s", err)
		}
		if intf == nil {
			return fmt.Errorf("Received DHCP packet with no interface information (this is a violation of dhcp4.Conn's contract, please file a bug)")
		}

		if err = s.isBootDHCP(pkt); err != nil {
			s.debug("DHCP", "Ignoring packet from %s: %s", pkt.HardwareAddr, err)
			continue
		}
		mach, isIpxe, fwtype, err := s.validateDHCP(pkt)
		if err != nil {
			s.log("DHCP", "Unusable packet from %s: %s", pkt.HardwareAddr, err)
			continue
		}

		s.debug("DHCP", "Got valid request to boot %s (%s)", mach.MAC, mach.Arch)

		spec, err := s.Booter.BootSpec(mach)
		if err != nil {
			s.log("DHCP", "Couldn't get bootspec for %s: %s", pkt.HardwareAddr, err)
			continue
		}
		if spec == nil {
			s.debug("DHCP", "No boot spec for %s, ignoring boot request", pkt.HardwareAddr)
			s.machineEvent(pkt.HardwareAddr, machineStateIgnored, "Machine should not netboot")
			continue
		}

		s.log("DHCP", "Offering to boot %s", pkt.HardwareAddr)
		if isIpxe {
			s.machineEvent(pkt.HardwareAddr, machineStateProxyDHCPIpxe, "Offering to boot iPXE")
		} else {
			s.machineEvent(pkt.HardwareAddr, machineStateProxyDHCP, "Offering to boot")
		}

		// Machine should be booted.
		serverIP, err := interfaceIP(intf)
		if err != nil {
			s.log("DHCP", "Want to boot %s on %s, but couldn't get a source address: %s", pkt.HardwareAddr, intf.Name, err)
			continue
		}

		resp, err := s.offerDHCP(pkt, mach, serverIP, isIpxe, fwtype)
		if err != nil {
			s.log("DHCP", "Failed to construct ProxyDHCP offer for %s: %s", pkt.HardwareAddr, err)
			continue
		}

		if err = conn.SendDHCP(resp, intf); err != nil {
			s.log("DHCP", "Failed to send ProxyDHCP offer for %s: %s", pkt.HardwareAddr, err)
			continue
		}
	}
}

func (s *Server) isBootDHCP(pkt *dhcp4.Packet) error {
	if pkt.Type != dhcp4.MsgDiscover {
		return fmt.Errorf("packet is %s, not %s", pkt.Type, dhcp4.MsgDiscover)
	}

	if pkt.Options[93] == nil {
		return errors.New("not a PXE boot request (missing option 93)")
	}

	return nil
}

func (s *Server) validateDHCP(pkt *dhcp4.Packet) (mach Machine, isIpxe bool, fwtype Firmware, err error) {
	fwt, err := pkt.Options.Uint16(93)
	if err != nil {
		return mach, false, 0, fmt.Errorf("malformed DHCP option 93 (required for PXE): %s", err)
	}
	fwtype = Firmware(fwt)
	if s.Ipxe[fwtype] == nil {
		return mach, false, 0, fmt.Errorf("unsupported client firmware type '%d' (please file a bug!)", fwtype)
	}

	guid := pkt.Options[97]
	switch len(guid) {
	case 0:
		// A missing GUID is invalid according to the spec, however
		// there are PXE ROMs in the wild that omit the GUID and still
		// expect to boot. The only thing we do with the GUID is
		// mirror it back to the client if it's there, so we might as
		// well accept these buggy ROMs.
	case 17:
		if guid[0] != 0 {
			return mach, false, 0, errors.New("malformed client GUID (option 97), leading byte must be zero")
		}
	default:
		return mach, false, 0, errors.New("malformed client GUID (option 97), wrong size")
	}

	// iPXE options
	if len(pkt.Options[175]) > 0 {
		bs := pkt.Options[175]
		for len(bs) > 0 {
			if len(bs) < 2 || len(bs)-2 < int(bs[1]) {
				return mach, false, 0, errors.New("malformed iPXE option")
			}
			switch bs[0] {
			case 19:
				// This iPXE build supports HTTP, so is appropriate
				// for going straight into the OS kernel, no need to
				// chainload our own.
				isIpxe = true
			}
			bs = bs[2+int(bs[1]):]
		}
	}

	mach.MAC = pkt.HardwareAddr
	mach.Arch = fwToArch[fwtype]
	return mach, isIpxe, fwtype, nil
}

func (s *Server) offerDHCP(pkt *dhcp4.Packet, mach Machine, serverIP net.IP, isIpxe bool, fwtype Firmware) (*dhcp4.Packet, error) {
	resp := &dhcp4.Packet{
		Type:          dhcp4.MsgOffer,
		TransactionID: pkt.TransactionID,
		Broadcast:     true,
		HardwareAddr:  mach.MAC,
		RelayAddr:     pkt.RelayAddr,
		ServerAddr:    serverIP,
		Options:       make(dhcp4.Options),
	}
	resp.Options[dhcp4.OptServerIdentifier] = serverIP
	// says the server should identify itself as a PXEClient vendor
	// type, even though it's a server. Strange.
	resp.Options[dhcp4.OptVendorIdentifier] = []byte("PXEClient")
	if pkt.Options[97] != nil {
		resp.Options[97] = pkt.Options[97]
	}

	if isIpxe {
		resp.BootFilename = fmt.Sprintf("http://%s:%d/_/ipxe?arch=%d&mac=%s", serverIP, s.HTTPPort, mach.Arch, mach.MAC)
	} else {
		resp.BootServerName = serverIP.String()
		resp.BootFilename = fmt.Sprintf("%s/%d", mach.MAC, fwtype)
	}

	if fwtype == FirmwareX86PC {
		// In theory, the PXE boot options are required by PXE
		// clients. However, some UEFI firmwares don't actually
		// support PXE properly, and will ignore ProxyDHCP responses
		// that include the option.
		//
		// On the other hand, seemingly all firmwares support a
		// variant of the protocol where option 43 is not
		// provided. They behave as if option 43 had pointed them to a
		// PXE boot server on port 4011 of the machine sending the
		// ProxyDHCP response. Looking at TianoCore sources, I believe
		// this is the BINL protocol, which is Microsoft-specific and
		// lacks a specification. However, empirically, this code
		// seems to work.
		//
		// But this code block is for classic old BIOS, which does
		// behave and want option 43 to tell it how to boot.

		pxe := dhcp4.Options{
			// PXE Boot Server Discovery Control - bypass, just boot from filename.
			6: []byte{8},
		}
		bs, err := pxe.Marshal()
		if err != nil {
			return nil, fmt.Errorf("failed to serialize PXE vendor options: %s", err)
		}
		resp.Options[43] = bs
	}
	return resp, nil
}

func interfaceIP(intf *net.Interface) (net.IP, error) {
	addrs, err := intf.Addrs()
	if err != nil {
		return nil, err
	}

	// Try to find an IPv4 address to use, in the following order:
	// global unicast (includes rfc1918), link-local unicast,
	// loopback.
	fs := [](func(net.IP) bool){
		net.IP.IsGlobalUnicast,
		net.IP.IsLinkLocalUnicast,
		net.IP.IsLoopback,
	}
	for _, f := range fs {
		for _, a := range addrs {
			ipaddr, ok := a.(*net.IPNet)
			if !ok {
				continue
			}
			ip := ipaddr.IP.To4()
			if ip == nil {
				continue
			}
			if f(ip) {
				return ip, nil
			}
		}
	}

	return nil, errors.New("no usable unicast address configured on interface")
}
<commit_msg>Also check foor bzImage support in the ProxyDHCP stage. #51<commit_after>// Copyright 2016 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 pixiecore

import (
	"errors"
	"fmt"
	"net"

	"go.universe.tf/netboot/dhcp4"
)

func (s *Server) serveDHCP(conn *dhcp4.Conn) error {
	for {
		pkt, intf, err := conn.RecvDHCP()
		if err != nil {
			return fmt.Errorf("Receiving DHCP packet: %s", err)
		}
		if intf == nil {
			return fmt.Errorf("Received DHCP packet with no interface information (this is a violation of dhcp4.Conn's contract, please file a bug)")
		}

		if err = s.isBootDHCP(pkt); err != nil {
			s.debug("DHCP", "Ignoring packet from %s: %s", pkt.HardwareAddr, err)
			continue
		}
		mach, isIpxe, fwtype, err := s.validateDHCP(pkt)
		if err != nil {
			s.log("DHCP", "Unusable packet from %s: %s", pkt.HardwareAddr, err)
			continue
		}

		s.debug("DHCP", "Got valid request to boot %s (%s)", mach.MAC, mach.Arch)

		spec, err := s.Booter.BootSpec(mach)
		if err != nil {
			s.log("DHCP", "Couldn't get bootspec for %s: %s", pkt.HardwareAddr, err)
			continue
		}
		if spec == nil {
			s.debug("DHCP", "No boot spec for %s, ignoring boot request", pkt.HardwareAddr)
			s.machineEvent(pkt.HardwareAddr, machineStateIgnored, "Machine should not netboot")
			continue
		}

		s.log("DHCP", "Offering to boot %s", pkt.HardwareAddr)
		if isIpxe {
			s.machineEvent(pkt.HardwareAddr, machineStateProxyDHCPIpxe, "Offering to boot iPXE")
		} else {
			s.machineEvent(pkt.HardwareAddr, machineStateProxyDHCP, "Offering to boot")
		}

		// Machine should be booted.
		serverIP, err := interfaceIP(intf)
		if err != nil {
			s.log("DHCP", "Want to boot %s on %s, but couldn't get a source address: %s", pkt.HardwareAddr, intf.Name, err)
			continue
		}

		resp, err := s.offerDHCP(pkt, mach, serverIP, isIpxe, fwtype)
		if err != nil {
			s.log("DHCP", "Failed to construct ProxyDHCP offer for %s: %s", pkt.HardwareAddr, err)
			continue
		}

		if err = conn.SendDHCP(resp, intf); err != nil {
			s.log("DHCP", "Failed to send ProxyDHCP offer for %s: %s", pkt.HardwareAddr, err)
			continue
		}
	}
}

func (s *Server) isBootDHCP(pkt *dhcp4.Packet) error {
	if pkt.Type != dhcp4.MsgDiscover {
		return fmt.Errorf("packet is %s, not %s", pkt.Type, dhcp4.MsgDiscover)
	}

	if pkt.Options[93] == nil {
		return errors.New("not a PXE boot request (missing option 93)")
	}

	return nil
}

func (s *Server) validateDHCP(pkt *dhcp4.Packet) (mach Machine, isIpxe bool, fwtype Firmware, err error) {
	fwt, err := pkt.Options.Uint16(93)
	if err != nil {
		return mach, false, 0, fmt.Errorf("malformed DHCP option 93 (required for PXE): %s", err)
	}
	fwtype = Firmware(fwt)
	if s.Ipxe[fwtype] == nil {
		return mach, false, 0, fmt.Errorf("unsupported client firmware type '%d' (please file a bug!)", fwtype)
	}

	guid := pkt.Options[97]
	switch len(guid) {
	case 0:
		// A missing GUID is invalid according to the spec, however
		// there are PXE ROMs in the wild that omit the GUID and still
		// expect to boot. The only thing we do with the GUID is
		// mirror it back to the client if it's there, so we might as
		// well accept these buggy ROMs.
	case 17:
		if guid[0] != 0 {
			return mach, false, 0, errors.New("malformed client GUID (option 97), leading byte must be zero")
		}
	default:
		return mach, false, 0, errors.New("malformed client GUID (option 97), wrong size")
	}

	// iPXE options
	supportsHTTP, supportsBzImage := false, false
	if len(pkt.Options[175]) > 0 {
		bs := pkt.Options[175]
		for len(bs) > 0 {
			if len(bs) < 2 || len(bs)-2 < int(bs[1]) {
				return mach, false, 0, errors.New("malformed iPXE option")
			}
			switch bs[0] {
			case 19:
				// This iPXE build supports HTTP.
				supportsHTTP = true
			case 24:
				// This iPXE build supports bzImage.
				supportsBzImage = true
			}
			bs = bs[2+int(bs[1]):]
		}
	}
	// This firmware is an appropriate iPXE if it can speak HTTP and
	// bzImage. If not, we'll chainload our own internal iPXE.
	isIpxe = supportsHTTP && supportsBzImage

	mach.MAC = pkt.HardwareAddr
	mach.Arch = fwToArch[fwtype]
	return mach, isIpxe, fwtype, nil
}

func (s *Server) offerDHCP(pkt *dhcp4.Packet, mach Machine, serverIP net.IP, isIpxe bool, fwtype Firmware) (*dhcp4.Packet, error) {
	resp := &dhcp4.Packet{
		Type:          dhcp4.MsgOffer,
		TransactionID: pkt.TransactionID,
		Broadcast:     true,
		HardwareAddr:  mach.MAC,
		RelayAddr:     pkt.RelayAddr,
		ServerAddr:    serverIP,
		Options:       make(dhcp4.Options),
	}
	resp.Options[dhcp4.OptServerIdentifier] = serverIP
	// says the server should identify itself as a PXEClient vendor
	// type, even though it's a server. Strange.
	resp.Options[dhcp4.OptVendorIdentifier] = []byte("PXEClient")
	if pkt.Options[97] != nil {
		resp.Options[97] = pkt.Options[97]
	}

	if isIpxe {
		resp.BootFilename = fmt.Sprintf("http://%s:%d/_/ipxe?arch=%d&mac=%s", serverIP, s.HTTPPort, mach.Arch, mach.MAC)
	} else {
		resp.BootServerName = serverIP.String()
		resp.BootFilename = fmt.Sprintf("%s/%d", mach.MAC, fwtype)
	}

	if fwtype == FirmwareX86PC {
		// In theory, the PXE boot options are required by PXE
		// clients. However, some UEFI firmwares don't actually
		// support PXE properly, and will ignore ProxyDHCP responses
		// that include the option.
		//
		// On the other hand, seemingly all firmwares support a
		// variant of the protocol where option 43 is not
		// provided. They behave as if option 43 had pointed them to a
		// PXE boot server on port 4011 of the machine sending the
		// ProxyDHCP response. Looking at TianoCore sources, I believe
		// this is the BINL protocol, which is Microsoft-specific and
		// lacks a specification. However, empirically, this code
		// seems to work.
		//
		// But this code block is for classic old BIOS, which does
		// behave and want option 43 to tell it how to boot.

		pxe := dhcp4.Options{
			// PXE Boot Server Discovery Control - bypass, just boot from filename.
			6: []byte{8},
		}
		bs, err := pxe.Marshal()
		if err != nil {
			return nil, fmt.Errorf("failed to serialize PXE vendor options: %s", err)
		}
		resp.Options[43] = bs
	}
	return resp, nil
}

func interfaceIP(intf *net.Interface) (net.IP, error) {
	addrs, err := intf.Addrs()
	if err != nil {
		return nil, err
	}

	// Try to find an IPv4 address to use, in the following order:
	// global unicast (includes rfc1918), link-local unicast,
	// loopback.
	fs := [](func(net.IP) bool){
		net.IP.IsGlobalUnicast,
		net.IP.IsLinkLocalUnicast,
		net.IP.IsLoopback,
	}
	for _, f := range fs {
		for _, a := range addrs {
			ipaddr, ok := a.(*net.IPNet)
			if !ok {
				continue
			}
			ip := ipaddr.IP.To4()
			if ip == nil {
				continue
			}
			if f(ip) {
				return ip, nil
			}
		}
	}

	return nil, errors.New("no usable unicast address configured on interface")
}
<|endoftext|>


<commit_before>/*
Copyright 2020 The Jetstack cert-manager contributors.

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.
*/

// This package was created to have a scheme that has the internal cert-manager types,
// and their conversion functions as well as the List object type registered, which is needed for ctl command like
// `convert` or `create certificaterequest`.
package ctl

import (
	metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"

	acmeinstall "github.com/jetstack/cert-manager/pkg/internal/apis/acme/install"
	cminstall "github.com/jetstack/cert-manager/pkg/internal/apis/certmanager/install"
	metainstall "github.com/jetstack/cert-manager/pkg/internal/apis/meta/install"
)

// Define a Scheme that has all cert-manager API types registered, including
// the internal API version, defaulting functions and conversion functions for
// all external versions.

var (
	// Scheme is a Kubernetes runtime.Scheme with all internal and external API
	// versions for cert-manager types registered.
	Scheme = runtime.NewScheme()
)

func init() {
	cminstall.Install(Scheme)
	acmeinstall.Install(Scheme)
	metainstall.Install(Scheme)

	// This is used to add the List object type
	//listGroupVersion := schema.GroupVersionKind{Group: "", Version: runtime.APIVersionInternal, Kind: "List"}
	//Scheme.AddKnownTypeWithName(listGroupVersion, &metainternalversion.List{})

	coreGroupVersion := schema.GroupVersion{Group: "", Version: runtime.APIVersionInternal}
	Scheme.AddKnownTypes(coreGroupVersion, &metav1.List{})

	metaGroupVersion := schema.GroupVersion{Group: "", Version: "v1"}
	Scheme.AddKnownTypes(metaGroupVersion, &metainternalversion.List{})
}
<commit_msg>Try and fail to fix list conversion<commit_after>/*
Copyright 2020 The Jetstack cert-manager contributors.

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.
*/

// This package was created to have a scheme that has the internal cert-manager types,
// and their conversion functions as well as the List object type registered, which is needed for ctl command like
// `convert` or `create certificaterequest`.
package ctl

import (
	metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"

	acmeinstall "github.com/jetstack/cert-manager/pkg/internal/apis/acme/install"
	cminstall "github.com/jetstack/cert-manager/pkg/internal/apis/certmanager/install"
	metainstall "github.com/jetstack/cert-manager/pkg/internal/apis/meta/install"
)

// Define a Scheme that has all cert-manager API types registered, including
// the internal API version, defaulting functions and conversion functions for
// all external versions.

var (
	// Scheme is a Kubernetes runtime.Scheme with all internal and external API
	// versions for cert-manager types registered.
	Scheme = runtime.NewScheme()
)

func init() {
	cminstall.Install(Scheme)
	acmeinstall.Install(Scheme)
	metainstall.Install(Scheme)

	// This is used to add the List object type
	listGroupVersion := schema.GroupVersionKind{Group: "", Version: runtime.APIVersionInternal}
	Scheme.AddKnownTypeWithName(listGroupVersion, &metainternalversion.List{})

	coreGroupVersion := schema.GroupVersion{Group: "", Version: "v1"}
	Scheme.AddKnownTypes(coreGroupVersion, &metav1.List{})
}
<|endoftext|>


<commit_before>package event

import (
	"gopkg.in/yaml.v2"
	"io"
	"io/ioutil"
	"os"
	"path"
	"strings"
)

func FromYaml(files string, recursive bool) []Event {
	pathNames := strings.Split(files, ",")
	events := make([]Event, 0)
	for _, pathName := range pathNames {
		event, err := read(pathName, recursive)
		if err != nil {
			panic(err) // TODO: could not panic later.
		}
		events = append(events, event...)
	}
	return events
}

func read(pathName string, recursive bool) ([]Event, error) {
	info, err := os.Stat(pathName)
	if err != nil {
		return nil, err
	}

	if info.IsDir() {
		return readDir(pathName, recursive)
	}
	return readFile(pathName)
}

func readFile(pathName string) ([]Event, error) {
	file, err := os.Open(pathName)
	if err != nil {
		return nil, err
	}
	defer func() {
		if err := file.Close(); err != nil {
			panic(err)
		}
	}()

	return decode(file)
}

func readDir(pathName string, recursive bool) ([]Event, error) {
	list, err := ioutil.ReadDir(pathName)
	if err != nil {
		return nil, err
	}

	events := make([]Event, 0)
	for _, f := range list {
		name := path.Join(pathName, f.Name())
		var evs []Event

		switch {
		case f.IsDir() && recursive:
			evs, err = readDir(name, recursive)
		case !f.IsDir():
			evs, err = readFile(name)
		}

		if err != nil {
			return nil, err
		}
		events = append(events, evs...)
	}
	return events, nil
}

func decode(reader io.Reader) ([]Event, error) {
	decoder := yaml.NewDecoder(reader)
	events := make([]Event, 0)
	var err error
	for {
		out := Event{}
		err = decoder.Decode(&out)
		if err != nil {
			break
		}
		events = append(events, out)
	}
	if err != io.EOF {
		return nil, err
	}
	return events, nil
}
<commit_msg>Allow dash "-" to be a file, as stdin. (#5)<commit_after>package event

import (
	"gopkg.in/yaml.v2"
	"io"
	"io/ioutil"
	"os"
	"path"
	"strings"
)

func FromYaml(files string, recursive bool) []Event {
	pathNames := strings.Split(files, ",")
	events := make([]Event, 0)
	for _, pathName := range pathNames {
		var event []Event
		var err error
		if pathName == "-" {
			event, err = decode(os.Stdin)
		} else {
			event, err = read(pathName, recursive)
		}
		if err != nil {
			panic(err) // TODO: could not panic later.
		}
		events = append(events, event...)
	}
	return events
}

func read(pathName string, recursive bool) ([]Event, error) {
	info, err := os.Stat(pathName)
	if err != nil {
		return nil, err
	}

	if info.IsDir() {
		return readDir(pathName, recursive)
	}
	return readFile(pathName)
}

func readFile(pathName string) ([]Event, error) {
	file, err := os.Open(pathName)
	if err != nil {
		return nil, err
	}
	defer func() {
		if err := file.Close(); err != nil {
			panic(err)
		}
	}()

	return decode(file)
}

func readDir(pathName string, recursive bool) ([]Event, error) {
	list, err := ioutil.ReadDir(pathName)
	if err != nil {
		return nil, err
	}

	events := make([]Event, 0)
	for _, f := range list {
		name := path.Join(pathName, f.Name())
		var evs []Event

		switch {
		case f.IsDir() && recursive:
			evs, err = readDir(name, recursive)
		case !f.IsDir():
			evs, err = readFile(name)
		}

		if err != nil {
			return nil, err
		}
		events = append(events, evs...)
	}
	return events, nil
}

func decode(reader io.Reader) ([]Event, error) {
	decoder := yaml.NewDecoder(reader)
	events := make([]Event, 0)
	var err error
	for {
		out := Event{}
		err = decoder.Decode(&out)
		if err != nil {
			break
		}
		events = append(events, out)
	}
	if err != io.EOF {
		return nil, err
	}
	return events, nil
}
<|endoftext|>


<commit_before>/*
Package log provides Logger
*/
package log

import (
	"net/http"
	"time"

	"github.com/vardius/golog"
)

// Logger allow to create logger based on env setting
type Logger struct {
	golog.Logger
}

// LogRequest wraps http.Handler with a logger middleware
func (l *Logger) LogRequest(next http.Handler) http.Handler {
	fn := func(w http.ResponseWriter, r *http.Request) {
		l.Info(r.Context(), "[Request|Start]: %s %s\n", r.Method, r.URL.String())
		start := time.Now()
		next.ServeHTTP(w, r)
		l.Info(r.Context(), "[Request|End]: %s %s %s\n", r.Method, r.URL.String(), time.Since(start).String())
	}

	return http.HandlerFunc(fn)
}

func getLogLevelByEnv(env string) string {
	logLevel := "info"
	if env == "development" {
		logLevel = "debug"
	}

	return logLevel
}

// New creates new logger based on environment
func New(env string) *Logger {
	var l golog.Logger
	if env == "development" {
		l = golog.New(getLogLevelByEnv(env))
	} else {
		l = golog.NewFileLogger(getLogLevelByEnv(env), "/tmp/prod.log")
	}

	return &Logger{l}
}
<commit_msg>Update logger<commit_after>/*
Package log provides Logger
*/
package log

import (
	"net/http"
	"time"

	"github.com/vardius/golog"
)

// Logger allow to create logger based on env setting
type Logger struct {
	golog.Logger
}

// LogRequest wraps http.Handler with a logger middleware
func (l *Logger) LogRequest(next http.Handler) http.Handler {
	fn := func(w http.ResponseWriter, r *http.Request) {
		l.Info(r.Context(), "[Request|Start]: %s %s\n", r.Method, r.URL.String())
		start := time.Now()
		next.ServeHTTP(w, r)
		l.Info(r.Context(), "[Request|End]: %s %s %s\n", r.Method, r.URL.String(), time.Since(start).String())
	}

	return http.HandlerFunc(fn)
}

// New creates new logger based on environment
func New(env string) *Logger {
	var l golog.Logger
	if env == "development" {
		l = golog.New(golog.Debug)
	} else {
		l = golog.NewFileLogger(golog.Info, "/tmp/prod.log")
	}

	return &Logger{l}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"time"
)

type mPlay struct {
	Args      []string          `json:"args"`
	Dir       string            `json:"dir"`
	Src       string            `json:"src"`
	Env       map[string]string `json:"env"`
	Cid       string            `json:"cid"`
	BuildOnly bool              `json:"build_only"`
	b         *Broker
}

// todo: send the client output as it comes
func (m *mPlay) Call() (interface{}, string) {
	env := envSlice(m.Env)

	tmpDir := m.Env["TMP"]
	if tmpDir == "" {
		tmpDir = os.TempDir()
	}
	tmpDir = filepath.Join(tmpDir, "GoSublime", "play")
	// if this fails then the next operation fails as well so no point in checking this
	os.MkdirAll(tmpDir, 0755)

	dir, err := ioutil.TempDir(tmpDir, "play-")
	if err != nil {
		return nil, err.Error()
	}
	defer os.RemoveAll(dir)

	if m.Src != "" {
		err = ioutil.WriteFile(filepath.Join(dir, "a.go"), []byte(m.Src), 0755)
		if err != nil {
			return nil, err.Error()
		}
		m.Dir = dir
	}

	if m.Args == nil {
		m.Args = []string{}
	}

	if m.Dir == "" {
		return nil, "missing directory"
	}

	if m.Cid == "" {
		m.Cid = "play.auto." + numbers.nextString()
	}

	stdErr := bytes.NewBuffer(nil)
	stdOut := bytes.NewBuffer(nil)
	runCmd := func(name string, args ...string) (M, error) {
		start := time.Now()
		stdOut.Reset()
		stdErr.Reset()
		c := exec.Command(name, args...)
		c.Stdout = stdOut
		c.Stderr = stdErr
		c.Dir = m.Dir
		c.Env = env

		watchCmd(m.Cid, c)
		defer unwatchCmd(m.Cid)

		err := c.Run()
		res := M{
			"out": stdOut.String(),
			"err": stdErr.String(),
			"dur": time.Now().Sub(start).String(),
		}

		return res, err
	}

	fn := filepath.Join(dir, "gosublime.a.exe")
	res, err := runCmd("go", "build", "-o", fn)
	if m.BuildOnly || err != nil {
		return res, errStr(err)
	}

	res, err = runCmd(fn, m.Args...)
	return res, errStr(err)
}

func init() {
	registry.Register("play", func(b *Broker) Caller {
		return &mPlay{
			b:   b,
			Env: map[string]string{},
		}
	})
}
<commit_msg>* kill any previous command sharing the cid<commit_after>package main

import (
	"bytes"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"time"
)

type mPlay struct {
	Args      []string          `json:"args"`
	Dir       string            `json:"dir"`
	Src       string            `json:"src"`
	Env       map[string]string `json:"env"`
	Cid       string            `json:"cid"`
	BuildOnly bool              `json:"build_only"`
	b         *Broker
}

// todo: send the client output as it comes
func (m *mPlay) Call() (interface{}, string) {
	env := envSlice(m.Env)

	tmpDir := m.Env["TMP"]
	if tmpDir == "" {
		tmpDir = os.TempDir()
	}
	tmpDir = filepath.Join(tmpDir, "GoSublime", "play")
	// if this fails then the next operation fails as well so no point in checking this
	os.MkdirAll(tmpDir, 0755)

	dir, err := ioutil.TempDir(tmpDir, "play-")
	if err != nil {
		return nil, err.Error()
	}
	defer os.RemoveAll(dir)

	if m.Src != "" {
		err = ioutil.WriteFile(filepath.Join(dir, "a.go"), []byte(m.Src), 0755)
		if err != nil {
			return nil, err.Error()
		}
		m.Dir = dir
	}

	if m.Args == nil {
		m.Args = []string{}
	}

	if m.Dir == "" {
		return nil, "missing directory"
	}

	if m.Cid == "" {
		m.Cid = "play.auto." + numbers.nextString()
	} else {
		killCmd(m.Cid)
	}

	stdErr := bytes.NewBuffer(nil)
	stdOut := bytes.NewBuffer(nil)
	runCmd := func(name string, args ...string) (M, error) {
		start := time.Now()
		stdOut.Reset()
		stdErr.Reset()
		c := exec.Command(name, args...)
		c.Stdout = stdOut
		c.Stderr = stdErr
		c.Dir = m.Dir
		c.Env = env

		watchCmd(m.Cid, c)
		defer unwatchCmd(m.Cid)

		err := c.Run()
		res := M{
			"out": stdOut.String(),
			"err": stdErr.String(),
			"dur": time.Now().Sub(start).String(),
		}

		return res, err
	}

	fn := filepath.Join(dir, "gosublime.a.exe")
	res, err := runCmd("go", "build", "-o", fn)
	if m.BuildOnly || err != nil {
		return res, errStr(err)
	}

	res, err = runCmd(fn, m.Args...)
	return res, errStr(err)
}

func init() {
	registry.Register("play", func(b *Broker) Caller {
		return &mPlay{
			b:   b,
			Env: map[string]string{},
		}
	})
}
<|endoftext|>


<commit_before>package conf

import (
	"errors"
	"os"
	"time"

	"github.com/joho/godotenv"
	"github.com/kelseyhightower/envconfig"
	"github.com/netlify/netlify-commons/nconf"
)

// OAuthProviderConfiguration holds all config related to external account providers.
type OAuthProviderConfiguration struct {
	ClientID    string `json:"client_id" split_words:"true"`
	Secret      string `json:"secret"`
	RedirectURI string `json:"redirect_uri" split_words:"true"`
	URL         string `json:"url"`
	Enabled     bool   `json:"enabled"`
}

// DBConfiguration holds all the database related configuration.
type DBConfiguration struct {
	Dialect     string `json:"dialect"`
	Driver      string `json:"driver" required:"true"`
	URL         string `json:"url" envconfig:"DATABASE_URL" required:"true"`
	Namespace   string `json:"namespace"`
	Automigrate bool   `json:"automigrate"`
}

// JWTConfiguration holds all the JWT related configuration.
type JWTConfiguration struct {
	Secret           string `json:"secret" required:"true"`
	Exp              int    `json:"exp"`
	Aud              string `json:"aud"`
	AdminGroupName   string `json:"admin_group_name" split_words:"true"`
	DefaultGroupName string `json:"default_group_name" split_words:"true"`
}

// GlobalConfiguration holds all the configuration that applies to all instances.
type GlobalConfiguration struct {
	API struct {
		Host     string
		Port     int `envconfig:"PORT" default:"8081"`
		Endpoint string
	}
	DB                DBConfiguration
	External          ExternalProviderConfiguration
	Logging           nconf.LoggingConfig `envconfig:"LOG"`
	OperatorToken     string              `split_words:"true" required:"true"`
	MultiInstanceMode bool
	SMTP              SMTPConfiguration
}

// EmailContentConfiguration holds the configuration for emails, both subjects and template URLs.
type EmailContentConfiguration struct {
	Invite       string `json:"invite"`
	Confirmation string `json:"confirmation"`
	Recovery     string `json:"recovery"`
	EmailChange  string `json:"email_change" split_words:"true"`
}

type ExternalProviderConfiguration struct {
	Bitbucket   OAuthProviderConfiguration `json:"bitbucket"`
	Github      OAuthProviderConfiguration `json:"github"`
	Gitlab      OAuthProviderConfiguration `json:"gitlab"`
	Google      OAuthProviderConfiguration `json:"google"`
	Facebook    OAuthProviderConfiguration `json:"facebook"`
	RedirectURL string                     `json:"redirect_url"`
}

type SMTPConfiguration struct {
	MaxFrequency time.Duration `json:"max_frequency" split_words:"true"`
	Host         string        `json:"host"`
	Port         int           `json:"port" default:"587"`
	User         string        `json:"user"`
	Pass         string        `json:"pass"`
	AdminEmail   string        `json:"admin_email" split_words:"true"`
}

// Configuration holds all the per-instance configuration.
type Configuration struct {
	SiteURL string            `json:"site_url" split_words:"true" required:"true"`
	JWT     JWTConfiguration  `json:"jwt"`
	SMTP    SMTPConfiguration `json:"smtp"`
	Mailer  struct {
		Autoconfirm bool                      `json:"autoconfirm"`
		Subjects    EmailContentConfiguration `json:"subjects"`
		Templates   EmailContentConfiguration `json:"templates"`
		URLPaths    EmailContentConfiguration `json:"url_paths"`
	} `json:"mailer"`
	External      ExternalProviderConfiguration `json:"external"`
	DisableSignup bool                          `json:"disable_signup" split_words:"true"`
	SignupHook    WebhookConfig                 `split_words:"true"`
	Cookie        struct {
		Key      string `json:"key"`
		Duration int    `json:"duration"`
	} `json:"cookies"`
}

func loadEnvironment(filename string) error {
	var err error
	if filename != "" {
		err = godotenv.Load(filename)
	} else {
		err = godotenv.Load()
		// handle if .env file does not exist, this is OK
		if os.IsNotExist(err) {
			return nil
		}
	}
	return err
}

type WebhookConfig struct {
	URL        string
	Retries    int
	TimeoutSec int
}

// LoadGlobal loads configuration from file and environment variables.
func LoadGlobal(filename string) (*GlobalConfiguration, error) {
	if err := loadEnvironment(filename); err != nil {
		return nil, err
	}

	config := new(GlobalConfiguration)
	if err := envconfig.Process("gotrue", config); err != nil {
		return nil, err
	}

	if _, err := nconf.ConfigureLogging(&config.Logging); err != nil {
		return nil, err
	}

	if config.SMTP.MaxFrequency == 0 {
		config.SMTP.MaxFrequency = 15 * time.Minute
	}
	return config, nil
}

// LoadConfig loads per-instance configuration.
func LoadConfig(filename string) (*Configuration, error) {
	if err := loadEnvironment(filename); err != nil {
		return nil, err
	}

	config := new(Configuration)
	if err := envconfig.Process("gotrue", config); err != nil {
		return nil, err
	}
	config.ApplyDefaults()
	return config, nil
}

// ApplyDefaults sets defaults for a Configuration
func (config *Configuration) ApplyDefaults() {
	if config.JWT.AdminGroupName == "" {
		config.JWT.AdminGroupName = "admin"
	}

	if config.JWT.Exp == 0 {
		config.JWT.Exp = 3600
	}

	if config.Mailer.URLPaths.Invite == "" {
		config.Mailer.URLPaths.Invite = "/"
	}
	if config.Mailer.URLPaths.Confirmation == "" {
		config.Mailer.URLPaths.Confirmation = "/"
	}
	if config.Mailer.URLPaths.Recovery == "" {
		config.Mailer.URLPaths.Recovery = "/"
	}
	if config.Mailer.URLPaths.EmailChange == "" {
		config.Mailer.URLPaths.EmailChange = "/"
	}

	if config.SMTP.MaxFrequency == 0 {
		config.SMTP.MaxFrequency = 15 * time.Minute
	}

	if config.Cookie.Key == "" {
		config.Cookie.Key = "nf_jwt"
	}

	if config.Cookie.Duration == 0 {
		config.Cookie.Duration = 86400
	}
}

func (o *OAuthProviderConfiguration) Validate() error {
	if !o.Enabled {
		return errors.New("Provider is not enabled")
	}
	if o.ClientID == "" {
		return errors.New("Missing Oauth client ID")
	}
	if o.Secret == "" {
		return errors.New("Missing Oauth secret")
	}
	if o.RedirectURI == "" {
		return errors.New("Missing redirect URI")
	}
	return nil
}
<commit_msg>add json tags<commit_after>package conf

import (
	"errors"
	"os"
	"time"

	"github.com/joho/godotenv"
	"github.com/kelseyhightower/envconfig"
	"github.com/netlify/netlify-commons/nconf"
)

// OAuthProviderConfiguration holds all config related to external account providers.
type OAuthProviderConfiguration struct {
	ClientID    string `json:"client_id" split_words:"true"`
	Secret      string `json:"secret"`
	RedirectURI string `json:"redirect_uri" split_words:"true"`
	URL         string `json:"url"`
	Enabled     bool   `json:"enabled"`
}

// DBConfiguration holds all the database related configuration.
type DBConfiguration struct {
	Dialect     string `json:"dialect"`
	Driver      string `json:"driver" required:"true"`
	URL         string `json:"url" envconfig:"DATABASE_URL" required:"true"`
	Namespace   string `json:"namespace"`
	Automigrate bool   `json:"automigrate"`
}

// JWTConfiguration holds all the JWT related configuration.
type JWTConfiguration struct {
	Secret           string `json:"secret" required:"true"`
	Exp              int    `json:"exp"`
	Aud              string `json:"aud"`
	AdminGroupName   string `json:"admin_group_name" split_words:"true"`
	DefaultGroupName string `json:"default_group_name" split_words:"true"`
}

// GlobalConfiguration holds all the configuration that applies to all instances.
type GlobalConfiguration struct {
	API struct {
		Host     string
		Port     int `envconfig:"PORT" default:"8081"`
		Endpoint string
	}
	DB                DBConfiguration
	External          ExternalProviderConfiguration
	Logging           nconf.LoggingConfig `envconfig:"LOG"`
	OperatorToken     string              `split_words:"true" required:"true"`
	MultiInstanceMode bool
	SMTP              SMTPConfiguration
}

// EmailContentConfiguration holds the configuration for emails, both subjects and template URLs.
type EmailContentConfiguration struct {
	Invite       string `json:"invite"`
	Confirmation string `json:"confirmation"`
	Recovery     string `json:"recovery"`
	EmailChange  string `json:"email_change" split_words:"true"`
}

type ExternalProviderConfiguration struct {
	Bitbucket   OAuthProviderConfiguration `json:"bitbucket"`
	Github      OAuthProviderConfiguration `json:"github"`
	Gitlab      OAuthProviderConfiguration `json:"gitlab"`
	Google      OAuthProviderConfiguration `json:"google"`
	Facebook    OAuthProviderConfiguration `json:"facebook"`
	RedirectURL string                     `json:"redirect_url"`
}

type SMTPConfiguration struct {
	MaxFrequency time.Duration `json:"max_frequency" split_words:"true"`
	Host         string        `json:"host"`
	Port         int           `json:"port" default:"587"`
	User         string        `json:"user"`
	Pass         string        `json:"pass"`
	AdminEmail   string        `json:"admin_email" split_words:"true"`
}

// Configuration holds all the per-instance configuration.
type Configuration struct {
	SiteURL string            `json:"site_url" split_words:"true" required:"true"`
	JWT     JWTConfiguration  `json:"jwt"`
	SMTP    SMTPConfiguration `json:"smtp"`
	Mailer  struct {
		Autoconfirm bool                      `json:"autoconfirm"`
		Subjects    EmailContentConfiguration `json:"subjects"`
		Templates   EmailContentConfiguration `json:"templates"`
		URLPaths    EmailContentConfiguration `json:"url_paths"`
	} `json:"mailer"`
	External      ExternalProviderConfiguration `json:"external"`
	DisableSignup bool                          `json:"disable_signup" split_words:"true"`
	SignupHook    WebhookConfig                 `json:"signup_hook" split_words:"true"`
	Cookie        struct {
		Key      string `json:"key"`
		Duration int    `json:"duration"`
	} `json:"cookies"`
}

func loadEnvironment(filename string) error {
	var err error
	if filename != "" {
		err = godotenv.Load(filename)
	} else {
		err = godotenv.Load()
		// handle if .env file does not exist, this is OK
		if os.IsNotExist(err) {
			return nil
		}
	}
	return err
}

type WebhookConfig struct {
	URL        string `json:"url"`
	Retries    int    `json:"retries"`
	TimeoutSec int    `json:"timeout_sec"`
}

// LoadGlobal loads configuration from file and environment variables.
func LoadGlobal(filename string) (*GlobalConfiguration, error) {
	if err := loadEnvironment(filename); err != nil {
		return nil, err
	}

	config := new(GlobalConfiguration)
	if err := envconfig.Process("gotrue", config); err != nil {
		return nil, err
	}

	if _, err := nconf.ConfigureLogging(&config.Logging); err != nil {
		return nil, err
	}

	if config.SMTP.MaxFrequency == 0 {
		config.SMTP.MaxFrequency = 15 * time.Minute
	}
	return config, nil
}

// LoadConfig loads per-instance configuration.
func LoadConfig(filename string) (*Configuration, error) {
	if err := loadEnvironment(filename); err != nil {
		return nil, err
	}

	config := new(Configuration)
	if err := envconfig.Process("gotrue", config); err != nil {
		return nil, err
	}
	config.ApplyDefaults()
	return config, nil
}

// ApplyDefaults sets defaults for a Configuration
func (config *Configuration) ApplyDefaults() {
	if config.JWT.AdminGroupName == "" {
		config.JWT.AdminGroupName = "admin"
	}

	if config.JWT.Exp == 0 {
		config.JWT.Exp = 3600
	}

	if config.Mailer.URLPaths.Invite == "" {
		config.Mailer.URLPaths.Invite = "/"
	}
	if config.Mailer.URLPaths.Confirmation == "" {
		config.Mailer.URLPaths.Confirmation = "/"
	}
	if config.Mailer.URLPaths.Recovery == "" {
		config.Mailer.URLPaths.Recovery = "/"
	}
	if config.Mailer.URLPaths.EmailChange == "" {
		config.Mailer.URLPaths.EmailChange = "/"
	}

	if config.SMTP.MaxFrequency == 0 {
		config.SMTP.MaxFrequency = 15 * time.Minute
	}

	if config.Cookie.Key == "" {
		config.Cookie.Key = "nf_jwt"
	}

	if config.Cookie.Duration == 0 {
		config.Cookie.Duration = 86400
	}
}

func (o *OAuthProviderConfiguration) Validate() error {
	if !o.Enabled {
		return errors.New("Provider is not enabled")
	}
	if o.ClientID == "" {
		return errors.New("Missing Oauth client ID")
	}
	if o.Secret == "" {
		return errors.New("Missing Oauth secret")
	}
	if o.RedirectURI == "" {
		return errors.New("Missing redirect URI")
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"

	"github.com/rosenhouse/cf-filler/creds"
	"github.com/rosenhouse/cf-filler/vars"
)

const (
	CfgNone             = 0
	CfgWithSubdomainURI = 1 << iota
	CfgWithHTTPSURL
)

type DeploymentVars map[string]interface{}

func (o DeploymentVars) GeneratePasswords(keynames ...string) {
	for _, name := range keynames {
		o[name] = creds.NewPassword()
	}
}

func (o DeploymentVars) GeneratePasswordArray(keyName string, numKeys int) {
	var passwords []string
	for i := 0; i < numKeys; i++ {
		passwords = append(passwords, creds.NewPassword())
	}
	o[keyName] = passwords
}

func (o DeploymentVars) GenerateBasicKeyPair(plainKeyPair *vars.BasicKeyPair) error {
	private, public, err := creds.NewRSAKeyPair()
	if err != nil {
		return fmt.Errorf("create RSA key pair: %s", err)
	}

	o[plainKeyPair.VarName_PublicKey] = public
	o[plainKeyPair.VarName_PrivateKey] = private
	return nil
}

func (o DeploymentVars) GenerateCerts(desiredCertSet *vars.CertSet) error {
	ca, err := creds.NewCA(desiredCertSet.CA.CommonName)
	if err != nil {
		return fmt.Errorf("init ca: %s", err)
	}

	if len(desiredCertSet.CA.VarName_CA) > 0 {
		o[desiredCertSet.CA.VarName_CA] = ca.CertPEM
	}

	for _, ckp := range desiredCertSet.CertKeyPairs {
		private, cert, err := ca.NewCertKeyPair(ckp.CommonName, ckp.Domains)
		if err != nil {
			return err
		}
		o[ckp.VarName_Cert] = cert
		o[ckp.VarName_Key] = private
	}

	return nil
}

func (o DeploymentVars) GenerateSSHKeyAndFingerprint(keyName string, fingerprintName string) error {
	sshPrivateKey, sshKeyFingerprint, err := creds.NewSSHKeyAndFingerprint()
	if err != nil {
		return fmt.Errorf("generate ssh key and fingerprint: %s", err)
	}

	o[keyName] = sshPrivateKey
	o[fingerprintName] = sshKeyFingerprint
	return nil
}
<commit_msg>Remove unused constants<commit_after>package main

import (
	"fmt"

	"github.com/rosenhouse/cf-filler/creds"
	"github.com/rosenhouse/cf-filler/vars"
)

type DeploymentVars map[string]interface{}

func (o DeploymentVars) GeneratePasswords(keynames ...string) {
	for _, name := range keynames {
		o[name] = creds.NewPassword()
	}
}

func (o DeploymentVars) GeneratePasswordArray(keyName string, numKeys int) {
	var passwords []string
	for i := 0; i < numKeys; i++ {
		passwords = append(passwords, creds.NewPassword())
	}
	o[keyName] = passwords
}

func (o DeploymentVars) GenerateBasicKeyPair(plainKeyPair *vars.BasicKeyPair) error {
	private, public, err := creds.NewRSAKeyPair()
	if err != nil {
		return fmt.Errorf("create RSA key pair: %s", err)
	}

	o[plainKeyPair.VarName_PublicKey] = public
	o[plainKeyPair.VarName_PrivateKey] = private
	return nil
}

func (o DeploymentVars) GenerateCerts(desiredCertSet *vars.CertSet) error {
	ca, err := creds.NewCA(desiredCertSet.CA.CommonName)
	if err != nil {
		return fmt.Errorf("init ca: %s", err)
	}

	if len(desiredCertSet.CA.VarName_CA) > 0 {
		o[desiredCertSet.CA.VarName_CA] = ca.CertPEM
	}

	for _, ckp := range desiredCertSet.CertKeyPairs {
		private, cert, err := ca.NewCertKeyPair(ckp.CommonName, ckp.Domains)
		if err != nil {
			return err
		}
		o[ckp.VarName_Cert] = cert
		o[ckp.VarName_Key] = private
	}

	return nil
}

func (o DeploymentVars) GenerateSSHKeyAndFingerprint(keyName string, fingerprintName string) error {
	sshPrivateKey, sshKeyFingerprint, err := creds.NewSSHKeyAndFingerprint()
	if err != nil {
		return fmt.Errorf("generate ssh key and fingerprint: %s", err)
	}

	o[keyName] = sshPrivateKey
	o[fingerprintName] = sshKeyFingerprint
	return nil
}
<|endoftext|>


<commit_before>// Geometry package implementing points, vectors, lines, planes, and triangles.
//
// Angles are in radians with zero being the positive x axis and positive
// corresponding to the counter-clockwise direction.
package geometry

import (
	"math"
)

// Check if a and b are very close.
func FuzzyEqual(a, b float64) bool {
	return math.Abs(a-b) <= 0.000000000001*math.Min(math.Abs(a), math.Abs(b))
}

// Clamp a such that it is at least min and no more than max.
func Clamp(a, min, max float64) float64 {
	if a < min {
		return min
	}
	if a > max {
		return max
	}
	return a
}

// Linear interpolation between x and y. With a == 0 corresponding to x and
// a == 1 corresponding to y.
func Mix(x, y, a float64) float64 {
	return x*(1-a) + y*a
}
<commit_msg>Cleaned up a bit.<commit_after>// Package geometry contains gemoetric primitives.
//
// Angles are in radians.
package geometry

import (
	"math"
)

// Check if a and b are very close.
func FuzzyEqual(a, b float64) bool {
	return math.Abs(a-b) <= 0.000000000001*math.Min(math.Abs(a), math.Abs(b))
}
<|endoftext|>


<commit_before>package get

import (
	"encoding/xml"
	"net/http"
)

type Repomd struct {
	Data []Data `xml:"data"`
}

type Data struct {
	Type     string   `xml:"type,attr"`
	Location Location `xml:"location"`
}

type Location struct {
	Href string `xml:"href,attr"`
}

// Get downloads one repo and returns its metadata
func Get(url string, storage *Storage) (repo map[string]string, err error) {
	resp, err := http.Get(url + "/repodata/repomd.xml")
	if err != nil {
		return
	}

	storingReader, err := storage.NewStoringReader("/repodata/repomd.xml", resp.Body)
	if err != nil {
		return
	}
	defer storingReader.Close()

	decoder := xml.NewDecoder(storingReader)
	var repomd Repomd
	err = decoder.Decode(&repomd)

	data := repomd.Data
	repo = make(map[string]string)
	for i := 0; i < len(data); i++ {
		repo[data[i].Type] = data[i].Location.Href
	}

	return
}
<commit_msg>Refactoring: extract constant<commit_after>package get

import (
	"encoding/xml"
	"net/http"
)

type Repomd struct {
	Data []Data `xml:"data"`
}

type Data struct {
	Type     string   `xml:"type,attr"`
	Location Location `xml:"location"`
}

type Location struct {
	Href string `xml:"href,attr"`
}

const repomdLocation = "/repodata/repomd.xml"

// Get downloads one repo and returns its metadata
func Get(url string, storage *Storage) (repo map[string]string, err error) {
	resp, err := http.Get(url + repomdLocation)
	if err != nil {
		return
	}

	storingReader, err := storage.NewStoringReader(repomdLocation, resp.Body)
	if err != nil {
		return
	}
	defer storingReader.Close()

	decoder := xml.NewDecoder(storingReader)
	var repomd Repomd
	err = decoder.Decode(&repomd)

	data := repomd.Data
	repo = make(map[string]string)
	for i := 0; i < len(data); i++ {
		repo[data[i].Type] = data[i].Location.Href
	}

	return
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"sync"

	log "github.com/Sirupsen/logrus"
	"github.com/datasektionen/taitan/fuzz"
	"github.com/datasektionen/taitan/pages"
)

var (
	debug     bool   // Show debug level messages.
	info      bool   // Show info level messages.
	responses Atomic // Our parsed responses.
)

func usage() {
	fmt.Fprintf(os.Stderr, "Usage: %s [OPTIONS] ROOT\n", os.Args[0])
	flag.PrintDefaults()
	os.Exit(1)
}

func init() {
	flag.BoolVar(&debug, "vv", false, "Print debug messages.")
	flag.BoolVar(&info, "v", false, "Print info messages.")
	flag.Usage = usage
	flag.Parse()
}

func getEnv(env string) string {
	e := os.Getenv(env)
	if e == "" {
		log.Fatalf("$%s environmental variable is not set.\n", env)
	}
	return e
}

func getRoot() string {
	content := getEnv("CONTENT_URL")
	u, err := url.Parse(content)
	if err != nil {
		log.Fatalln("getContent: ", err)
	}

	// https://<token>@github.com/username/repo.git
	u.User = url.User(getEnv("TOKEN"))

	base := filepath.Base(u.Path)
	return strings.TrimSuffix(base, filepath.Ext(base))
}

func getContent() {
	content := getEnv("CONTENT_URL")
	u, err := url.Parse(content)
	if err != nil {
		log.Fatalln("getContent: ", err)
	}

	// https://<token>@github.com/username/repo.git
	u.User = url.User(getEnv("TOKEN"))

	root := getRoot()
	if _, err = os.Stat(root); os.IsNotExist(err) {
		runGit("clone", []string{"clone", u.String()})
	} else {
		runGit("pull", []string{"-C", root, "pull"})
	}
}

func runGit(action string, args []string) {
	log.Infof("Found root directory - %sing updates!", action)
	log.Debugf("Commands %#v!", args)
	cmd := exec.Command("git", args...)
	err := cmd.Start()
	if err != nil {
		log.Fatal(err)
	}
	log.Infof("Waiting for git %s to finish...", action)
	err = cmd.Wait()
	if err != nil {
		log.Warnf("%sed with error: %v\n", action, err)
	}
	log.Infof("Git %s finished!", action)
}

// setVerbosity sets the amount of messages printed.
func setVerbosity() {
	switch {
	case debug:
		log.SetLevel(log.DebugLevel)
	case info:
		log.SetLevel(log.InfoLevel)
	default:
		log.SetLevel(log.WarnLevel)
	}
}

// Atomic responses.
type Atomic struct {
	sync.Mutex
	Resps map[string]*pages.Resp
}

func validRoot(root string) {
	fi, err := os.Stat(root)
	if err != nil {
		if os.IsNotExist(err) {
			log.Fatalf("Directory doesn't exist: %q", root)
		}
		log.Fatalln(err)
	}
	if !fi.IsDir() {
		log.Fatalf("Supplied path is not a directory: %q", root)
	}
}

var jumpfile map[string]interface{}

func main() {
	setVerbosity()

	// Get port or die.
	port := getEnv("PORT")

	// Get content or die.
	getContent()

	root := getRoot()
	log.WithField("Root", root).Info("Our root directory")

	// We'll parse and store the responses ahead of time.
	resps, err := pages.Load(root)
	if err != nil {
		log.Fatalf("pages.Load: unexpected error: %s", err)
	}
	log.WithField("Resps", resps).Debug("The parsed responses")
	responses = Atomic{Resps: resps}

	log.Info("Starting server.")
	log.Info("Listening on port: ", port)

	buf, err := ioutil.ReadFile("jumpfile.json")
	if err != nil {
		log.Fatalf("jumpfile readfile: unexpected error: %s", err)
	}
	err = json.Unmarshal(buf, &jumpfile)
	if err != nil {
		log.Fatalf("jumpfile unmarshal: unexpected error: %s", err)
	}
	log.Debugln(jumpfile)

	// Our request handler.
	http.HandleFunc("/", handler)

	// Listen on port and serve with our handler.
	err = http.ListenAndServe(":"+port, nil)
	if err != nil {
		panic(err)
	}
}

type Subs struct {
	Children []string `json:"children"`
}

// handler parses and serves responses to our file queries.
func handler(res http.ResponseWriter, req *http.Request) {
	if v, ok := jumpfile[req.URL.Path]; ok {
		req.URL.Path = v.(string)
		http.Redirect(res, req, req.URL.String(), http.StatusSeeOther)
		log.Infoln("Redirect: " + req.URL.String())
		return
	}
	if req.URL.Path == "/fuzzyfile" {
		log.Info("Fuzzyfile")
		buf, err := json.Marshal(fuzz.NewFile(responses.Resps))
		if err != nil {
			log.Warnf("handler: unexpected error: %#v\n", err)
			res.WriteHeader(http.StatusInternalServerError)

			return
		}
		log.Debugf("Response: %#v\n", string(buf))
		res.Header().Set("Content-Type", "application/json; charset=utf-8")
		res.Write(buf)
		return
	}
	if req.Header.Get("X-Github-Event") == "push" {
		var err error
		log.Infoln("Push hook")
		getContent()
		responses.Lock()
		responses.Resps, err = pages.Load(getRoot())
		if err != nil {
			log.Error(err)
		}
		responses.Unlock()
		return
	}
	// Requested URL. We extract the path.
	query := req.URL.Path
	log.WithField("query", query).Info("Recieved query")

	clean := filepath.Clean(query)
	log.WithField("clean", clean).Info("Sanitized path")

	responses.Lock()
	r, ok := responses.Resps[clean]
	responses.Unlock()
	if !ok {
		log.WithField("page", clean).Warn("Page doesn't exist")
		res.WriteHeader(http.StatusNotFound)
		return
	}
	log.Info("Marshaling the response.")

	ps := make([]string, 0)
	if _, ok := req.URL.Query()["subpages"]; ok {
		for p := range responses.Resps {
			if strings.HasPrefix(p, req.URL.Path) && p != req.URL.Path {
				ps = append(ps, p)
			}
		}
		log.Warnln(ps)
	}

	r.Children = ps
	buf, err := json.Marshal(r)
	if err != nil {
		log.Warnf("handler: unexpected error: %#v\n", err)
		res.WriteHeader(http.StatusInternalServerError)
		return
	}
	log.Info("Serve the response.")
	log.Debugf("Response: %#v\n", string(buf))
	res.Header().Set("Content-Type", "application/json; charset=utf-8")
	res.Write(buf)
}
<commit_msg>fix jumps<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"sync"

	log "github.com/Sirupsen/logrus"
	"github.com/datasektionen/taitan/fuzz"
	"github.com/datasektionen/taitan/pages"
)

var (
	debug     bool   // Show debug level messages.
	info      bool   // Show info level messages.
	responses Atomic // Our parsed responses.
)

func usage() {
	fmt.Fprintf(os.Stderr, "Usage: %s [OPTIONS] ROOT\n", os.Args[0])
	flag.PrintDefaults()
	os.Exit(1)
}

func init() {
	flag.BoolVar(&debug, "vv", false, "Print debug messages.")
	flag.BoolVar(&info, "v", false, "Print info messages.")
	flag.Usage = usage
	flag.Parse()
}

func getEnv(env string) string {
	e := os.Getenv(env)
	if e == "" {
		log.Fatalf("$%s environmental variable is not set.\n", env)
	}
	return e
}

func getRoot() string {
	content := getEnv("CONTENT_URL")
	u, err := url.Parse(content)
	if err != nil {
		log.Fatalln("getContent: ", err)
	}

	// https://<token>@github.com/username/repo.git
	u.User = url.User(getEnv("TOKEN"))

	base := filepath.Base(u.Path)
	return strings.TrimSuffix(base, filepath.Ext(base))
}

func getContent() {
	content := getEnv("CONTENT_URL")
	u, err := url.Parse(content)
	if err != nil {
		log.Fatalln("getContent: ", err)
	}

	// https://<token>@github.com/username/repo.git
	u.User = url.User(getEnv("TOKEN"))

	root := getRoot()
	if _, err = os.Stat(root); os.IsNotExist(err) {
		runGit("clone", []string{"clone", u.String()})
	} else {
		runGit("pull", []string{"-C", root, "pull"})
	}
}

func runGit(action string, args []string) {
	log.Infof("Found root directory - %sing updates!", action)
	log.Debugf("Commands %#v!", args)
	cmd := exec.Command("git", args...)
	err := cmd.Start()
	if err != nil {
		log.Fatal(err)
	}
	log.Infof("Waiting for git %s to finish...", action)
	err = cmd.Wait()
	if err != nil {
		log.Warnf("%sed with error: %v\n", action, err)
	}
	log.Infof("Git %s finished!", action)
}

// setVerbosity sets the amount of messages printed.
func setVerbosity() {
	switch {
	case debug:
		log.SetLevel(log.DebugLevel)
	case info:
		log.SetLevel(log.InfoLevel)
	default:
		log.SetLevel(log.WarnLevel)
	}
}

// Atomic responses.
type Atomic struct {
	sync.Mutex
	Resps map[string]*pages.Resp
}

func validRoot(root string) {
	fi, err := os.Stat(root)
	if err != nil {
		if os.IsNotExist(err) {
			log.Fatalf("Directory doesn't exist: %q", root)
		}
		log.Fatalln(err)
	}
	if !fi.IsDir() {
		log.Fatalf("Supplied path is not a directory: %q", root)
	}
}

var jumpfile map[string]interface{}

func main() {
	setVerbosity()

	// Get port or die.
	port := getEnv("PORT")

	// Get content or die.
	getContent()

	root := getRoot()
	log.WithField("Root", root).Info("Our root directory")

	// We'll parse and store the responses ahead of time.
	resps, err := pages.Load(root)
	if err != nil {
		log.Fatalf("pages.Load: unexpected error: %s", err)
	}
	log.WithField("Resps", resps).Debug("The parsed responses")
	responses = Atomic{Resps: resps}

	log.Info("Starting server.")
	log.Info("Listening on port: ", port)

	buf, err := ioutil.ReadFile("jumpfile.json")
	if err != nil {
		log.Fatalf("jumpfile readfile: unexpected error: %s", err)
	}
	err = json.Unmarshal(buf, &jumpfile)
	if err != nil {
		log.Fatalf("jumpfile unmarshal: unexpected error: %s", err)
	}
	log.Debugln(jumpfile)

	// Our request handler.
	http.HandleFunc("/", handler)

	// Listen on port and serve with our handler.
	err = http.ListenAndServe(":"+port, nil)
	if err != nil {
		panic(err)
	}
}

type Subs struct {
	Children []string `json:"children"`
}

// handler parses and serves responses to our file queries.
func handler(res http.ResponseWriter, req *http.Request) {
	if v, ok := jumpfile[filepath.Clean(req.URL.Path)]; ok {
		req.URL.Path = v.(string)
		http.Redirect(res, req, req.URL.String(), http.StatusSeeOther)
		log.Infoln("Redirect: " + req.URL.String())
		return
	}
	if req.URL.Path == "/fuzzyfile" {
		log.Info("Fuzzyfile")
		buf, err := json.Marshal(fuzz.NewFile(responses.Resps))
		if err != nil {
			log.Warnf("handler: unexpected error: %#v\n", err)
			res.WriteHeader(http.StatusInternalServerError)

			return
		}
		log.Debugf("Response: %#v\n", string(buf))
		res.Header().Set("Content-Type", "application/json; charset=utf-8")
		res.Write(buf)
		return
	}
	if req.Header.Get("X-Github-Event") == "push" {
		var err error
		log.Infoln("Push hook")
		getContent()
		responses.Lock()
		responses.Resps, err = pages.Load(getRoot())
		if err != nil {
			log.Error(err)
		}
		responses.Unlock()
		return
	}
	// Requested URL. We extract the path.
	query := req.URL.Path
	log.WithField("query", query).Info("Recieved query")

	clean := filepath.Clean(query)
	log.WithField("clean", clean).Info("Sanitized path")

	responses.Lock()
	r, ok := responses.Resps[clean]
	responses.Unlock()
	if !ok {
		log.WithField("page", clean).Warn("Page doesn't exist")
		res.WriteHeader(http.StatusNotFound)
		return
	}
	log.Info("Marshaling the response.")

	ps := make([]string, 0)
	if _, ok := req.URL.Query()["subpages"]; ok {
		for p := range responses.Resps {
			if strings.HasPrefix(p, req.URL.Path) && p != req.URL.Path {
				ps = append(ps, p)
			}
		}
		log.Warnln(ps)
	}

	r.Children = ps
	buf, err := json.Marshal(r)
	if err != nil {
		log.Warnf("handler: unexpected error: %#v\n", err)
		res.WriteHeader(http.StatusInternalServerError)
		return
	}
	log.Info("Serve the response.")
	log.Debugf("Response: %#v\n", string(buf))
	res.Header().Set("Content-Type", "application/json; charset=utf-8")
	res.Write(buf)
}
<|endoftext|>


<commit_before>package digest

import (
	"fmt"

	"regexp"
)

// TarSumRegexp defines a regular expression to match tarsum identifiers.
var TarsumRegexp = regexp.MustCompile("tarsum(?:.[a-z0-9]+)?\\+[a-zA-Z0-9]+:[A-Fa-f0-9]+")

// TarsumRegexpCapturing defines a regular expression to match tarsum identifiers with
// capture groups corresponding to each component.
var TarsumRegexpCapturing = regexp.MustCompile("(tarsum)(.([a-z0-9]+))?\\+([a-zA-Z0-9]+):([A-Fa-f0-9]+)")

// TarSumInfo contains information about a parsed tarsum.
type TarSumInfo struct {
	// Version contains the version of the tarsum.
	Version string

	// Algorithm contains the algorithm for the final digest
	Algorithm string

	// Digest contains the hex-encoded digest.
	Digest string
}

// InvalidTarSumError provides informations about a TarSum that cannot be parsed
// by ParseTarSum.
type InvalidTarSumError string

func (e InvalidTarSumError) Error() string {
	return fmt.Sprintf("invalid tarsum: %q", string(e))
}

// ParseTarSum parses a tarsum string into its components of interest. For
// example, this method may receive the tarsum in the following format:
//
//		tarsum.v1+sha256:220a60ecd4a3c32c282622a625a54db9ba0ff55b5ba9c29c7064a2bc358b6a3e
//
// The function will return the following:
//
//		TarSumInfo{
//			Version: "v1",
//			Algorithm: "sha256",
//			Digest: "220a60ecd4a3c32c282622a625a54db9ba0ff55b5ba9c29c7064a2bc358b6a3e",
//		}
//
func ParseTarSum(tarSum string) (tsi TarSumInfo, err error) {
	components := TarsumRegexpCapturing.FindStringSubmatch(tarSum)

	if len(components) != 1+TarsumRegexpCapturing.NumSubexp() {
		return TarSumInfo{}, InvalidTarSumError(tarSum)
	}

	return TarSumInfo{
		Version:   components[3],
		Algorithm: components[4],
		Digest:    components[5],
	}, nil
}

// String returns the valid, string representation of the tarsum info.
func (tsi TarSumInfo) String() string {
	if tsi.Version == "" {
		return fmt.Sprintf("tarsum+%s:%s", tsi.Algorithm, tsi.Digest)
	}

	return fmt.Sprintf("tarsum.%s+%s:%s", tsi.Version, tsi.Algorithm, tsi.Digest)
}
<commit_msg>Correct two golint comment issues<commit_after>package digest

import (
	"fmt"

	"regexp"
)

// TarsumRegexp defines a regular expression to match tarsum identifiers.
var TarsumRegexp = regexp.MustCompile("tarsum(?:.[a-z0-9]+)?\\+[a-zA-Z0-9]+:[A-Fa-f0-9]+")

// TarsumRegexpCapturing defines a regular expression to match tarsum identifiers with
// capture groups corresponding to each component.
var TarsumRegexpCapturing = regexp.MustCompile("(tarsum)(.([a-z0-9]+))?\\+([a-zA-Z0-9]+):([A-Fa-f0-9]+)")

// TarSumInfo contains information about a parsed tarsum.
type TarSumInfo struct {
	// Version contains the version of the tarsum.
	Version string

	// Algorithm contains the algorithm for the final digest
	Algorithm string

	// Digest contains the hex-encoded digest.
	Digest string
}

// InvalidTarSumError provides informations about a TarSum that cannot be parsed
// by ParseTarSum.
type InvalidTarSumError string

func (e InvalidTarSumError) Error() string {
	return fmt.Sprintf("invalid tarsum: %q", string(e))
}

// ParseTarSum parses a tarsum string into its components of interest. For
// example, this method may receive the tarsum in the following format:
//
//		tarsum.v1+sha256:220a60ecd4a3c32c282622a625a54db9ba0ff55b5ba9c29c7064a2bc358b6a3e
//
// The function will return the following:
//
//		TarSumInfo{
//			Version: "v1",
//			Algorithm: "sha256",
//			Digest: "220a60ecd4a3c32c282622a625a54db9ba0ff55b5ba9c29c7064a2bc358b6a3e",
//		}
//
func ParseTarSum(tarSum string) (tsi TarSumInfo, err error) {
	components := TarsumRegexpCapturing.FindStringSubmatch(tarSum)

	if len(components) != 1+TarsumRegexpCapturing.NumSubexp() {
		return TarSumInfo{}, InvalidTarSumError(tarSum)
	}

	return TarSumInfo{
		Version:   components[3],
		Algorithm: components[4],
		Digest:    components[5],
	}, nil
}

// String returns the valid, string representation of the tarsum info.
func (tsi TarSumInfo) String() string {
	if tsi.Version == "" {
		return fmt.Sprintf("tarsum+%s:%s", tsi.Algorithm, tsi.Digest)
	}

	return fmt.Sprintf("tarsum.%s+%s:%s", tsi.Version, tsi.Algorithm, tsi.Digest)
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"github.com/seanpont/gobro"
	"os"
	"strings"
	"time"
)

func testReader(args []string) {
	fmt.Print("\033[2J\033[1;1H:\n:\n$ ")

	go func() {
		for i := 0; i < 20; i++ {
			time.Sleep(time.Second)
			print(": hello %v", i)
		}
	}()

	reader := bufio.NewReader(os.Stdin)
	for {
		line, _, err := reader.ReadLine()
		if err != nil {
			return
		}
		fmt.Print("\033[2J\033[1;1H:\n:" + strings.ToUpper(string(line)) + "\n$ ")
	}
}

func print(format string, a ...interface{}) {
	message := fmt.Sprintf(format, a...)
	fmt.Print("\033[s\033[1;1H" + message + "\033[u")
}

func test2(args []string) {
	fmt.Print("\033[2J\033[1;1H")
	fmt.Print("one\ntwo\nthree\n")
	go func() {
		time.Sleep(time.Second)
		fmt.Print("\033[s" + strings.Repeat("\033[A\033[K", 4) + "\033[1;1H" + "four\nfive" + "\033[u")
	}()
	gobro.Prompt("$ ")
}

func main() {
	gobro.NewCommandMap(
		testReader,
		test2,
		simpleTapServer,
		connTapServer,
		connTapClient).Run(os.Args)
}
<commit_msg>cleanup<commit_after>package main

import (
	"github.com/seanpont/gobro"
	"os"
)

func main() {
	gobro.NewCommandMap(
		simpleTapServer,
		connTapServer,
		connTapClient).Run(os.Args)
}
<|endoftext|>


<commit_before>// Copyright 2015 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package kvm

import (
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"sync"
	"time"

	"github.com/google/syzkaller/vm"
)

const hostAddr = "192.168.33.1"
const logOutput = true

func init() {
	vm.Register("kvm", ctor)
}

type kvm struct {
	params
	workdir   string
	crashdir  string
	callsFlag string
	id        int
	mgrPort   int
}

type params struct {
	Lkvm     string
	Kernel   string
	Cmdline  string
	Fuzzer   string
	Executor string
	Cpu      int
	Mem      int
}

func ctor(cfg *vm.Config, index int) (vm.Instance, error) {
	p := new(params)
	if err := json.Unmarshal(cfg.Params, p); err != nil {
		return nil, fmt.Errorf("failed to unmarshal kvm params: %v", err)
	}
	if _, err := os.Stat(p.Kernel); err != nil {
		return nil, fmt.Errorf("kernel '%v' does not exist: %v", p.Kernel, err)
	}
	if _, err := os.Stat(p.Fuzzer); err != nil {
		return nil, fmt.Errorf("fuzzer binary '%v' does not exist: %v", p.Fuzzer, err)
	}
	if _, err := os.Stat(p.Executor); err != nil {
		return nil, fmt.Errorf("executor binary '%v' does not exist: %v", p.Executor, err)
	}
	if p.Lkvm == "" {
		p.Lkvm = "lkvm"
	}
	if p.Cpu <= 0 || p.Cpu > 1024 {
		return nil, fmt.Errorf("bad kvm cpu: %v, want [1-1024]", p.Cpu)
	}
	if p.Mem < 128 || p.Mem > 1048576 {
		return nil, fmt.Errorf("bad kvm mem: %v, want [128-1048576]", p.Mem)
	}

	crashdir := filepath.Join(cfg.Workdir, "crashes")
	os.MkdirAll(crashdir, 0770)

	workdir := filepath.Join(cfg.Workdir, "kvm")
	os.MkdirAll(workdir, 0770)

	vm := &kvm{
		params:   *p,
		workdir:  workdir,
		crashdir: crashdir,
		id:       index,
		mgrPort:  cfg.ManagerPort,
	}

	if cfg.EnabledSyscalls != "" {
		vm.callsFlag = "-calls=" + cfg.EnabledSyscalls
	}

	return vm, nil
}

func (vm *kvm) Run() {
	log.Printf("kvm/%v: started\n", vm.id)
	sandbox := fmt.Sprintf("syz-%v", vm.id)
	sandboxPath := filepath.Join(os.Getenv("HOME"), ".lkvm", sandbox)
	scriptPath := filepath.Join(vm.workdir, sandbox+".sh")
	script := fmt.Sprintf("#! /bin/bash\n/syzkaller_fuzzer -name kvm/%v -executor /syzkaller_executor -manager %v:%v %v\n",
		vm.id, hostAddr, vm.mgrPort, vm.callsFlag)
	if err := ioutil.WriteFile(scriptPath, []byte(script), 0770); err != nil {
		log.Fatalf("failed to create run script: %v", err)
	}
	for run := 0; ; run++ {
		logname := filepath.Join(vm.workdir, fmt.Sprintf("log%v-%v-%v", vm.id, run, time.Now().Unix()))
		var logf *os.File
		if logOutput {
			var err error
			logf, err = os.Create(logname)
			if err != nil {
				log.Printf("failed to create log file: %v", err)
				time.Sleep(10 * time.Second)
				continue
			}
		}
		rpipe, wpipe, err := os.Pipe()
		if err != nil {
			log.Printf("failed to create pipe: %v", err)
			if logf != nil {
				logf.Close()
			}
			time.Sleep(10 * time.Second)
			continue
		}
		os.RemoveAll(sandboxPath)
		out, err := exec.Command(vm.Lkvm, "setup", sandbox).CombinedOutput()
		if err != nil {
			log.Printf("failed to lkvm setup: %v\n%s", err, out)
			if logf != nil {
				logf.Close()
			}
			rpipe.Close()
			wpipe.Close()
			time.Sleep(10 * time.Second)
			continue
		}
		if err := copyFile(vm.Fuzzer, filepath.Join(sandboxPath, "/syzkaller_fuzzer")); err != nil {
			log.Printf("failed to copy file into sandbox: %v", err)
			os.RemoveAll(sandboxPath)
			if logf != nil {
				logf.Close()
			}
			rpipe.Close()
			wpipe.Close()
			time.Sleep(10 * time.Second)
			continue
		}
		if err := copyFile(vm.Executor, filepath.Join(sandboxPath, "/syzkaller_executor")); err != nil {
			log.Printf("failed to copy file into sandbox: %v", err)
			os.RemoveAll(sandboxPath)
			if logf != nil {
				logf.Close()
			}
			rpipe.Close()
			wpipe.Close()
			time.Sleep(10 * time.Second)
			continue
		}
		os.Chmod(filepath.Join(sandboxPath, "/syzkaller_fuzzer"), 0770)
		os.Chmod(filepath.Join(sandboxPath, "/syzkaller_executor"), 0770)
		inst := &Instance{
			id:          vm.id,
			crashdir:    vm.crashdir,
			params:      vm.params,
			name:        fmt.Sprintf("kvm/%v-%v", vm.id, run),
			sandbox:     sandbox,
			sandboxPath: sandboxPath,
			scriptPath:  scriptPath,
			callsFlag:   vm.callsFlag,
			log:         logf,
			rpipe:       rpipe,
			wpipe:       wpipe,
			cmds:        make(map[*Command]bool),
		}
		inst.Run()
		inst.Shutdown()
		time.Sleep(10 * time.Second)
	}
}

type Instance struct {
	params
	sync.Mutex
	id          int
	crashdir    string
	name        string
	sandbox     string
	sandboxPath string
	scriptPath  string
	callsFlag   string
	log         *os.File
	rpipe       *os.File
	wpipe       *os.File
	cmds        map[*Command]bool
	kvm         *Command
}

type Command struct {
	sync.Mutex
	cmd    *exec.Cmd
	done   chan struct{}
	failed bool
	out    []byte
	outpos int
}

func (inst *Instance) Run() {
	var outputMu sync.Mutex
	var output []byte
	go func() {
		var buf [64 << 10]byte
		for {
			n, err := inst.rpipe.Read(buf[:])
			if n != 0 {
				outputMu.Lock()
				output = append(output, buf[:n]...)
				outputMu.Unlock()
				if inst.log != nil {
					inst.log.Write(buf[:n])
				}
			}
			if err != nil {
				break
			}
		}
	}()

	// Start the instance.
	inst.kvm = inst.CreateCommand(
		"taskset", "1",
		inst.Lkvm, "sandbox",
		"--disk", inst.sandbox,
		fmt.Sprintf("--mem=%v", inst.Mem),
		fmt.Sprintf("--cpus=%v", inst.Cpu),
		"--kernel", inst.Kernel,
		"--network", "mode=user",
		"--sandbox", inst.scriptPath,
	)

	start := time.Now()
	deadline := start.Add(time.Hour)
	lastOutput := time.Now()
	lastOutputLen := 0
	matchPos := 0
	crashRe := regexp.MustCompile("\\[ cut here \\]|Kernel panic| BUG: | WARNING: | INFO: |unable to handle kernel NULL pointer dereference|general protection fault")
	const contextSize = 64 << 10
	for range time.NewTicker(5 * time.Second).C {
		outputMu.Lock()
		if lastOutputLen != len(output) {
			lastOutput = time.Now()
		}
		if loc := crashRe.FindAllIndex(output[matchPos:], -1); len(loc) != 0 {
			// Give it some time to finish writing the error message.
			outputMu.Unlock()
			time.Sleep(5 * time.Second)
			outputMu.Lock()
			loc = crashRe.FindAllIndex(output[matchPos:], -1)
			start := loc[0][0] - contextSize
			if start < 0 {
				start = 0
			}
			end := loc[len(loc)-1][1] + contextSize
			if end > len(output) {
				end = len(output)
			}
			inst.SaveCrasher(output[start:end])
		}
		if len(output) > 2*contextSize {
			copy(output, output[len(output)-contextSize:])
			output = output[:contextSize]
		}
		matchPos = len(output) - 128
		if matchPos < 0 {
			matchPos = 0
		}
		lastOutputLen = len(output)
		outputMu.Unlock()

		if time.Since(lastOutput) > 3*time.Minute {
			time.Sleep(time.Second)
			outputMu.Lock()
			output = append(output, "\nno output from fuzzer, restarting\n"...)
			inst.SaveCrasher(output)
			outputMu.Unlock()
			inst.Logf("no output from fuzzer, restarting")
			inst.kvm.cmd.Process.Kill()
			inst.kvm.cmd.Process.Kill()
			return
		}
		if inst.kvm.Exited() {
			time.Sleep(time.Second)
			outputMu.Lock()
			output = append(output, "\nfuzzer binary stopped or lost connection\n"...)
			inst.SaveCrasher(output)
			outputMu.Unlock()
			inst.Logf("fuzzer binary stopped or lost connection")
			return
		}
		if time.Now().After(deadline) {
			inst.Logf("running for long enough, restarting")
			inst.kvm.cmd.Process.Kill()
			inst.kvm.cmd.Process.Kill()
			return
		}
	}
}

func (inst *Instance) SaveCrasher(output []byte) {
	ioutil.WriteFile(filepath.Join(inst.crashdir, fmt.Sprintf("crash%v-%v", inst.id, time.Now().UnixNano())), output, 0660)
}

func (inst *Instance) Shutdown() {
	defer func() {
		os.RemoveAll(inst.sandboxPath)
		inst.rpipe.Close()
		inst.wpipe.Close()
		if inst.log != nil {
			inst.log.Close()
		}
	}()
	if inst.kvm.cmd == nil {
		// CreateCommand should have been failed very early.
		return
	}
	for try := 0; try < 10; try++ {
		inst.kvm.cmd.Process.Kill()
		time.Sleep(time.Second)
		inst.Lock()
		n := len(inst.cmds)
		inst.Unlock()
		if n == 0 {
			return
		}
	}
	inst.Logf("hanged processes after kill")
	inst.Lock()
	for cmd := range inst.cmds {
		cmd.cmd.Process.Kill()
		cmd.cmd.Process.Kill()
	}
	inst.Unlock()
	time.Sleep(3 * time.Second)
}

func (inst *Instance) CreateCommand(args ...string) *Command {
	if inst.log != nil {
		fmt.Fprintf(inst.log, "executing command: %v\n", args)
	}
	cmd := &Command{}
	cmd.done = make(chan struct{})
	cmd.cmd = exec.Command(args[0], args[1:]...)
	cmd.cmd.Stdout = inst.wpipe
	cmd.cmd.Stderr = inst.wpipe
	if err := cmd.cmd.Start(); err != nil {
		inst.Logf("failed to start command '%v': %v\n", args, err)
		cmd.failed = true
		close(cmd.done)
		return cmd
	}
	inst.Lock()
	inst.cmds[cmd] = true
	inst.Unlock()
	go func() {
		err := cmd.cmd.Wait()
		inst.Lock()
		delete(inst.cmds, cmd)
		inst.Unlock()
		if inst.log != nil {
			fmt.Fprintf(inst.log, "command '%v' exited: %v\n", args, err)
		}
		cmd.failed = err != nil
		close(cmd.done)
	}()
	return cmd
}

func (inst *Instance) Logf(str string, args ...interface{}) {
	fmt.Fprintf(inst.wpipe, str+"\n", args...)
	log.Printf("%v: "+str, append([]interface{}{inst.name}, args...)...)
}

func (cmd *Command) Wait(max time.Duration) bool {
	select {
	case <-cmd.done:
		return !cmd.failed
	case <-time.After(max):
		return false
	}
}

func (cmd *Command) Exited() bool {
	select {
	case <-cmd.done:
		return true
	default:
		return false
	}
}

func copyFile(oldfn, newfn string) error {
	oldf, err := os.Open(oldfn)
	if err != nil {
		return err
	}
	defer oldf.Close()
	newf, err := os.Create(newfn)
	if err != nil {
		return err
	}
	defer newf.Close()
	_, err = io.Copy(newf, oldf)
	if err != nil {
		return err
	}
	return nil
}
<commit_msg>fix crash report extraction from logs<commit_after>// Copyright 2015 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package kvm

import (
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"sync"
	"time"

	"github.com/google/syzkaller/vm"
)

const hostAddr = "192.168.33.1"
const logOutput = true

func init() {
	vm.Register("kvm", ctor)
}

type kvm struct {
	params
	workdir   string
	crashdir  string
	callsFlag string
	id        int
	mgrPort   int
}

type params struct {
	Lkvm     string
	Kernel   string
	Cmdline  string
	Fuzzer   string
	Executor string
	Cpu      int
	Mem      int
}

func ctor(cfg *vm.Config, index int) (vm.Instance, error) {
	p := new(params)
	if err := json.Unmarshal(cfg.Params, p); err != nil {
		return nil, fmt.Errorf("failed to unmarshal kvm params: %v", err)
	}
	if _, err := os.Stat(p.Kernel); err != nil {
		return nil, fmt.Errorf("kernel '%v' does not exist: %v", p.Kernel, err)
	}
	if _, err := os.Stat(p.Fuzzer); err != nil {
		return nil, fmt.Errorf("fuzzer binary '%v' does not exist: %v", p.Fuzzer, err)
	}
	if _, err := os.Stat(p.Executor); err != nil {
		return nil, fmt.Errorf("executor binary '%v' does not exist: %v", p.Executor, err)
	}
	if p.Lkvm == "" {
		p.Lkvm = "lkvm"
	}
	if p.Cpu <= 0 || p.Cpu > 1024 {
		return nil, fmt.Errorf("bad kvm cpu: %v, want [1-1024]", p.Cpu)
	}
	if p.Mem < 128 || p.Mem > 1048576 {
		return nil, fmt.Errorf("bad kvm mem: %v, want [128-1048576]", p.Mem)
	}

	crashdir := filepath.Join(cfg.Workdir, "crashes")
	os.MkdirAll(crashdir, 0770)

	workdir := filepath.Join(cfg.Workdir, "kvm")
	os.MkdirAll(workdir, 0770)

	vm := &kvm{
		params:   *p,
		workdir:  workdir,
		crashdir: crashdir,
		id:       index,
		mgrPort:  cfg.ManagerPort,
	}

	if cfg.EnabledSyscalls != "" {
		vm.callsFlag = "-calls=" + cfg.EnabledSyscalls
	}

	return vm, nil
}

func (vm *kvm) Run() {
	log.Printf("kvm/%v: started\n", vm.id)
	sandbox := fmt.Sprintf("syz-%v", vm.id)
	sandboxPath := filepath.Join(os.Getenv("HOME"), ".lkvm", sandbox)
	scriptPath := filepath.Join(vm.workdir, sandbox+".sh")
	script := fmt.Sprintf("#! /bin/bash\n/syzkaller_fuzzer -name kvm/%v -executor /syzkaller_executor -manager %v:%v %v\n",
		vm.id, hostAddr, vm.mgrPort, vm.callsFlag)
	if err := ioutil.WriteFile(scriptPath, []byte(script), 0770); err != nil {
		log.Fatalf("failed to create run script: %v", err)
	}
	for run := 0; ; run++ {
		logname := filepath.Join(vm.workdir, fmt.Sprintf("log%v-%v-%v", vm.id, run, time.Now().Unix()))
		var logf *os.File
		if logOutput {
			var err error
			logf, err = os.Create(logname)
			if err != nil {
				log.Printf("failed to create log file: %v", err)
				time.Sleep(10 * time.Second)
				continue
			}
		}
		rpipe, wpipe, err := os.Pipe()
		if err != nil {
			log.Printf("failed to create pipe: %v", err)
			if logf != nil {
				logf.Close()
			}
			time.Sleep(10 * time.Second)
			continue
		}
		os.RemoveAll(sandboxPath)
		out, err := exec.Command(vm.Lkvm, "setup", sandbox).CombinedOutput()
		if err != nil {
			log.Printf("failed to lkvm setup: %v\n%s", err, out)
			if logf != nil {
				logf.Close()
			}
			rpipe.Close()
			wpipe.Close()
			time.Sleep(10 * time.Second)
			continue
		}
		if err := copyFile(vm.Fuzzer, filepath.Join(sandboxPath, "/syzkaller_fuzzer")); err != nil {
			log.Printf("failed to copy file into sandbox: %v", err)
			os.RemoveAll(sandboxPath)
			if logf != nil {
				logf.Close()
			}
			rpipe.Close()
			wpipe.Close()
			time.Sleep(10 * time.Second)
			continue
		}
		if err := copyFile(vm.Executor, filepath.Join(sandboxPath, "/syzkaller_executor")); err != nil {
			log.Printf("failed to copy file into sandbox: %v", err)
			os.RemoveAll(sandboxPath)
			if logf != nil {
				logf.Close()
			}
			rpipe.Close()
			wpipe.Close()
			time.Sleep(10 * time.Second)
			continue
		}
		os.Chmod(filepath.Join(sandboxPath, "/syzkaller_fuzzer"), 0770)
		os.Chmod(filepath.Join(sandboxPath, "/syzkaller_executor"), 0770)
		inst := &Instance{
			id:          vm.id,
			crashdir:    vm.crashdir,
			params:      vm.params,
			name:        fmt.Sprintf("kvm/%v-%v", vm.id, run),
			sandbox:     sandbox,
			sandboxPath: sandboxPath,
			scriptPath:  scriptPath,
			callsFlag:   vm.callsFlag,
			log:         logf,
			rpipe:       rpipe,
			wpipe:       wpipe,
			cmds:        make(map[*Command]bool),
		}
		inst.Run()
		inst.Shutdown()
		time.Sleep(10 * time.Second)
	}
}

type Instance struct {
	params
	sync.Mutex
	id          int
	crashdir    string
	name        string
	sandbox     string
	sandboxPath string
	scriptPath  string
	callsFlag   string
	log         *os.File
	rpipe       *os.File
	wpipe       *os.File
	cmds        map[*Command]bool
	kvm         *Command
}

type Command struct {
	sync.Mutex
	cmd    *exec.Cmd
	done   chan struct{}
	failed bool
	out    []byte
	outpos int
}

func (inst *Instance) Run() {
	var outputMu sync.Mutex
	var output []byte
	go func() {
		var buf [64 << 10]byte
		for {
			n, err := inst.rpipe.Read(buf[:])
			if n != 0 {
				outputMu.Lock()
				output = append(output, buf[:n]...)
				outputMu.Unlock()
				if inst.log != nil {
					inst.log.Write(buf[:n])
				}
			}
			if err != nil {
				break
			}
		}
	}()

	// Start the instance.
	inst.kvm = inst.CreateCommand(
		"taskset", "1",
		inst.Lkvm, "sandbox",
		"--disk", inst.sandbox,
		fmt.Sprintf("--mem=%v", inst.Mem),
		fmt.Sprintf("--cpus=%v", inst.Cpu),
		"--kernel", inst.Kernel,
		"--network", "mode=user",
		"--sandbox", inst.scriptPath,
	)

	start := time.Now()
	deadline := start.Add(time.Hour)
	lastOutput := time.Now()
	lastOutputLen := 0
	matchPos := 0
	crashRe := regexp.MustCompile("\\[ cut here \\]|Kernel panic| BUG: | WARNING: | INFO: |unable to handle kernel NULL pointer dereference|general protection fault")
	const contextSize = 64 << 10
	for range time.NewTicker(5 * time.Second).C {
		outputMu.Lock()
		if lastOutputLen != len(output) {
			lastOutput = time.Now()
		}
		if loc := crashRe.FindAllIndex(output[matchPos:], -1); len(loc) != 0 {
			// Give it some time to finish writing the error message.
			outputMu.Unlock()
			time.Sleep(5 * time.Second)
			outputMu.Lock()
			output = output[matchPos:]
			loc = crashRe.FindAllIndex(output, -1)
			start := loc[0][0] - contextSize
			if start < 0 {
				start = 0
			}
			end := loc[len(loc)-1][1] + contextSize
			if end > len(output) {
				end = len(output)
			}
			text := append(output[start:end:end], "\n\nfound crasher:\n"...)
			text = append(text, output[loc[0][0]:loc[0][1]]...)
			inst.SaveCrasher(text)
		}
		if len(output) > 2*contextSize {
			copy(output, output[len(output)-contextSize:])
			output = output[:contextSize]
		}
		matchPos = len(output) - 128
		if matchPos < 0 {
			matchPos = 0
		}
		lastOutputLen = len(output)
		outputMu.Unlock()

		if time.Since(lastOutput) > 3*time.Minute {
			time.Sleep(time.Second)
			outputMu.Lock()
			output = append(output, "\nno output from fuzzer, restarting\n"...)
			inst.SaveCrasher(output)
			outputMu.Unlock()
			inst.Logf("no output from fuzzer, restarting")
			inst.kvm.cmd.Process.Kill()
			inst.kvm.cmd.Process.Kill()
			return
		}
		if inst.kvm.Exited() {
			time.Sleep(time.Second)
			outputMu.Lock()
			output = append(output, "\nfuzzer binary stopped or lost connection\n"...)
			inst.SaveCrasher(output)
			outputMu.Unlock()
			inst.Logf("fuzzer binary stopped or lost connection")
			return
		}
		if time.Now().After(deadline) {
			inst.Logf("running for long enough, restarting")
			inst.kvm.cmd.Process.Kill()
			inst.kvm.cmd.Process.Kill()
			return
		}
	}
}

func (inst *Instance) SaveCrasher(output []byte) {
	ioutil.WriteFile(filepath.Join(inst.crashdir, fmt.Sprintf("crash%v-%v", inst.id, time.Now().UnixNano())), output, 0660)
}

func (inst *Instance) Shutdown() {
	defer func() {
		os.RemoveAll(inst.sandboxPath)
		inst.rpipe.Close()
		inst.wpipe.Close()
		if inst.log != nil {
			inst.log.Close()
		}
	}()
	if inst.kvm.cmd == nil {
		// CreateCommand should have been failed very early.
		return
	}
	for try := 0; try < 10; try++ {
		inst.kvm.cmd.Process.Kill()
		time.Sleep(time.Second)
		inst.Lock()
		n := len(inst.cmds)
		inst.Unlock()
		if n == 0 {
			return
		}
	}
	inst.Logf("hanged processes after kill")
	inst.Lock()
	for cmd := range inst.cmds {
		cmd.cmd.Process.Kill()
		cmd.cmd.Process.Kill()
	}
	inst.Unlock()
	time.Sleep(3 * time.Second)
}

func (inst *Instance) CreateCommand(args ...string) *Command {
	if inst.log != nil {
		fmt.Fprintf(inst.log, "executing command: %v\n", args)
	}
	cmd := &Command{}
	cmd.done = make(chan struct{})
	cmd.cmd = exec.Command(args[0], args[1:]...)
	cmd.cmd.Stdout = inst.wpipe
	cmd.cmd.Stderr = inst.wpipe
	if err := cmd.cmd.Start(); err != nil {
		inst.Logf("failed to start command '%v': %v\n", args, err)
		cmd.failed = true
		close(cmd.done)
		return cmd
	}
	inst.Lock()
	inst.cmds[cmd] = true
	inst.Unlock()
	go func() {
		err := cmd.cmd.Wait()
		inst.Lock()
		delete(inst.cmds, cmd)
		inst.Unlock()
		if inst.log != nil {
			fmt.Fprintf(inst.log, "command '%v' exited: %v\n", args, err)
		}
		cmd.failed = err != nil
		close(cmd.done)
	}()
	return cmd
}

func (inst *Instance) Logf(str string, args ...interface{}) {
	fmt.Fprintf(inst.wpipe, str+"\n", args...)
	log.Printf("%v: "+str, append([]interface{}{inst.name}, args...)...)
}

func (cmd *Command) Wait(max time.Duration) bool {
	select {
	case <-cmd.done:
		return !cmd.failed
	case <-time.After(max):
		return false
	}
}

func (cmd *Command) Exited() bool {
	select {
	case <-cmd.done:
		return true
	default:
		return false
	}
}

func copyFile(oldfn, newfn string) error {
	oldf, err := os.Open(oldfn)
	if err != nil {
		return err
	}
	defer oldf.Close()
	newf, err := os.Create(newfn)
	if err != nil {
		return err
	}
	defer newf.Close()
	_, err = io.Copy(newf, oldf)
	if err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>package vsphere

import "github.com/cloudfoundry/bosh-bootloader/storage"

type TemplateGenerator struct{}

func NewTemplateGenerator() TemplateGenerator {
	return TemplateGenerator{}
}

func (t TemplateGenerator) Generate(state storage.State) string {
	return ""
}
<commit_msg>Add dummy terraform output because terraform output -json exits 1<commit_after>package vsphere

import "github.com/cloudfoundry/bosh-bootloader/storage"

type TemplateGenerator struct{}

func NewTemplateGenerator() TemplateGenerator {
	return TemplateGenerator{}
}

func (t TemplateGenerator) Generate(state storage.State) string {
	return `output "dummy" { value = "dummy" }`
}
<|endoftext|>