<commit_before>package tenho

import (
	"fmt"
	"math/rand"
	"sort"
	"time"
)

func Start() {
	start := time.Now()
	// 処理
	var i float64
	i = 0
	for {
		i++
		end := time.Now()
		diff := float64(end.Sub(start) / 1000 / 1000 / 1000)
		m := int(i / diff)
		out := 0
		if m >= 0 {
			out = m
		}
		fmt.Printf("\r")
		fmt.Printf("\r%v回試行  %v秒経過 %v回/秒", i, diff, out)
		seed := time.Now().UnixNano()
		var hai string
		var ok bool
		hai, ok = tryOnce(seed)
		fmt.Printf("%v", hai)
		if ok {
			break
		}
	}
	fmt.Printf("\n")
}

type Hand []int

func tryOnce(seed int64) (string, bool) {
	hand := ShuffledHand(seed)
	hai := hand.HaiString()
	ok := hand.Solve()
	return hai, ok
}

// http://d.hatena.ne.jp/hake/20150930/p1
func shuffle(hand Hand) {
	for i := len(hand); i > 1; i-- {
		j := rand.Intn(i) // 0 .. i-1 の乱数発生
		hand[i-1], hand[j] = hand[j], hand[i-1]
	}
}

func ShuffledHand(seed int64) Hand {
	rand.Seed(seed)

	// データ要素数指定、および初期データ作成
	size := 136
	hand := make(Hand, size, size)
	for i := 0; i < size; i++ {
		hand[i] = i / 4
	}

	// シャッフル
	shuffle(hand)

	return hand[:14]
}

// 牌文字への変換(スペース区切り)
func (c Hand) HaiString() string {
	// http://qiita.com/ruiu/items/2bb83b29baeae2433a79
	// サイズ0、内部バッファの長さ69の[]byteの値を割り当てる
	b := make([]byte, 0, 70)

	// bに文字列を追加
	for j := 0; j < 14; j++ {
		// コードポイント上、普通の麻雀牌はU+1F000からの34個。
		// U+1F000 is 'MAHJONG TILE EAST WIND' ('東')
		// https://codepoints.net/U+1F000
		b = append(b, string(c[j]+0x1F000)...) // appendするには...が必要
		// 自分のMacではスペース区切りでないとうまく表示されないためスペースを挿入する
		// U+0020 is 'SPACE'
		// https://codepoints.net/U+0020
		b = append(b, string(0x20)...) // appendするには...が必要
	}
	return string(b)
}

// 七対子判定
func (hand Hand) is_chitoitsu() bool {
	//カウンタ
	c := map[int]int{}

	for _, v := range hand {
		count, ok := c[v]
		if ok {
			if count == 1 {
				c[v] = 2
			} else {
				// c[v] == 2
				return false
			}
		} else {
			c[v] = 1
		}
		//8個チェック
		if len(c) >= 8 {
			return false
		}
	}
	return true
}

// あがり判定する
func (hand Hand) Solve() bool {
	return hand.is_chitoitsu() || hand.GroupSuit().Solve()
}

type SuitGroup []int

type SuitsGroupedHand []SuitGroup

// スート分類
func (hand Hand) GroupSuit() SuitsGroupedHand {
	m := SuitsGroupedHand{{}, {}, {}, {}}
	for _, i := range hand {
		switch {
		case i < 7:
			m[0] = append(m[0], i)
		case i < 7+(9*1):
			m[1] = append(m[1], i-7)
		case i < 7+(9*2):
			m[2] = append(m[2], i-7-(9*1))
		case i < 7+(9*3):
			m[3] = append(m[3], i-7-(9*2))
		}
	}
	return m
}

func (m SuitsGroupedHand) Solve() bool {
	return m.a_pair_existible() && m.valid_33332()
}

func (m SuitsGroupedHand) a_pair_existible() bool {
	//スートのサイズを3で割った時
	//あまりが2であるスートグループが1つであること
	c := 0
	for _, a := range m {
		switch len(a) % 3 {
		case 0:
			// noop
		case 1:
			return false
		case 2:
			c++
		}
	}
	return c == 1
}

func (m SuitsGroupedHand) valid_33332() bool {
	for i := 0; i < 4; i++ {
		if !m[i].valid_suit_group(i) {
			return false
		}
	}
	return true
}

// 33332形を形成するスートグループがどうかを判定
func (a SuitGroup) valid_suit_group(i int) bool {
	// 対子が含まれているスートグループがただ1つある前提

	//ソート
	sort.Ints(a)
	if len(a)%3 == 2 {
		//ペアを探す
		pair_numbers := a.pairable_numbers()
		//ペア候補がなかったらぬける
		if len(pair_numbers) == 0 {
			return false
		}
		//ペア候補毎に繰り返し処理
		for _, v := range pair_numbers {
			//ペアとなる２枚を除去
			rest := SuitGroup{}
			c := 2
			for _, w := range a {
				// ペア候補以外は新スライスに入れる
				// ペア候補は３枚目以降は新スライスに入れる
				if w != v || c <= 0 {
					rest = append(rest, w)
				}
				if w == v {
					c--
				}
			}
			if rest.valid_3cards(i) {
				return true
			} else {
				continue
			}
		}
		return false
	} else if len(a)%3 == 0 {
		return a.valid_3cards(i)
	}
	// 到達しないはず
	panic("到達しないはず")
}

func (a SuitGroup) valid_3cards(i int) bool {
	// 刻子や順子のみで構成されている場合true
	// a is sorted
	// a.size % 3 is0
	// 引数は字牌のとき0
	ok := false
	for {
		a, ok = a.remove_kotsu()
		if ok {
			continue
		}
		if i > 0 {
			a, ok = a.remove_shuntsu()
			if ok {
				continue
			}
		}
		return len(a) == 0
	}
}

func (a SuitGroup) remove_kotsu() (SuitGroup, bool) {
	// 刻子を除去できればtrue
	// a is sorted
	retval := a
	if len(a) < 3 {
		return retval, false
	}
	if a[0] == a[1] && a[0] == a[2] {
		retval = a[3:]
		return retval, true
	}
	return retval, false
}

func (a SuitGroup) remove_shuntsu() (SuitGroup, bool) {
	// 順子を除去できればtrue
	// a is sorted
	rest := SuitGroup{}
	first := -1
	second := -1
	found := false
	for _, v := range a {
		if found {
			rest = append(rest, v)
			continue
		}
		if first == -1 {
			first = v
		} else if second == -1 && first+1 == v {
			second = v
		} else if second != -1 && first+2 == v {
			//flush
			first = -1
			second = -1
			found = true
		} else {
			rest = append(rest, v)
		}
	}
	return rest, found
}

func (a SuitGroup) pairable_numbers() SuitGroup {
	// a is sorted
	counter := []int{}
	x := 999 // 2つ前
	y := 999 // 1つ前
	for _, v := range a {
		if y == v && x != v {
			counter = append(counter, v)
		} else {
			y = v
		}
	}
	return counter
}
<commit_msg>Refactor<commit_after>package tenho

import (
	"fmt"
	"math/rand"
	"sort"
	"time"
)

func Start() {
	start := time.Now()
	// 処理
	var i float64
	i = 0
	for {
		i++
		end := time.Now()
		diff := float64(end.Sub(start) / 1000 / 1000 / 1000)
		m := int(i / diff)
		out := 0
		if m >= 0 {
			out = m
		}
		fmt.Printf("\r")
		fmt.Printf("\r%v回試行  %v秒経過 %v回/秒", i, diff, out)
		seed := time.Now().UnixNano()
		var hai string
		var ok bool
		hai, ok = tryOnce(seed)
		fmt.Printf("%v", hai)
		if ok {
			break
		}
	}
	fmt.Printf("\n")
}

type Hand []int

func tryOnce(seed int64) (string, bool) {
	hand := ShuffledHand(seed)
	hai := hand.HaiString()
	ok := hand.Solve()
	return hai, ok
}

// http://d.hatena.ne.jp/hake/20150930/p1
func shuffle(hand Hand) {
	for i := len(hand); i > 1; i-- {
		j := rand.Intn(i) // 0 .. i-1 の乱数発生
		hand[i-1], hand[j] = hand[j], hand[i-1]
	}
}

func ShuffledHand(seed int64) Hand {
	rand.Seed(seed)

	// データ要素数指定、および初期データ作成
	size := 136
	hand := make(Hand, size, size)
	for i := 0; i < size; i++ {
		hand[i] = i / 4
	}

	// シャッフル
	shuffle(hand)

	return hand[:14]
}

// 牌文字への変換(スペース区切り)
func (hand Hand) HaiString() string {
	// http://qiita.com/ruiu/items/2bb83b29baeae2433a79
	// サイズ0、内部バッファの長さ69の[]byteの値を割り当てる
	b := make([]byte, 0, 70)

	// bに文字列を追加
	for j := 0; j < 14; j++ {
		// コードポイント上、普通の麻雀牌はU+1F000からの34個。
		// U+1F000 is 'MAHJONG TILE EAST WIND' ('東')
		// https://codepoints.net/U+1F000
		b = append(b, string(hand[j]+0x1F000)...) // appendするには...が必要
		// 自分のMacではスペース区切りでないとうまく表示されないためスペースを挿入する
		// U+0020 is 'SPACE'
		// https://codepoints.net/U+0020
		b = append(b, string(0x20)...) // appendするには...が必要
	}
	return string(b)
}

// 七対子判定
func (hand Hand) is_chitoitsu() bool {
	//カウンタ
	c := map[int]int{}

	for _, v := range hand {
		count, ok := c[v]
		if ok {
			if count == 1 {
				c[v] = 2
			} else {
				// c[v] == 2
				return false
			}
		} else {
			c[v] = 1
		}
		//8個チェック
		if len(c) >= 8 {
			return false
		}
	}
	return true
}

// あがり判定する
func (hand Hand) Solve() bool {
	return hand.is_chitoitsu() || hand.GroupSuit().Solve()
}

type SuitGroup []int

type SuitsGroupedHand []SuitGroup

// スート分類
func (hand Hand) GroupSuit() SuitsGroupedHand {
	m := SuitsGroupedHand{{}, {}, {}, {}}
	for _, i := range hand {
		switch {
		case i < 7:
			m[0] = append(m[0], i)
		case i < 7+(9*1):
			m[1] = append(m[1], i-7)
		case i < 7+(9*2):
			m[2] = append(m[2], i-7-(9*1))
		case i < 7+(9*3):
			m[3] = append(m[3], i-7-(9*2))
		}
	}
	return m
}

func (m SuitsGroupedHand) Solve() bool {
	return m.a_pair_existible() && m.valid_33332()
}

func (m SuitsGroupedHand) a_pair_existible() bool {
	//スートのサイズを3で割った時
	//あまりが2であるスートグループが1つであること
	c := 0
	for _, a := range m {
		switch len(a) % 3 {
		case 0:
			// noop
		case 1:
			return false
		case 2:
			c++
		}
	}
	return c == 1
}

func (m SuitsGroupedHand) valid_33332() bool {
	for i := 0; i < 4; i++ {
		if !m[i].valid_suit_group(i) {
			return false
		}
	}
	return true
}

// 33332形を形成するスートグループがどうかを判定
func (a SuitGroup) valid_suit_group(i int) bool {
	// 対子が含まれているスートグループがただ1つある前提

	//ソート
	sort.Ints(a)
	if len(a)%3 == 2 {
		//ペアを探す
		pair_numbers := a.pairable_numbers()
		//ペア候補がなかったらぬける
		if len(pair_numbers) == 0 {
			return false
		}
		//ペア候補毎に繰り返し処理
		for _, v := range pair_numbers {
			//ペアとなる２枚を除去
			rest := SuitGroup{}
			c := 2
			for _, w := range a {
				// ペア候補以外は新スライスに入れる
				// ペア候補は３枚目以降は新スライスに入れる
				if w != v || c <= 0 {
					rest = append(rest, w)
				}
				if w == v {
					c--
				}
			}
			if rest.valid_3cards(i) {
				return true
			} else {
				continue
			}
		}
		return false
	} else if len(a)%3 == 0 {
		return a.valid_3cards(i)
	}
	// 到達しないはず
	panic("到達しないはず")
}

func (a SuitGroup) valid_3cards(i int) bool {
	// 刻子や順子のみで構成されている場合true
	// a is sorted
	// a.size % 3 is0
	// 引数は字牌のとき0
	ok := false
	for {
		a, ok = a.remove_kotsu()
		if ok {
			continue
		}
		if i > 0 {
			a, ok = a.remove_shuntsu()
			if ok {
				continue
			}
		}
		return len(a) == 0
	}
}

func (a SuitGroup) remove_kotsu() (SuitGroup, bool) {
	// 刻子を除去できればtrue
	// a is sorted
	retval := a
	if len(a) < 3 {
		return retval, false
	}
	if a[0] == a[1] && a[0] == a[2] {
		retval = a[3:]
		return retval, true
	}
	return retval, false
}

func (a SuitGroup) remove_shuntsu() (SuitGroup, bool) {
	// 順子を除去できればtrue
	// a is sorted
	rest := SuitGroup{}
	first := -1
	second := -1
	found := false
	for _, v := range a {
		if found {
			rest = append(rest, v)
			continue
		}
		if first == -1 {
			first = v
		} else if second == -1 && first+1 == v {
			second = v
		} else if second != -1 && first+2 == v {
			//flush
			first = -1
			second = -1
			found = true
		} else {
			rest = append(rest, v)
		}
	}
	return rest, found
}

func (a SuitGroup) pairable_numbers() SuitGroup {
	// a is sorted
	counter := []int{}
	x := 999 // 2つ前
	y := 999 // 1つ前
	for _, v := range a {
		if y == v && x != v {
			counter = append(counter, v)
		} else {
			y = v
		}
	}
	return counter
}
<|endoftext|>


<commit_before>package command

import (
	"github.com/cloudfoundry/cli/cf/command_metadata"
	"github.com/cloudfoundry/cli/cf/requirements"
	"github.com/codegangsta/cli"
)

type Command interface {
	Metadata() command_metadata.CommandMetadata
	GetRequirements(requirementsFactory requirements.Factory, c *cli.Context) (reqs []requirements.Requirement, err error)
	Run(c *cli.Context)
}
<commit_msg>Rename some variables on Command interface<commit_after>package command

import (
	"github.com/cloudfoundry/cli/cf/command_metadata"
	"github.com/cloudfoundry/cli/cf/requirements"
	"github.com/codegangsta/cli"
)

type Command interface {
	Metadata() command_metadata.CommandMetadata
	GetRequirements(requirementsFactory requirements.Factory, context *cli.Context) (reqs []requirements.Requirement, err error)
	Run(context *cli.Context)
}
<|endoftext|>


<commit_before>package systemdata

import "encoding/json"

var _ json.Marshaler = &SystemData{}

type SystemData struct {
	CreatedBy          string `json:"createdBy"`
	CreatedByType      string `json:"createdByType"`
	CreatedAt          string `json:"createdAt"`
	LastModifiedBy     string `json:"lastModifiedBy"`
	LastModifiedbyType string `json:"lastModifiedbyType"`
	LastModifiedAt     string `json:"lastModifiedAt"`
}

// SystemData is a Read Only type. If Systemdata is part of a request some Azure APIs will ignore it,
// others will return HTTP 400. We're returning nothing on purpose to avoid the error.
func (s *SystemData) MarshalJSON() ([]byte, error) {
	return json.Marshal([]byte{})
}
<commit_msg>systemdata: marshaling as nil<commit_after>package systemdata

import "encoding/json"

var _ json.Marshaler = &SystemData{}

type SystemData struct {
	CreatedBy          string `json:"createdBy"`
	CreatedByType      string `json:"createdByType"`
	CreatedAt          string `json:"createdAt"`
	LastModifiedBy     string `json:"lastModifiedBy"`
	LastModifiedbyType string `json:"lastModifiedbyType"`
	LastModifiedAt     string `json:"lastModifiedAt"`
}

func (s *SystemData) MarshalJSON() ([]byte, error) {
	// SystemData is a Read Only type. If Systemdata is part of a request some Azure APIs will ignore it,
	// others will return HTTP 400. We're returning nothing on purpose to avoid the error.
	return json.Marshal(nil)
}
<|endoftext|>


<commit_before>package ufop

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/qiniu/api/auth/digest"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
	"time"
)

var (
	ufopPrefix  string
	jobHandlers map[string]UfopJobHandler
	unzipper    *UnZipper
	mkzipper    *Mkziper
	amerger     *AudioMerger
)

type UfopJobHandler interface {
	Do(ufopReq UfopRequest) (interface{}, string, error)
}

type UfopServer struct {
	cfg *UfopConfig
}

func NewServer(cfg *UfopConfig) *UfopServer {
	serv := UfopServer{}
	serv.cfg = cfg
	return &serv
}

func (this *UfopServer) registerJobHandlers() {
	mac := digest.Mac{
		AccessKey: this.cfg.AccessKey,
		SecretKey: []byte(this.cfg.SecretKey),
	}
	jobHandlers = make(map[string]UfopJobHandler, 0)
	ufopPrefix = this.cfg.UfopPrefix
	//unzipper
	unzipper = &UnZipper{
		mac:              &mac,
		maxZipFileLength: this.cfg.UnzipMaxZipFileLength,
		maxFileLength:    this.cfg.UnzipMaxFileLength,
		maxFileCount:     this.cfg.UnzipMaxFileCount,
	}
	//mkzipper
	mkzipper = &Mkziper{
		mac:           &mac,
		maxFileLength: this.cfg.MkzipMaxFileLength,
		maxFileCount:  this.cfg.MkzipMaxFileCount,
	}
	//audio merger
	amerger = &AudioMerger{
		mac:                 &mac,
		maxFirstFileLength:  this.cfg.AmergeMaxFirstFileLength,
		maxSecondFileLength: this.cfg.AmergeMaxSecondFileLength,
	}

	jobHandlers[ufopPrefix+"unzip"] = unzipper
	jobHandlers[ufopPrefix+"mkzip"] = mkzipper
	jobHandlers[ufopPrefix+"amerge"] = amerger
}

func (this *UfopServer) Listen() {
	//register
	this.registerJobHandlers()

	//define handler
	http.HandleFunc("/uop", serveUfop)

	//bind and listen
	endPoint := fmt.Sprintf("%s:%d", this.cfg.ListenHost, this.cfg.ListenPort)
	ufopServer := &http.Server{
		Addr:           endPoint,
		ReadTimeout:    time.Duration(this.cfg.ReadTimeout) * time.Second,
		WriteTimeout:   time.Duration(this.cfg.WriteTimeout) * time.Second,
		MaxHeaderBytes: this.cfg.MaxHeaderBytes,
	}

	listenErr := ufopServer.ListenAndServe()
	if listenErr != nil {
		log.Println(listenErr)
	}
}

func serveUfop(w http.ResponseWriter, req *http.Request) {
	//check method
	if req.Method != "POST" {
		writeJsonError(w, 405, "method not allowed")
		return
	}

	defer req.Body.Close()
	var err error
	var ufopReq UfopRequest
	var ufopResult interface{}
	var ufopResultContentType string

	ufopReqData, err := ioutil.ReadAll(req.Body)
	if err != nil {
		writeJsonError(w, 500, "read ufop request body error")
		return
	}

	err = json.Unmarshal(ufopReqData, &ufopReq)
	if err != nil {
		writeJsonError(w, 500, "parse ufop request body error")
		return
	}

	ufopResult, ufopResultContentType, err = handleJob(ufopReq)
	if err != nil {
		ufopErr := UfopError{
			Request: ufopReq,
			Error:   err.Error(),
		}
		logBytes, _ := json.Marshal(&ufopErr)
		log.Println(string(logBytes))
		writeJsonError(w, 400, err.Error())
	} else {
		switch ufopResultContentType {
		case "application/json":
			writeJsonResult(w, 200, ufopResult)
		default:
			writeOctetResultWithMime(w, 200, ufopResult, ufopResultContentType)
		}
	}
}

func handleJob(ufopReq UfopRequest) (interface{}, string, error) {
	var ufopResult interface{}
	var contentType string
	var err error
	cmd := ufopReq.Cmd

	items := strings.SplitN(cmd, "/", 2)
	fop := items[0]
	if jobHandler, ok := jobHandlers[fop]; ok {
		ufopReq.Cmd = strings.TrimPrefix(ufopReq.Cmd, ufopPrefix)
		ufopResult, contentType, err = jobHandler.Do(ufopReq)
	} else {
		err = errors.New("no fop available for the request")
	}
	return ufopResult, contentType, err
}

func writeJsonError(w http.ResponseWriter, statusCode int, message string) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(statusCode)
	io.WriteString(w, fmt.Sprintf(`{"error": "%s"}`, message))
}

func writeJsonResult(w http.ResponseWriter, statusCode int, result interface{}) {
	w.Header().Set("Content-Type", "application/json")
	data, err := json.Marshal(result)
	if err != nil {
		log.Println("encode ufop result error,", err)
		writeJsonError(w, 500, "encode ufop result error")
	} else {
		_, err := io.WriteString(w, string(data))
		if err != nil {
			log.Println("write json response error", err)
		}
	}
}

func writeOctetResultWithMime(w http.ResponseWriter, statusCode int, result interface{}, mimeType string) {
	w.Header().Set("Content-Type", mimeType)
	if respData := result.([]byte); respData != nil {
		_, err := w.Write(respData)
		if err != nil {
			log.Println("write octect response error", err)
		}
	}
}
<commit_msg>Let server auto detect if response mime type not set.<commit_after>package ufop

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/qiniu/api/auth/digest"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
	"time"
)

var (
	ufopPrefix  string
	jobHandlers map[string]UfopJobHandler
	unzipper    *UnZipper
	mkzipper    *Mkziper
	amerger     *AudioMerger
)

type UfopJobHandler interface {
	Do(ufopReq UfopRequest) (interface{}, string, error)
}

type UfopServer struct {
	cfg *UfopConfig
}

func NewServer(cfg *UfopConfig) *UfopServer {
	serv := UfopServer{}
	serv.cfg = cfg
	return &serv
}

func (this *UfopServer) registerJobHandlers() {
	mac := digest.Mac{
		AccessKey: this.cfg.AccessKey,
		SecretKey: []byte(this.cfg.SecretKey),
	}
	jobHandlers = make(map[string]UfopJobHandler, 0)
	ufopPrefix = this.cfg.UfopPrefix
	//unzipper
	unzipper = &UnZipper{
		mac:              &mac,
		maxZipFileLength: this.cfg.UnzipMaxZipFileLength,
		maxFileLength:    this.cfg.UnzipMaxFileLength,
		maxFileCount:     this.cfg.UnzipMaxFileCount,
	}
	//mkzipper
	mkzipper = &Mkziper{
		mac:           &mac,
		maxFileLength: this.cfg.MkzipMaxFileLength,
		maxFileCount:  this.cfg.MkzipMaxFileCount,
	}
	//audio merger
	amerger = &AudioMerger{
		mac:                 &mac,
		maxFirstFileLength:  this.cfg.AmergeMaxFirstFileLength,
		maxSecondFileLength: this.cfg.AmergeMaxSecondFileLength,
	}

	jobHandlers[ufopPrefix+"unzip"] = unzipper
	jobHandlers[ufopPrefix+"mkzip"] = mkzipper
	jobHandlers[ufopPrefix+"amerge"] = amerger
}

func (this *UfopServer) Listen() {
	//register
	this.registerJobHandlers()

	//define handler
	http.HandleFunc("/uop", serveUfop)

	//bind and listen
	endPoint := fmt.Sprintf("%s:%d", this.cfg.ListenHost, this.cfg.ListenPort)
	ufopServer := &http.Server{
		Addr:           endPoint,
		ReadTimeout:    time.Duration(this.cfg.ReadTimeout) * time.Second,
		WriteTimeout:   time.Duration(this.cfg.WriteTimeout) * time.Second,
		MaxHeaderBytes: this.cfg.MaxHeaderBytes,
	}

	listenErr := ufopServer.ListenAndServe()
	if listenErr != nil {
		log.Println(listenErr)
	}
}

func serveUfop(w http.ResponseWriter, req *http.Request) {
	//check method
	if req.Method != "POST" {
		writeJsonError(w, 405, "method not allowed")
		return
	}

	defer req.Body.Close()
	var err error
	var ufopReq UfopRequest
	var ufopResult interface{}
	var ufopResultContentType string

	ufopReqData, err := ioutil.ReadAll(req.Body)
	if err != nil {
		writeJsonError(w, 500, "read ufop request body error")
		return
	}

	err = json.Unmarshal(ufopReqData, &ufopReq)
	if err != nil {
		writeJsonError(w, 500, "parse ufop request body error")
		return
	}

	ufopResult, ufopResultContentType, err = handleJob(ufopReq)
	if err != nil {
		ufopErr := UfopError{
			Request: ufopReq,
			Error:   err.Error(),
		}
		logBytes, _ := json.Marshal(&ufopErr)
		log.Println(string(logBytes))
		writeJsonError(w, 400, err.Error())
	} else {
		switch ufopResultContentType {
		case "application/json":
			writeJsonResult(w, 200, ufopResult)
		default:
			writeOctetResultWithMime(w, 200, ufopResult, ufopResultContentType)
		}
	}
}

func handleJob(ufopReq UfopRequest) (interface{}, string, error) {
	var ufopResult interface{}
	var contentType string
	var err error
	cmd := ufopReq.Cmd

	items := strings.SplitN(cmd, "/", 2)
	fop := items[0]
	if jobHandler, ok := jobHandlers[fop]; ok {
		ufopReq.Cmd = strings.TrimPrefix(ufopReq.Cmd, ufopPrefix)
		ufopResult, contentType, err = jobHandler.Do(ufopReq)
	} else {
		err = errors.New("no fop available for the request")
	}
	return ufopResult, contentType, err
}

func writeJsonError(w http.ResponseWriter, statusCode int, message string) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(statusCode)
	io.WriteString(w, fmt.Sprintf(`{"error": "%s"}`, message))
}

func writeJsonResult(w http.ResponseWriter, statusCode int, result interface{}) {
	w.Header().Set("Content-Type", "application/json")
	data, err := json.Marshal(result)
	if err != nil {
		log.Println("encode ufop result error,", err)
		writeJsonError(w, 500, "encode ufop result error")
	} else {
		_, err := io.WriteString(w, string(data))
		if err != nil {
			log.Println("write json response error", err)
		}
	}
}

func writeOctetResultWithMime(w http.ResponseWriter, statusCode int, result interface{}, mimeType string) {
	if mimeType != "" {
		w.Header().Set("Content-Type", mimeType)
	}
	if respData := result.([]byte); respData != nil {
		_, err := w.Write(respData)
		if err != nil {
			log.Println("write octect response error", err)
		}
	}
}
<|endoftext|>


<commit_before>// Library for general purpose functions used by the Yieldbot Infrastructure
// teams in sensu.
//
// LICENSE:
//   Copyright 2015 Yieldbot. <devops@yieldbot.com>
//   Released under the MIT License; see LICENSE
//   for details.

package sensuutil

import (
	"fmt"
	"os"
	"strings"
)

// EHndlr is for generic error handling in all Yieldbot monitoring packages.
func EHndlr(e error) {
	if e != nil {
		fmt.Printf("ERROR: %v", e)
		os.Exit(129)
	}
}

// Exit method for all sensu checks that will print the output and desired
// exit code
func Exit(args ...interface{}) {
	// YELLOW need to make sure that condition exists
	var exitCode int
	output := ""

	if 1 > len(args) {
		panic("Not enough parameters.")
	}

	for i, p := range args {
		switch i {
		case 0: // name
			param, ok := p.(string)
			if !ok {
				panic("1st parameter not type string.")
			}

			for k := range MonitoringErrorCodes {
				if k == strings.ToUpper(param) {
					exitCode = MonitoringErrorCodes[k]
				}
			}

		case 1: // x
			param, ok := p.(string)
			if !ok {
				panic("2nd parameter not type string.")
			}
			output = param

		default:
			panic("Wrong parameter count.")
		}
	}

	fmt.Printf("%v", output)
	os.Exit(exitCode)
}
<commit_msg>document exit function with examples<commit_after>// Library for general purpose functions used by the Yieldbot Infrastructure
// teams in sensu.
//
// LICENSE:
//   Copyright 2015 Yieldbot. <devops@yieldbot.com>
//   Released under the MIT License; see LICENSE
//   for details.

package sensuutil

import (
	"fmt"
	"os"
	"strings"
)

// EHndlr is for generic error handling in all Yieldbot monitoring packages.
func EHndlr(e error) {
	if e != nil {
		fmt.Printf("ERROR: %v", e)
		os.Exit(129)
	}
}

// Exit method for all sensu checks that will print the output and desired
// exit code
// To use you want to pass it in the state you want and an opitional text you would want outputed with the check.
//Ex. sensuutil.Exit("ok", "Everything is fine")
//    sensuutil.Exit("critical", variable)
// A list of error codes currently supported can be foun in common.go
func Exit(args ...interface{}) {
	// YELLOW need to make sure that condition exists
	var exitCode int
	output := ""

	if 1 > len(args) {
		panic("Not enough parameters.")
	}

	for i, p := range args {
		switch i {
		case 0: // name
			param, ok := p.(string)
			if !ok {
				panic("1st parameter not type string.")
			}

			for k := range MonitoringErrorCodes {
				if k == strings.ToUpper(param) {
					exitCode = MonitoringErrorCodes[k]
				}
			}

		case 1: // x
			param, ok := p.(string)
			if !ok {
				panic("2nd parameter not type string.")
			}
			output = param

		default:
			panic("Wrong parameter count.")
		}
	}

	fmt.Printf("%v", output)
	os.Exit(exitCode)
}
<|endoftext|>


<commit_before>// Library for general purpose functions used by the Yieldbot Infrastructure
// teams in sensu.
//
// LICENSE:
//   Copyright 2015 Yieldbot. <devops@yieldbot.com>
//   Released under the MIT License; see LICENSE
//   for details.

package sensuutil

import (
	"fmt"
	"os"
	"strings"
)

// EHndlr is for generic error handling in all Yieldbot monitoring packages.
func EHndlr(e error) {
	if e != nil {
		fmt.Printf("ERROR: %v", e)
	}
}

// Exit method for all sensu checks that will print the output and desired
// exit code
// To use you want to pass it in the state you want and an opitional text you would want outputed with the check.
//Ex. sensuutil.Exit("ok", "Everything is fine")
//    sensuutil.Exit("critical", variable)
// A list of error codes currently supported can be found in common.go
func Exit(args ...interface{}) {
	// YELLOW need to make sure that condition exists
	var exitCode int
	output := ""

	if 1 > len(args) {
		panic("Not enough parameters.")
	}

	for i, p := range args {
		switch i {
		case 0: // name
			param, ok := p.(string)
			if !ok {
				panic("1st parameter not type string.")
			}

			for k := range MonitoringErrorCodes {
				if k == strings.ToUpper(param) {
					exitCode = MonitoringErrorCodes[k]
				}
			}

		case 1: // x
			param, ok := p.(string)
			if !ok {
				panic("2nd parameter not type string.")
			}
			output = param

		default:
			panic("Wrong parameter count.")
		}
	}

	fmt.Printf("%v\n", output)
	os.Exit(exitCode)
}
<commit_msg>fix some cruft<commit_after>// Library for general purpose functions used by the Yieldbot Infrastructure
// teams in sensu.
//
// LICENSE:
//   Copyright 2015 Yieldbot. <devops@yieldbot.com>
//   Released under the MIT License; see LICENSE
//   for details.

package sensuutil

import (
	"fmt"
	"os"
	"strings"
)

// EHndlr is for generic error handling in all Yieldbot monitoring packages.
func EHndlr(e error) {
	if e != nil {
		fmt.Printf("ERROR: %v", e)
	}
}

// Exit method for all sensu checks that will print the output and desired exit code
// To use, pass it in the state you want and an optional text you would want outputted with the check.
//Ex. sensuutil.Exit("ok", "Everything is fine")
//    sensuutil.Exit("critical", variable)
// A list of error codes currently supported can be found in common.go
func Exit(args ...interface{}) {
	// YELLOW need to make sure that condition exists
	// panic is bad
	var exitCode int
	output := ""

	if 1 > len(args) {
		panic("Not enough parameters.")
	}

	for i, p := range args {
		switch i {
		case 0: // name
			param, ok := p.(string)
			if !ok {
				panic("1st paramete not type string.")
			}

			for k := range MonitoringErrorCodes {
				if k == strings.ToUpper(param) {
					exitCode = MonitoringErrorCodes[k]
				}
			}

		case 1: // optional text
			param, ok := p.(string)
			if !ok {
				panic("2nd parameter not type string.")
			}
			output = param

		default:
			panic("Incorrect parameters")
		}
	}

	fmt.Printf("%v\n", output)
	os.Exit(exitCode)
}
<|endoftext|>


<commit_before>// Filter manager
// @author Robin Verlangen

package main

import (
	"code.google.com/p/go-uuid/uuid"
	"encoding/json"
	"fmt"
	"github.com/boltdb/bolt"
	"log"
	"sync"
)

type FilterManager struct {
	db            *bolt.DB
	filterTable   string
	filterResults map[string][]string
}

type Filter struct {
	Regex      string `json:"regex"`
	Name       string `json:"name"`
	ClientHost string `json:"client_host"`
	Id         string `json:"id"`
	//Results    []string `json:"results"`
	resultsMux sync.RWMutex
}

func (f *Filter) Results() []string {
	if filterManager.filterResults[f.Id] == nil {
		filterManager.filterResults[f.Id] = make([]string, 0)
	}
	return filterManager.filterResults[f.Id]
}

func (f *Filter) ToJson() (string, error) {
	bytes, err := json.Marshal(f)
	if err != nil {
		return "", err
	}
	return string(bytes), nil
}

func (f *Filter) Save() bool {
	var res bool = false
	json, jsonEr := f.ToJson()
	if jsonEr != nil {
		log.Printf("Json error %s", jsonEr)
		return false
	}
	var wg sync.WaitGroup
	wg.Add(1)
	var err error = nil
	filterManager.db.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(filterManager.filterTable))
		err = b.Put([]byte(f.Id), []byte(json))
		if err == nil {
			log.Printf("Saved filter %s", f.Id)
			res = true
		}
		wg.Done()
		return err
	})
	wg.Wait()
	return res
}

func (f *Filter) AddResults(res []string) bool {
	f.resultsMux.Lock()

	// Init variable
	if filterManager.filterResults[f.Id] == nil {
		filterManager.filterResults[f.Id] = make([]string, 0)
	}

	// Exceed limit?
	newCount := len(res)
	currentCount := len(filterManager.filterResults[f.Id])
	newPlusCurrent := newCount + currentCount
	if newPlusCurrent > maxMsgMemory {
		log.Printf("Truncating memory for filter %s, exceeding limit of %d messages", f.Id, maxMsgMemory)
		tmp := make([]string, 0)
		tooMany := newPlusCurrent - maxMsgMemory
		log.Printf("len %d", len(filterManager.filterResults[f.Id]))
		log.Printf("tm %d", tooMany)
		log.Printf("c %d", currentCount)
		for i := tooMany; i < currentCount-1; i++ {
			log.Printf("%d", i)
			tmp = append(tmp, filterManager.filterResults[f.Id][i])
		}
		filterManager.filterResults[f.Id] = tmp
	}

	// Add lines
	for _, line := range res {
		filterManager.filterResults[f.Id] = append(filterManager.filterResults[f.Id], line)
	}
	f.resultsMux.Unlock()
	return true
}

func NewFilterManager() *FilterManager {
	fm := &FilterManager{
		filterTable:   "filters",
		filterResults: make(map[string][]string),
	}
	fm.Open()
	return fm
}

func (fm *FilterManager) Open() {
	// Open DB
	db, err := bolt.Open(dbFile, 0600, nil)
	if err != nil {
		log.Fatal(err)
	}
	fm.db = db

	// Create buckets
	var wg sync.WaitGroup
	wg.Add(1)
	fm.db.Update(func(tx *bolt.Tx) error {
		_, err := tx.CreateBucketIfNotExists([]byte(fm.filterTable))
		if err != nil {
			log.Fatal(fmt.Errorf("create bucket: %s", err))
		}
		wg.Done()
		return nil
	})

	// Wait until buckets are ready
	wg.Wait()
}

func (fm *FilterManager) GetFilters() []*Filter {
	var wg sync.WaitGroup
	var list []*Filter = make([]*Filter, 0)
	wg.Add(1)
	fm.db.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(fm.filterTable))
		c := b.Cursor()

		for k, v := c.First(); k != nil; k, v = c.Next() {
			//fmt.Printf("key=%s, value=%s\n", k, v)
			elm := filterFromJson(v)
			if elm != nil {
				list = append(list, elm)
			}
		}
		wg.Done()
		return nil
	})
	wg.Wait()
	return list
}

func (fm *FilterManager) GetFilter(id string) *Filter {
	var wg sync.WaitGroup
	var elm *Filter = nil
	wg.Add(1)
	fm.db.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(fm.filterTable))
		res := b.Get([]byte(id))
		elm = filterFromJson(res)
		wg.Done()
		return nil
	})
	wg.Wait()
	return elm
}

func (fm *FilterManager) DeleteFilter(id string) bool {
	var val bool = false
	var wg sync.WaitGroup
	wg.Add(1)
	var err error = nil
	fm.db.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(fm.filterTable))
		err = b.Delete([]byte(id))
		if err == nil {
			val = true
		}
		wg.Done()
		return err
	})
	wg.Wait()
	return val
}

func (fm *FilterManager) CreateFilter(name string, clientHost string, regex string) (string, error) {
	var id string = uuid.New()
	var filter *Filter = newFilter()
	filter.Regex = regex
	filter.Name = name
	filter.ClientHost = clientHost
	filter.Id = id

	// To JSON
	json, jsonErr := filter.ToJson()
	if jsonErr != nil {
		log.Fatal(fmt.Sprintf("Failed JSON: %s", jsonErr))
	}

	// Create
	var wg sync.WaitGroup
	wg.Add(1)
	var err error = nil
	fm.db.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(fm.filterTable))
		err = b.Put([]byte(id), []byte(json))
		if err == nil {
			log.Printf("Created filter %s", id)
		}
		wg.Done()
		return err
	})
	wg.Wait()
	return id, err
}

func filterFromJson(b []byte) *Filter {
	f := newFilter()
	if err := json.Unmarshal(b, &f); err != nil {
		log.Printf("Failed json umarshal %s", err)
		return nil
	}
	return f
}

func newFilter() *Filter {
	return &Filter{}
}
<commit_msg>More dbg<commit_after>// Filter manager
// @author Robin Verlangen

package main

import (
	"code.google.com/p/go-uuid/uuid"
	"encoding/json"
	"fmt"
	"github.com/boltdb/bolt"
	"log"
	"sync"
)

type FilterManager struct {
	db            *bolt.DB
	filterTable   string
	filterResults map[string][]string
}

type Filter struct {
	Regex      string `json:"regex"`
	Name       string `json:"name"`
	ClientHost string `json:"client_host"`
	Id         string `json:"id"`
	//Results    []string `json:"results"`
	resultsMux sync.RWMutex
}

func (f *Filter) Results() []string {
	if filterManager.filterResults[f.Id] == nil {
		filterManager.filterResults[f.Id] = make([]string, 0)
	}
	return filterManager.filterResults[f.Id]
}

func (f *Filter) ToJson() (string, error) {
	bytes, err := json.Marshal(f)
	if err != nil {
		return "", err
	}
	return string(bytes), nil
}

func (f *Filter) Save() bool {
	var res bool = false
	json, jsonEr := f.ToJson()
	if jsonEr != nil {
		log.Printf("Json error %s", jsonEr)
		return false
	}
	var wg sync.WaitGroup
	wg.Add(1)
	var err error = nil
	filterManager.db.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(filterManager.filterTable))
		err = b.Put([]byte(f.Id), []byte(json))
		if err == nil {
			log.Printf("Saved filter %s", f.Id)
			res = true
		}
		wg.Done()
		return err
	})
	wg.Wait()
	return res
}

func (f *Filter) AddResults(res []string) bool {
	f.resultsMux.Lock()

	// Init variable
	if filterManager.filterResults[f.Id] == nil {
		filterManager.filterResults[f.Id] = make([]string, 0)
	}

	// Exceed limit?
	newCount := len(res)
	currentCount := len(filterManager.filterResults[f.Id])
	newPlusCurrent := newCount + currentCount
	if newPlusCurrent > maxMsgMemory {
		log.Printf("Truncating memory for filter %s, exceeding limit of %d messages", f.Id, maxMsgMemory)
		tmp := make([]string, 0)
		tooMany := newPlusCurrent - maxMsgMemory
		log.Printf("new %d", newCount)
		log.Printf("len %d", len(filterManager.filterResults[f.Id]))
		log.Printf("tm %d", tooMany)
		log.Printf("c %d", currentCount)
		for i := tooMany; i < currentCount-1; i++ {
			log.Printf("%d", i)
			tmp = append(tmp, filterManager.filterResults[f.Id][i])
		}
		log.Printf("len after %d", len(filterManager.filterResults[f.Id]))
		filterManager.filterResults[f.Id] = tmp
	}

	// Add lines
	for _, line := range res {
		filterManager.filterResults[f.Id] = append(filterManager.filterResults[f.Id], line)
	}
	f.resultsMux.Unlock()
	return true
}

func NewFilterManager() *FilterManager {
	fm := &FilterManager{
		filterTable:   "filters",
		filterResults: make(map[string][]string),
	}
	fm.Open()
	return fm
}

func (fm *FilterManager) Open() {
	// Open DB
	db, err := bolt.Open(dbFile, 0600, nil)
	if err != nil {
		log.Fatal(err)
	}
	fm.db = db

	// Create buckets
	var wg sync.WaitGroup
	wg.Add(1)
	fm.db.Update(func(tx *bolt.Tx) error {
		_, err := tx.CreateBucketIfNotExists([]byte(fm.filterTable))
		if err != nil {
			log.Fatal(fmt.Errorf("create bucket: %s", err))
		}
		wg.Done()
		return nil
	})

	// Wait until buckets are ready
	wg.Wait()
}

func (fm *FilterManager) GetFilters() []*Filter {
	var wg sync.WaitGroup
	var list []*Filter = make([]*Filter, 0)
	wg.Add(1)
	fm.db.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(fm.filterTable))
		c := b.Cursor()

		for k, v := c.First(); k != nil; k, v = c.Next() {
			//fmt.Printf("key=%s, value=%s\n", k, v)
			elm := filterFromJson(v)
			if elm != nil {
				list = append(list, elm)
			}
		}
		wg.Done()
		return nil
	})
	wg.Wait()
	return list
}

func (fm *FilterManager) GetFilter(id string) *Filter {
	var wg sync.WaitGroup
	var elm *Filter = nil
	wg.Add(1)
	fm.db.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(fm.filterTable))
		res := b.Get([]byte(id))
		elm = filterFromJson(res)
		wg.Done()
		return nil
	})
	wg.Wait()
	return elm
}

func (fm *FilterManager) DeleteFilter(id string) bool {
	var val bool = false
	var wg sync.WaitGroup
	wg.Add(1)
	var err error = nil
	fm.db.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(fm.filterTable))
		err = b.Delete([]byte(id))
		if err == nil {
			val = true
		}
		wg.Done()
		return err
	})
	wg.Wait()
	return val
}

func (fm *FilterManager) CreateFilter(name string, clientHost string, regex string) (string, error) {
	var id string = uuid.New()
	var filter *Filter = newFilter()
	filter.Regex = regex
	filter.Name = name
	filter.ClientHost = clientHost
	filter.Id = id

	// To JSON
	json, jsonErr := filter.ToJson()
	if jsonErr != nil {
		log.Fatal(fmt.Sprintf("Failed JSON: %s", jsonErr))
	}

	// Create
	var wg sync.WaitGroup
	wg.Add(1)
	var err error = nil
	fm.db.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(fm.filterTable))
		err = b.Put([]byte(id), []byte(json))
		if err == nil {
			log.Printf("Created filter %s", id)
		}
		wg.Done()
		return err
	})
	wg.Wait()
	return id, err
}

func filterFromJson(b []byte) *Filter {
	f := newFilter()
	if err := json.Unmarshal(b, &f); err != nil {
		log.Printf("Failed json umarshal %s", err)
		return nil
	}
	return f
}

func newFilter() *Filter {
	return &Filter{}
}
<|endoftext|>


<commit_before>package http

import (
	"fmt"
	"io/ioutil"
	"net/http"

	"github.com/asim/mq/broker"
	"github.com/gorilla/websocket"
)

var upgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
	CheckOrigin: func(r *http.Request) bool {
		return true
	},
}

func pub(w http.ResponseWriter, r *http.Request) {
	topic := r.URL.Query().Get("topic")

	if websocket.IsWebSocketUpgrade(r) {
		conn, err := upgrader.Upgrade(w, r, w.Header())
		if err != nil {
			return
		}
		for {
			messageType, b, err := conn.ReadMessage()
			if messageType == -1 {
				return
			}
			if err != nil {
				continue
			}
			broker.Publish(topic, b)
		}
	} else {
		b, err := ioutil.ReadAll(r.Body)
		if err != nil {
			http.Error(w, "Pub error", http.StatusInternalServerError)
			return
		}
		r.Body.Close()
		if err := broker.Publish(topic, b); err != nil {
			http.Error(w, "Pub error", http.StatusInternalServerError)
		}
	}
}

func sub(w http.ResponseWriter, r *http.Request) {
	var wr writer

	if websocket.IsWebSocketUpgrade(r) {
		conn, err := upgrader.Upgrade(w, r, w.Header())
		if err != nil {
			return
		}
		wr = &wsWriter{conn}
	} else {
		wr = &httpWriter{w}
	}

	topic := r.URL.Query().Get("topic")

	ch, err := broker.Subscribe(topic)
	if err != nil {
		http.Error(w, fmt.Sprintf("Could not retrieve events: %v", err), http.StatusInternalServerError)
		return
	}
	defer broker.Unsubscribe(topic, ch)

	for {
		select {
		case e := <-ch:
			if err = wr.Write(e); err != nil {
				return
			}
		}
	}
}
<commit_msg>Properly drain the websocket connection<commit_after>package http

import (
	"fmt"
	"io/ioutil"
	"net/http"

	"github.com/asim/mq/broker"
	"github.com/gorilla/websocket"
)

var upgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
	CheckOrigin: func(r *http.Request) bool {
		return true
	},
}

func pub(w http.ResponseWriter, r *http.Request) {
	topic := r.URL.Query().Get("topic")

	if websocket.IsWebSocketUpgrade(r) {
		conn, err := upgrader.Upgrade(w, r, w.Header())
		if err != nil {
			return
		}
		for {
			messageType, b, err := conn.ReadMessage()
			if messageType == -1 {
				return
			}
			if err != nil {
				continue
			}
			broker.Publish(topic, b)
		}
	} else {
		b, err := ioutil.ReadAll(r.Body)
		if err != nil {
			http.Error(w, "Pub error", http.StatusInternalServerError)
			return
		}
		r.Body.Close()
		if err := broker.Publish(topic, b); err != nil {
			http.Error(w, "Pub error", http.StatusInternalServerError)
		}
	}
}

func sub(w http.ResponseWriter, r *http.Request) {
	var wr writer

	if websocket.IsWebSocketUpgrade(r) {
		conn, err := upgrader.Upgrade(w, r, w.Header())
		if err != nil {
			return
		}
		// Drain the websocket so that we handle pings and connection close
		go func(c *websocket.Conn) {
			for {
				if _, _, err := c.NextReader(); err != nil {
					c.Close()
					break
				}
			}
		}(conn)
		wr = &wsWriter{conn}
	} else {
		wr = &httpWriter{w}
	}

	topic := r.URL.Query().Get("topic")

	ch, err := broker.Subscribe(topic)
	if err != nil {
		http.Error(w, fmt.Sprintf("Could not retrieve events: %v", err), http.StatusInternalServerError)
		return
	}
	defer broker.Unsubscribe(topic, ch)

	for {
		select {
		case e := <-ch:
			if err = wr.Write(e); err != nil {
				return
			}
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"io"
)

// Request is a generic all-purpose JSON request structure.
type Request struct {
	// Token is required for all requests to manipulate data, or read privileged information.
	Token string `json:"token,omitempty"`
	// Username is used for authentication requests only.
	Username string `json:"username,omitempty"`
	// Password is used for authentication requests only.
	Password string `json:"password,omitempty"`
	// ID is used to retrieve notes and lists.
	ID uint64 `json:"id,omitempty"`
	// Note is used when adding notes.
	// For changing public/private status
	Public bool   `json:"public,omitempty"`
	Note   string `json:"note,omitempty"`
	// List is used when adding lists.
	List string `json:"list,omitempty"`
	// ListItems are used when creating lists or appending to them.
	ListItems []string `json:"listitems,omitempty"`
	// Start of a range to fetch.
	Start int `json:"start,omitempty"`
	// Count is the number of items to fetch.
	Count int `json:"count,omitempty"`
}

// Result is returned from any JSON request.
type Result struct {
	Status     string `json:"status,omitempty"`
	StatusCode int    `json:"statuscode"`
	Token      string `json:"token,omitempty"`
}

// SetStatus fills in the status text from a code.
func (r *Result) SetStatus(code int) {
	s, ok := messages[code]
	if !ok {
		r.StatusCode = StatusOK
		r.Status = messages[StatusOK]
		return
	}
	r.StatusCode = code
	r.Status = s
}

func respond(w io.Writer, r interface{}) error {
	res, err := json.Marshal(r)
	if err != nil {
		return err
	}

	_, err = w.Write(res)
	if err != nil {
		return err
	}

	return nil
}
<commit_msg>Removed leftover Request structure.<commit_after>package main

import (
	"encoding/json"
	"io"
)

// Result is returned from any JSON request.
type Result struct {
	Status     string `json:"status,omitempty"`
	StatusCode int    `json:"statuscode"`
	Token      string `json:"token,omitempty"`
}

// SetStatus fills in the status text from a code.
func (r *Result) SetStatus(code int) {
	s, ok := messages[code]
	if !ok {
		r.StatusCode = StatusOK
		r.Status = messages[StatusOK]
		return
	}
	r.StatusCode = code
	r.Status = s
}

func respond(w io.Writer, r interface{}) error {
	res, err := json.Marshal(r)
	if err != nil {
		return err
	}

	_, err = w.Write(res)
	if err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package amazonebs

import (
	"fmt"
	"github.com/mitchellh/goamz/ec2"
	"github.com/mitchellh/multistep"
	"github.com/mitchellh/packer/packer"
	"log"
)

type stepRunSourceInstance struct {
	instance *ec2.Instance
}

func (s *stepRunSourceInstance) Run(state map[string]interface{}) multistep.StepAction {
	config := state["config"].(config)
	ec2conn := state["ec2"].(*ec2.EC2)
	keyName := state["keyPair"].(string)
	securityGroupId := state["securityGroupId"].(string)
	ui := state["ui"].(packer.Ui)

	runOpts := &ec2.RunInstances{
		KeyName:        keyName,
		ImageId:        config.SourceAmi,
		InstanceType:   config.InstanceType,
		MinCount:       0,
		MaxCount:       0,
		SecurityGroups: []ec2.SecurityGroup{ec2.SecurityGroup{Id: securityGroupId}},
	}

	ui.Say("Launching a source AWS instance...")
	runResp, err := ec2conn.RunInstances(runOpts)
	if err != nil {
		err := fmt.Errorf("Error launching source instance: %s", err)
		state["error"] = err
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	s.instance = &runResp.Instances[0]
	log.Printf("instance id: %s", s.instance.InstanceId)

	ui.Say("Waiting for instance to become ready...")
	s.instance, err = waitForState(ec2conn, s.instance, []string{"pending"}, "running")
	if err != nil {
		err := fmt.Errorf("Error waiting for instance to become ready: %s", err)
		state["error"] = err
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	state["instance"] = s.instance

	return multistep.ActionContinue
}

func (s *stepRunSourceInstance) Cleanup(state map[string]interface{}) {
	if s.instance == nil {
		return
	}

	ec2conn := state["ec2"].(*ec2.EC2)
	ui := state["ui"].(packer.Ui)

	ui.Say("Terminating the source AWS instance...")
	if _, err := ec2conn.TerminateInstances([]string{s.instance.InstanceId}); err != nil {
		ui.Error(fmt.Sprintf("Error terminating instance, may still be around: %s", err))
		return
	}

	pending := []string{"pending", "running", "shutting-down", "stopped", "stopping"}
	waitForState(ec2conn, s.instance, pending, "terminated")
}
<commit_msg>Add AWS instance id to normal output<commit_after>package amazonebs

import (
	"fmt"
	"github.com/mitchellh/goamz/ec2"
	"github.com/mitchellh/multistep"
	"github.com/mitchellh/packer/packer"
	"log"
)

type stepRunSourceInstance struct {
	instance *ec2.Instance
}

func (s *stepRunSourceInstance) Run(state map[string]interface{}) multistep.StepAction {
	config := state["config"].(config)
	ec2conn := state["ec2"].(*ec2.EC2)
	keyName := state["keyPair"].(string)
	securityGroupId := state["securityGroupId"].(string)
	ui := state["ui"].(packer.Ui)

	runOpts := &ec2.RunInstances{
		KeyName:        keyName,
		ImageId:        config.SourceAmi,
		InstanceType:   config.InstanceType,
		MinCount:       0,
		MaxCount:       0,
		SecurityGroups: []ec2.SecurityGroup{ec2.SecurityGroup{Id: securityGroupId}},
	}

	ui.Say("Launching a source AWS instance...")
	runResp, err := ec2conn.RunInstances(runOpts)
	if err != nil {
		err := fmt.Errorf("Error launching source instance: %s", err)
		state["error"] = err
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	s.instance = &runResp.Instances[0]
	log.Printf("instance id: %s", s.instance.InstanceId)

	ui.Say(fmt.Sprintf("Waiting for instance (%s) to become ready...", s.instance.InstanceId))
	s.instance, err = waitForState(ec2conn, s.instance, []string{"pending"}, "running")
	if err != nil {
		err := fmt.Errorf("Error waiting for instance (%s) to become ready: %s", s.instance.InstanceId, err)
		state["error"] = err
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	state["instance"] = s.instance

	return multistep.ActionContinue
}

func (s *stepRunSourceInstance) Cleanup(state map[string]interface{}) {
	if s.instance == nil {
		return
	}

	ec2conn := state["ec2"].(*ec2.EC2)
	ui := state["ui"].(packer.Ui)

	ui.Say("Terminating the source AWS instance...")
	if _, err := ec2conn.TerminateInstances([]string{s.instance.InstanceId}); err != nil {
		ui.Error(fmt.Sprintf("Error terminating instance, may still be around: %s", err))
		return
	}

	pending := []string{"pending", "running", "shutting-down", "stopped", "stopping"}
	waitForState(ec2conn, s.instance, pending, "terminated")
}
<|endoftext|>


<commit_before>package plugin

import (
	_ "github.com/mickael-kerjean/filestash/server/plugin/plg_starter_http"
	_ "github.com/mickael-kerjean/filestash/server/plugin/plg_starter_tor"
	_ "github.com/mickael-kerjean/filestash/server/plugin/plg_handler_console"
	_ "github.com/mickael-kerjean/filestash/server/plugin/plg_video_transcoder"
	_ "github.com/mickael-kerjean/filestash/server/plugin/plg_editor_onlyoffice"
	_ "github.com/mickael-kerjean/filestash/server/plugin/plg_handler_syncthing"
	_ "github.com/mickael-kerjean/filestash/server/plugin/plg_image_light"
	_ "github.com/mickael-kerjean/filestash/server/plugin/plg_backend_ftp"
	_ "github.com/mickael-kerjean/filestash/server/plugin/plg_backend_backblaze"
	_ "github.com/mickael-kerjean/filestash/server/plugin/plg_backend_dav"
	_ "github.com/mickael-kerjean/filestash/server/plugin/plg_backend_mysql"
	_ "github.com/mickael-kerjean/filestash/server/plugin/plg_backend_s3"
	_ "github.com/mickael-kerjean/filestash/server/plugin/plg_backend_ldap"
	_ "github.com/mickael-kerjean/filestash/server/plugin/plg_backend_dropbox"
	//_ "github.com/mickael-kerjean/filestash/server/plugin/plg_backend_samba"
	_ "github.com/mickael-kerjean/filestash/server/plugin/plg_security_scanner"
	_ "github.com/mickael-kerjean/filestash/server/plugin/plg_security_svg"
	. "github.com/mickael-kerjean/filestash/server/common"
)

func init() {
	Log.Debug("Plugin loader")
}
<commit_msg>fix (test): missing webdav backend<commit_after>package plugin

import (
	_ "github.com/mickael-kerjean/filestash/server/plugin/plg_starter_http"
	_ "github.com/mickael-kerjean/filestash/server/plugin/plg_starter_tor"
	_ "github.com/mickael-kerjean/filestash/server/plugin/plg_handler_console"
	_ "github.com/mickael-kerjean/filestash/server/plugin/plg_video_transcoder"
	_ "github.com/mickael-kerjean/filestash/server/plugin/plg_editor_onlyoffice"
	_ "github.com/mickael-kerjean/filestash/server/plugin/plg_handler_syncthing"
	_ "github.com/mickael-kerjean/filestash/server/plugin/plg_image_light"
	_ "github.com/mickael-kerjean/filestash/server/plugin/plg_backend_ftp"
	_ "github.com/mickael-kerjean/filestash/server/plugin/plg_backend_backblaze"
	_ "github.com/mickael-kerjean/filestash/server/plugin/plg_backend_dav"
	_ "github.com/mickael-kerjean/filestash/server/plugin/plg_backend_webdav"
	_ "github.com/mickael-kerjean/filestash/server/plugin/plg_backend_mysql"
	_ "github.com/mickael-kerjean/filestash/server/plugin/plg_backend_s3"
	_ "github.com/mickael-kerjean/filestash/server/plugin/plg_backend_ldap"
	_ "github.com/mickael-kerjean/filestash/server/plugin/plg_backend_dropbox"
	//_ "github.com/mickael-kerjean/filestash/server/plugin/plg_backend_samba"
	_ "github.com/mickael-kerjean/filestash/server/plugin/plg_security_scanner"
	_ "github.com/mickael-kerjean/filestash/server/plugin/plg_security_svg"
	. "github.com/mickael-kerjean/filestash/server/common"
)

func init() {
	Log.Debug("Plugin loader")
}
<|endoftext|>


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

package xorm

import (
	"fmt"
	"os"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
)

func TestStoreEngine(t *testing.T) {
	assert.NoError(t, prepareEngine())

	assert.NoError(t, testEngine.DropTables("user_store_engine"))

	type UserinfoStoreEngine struct {
		Id   int64
		Name string
	}

	assert.NoError(t, testEngine.StoreEngine("InnoDB").Table("user_store_engine").CreateTable(&UserinfoStoreEngine{}))
}

func TestCreateTable(t *testing.T) {
	assert.NoError(t, prepareEngine())

	assert.NoError(t, testEngine.DropTables("user_user"))

	type UserinfoCreateTable struct {
		Id   int64
		Name string
	}

	assert.NoError(t, testEngine.Table("user_user").CreateTable(&UserinfoCreateTable{}))
}

func TestCreateMultiTables(t *testing.T) {
	assert.NoError(t, prepareEngine())

	session := testEngine.NewSession()
	defer session.Close()

	type UserinfoMultiTable struct {
		Id   int64
		Name string
	}

	user := &UserinfoMultiTable{}
	assert.NoError(t, session.Begin())

	for i := 0; i < 10; i++ {
		tableName := fmt.Sprintf("user_%v", i)

		assert.NoError(t, session.DropTable(tableName))

		assert.NoError(t, session.Table(tableName).CreateTable(user))
	}

	assert.NoError(t, session.Commit())
}

type SyncTable1 struct {
	Id   int64
	Name string
	Dev  int `xorm:"index"`
}

type SyncTable2 struct {
	Id     int64
	Name   string `xorm:"unique"`
	Number string `xorm:"index"`
	Dev    int
	Age    int
}

func (SyncTable2) TableName() string {
	return "sync_table1"
}

func TestSyncTable(t *testing.T) {
	assert.NoError(t, prepareEngine())

	assert.NoError(t, testEngine.Sync2(new(SyncTable1)))

	assert.NoError(t, testEngine.Sync2(new(SyncTable2)))
}

func TestIsTableExist(t *testing.T) {
	assert.NoError(t, prepareEngine())

	exist, err := testEngine.IsTableExist(new(CustomTableName))
	assert.NoError(t, err)
	assert.False(t, exist)

	assert.NoError(t, testEngine.CreateTables(new(CustomTableName)))

	exist, err = testEngine.IsTableExist(new(CustomTableName))
	assert.NoError(t, err)
	assert.True(t, exist)
}

func TestIsTableEmpty(t *testing.T) {
	assert.NoError(t, prepareEngine())

	type NumericEmpty struct {
		Numeric float64 `xorm:"numeric(26,2)"`
	}

	type PictureEmpty struct {
		Id          int64
		Url         string `xorm:"unique"` //image's url
		Title       string
		Description string
		Created     time.Time `xorm:"created"`
		ILike       int
		PageView    int
		From_url    string
		Pre_url     string `xorm:"unique"` //pre view image's url
		Uid         int64
	}

	assert.NoError(t, testEngine.DropTables(&PictureEmpty{}, &NumericEmpty{}))

	assert.NoError(t, testEngine.Sync2(new(PictureEmpty), new(NumericEmpty)))

	isEmpty, err := testEngine.IsTableEmpty(&PictureEmpty{})
	assert.NoError(t, err)
	assert.True(t, isEmpty)

	tbName := testEngine.GetTableMapper().Obj2Table("PictureEmpty")
	isEmpty, err = testEngine.IsTableEmpty(tbName)
	assert.NoError(t, err)
	assert.True(t, isEmpty)
}

type CustomTableName struct {
	Id   int64
	Name string
}

func (c *CustomTableName) TableName() string {
	return "customtablename"
}

func TestCustomTableName(t *testing.T) {
	assert.NoError(t, prepareEngine())

	c := new(CustomTableName)
	assert.NoError(t, testEngine.DropTables(c))

	assert.NoError(t, testEngine.CreateTables(c))
}

func TestDump(t *testing.T) {
	assert.NoError(t, prepareEngine())

	fp := testEngine.Dialect().URI().DbName + ".sql"
	os.Remove(fp)
	assert.NoError(t, testEngine.DumpAllToFile(fp))
}

type IndexOrUnique struct {
	Id        int64
	Index     int `xorm:"index"`
	Unique    int `xorm:"unique"`
	Group1    int `xorm:"index(ttt)"`
	Group2    int `xorm:"index(ttt)"`
	UniGroup1 int `xorm:"unique(lll)"`
	UniGroup2 int `xorm:"unique(lll)"`
}

func TestIndexAndUnique(t *testing.T) {
	assert.NoError(t, prepareEngine())

	assert.NoError(t, testEngine.CreateTables(&IndexOrUnique{}))

	assert.NoError(t, testEngine.DropTables(&IndexOrUnique{}))

	assert.NoError(t, testEngine.CreateTables(&IndexOrUnique{}))

	assert.NoError(t, testEngine.CreateIndexes(&IndexOrUnique{}))

	assert.NoError(t, testEngine.CreateUniques(&IndexOrUnique{}))

	assert.NoError(t, testEngine.DropIndexes(&IndexOrUnique{}))
}

func TestMetaInfo(t *testing.T) {
	assert.NoError(t, prepareEngine())
	assert.NoError(t, testEngine.Sync2(new(CustomTableName), new(IndexOrUnique)))

	tables, err := testEngine.DBMetas()
	assert.NoError(t, err)
	assert.EqualValues(t, 2, len(tables))
	tableNames := []string{tables[0].Name, tables[1].Name}
	assert.Contains(t, tableNames, "customtablename")
	assert.Contains(t, tableNames, "index_or_unique")
}

func TestCharst(t *testing.T) {
	assert.NoError(t, prepareEngine())

	err := testEngine.DropTables("user_charset")
	if err != nil {
		t.Error(err)
		panic(err)
	}

	err = testEngine.Charset("utf8").Table("user_charset").CreateTable(&Userinfo{})
	if err != nil {
		t.Error(err)
		panic(err)
	}
}

func TestSync2_1(t *testing.T) {
	type WxTest struct {
		Id                 int   `xorm:"not null pk autoincr INT(64)`
		Passport_user_type int16 `xorm:"null int"`
		Id_delete          int8  `xorm:"null int default 1"`
	}

	assert.NoError(t, prepareEngine())

	assert.NoError(t, testEngine.DropTables("wx_test"))
	assert.NoError(t, testEngine.Sync2(new(WxTest)))
	assert.NoError(t, testEngine.Sync2(new(WxTest)))
}
<commit_msg>add test for unique<commit_after>// Copyright 2017 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package xorm

import (
	"fmt"
	"os"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
)

func TestStoreEngine(t *testing.T) {
	assert.NoError(t, prepareEngine())

	assert.NoError(t, testEngine.DropTables("user_store_engine"))

	type UserinfoStoreEngine struct {
		Id   int64
		Name string
	}

	assert.NoError(t, testEngine.StoreEngine("InnoDB").Table("user_store_engine").CreateTable(&UserinfoStoreEngine{}))
}

func TestCreateTable(t *testing.T) {
	assert.NoError(t, prepareEngine())

	assert.NoError(t, testEngine.DropTables("user_user"))

	type UserinfoCreateTable struct {
		Id   int64
		Name string
	}

	assert.NoError(t, testEngine.Table("user_user").CreateTable(&UserinfoCreateTable{}))
}

func TestCreateMultiTables(t *testing.T) {
	assert.NoError(t, prepareEngine())

	session := testEngine.NewSession()
	defer session.Close()

	type UserinfoMultiTable struct {
		Id   int64
		Name string
	}

	user := &UserinfoMultiTable{}
	assert.NoError(t, session.Begin())

	for i := 0; i < 10; i++ {
		tableName := fmt.Sprintf("user_%v", i)

		assert.NoError(t, session.DropTable(tableName))

		assert.NoError(t, session.Table(tableName).CreateTable(user))
	}

	assert.NoError(t, session.Commit())
}

type SyncTable1 struct {
	Id   int64
	Name string
	Dev  int `xorm:"index"`
}

type SyncTable2 struct {
	Id     int64
	Name   string `xorm:"unique"`
	Number string `xorm:"index"`
	Dev    int
	Age    int
}

func (SyncTable2) TableName() string {
	return "sync_table1"
}

func TestSyncTable(t *testing.T) {
	assert.NoError(t, prepareEngine())

	assert.NoError(t, testEngine.Sync2(new(SyncTable1)))

	assert.NoError(t, testEngine.Sync2(new(SyncTable2)))
}

func TestIsTableExist(t *testing.T) {
	assert.NoError(t, prepareEngine())

	exist, err := testEngine.IsTableExist(new(CustomTableName))
	assert.NoError(t, err)
	assert.False(t, exist)

	assert.NoError(t, testEngine.CreateTables(new(CustomTableName)))

	exist, err = testEngine.IsTableExist(new(CustomTableName))
	assert.NoError(t, err)
	assert.True(t, exist)
}

func TestIsTableEmpty(t *testing.T) {
	assert.NoError(t, prepareEngine())

	type NumericEmpty struct {
		Numeric float64 `xorm:"numeric(26,2)"`
	}

	type PictureEmpty struct {
		Id          int64
		Url         string `xorm:"unique"` //image's url
		Title       string
		Description string
		Created     time.Time `xorm:"created"`
		ILike       int
		PageView    int
		From_url    string
		Pre_url     string `xorm:"unique"` //pre view image's url
		Uid         int64
	}

	assert.NoError(t, testEngine.DropTables(&PictureEmpty{}, &NumericEmpty{}))

	assert.NoError(t, testEngine.Sync2(new(PictureEmpty), new(NumericEmpty)))

	isEmpty, err := testEngine.IsTableEmpty(&PictureEmpty{})
	assert.NoError(t, err)
	assert.True(t, isEmpty)

	tbName := testEngine.GetTableMapper().Obj2Table("PictureEmpty")
	isEmpty, err = testEngine.IsTableEmpty(tbName)
	assert.NoError(t, err)
	assert.True(t, isEmpty)
}

type CustomTableName struct {
	Id   int64
	Name string
}

func (c *CustomTableName) TableName() string {
	return "customtablename"
}

func TestCustomTableName(t *testing.T) {
	assert.NoError(t, prepareEngine())

	c := new(CustomTableName)
	assert.NoError(t, testEngine.DropTables(c))

	assert.NoError(t, testEngine.CreateTables(c))
}

func TestDump(t *testing.T) {
	assert.NoError(t, prepareEngine())

	fp := testEngine.Dialect().URI().DbName + ".sql"
	os.Remove(fp)
	assert.NoError(t, testEngine.DumpAllToFile(fp))
}

type IndexOrUnique struct {
	Id        int64
	Index     int `xorm:"index"`
	Unique    int `xorm:"unique"`
	Group1    int `xorm:"index(ttt)"`
	Group2    int `xorm:"index(ttt)"`
	UniGroup1 int `xorm:"unique(lll)"`
	UniGroup2 int `xorm:"unique(lll)"`
}

func TestIndexAndUnique(t *testing.T) {
	assert.NoError(t, prepareEngine())

	assert.NoError(t, testEngine.CreateTables(&IndexOrUnique{}))

	assert.NoError(t, testEngine.DropTables(&IndexOrUnique{}))

	assert.NoError(t, testEngine.CreateTables(&IndexOrUnique{}))

	assert.NoError(t, testEngine.CreateIndexes(&IndexOrUnique{}))

	assert.NoError(t, testEngine.CreateUniques(&IndexOrUnique{}))

	assert.NoError(t, testEngine.DropIndexes(&IndexOrUnique{}))
}

func TestMetaInfo(t *testing.T) {
	assert.NoError(t, prepareEngine())
	assert.NoError(t, testEngine.Sync2(new(CustomTableName), new(IndexOrUnique)))

	tables, err := testEngine.DBMetas()
	assert.NoError(t, err)
	assert.EqualValues(t, 2, len(tables))
	tableNames := []string{tables[0].Name, tables[1].Name}
	assert.Contains(t, tableNames, "customtablename")
	assert.Contains(t, tableNames, "index_or_unique")
}

func TestCharst(t *testing.T) {
	assert.NoError(t, prepareEngine())

	err := testEngine.DropTables("user_charset")
	if err != nil {
		t.Error(err)
		panic(err)
	}

	err = testEngine.Charset("utf8").Table("user_charset").CreateTable(&Userinfo{})
	if err != nil {
		t.Error(err)
		panic(err)
	}
}

func TestSync2_1(t *testing.T) {
	type WxTest struct {
		Id                 int   `xorm:"not null pk autoincr INT(64)`
		Passport_user_type int16 `xorm:"null int"`
		Id_delete          int8  `xorm:"null int default 1"`
	}

	assert.NoError(t, prepareEngine())

	assert.NoError(t, testEngine.DropTables("wx_test"))
	assert.NoError(t, testEngine.Sync2(new(WxTest)))
	assert.NoError(t, testEngine.Sync2(new(WxTest)))
}

func TestUnique_1(t *testing.T) {
	type UserUnique struct {
		Id        int64
		UserName  string    `xorm:"unique varchar(25) not null"`
		Password  string    `xorm:"varchar(255) not null"`
		Admin     bool      `xorm:"not null"`
		CreatedAt time.Time `xorm:"created"`
		UpdatedAt time.Time `xorm:"updated"`
	}

	assert.NoError(t, prepareEngine())

	assert.NoError(t, testEngine.DropTables("user_unique"))
	assert.NoError(t, testEngine.Sync2(new(UserUnique)))

	assert.NoError(t, testEngine.DropTables("user_unique"))
	assert.NoError(t, testEngine.CreateTables(new(UserUnique)))
	assert.NoError(t, testEngine.CreateUniques(new(UserUnique)))
}
<|endoftext|>


<commit_before>package signer

import (
	"bytes"
	"crypto/x509"
	"encoding/asn1"
	"encoding/hex"
	"fmt"
	"reflect"
	"testing"

	"github.com/cloudflare/cfssl/config"
)

func TestAppendIf(t *testing.T) {
	s := ""
	a := make([]string, 0, 5)
	appendIf(s, &a)
	if len(a) != 0 {
		t.Fatal("appendIf should not append to a with an empty s")
	}
	s = "test"
	appendIf(s, &a)
	if len(a[0]) != 4 {
		t.Fatal("appendIf should append s to a")
	}
}

func TestSplitHosts(t *testing.T) {
	list := SplitHosts("")
	if list != nil {
		t.Fatal("SplitHost should return nil with empty input")
	}

	list = SplitHosts("single.domain")
	if len(list) != 1 {
		t.Fatal("SplitHost fails to split single domain")
	}

	list = SplitHosts("comma,separated,values")
	if len(list) != 3 {
		t.Fatal("SplitHost fails to split multiple domains")
	}
	if list[0] != "comma" || list[1] != "separated" || list[2] != "values" {
		t.Fatal("SplitHost fails to split multiple domains")
	}
}

func TestAddPolicies(t *testing.T) {
	var cert x509.Certificate
	addPolicies(&cert, []config.CertificatePolicy{
		config.CertificatePolicy{
			ID: config.OID([]int{1, 2, 3, 4}),
		},
	})

	if len(cert.ExtraExtensions) != 1 {
		t.Fatal("No extension added")
	}
	ext := cert.ExtraExtensions[0]
	if !reflect.DeepEqual(ext.Id, asn1.ObjectIdentifier{2, 5, 29, 32}) {
		t.Fatal(fmt.Sprintf("Wrong OID for policy qualifier %v", ext.Id))
	}
	if ext.Critical {
		t.Fatal("Policy qualifier marked critical")
	}
	expectedBytes, _ := hex.DecodeString("3007300506032a0304")
	if !bytes.Equal(ext.Value, expectedBytes) {
		t.Fatal(fmt.Sprintf("Value didn't match expected bytes: got %s, expected %s",
			hex.EncodeToString(ext.Value), hex.EncodeToString(expectedBytes)))
	}
}

func TestAddPoliciesWithQualifiers(t *testing.T) {
	var cert x509.Certificate
	addPolicies(&cert, []config.CertificatePolicy{
		config.CertificatePolicy{
			ID: config.OID([]int{1, 2, 3, 4}),
			Qualifiers: []config.CertificatePolicyQualifier{
				config.CertificatePolicyQualifier{
					Type:  "id-qt-cps",
					Value: "http://example.com/cps",
				},
				config.CertificatePolicyQualifier{
					Type:  "id-qt-unotice",
					Value: "Do What Thou Wilt",
				},
			},
		},
	})

	if len(cert.ExtraExtensions) != 1 {
		t.Fatal("No extension added")
	}
	ext := cert.ExtraExtensions[0]
	if !reflect.DeepEqual(ext.Id, asn1.ObjectIdentifier{2, 5, 29, 32}) {
		t.Fatal(fmt.Sprintf("Wrong OID for policy qualifier %v", ext.Id))
	}
	if ext.Critical {
		t.Fatal("Policy qualifier marked critical")
	}
	expectedBytes, _ := hex.DecodeString("304e304c06032a03043045302206082b060105050702011616687474703a2f2f6578616d706c652e636f6d2f637073301f06082b0601050507020230130c11446f20576861742054686f752057696c74")
	if !bytes.Equal(ext.Value, expectedBytes) {
		t.Fatal(fmt.Sprintf("Value didn't match expected bytes: %s vs %s",
			hex.EncodeToString(ext.Value), hex.EncodeToString(expectedBytes)))
	}
}
<commit_msg>add tests for Subject.Name<commit_after>package signer

import (
	"bytes"
	"crypto/x509"
	"encoding/asn1"
	"encoding/hex"
	"fmt"
	"reflect"
	"testing"

	"github.com/cloudflare/cfssl/config"
	"github.com/cloudflare/cfssl/csr"
)

func TestAppendIf(t *testing.T) {
	s := ""
	a := make([]string, 0, 5)
	appendIf(s, &a)
	if len(a) != 0 {
		t.Fatal("appendIf should not append to a with an empty s")
	}
	s = "test"
	appendIf(s, &a)
	if len(a[0]) != 4 {
		t.Fatal("appendIf should append s to a")
	}
}

func TestSplitHosts(t *testing.T) {
	list := SplitHosts("")
	if list != nil {
		t.Fatal("SplitHost should return nil with empty input")
	}

	list = SplitHosts("single.domain")
	if len(list) != 1 {
		t.Fatal("SplitHost fails to split single domain")
	}

	list = SplitHosts("comma,separated,values")
	if len(list) != 3 {
		t.Fatal("SplitHost fails to split multiple domains")
	}
	if list[0] != "comma" || list[1] != "separated" || list[2] != "values" {
		t.Fatal("SplitHost fails to split multiple domains")
	}
}

func TestAddPolicies(t *testing.T) {
	var cert x509.Certificate
	addPolicies(&cert, []config.CertificatePolicy{
		config.CertificatePolicy{
			ID: config.OID([]int{1, 2, 3, 4}),
		},
	})

	if len(cert.ExtraExtensions) != 1 {
		t.Fatal("No extension added")
	}
	ext := cert.ExtraExtensions[0]
	if !reflect.DeepEqual(ext.Id, asn1.ObjectIdentifier{2, 5, 29, 32}) {
		t.Fatal(fmt.Sprintf("Wrong OID for policy qualifier %v", ext.Id))
	}
	if ext.Critical {
		t.Fatal("Policy qualifier marked critical")
	}
	expectedBytes, _ := hex.DecodeString("3007300506032a0304")
	if !bytes.Equal(ext.Value, expectedBytes) {
		t.Fatal(fmt.Sprintf("Value didn't match expected bytes: got %s, expected %s",
			hex.EncodeToString(ext.Value), hex.EncodeToString(expectedBytes)))
	}
}

func TestAddPoliciesWithQualifiers(t *testing.T) {
	var cert x509.Certificate
	addPolicies(&cert, []config.CertificatePolicy{
		config.CertificatePolicy{
			ID: config.OID([]int{1, 2, 3, 4}),
			Qualifiers: []config.CertificatePolicyQualifier{
				config.CertificatePolicyQualifier{
					Type:  "id-qt-cps",
					Value: "http://example.com/cps",
				},
				config.CertificatePolicyQualifier{
					Type:  "id-qt-unotice",
					Value: "Do What Thou Wilt",
				},
			},
		},
	})

	if len(cert.ExtraExtensions) != 1 {
		t.Fatal("No extension added")
	}
	ext := cert.ExtraExtensions[0]
	if !reflect.DeepEqual(ext.Id, asn1.ObjectIdentifier{2, 5, 29, 32}) {
		t.Fatal(fmt.Sprintf("Wrong OID for policy qualifier %v", ext.Id))
	}
	if ext.Critical {
		t.Fatal("Policy qualifier marked critical")
	}
	expectedBytes, _ := hex.DecodeString("304e304c06032a03043045302206082b060105050702011616687474703a2f2f6578616d706c652e636f6d2f637073301f06082b0601050507020230130c11446f20576861742054686f752057696c74")
	if !bytes.Equal(ext.Value, expectedBytes) {
		t.Fatal(fmt.Sprintf("Value didn't match expected bytes: %s vs %s",
			hex.EncodeToString(ext.Value), hex.EncodeToString(expectedBytes)))
	}
}

func TestName(t *testing.T) {
	sub := &Subject{
		CN: "foobar",
		Names: []csr.Name{
			{
				C:  "US",
				ST: "CA",
				L:  "Cool Locality",
				O:  "Cool Org",
				OU: "Really Cool Sub Org",
			},
			{
				L: "Another Cool Locality",
			},
		},
		SerialNumber: "deadbeef",
	}
	name := sub.Name()
	if name.CommonName != sub.CN {
		t.Errorf("CommonName: want %#v, got %#v", sub.CN, name.CommonName)
	}
	if name.SerialNumber != sub.SerialNumber {
		t.Errorf("SerialNumber: want %#v, got %#v", sub.SerialNumber, name.SerialNumber)
	}
	if !reflect.DeepEqual([]string{"US"}, name.Country) {
		t.Errorf("Country: want %s, got %s", []string{"US"}, name.Country)
	}
	if !reflect.DeepEqual([]string{"CA"}, name.Province) {
		t.Errorf("Province: want %s, got %s", []string{"CA"}, name.Province)
	}
	if !reflect.DeepEqual([]string{"Cool Org"}, name.Organization) {
		t.Errorf("Organization: want %s, got %s", []string{"Cool Org"}, name.Organization)
	}
	if !reflect.DeepEqual([]string{"Really Cool Sub Org"}, name.OrganizationalUnit) {
		t.Errorf("Province: want %s, got %s", []string{"Really Cool Sub Org"}, name.OrganizationalUnit)
	}
	if !reflect.DeepEqual([]string{"Cool Locality", "Another Cool Locality"}, name.Locality) {
		t.Errorf("Locality: want %s, got %s", []string{"CA"}, name.Locality)
	}

}
<|endoftext|>


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

package syscall

import (
	"unsafe"
)

type SysProcAttr struct {
	Chroot     string      // Chroot.
	Credential *Credential // Credential.
	Setsid     bool        // Create session.
	Setpgid    bool        // Set process group ID to Pgid, or, if Pgid == 0, to new pid.
	Setctty    bool        // Set controlling terminal to fd Ctty
	Noctty     bool        // Detach fd 0 from controlling terminal
	Ctty       int         // Controlling TTY fd
	Foreground bool        // Place child's process group in foreground. (Implies Setpgid. Uses Ctty as fd of controlling TTY)
	Pgid       int         // Child's process group ID if Setpgid.
}

// Implemented in runtime package.
func runtime_BeforeFork()
func runtime_AfterFork()

func chdir(path uintptr) (err Errno)
func chroot1(path uintptr) (err Errno)
func close(fd uintptr) (err Errno)
func execve(path uintptr, argv uintptr, envp uintptr) (err Errno)
func exit(code uintptr)
func fcntl1(fd uintptr, cmd uintptr, arg uintptr) (val uintptr, err Errno)
func forkx(flags uintptr) (pid uintptr, err Errno)
func getpid() (pid uintptr, err Errno)
func ioctl(fd uintptr, req uintptr, arg uintptr) (err Errno)
func setgid(gid uintptr) (err Errno)
func setgroups1(ngid uintptr, gid uintptr) (err Errno)
func setsid() (pid uintptr, err Errno)
func setuid(uid uintptr) (err Errno)
func setpgid(pid uintptr, pgid uintptr) (err Errno)
func write1(fd uintptr, buf uintptr, nbyte uintptr) (n uintptr, err Errno)

// Fork, dup fd onto 0..len(fd), and exec(argv0, argvv, envv) in child.
// If a dup or exec fails, write the errno error to pipe.
// (Pipe is close-on-exec so if exec succeeds, it will be closed.)
// In the child, this function must not acquire any locks, because
// they might have been locked at the time of the fork. This means
// no rescheduling, no malloc calls, and no new stack segments.
//
// We call hand-crafted syscalls, implemented in
// ../runtime/syscall_solaris.go, rather than generated libc wrappers
// because we need to avoid lazy-loading the functions (might malloc,
// split the stack, or acquire mutexes). We can't call RawSyscall
// because it's not safe even for BSD-subsystem calls.
//go:norace
func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err Errno) {
	// Declare all variables at top in case any
	// declarations require heap allocation (e.g., err1).
	var (
		r1     uintptr
		err1   Errno
		nextfd int
		i      int
	)

	// guard against side effects of shuffling fds below.
	// Make sure that nextfd is beyond any currently open files so
	// that we can't run the risk of overwriting any of them.
	fd := make([]int, len(attr.Files))
	nextfd = len(attr.Files)
	for i, ufd := range attr.Files {
		if nextfd < int(ufd) {
			nextfd = int(ufd)
		}
		fd[i] = int(ufd)
	}
	nextfd++

	// About to call fork.
	// No more allocation or calls of non-assembly functions.
	runtime_BeforeFork()
	r1, err1 = forkx(0x1) // FORK_NOSIGCHLD
	if err1 != 0 {
		runtime_AfterFork()
		return 0, err1
	}

	if r1 != 0 {
		// parent; return PID
		runtime_AfterFork()
		return int(r1), 0
	}

	// Fork succeeded, now in child.

	// Session ID
	if sys.Setsid {
		_, err1 = setsid()
		if err1 != 0 {
			goto childerror
		}
	}

	// Set process group
	if sys.Setpgid || sys.Foreground {
		// Place child in process group.
		err1 = setpgid(0, uintptr(sys.Pgid))
		if err1 != 0 {
			goto childerror
		}
	}

	if sys.Foreground {
		pgrp := sys.Pgid
		if pgrp == 0 {
			r1, err1 = getpid()
			if err1 != 0 {
				goto childerror
			}

			pgrp = int(r1)
		}

		// Place process group in foreground.
		err1 = ioctl(uintptr(sys.Ctty), uintptr(TIOCSPGRP), uintptr(unsafe.Pointer(&pgrp)))
		if err1 != 0 {
			goto childerror
		}
	}

	// Chroot
	if chroot != nil {
		err1 = chroot1(uintptr(unsafe.Pointer(chroot)))
		if err1 != 0 {
			goto childerror
		}
	}

	// User and groups
	if cred := sys.Credential; cred != nil {
		ngroups := uintptr(len(cred.Groups))
		groups := uintptr(0)
		if ngroups > 0 {
			groups = uintptr(unsafe.Pointer(&cred.Groups[0]))
		}
		err1 = setgroups1(ngroups, groups)
		if err1 != 0 {
			goto childerror
		}
		err1 = setgid(uintptr(cred.Gid))
		if err1 != 0 {
			goto childerror
		}
		err1 = setuid(uintptr(cred.Uid))
		if err1 != 0 {
			goto childerror
		}
	}

	// Chdir
	if dir != nil {
		err1 = chdir(uintptr(unsafe.Pointer(dir)))
		if err1 != 0 {
			goto childerror
		}
	}

	// Pass 1: look for fd[i] < i and move those up above len(fd)
	// so that pass 2 won't stomp on an fd it needs later.
	if pipe < nextfd {
		_, err1 = fcntl1(uintptr(pipe), F_DUP2FD, uintptr(nextfd))
		if err1 != 0 {
			goto childerror
		}
		fcntl1(uintptr(nextfd), F_SETFD, FD_CLOEXEC)
		pipe = nextfd
		nextfd++
	}
	for i = 0; i < len(fd); i++ {
		if fd[i] >= 0 && fd[i] < int(i) {
			if nextfd == pipe { // don't stomp on pipe
				nextfd++
			}
			_, err1 = fcntl1(uintptr(fd[i]), F_DUP2FD, uintptr(nextfd))
			if err1 != 0 {
				goto childerror
			}
			fcntl1(uintptr(nextfd), F_SETFD, FD_CLOEXEC)
			fd[i] = nextfd
			nextfd++
		}
	}

	// Pass 2: dup fd[i] down onto i.
	for i = 0; i < len(fd); i++ {
		if fd[i] == -1 {
			close(uintptr(i))
			continue
		}
		if fd[i] == int(i) {
			// dup2(i, i) won't clear close-on-exec flag on Linux,
			// probably not elsewhere either.
			_, err1 = fcntl1(uintptr(fd[i]), F_SETFD, 0)
			if err1 != 0 {
				goto childerror
			}
			continue
		}
		// The new fd is created NOT close-on-exec,
		// which is exactly what we want.
		_, err1 = fcntl1(uintptr(fd[i]), F_DUP2FD, uintptr(i))
		if err1 != 0 {
			goto childerror
		}
	}

	// By convention, we don't close-on-exec the fds we are
	// started with, so if len(fd) < 3, close 0, 1, 2 as needed.
	// Programs that know they inherit fds >= 3 will need
	// to set them close-on-exec.
	for i = len(fd); i < 3; i++ {
		close(uintptr(i))
	}

	// Detach fd 0 from tty
	if sys.Noctty {
		err1 = ioctl(0, uintptr(TIOCNOTTY), 0)
		if err1 != 0 {
			goto childerror
		}
	}

	// Set the controlling TTY to Ctty
	if sys.Setctty {
		err1 = ioctl(uintptr(sys.Ctty), uintptr(TIOCSCTTY), 0)
		if err1 != 0 {
			goto childerror
		}
	}

	// Time to exec.
	err1 = execve(
		uintptr(unsafe.Pointer(argv0)),
		uintptr(unsafe.Pointer(&argv[0])),
		uintptr(unsafe.Pointer(&envv[0])))

childerror:
	// send error code on pipe
	write1(uintptr(pipe), uintptr(unsafe.Pointer(&err1)), unsafe.Sizeof(err1))
	for {
		exit(253)
	}
}

// Try to open a pipe with O_CLOEXEC set on both file descriptors.
func forkExecPipe(p []int) error {
	err := Pipe(p)
	if err != nil {
		return err
	}
	_, err = fcntl(p[0], F_SETFD, FD_CLOEXEC)
	if err != nil {
		return err
	}
	_, err = fcntl(p[1], F_SETFD, FD_CLOEXEC)
	return err
}
<commit_msg>runtime: fix process group setting for sparc64<commit_after>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package syscall

import (
	"unsafe"
)

type SysProcAttr struct {
	Chroot     string      // Chroot.
	Credential *Credential // Credential.
	Setsid     bool        // Create session.
	Setpgid    bool        // Set process group ID to Pgid, or, if Pgid == 0, to new pid.
	Setctty    bool        // Set controlling terminal to fd Ctty
	Noctty     bool        // Detach fd 0 from controlling terminal
	Ctty       int         // Controlling TTY fd
	Foreground bool        // Place child's process group in foreground. (Implies Setpgid. Uses Ctty as fd of controlling TTY)
	Pgid       int         // Child's process group ID if Setpgid.
}

// Implemented in runtime package.
func runtime_BeforeFork()
func runtime_AfterFork()

func chdir(path uintptr) (err Errno)
func chroot1(path uintptr) (err Errno)
func close(fd uintptr) (err Errno)
func execve(path uintptr, argv uintptr, envp uintptr) (err Errno)
func exit(code uintptr)
func fcntl1(fd uintptr, cmd uintptr, arg uintptr) (val uintptr, err Errno)
func forkx(flags uintptr) (pid uintptr, err Errno)
func getpid() (pid uintptr, err Errno)
func ioctl(fd uintptr, req uintptr, arg uintptr) (err Errno)
func setgid(gid uintptr) (err Errno)
func setgroups1(ngid uintptr, gid uintptr) (err Errno)
func setsid() (pid uintptr, err Errno)
func setuid(uid uintptr) (err Errno)
func setpgid(pid uintptr, pgid uintptr) (err Errno)
func write1(fd uintptr, buf uintptr, nbyte uintptr) (n uintptr, err Errno)

// Fork, dup fd onto 0..len(fd), and exec(argv0, argvv, envv) in child.
// If a dup or exec fails, write the errno error to pipe.
// (Pipe is close-on-exec so if exec succeeds, it will be closed.)
// In the child, this function must not acquire any locks, because
// they might have been locked at the time of the fork. This means
// no rescheduling, no malloc calls, and no new stack segments.
//
// We call hand-crafted syscalls, implemented in
// ../runtime/syscall_solaris.go, rather than generated libc wrappers
// because we need to avoid lazy-loading the functions (might malloc,
// split the stack, or acquire mutexes). We can't call RawSyscall
// because it's not safe even for BSD-subsystem calls.
//go:norace
func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err Errno) {
	// Declare all variables at top in case any
	// declarations require heap allocation (e.g., err1).
	var (
		r1     uintptr
		err1   Errno
		nextfd int
		i      int
	)

	// guard against side effects of shuffling fds below.
	// Make sure that nextfd is beyond any currently open files so
	// that we can't run the risk of overwriting any of them.
	fd := make([]int, len(attr.Files))
	nextfd = len(attr.Files)
	for i, ufd := range attr.Files {
		if nextfd < int(ufd) {
			nextfd = int(ufd)
		}
		fd[i] = int(ufd)
	}
	nextfd++

	// About to call fork.
	// No more allocation or calls of non-assembly functions.
	runtime_BeforeFork()
	r1, err1 = forkx(0x1) // FORK_NOSIGCHLD
	if err1 != 0 {
		runtime_AfterFork()
		return 0, err1
	}

	if r1 != 0 {
		// parent; return PID
		runtime_AfterFork()
		return int(r1), 0
	}

	// Fork succeeded, now in child.

	// Session ID
	if sys.Setsid {
		_, err1 = setsid()
		if err1 != 0 {
			goto childerror
		}
	}

	// Set process group
	if sys.Setpgid || sys.Foreground {
		// Place child in process group.
		err1 = setpgid(0, uintptr(sys.Pgid))
		if err1 != 0 {
			goto childerror
		}
	}

	if sys.Foreground {
		pgrp := int32(sys.Pgid)
		if pgrp == 0 {
			r1, err1 = getpid()
			if err1 != 0 {
				goto childerror
			}

			pgrp = int32(r1)
		}

		// Place process group in foreground.
		err1 = ioctl(uintptr(sys.Ctty), uintptr(TIOCSPGRP), uintptr(unsafe.Pointer(&pgrp)))
		if err1 != 0 {
			goto childerror
		}
	}

	// Chroot
	if chroot != nil {
		err1 = chroot1(uintptr(unsafe.Pointer(chroot)))
		if err1 != 0 {
			goto childerror
		}
	}

	// User and groups
	if cred := sys.Credential; cred != nil {
		ngroups := uintptr(len(cred.Groups))
		groups := uintptr(0)
		if ngroups > 0 {
			groups = uintptr(unsafe.Pointer(&cred.Groups[0]))
		}
		err1 = setgroups1(ngroups, groups)
		if err1 != 0 {
			goto childerror
		}
		err1 = setgid(uintptr(cred.Gid))
		if err1 != 0 {
			goto childerror
		}
		err1 = setuid(uintptr(cred.Uid))
		if err1 != 0 {
			goto childerror
		}
	}

	// Chdir
	if dir != nil {
		err1 = chdir(uintptr(unsafe.Pointer(dir)))
		if err1 != 0 {
			goto childerror
		}
	}

	// Pass 1: look for fd[i] < i and move those up above len(fd)
	// so that pass 2 won't stomp on an fd it needs later.
	if pipe < nextfd {
		_, err1 = fcntl1(uintptr(pipe), F_DUP2FD, uintptr(nextfd))
		if err1 != 0 {
			goto childerror
		}
		fcntl1(uintptr(nextfd), F_SETFD, FD_CLOEXEC)
		pipe = nextfd
		nextfd++
	}
	for i = 0; i < len(fd); i++ {
		if fd[i] >= 0 && fd[i] < int(i) {
			if nextfd == pipe { // don't stomp on pipe
				nextfd++
			}
			_, err1 = fcntl1(uintptr(fd[i]), F_DUP2FD, uintptr(nextfd))
			if err1 != 0 {
				goto childerror
			}
			fcntl1(uintptr(nextfd), F_SETFD, FD_CLOEXEC)
			fd[i] = nextfd
			nextfd++
		}
	}

	// Pass 2: dup fd[i] down onto i.
	for i = 0; i < len(fd); i++ {
		if fd[i] == -1 {
			close(uintptr(i))
			continue
		}
		if fd[i] == int(i) {
			// dup2(i, i) won't clear close-on-exec flag on Linux,
			// probably not elsewhere either.
			_, err1 = fcntl1(uintptr(fd[i]), F_SETFD, 0)
			if err1 != 0 {
				goto childerror
			}
			continue
		}
		// The new fd is created NOT close-on-exec,
		// which is exactly what we want.
		_, err1 = fcntl1(uintptr(fd[i]), F_DUP2FD, uintptr(i))
		if err1 != 0 {
			goto childerror
		}
	}

	// By convention, we don't close-on-exec the fds we are
	// started with, so if len(fd) < 3, close 0, 1, 2 as needed.
	// Programs that know they inherit fds >= 3 will need
	// to set them close-on-exec.
	for i = len(fd); i < 3; i++ {
		close(uintptr(i))
	}

	// Detach fd 0 from tty
	if sys.Noctty {
		err1 = ioctl(0, uintptr(TIOCNOTTY), 0)
		if err1 != 0 {
			goto childerror
		}
	}

	// Set the controlling TTY to Ctty
	if sys.Setctty {
		err1 = ioctl(uintptr(sys.Ctty), uintptr(TIOCSCTTY), 0)
		if err1 != 0 {
			goto childerror
		}
	}

	// Time to exec.
	err1 = execve(
		uintptr(unsafe.Pointer(argv0)),
		uintptr(unsafe.Pointer(&argv[0])),
		uintptr(unsafe.Pointer(&envv[0])))

childerror:
	// send error code on pipe
	write1(uintptr(pipe), uintptr(unsafe.Pointer(&err1)), unsafe.Sizeof(err1))
	for {
		exit(253)
	}
}

// Try to open a pipe with O_CLOEXEC set on both file descriptors.
func forkExecPipe(p []int) error {
	err := Pipe(p)
	if err != nil {
		return err
	}
	_, err = fcntl(p[0], F_SETFD, FD_CLOEXEC)
	if err != nil {
		return err
	}
	_, err = fcntl(p[1], F_SETFD, FD_CLOEXEC)
	return err
}
<|endoftext|>


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

// Fork, exec, wait, etc.

package syscall

import (
	"sync"
	"unicode/utf16"
	"unsafe"
)

var ForkLock sync.RWMutex

// EscapeArg rewrites command line argument s as prescribed
// in https://msdn.microsoft.com/en-us/library/ms880421.
// This function returns "" (2 double quotes) if s is empty.
// Alternatively, these transformations are done:
// - every back slash (\) is doubled, but only if immediately
//   followed by double quote (");
// - every double quote (") is escaped by back slash (\);
// - finally, s is wrapped with double quotes (arg -> "arg"),
//   but only if there is space or tab inside s.
func EscapeArg(s string) string {
	if len(s) == 0 {
		return "\"\""
	}
	n := len(s)
	hasSpace := false
	for i := 0; i < len(s); i++ {
		switch s[i] {
		case '"', '\\':
			n++
		case ' ', '\t':
			hasSpace = true
		}
	}
	if hasSpace {
		n += 2
	}
	if n == len(s) {
		return s
	}

	qs := make([]byte, n)
	j := 0
	if hasSpace {
		qs[j] = '"'
		j++
	}
	slashes := 0
	for i := 0; i < len(s); i++ {
		switch s[i] {
		default:
			slashes = 0
			qs[j] = s[i]
		case '\\':
			slashes++
			qs[j] = s[i]
		case '"':
			for ; slashes > 0; slashes-- {
				qs[j] = '\\'
				j++
			}
			qs[j] = '\\'
			j++
			qs[j] = s[i]
		}
		j++
	}
	if hasSpace {
		for ; slashes > 0; slashes-- {
			qs[j] = '\\'
			j++
		}
		qs[j] = '"'
		j++
	}
	return string(qs[:j])
}

// makeCmdLine builds a command line out of args by escaping "special"
// characters and joining the arguments with spaces.
func makeCmdLine(args []string) string {
	var s string
	for _, v := range args {
		if s != "" {
			s += " "
		}
		s += EscapeArg(v)
	}
	return s
}

// createEnvBlock converts an array of environment strings into
// the representation required by CreateProcess: a sequence of NUL
// terminated strings followed by a nil.
// Last bytes are two UCS-2 NULs, or four NUL bytes.
func createEnvBlock(envv []string) *uint16 {
	if len(envv) == 0 {
		return &utf16.Encode([]rune("\x00\x00"))[0]
	}
	length := 0
	for _, s := range envv {
		length += len(s) + 1
	}
	length += 1

	b := make([]byte, length)
	i := 0
	for _, s := range envv {
		l := len(s)
		copy(b[i:i+l], []byte(s))
		copy(b[i+l:i+l+1], []byte{0})
		i = i + l + 1
	}
	copy(b[i:i+1], []byte{0})

	return &utf16.Encode([]rune(string(b)))[0]
}

func CloseOnExec(fd Handle) {
	SetHandleInformation(Handle(fd), HANDLE_FLAG_INHERIT, 0)
}

func SetNonblock(fd Handle, nonblocking bool) (err error) {
	return nil
}

// FullPath retrieves the full path of the specified file.
func FullPath(name string) (path string, err error) {
	p, err := UTF16PtrFromString(name)
	if err != nil {
		return "", err
	}
	n := uint32(100)
	for {
		buf := make([]uint16, n)
		n, err = GetFullPathName(p, uint32(len(buf)), &buf[0], nil)
		if err != nil {
			return "", err
		}
		if n <= uint32(len(buf)) {
			return UTF16ToString(buf[:n]), nil
		}
	}
}

func isSlash(c uint8) bool {
	return c == '\\' || c == '/'
}

func normalizeDir(dir string) (name string, err error) {
	ndir, err := FullPath(dir)
	if err != nil {
		return "", err
	}
	if len(ndir) > 2 && isSlash(ndir[0]) && isSlash(ndir[1]) {
		// dir cannot have \\server\share\path form
		return "", EINVAL
	}
	return ndir, nil
}

func volToUpper(ch int) int {
	if 'a' <= ch && ch <= 'z' {
		ch += 'A' - 'a'
	}
	return ch
}

func joinExeDirAndFName(dir, p string) (name string, err error) {
	if len(p) == 0 {
		return "", EINVAL
	}
	if len(p) > 2 && isSlash(p[0]) && isSlash(p[1]) {
		// \\server\share\path form
		return p, nil
	}
	if len(p) > 1 && p[1] == ':' {
		// has drive letter
		if len(p) == 2 {
			return "", EINVAL
		}
		if isSlash(p[2]) {
			return p, nil
		} else {
			d, err := normalizeDir(dir)
			if err != nil {
				return "", err
			}
			if volToUpper(int(p[0])) == volToUpper(int(d[0])) {
				return FullPath(d + "\\" + p[2:])
			} else {
				return FullPath(p)
			}
		}
	} else {
		// no drive letter
		d, err := normalizeDir(dir)
		if err != nil {
			return "", err
		}
		if isSlash(p[0]) {
			return FullPath(d[:2] + p)
		} else {
			return FullPath(d + "\\" + p)
		}
	}
}

type ProcAttr struct {
	Dir   string
	Env   []string
	Files []uintptr
	Sys   *SysProcAttr
}

type SysProcAttr struct {
	HideWindow        bool
	CmdLine           string // used if non-empty, else the windows command line is built by escaping the arguments passed to StartProcess
	CreationFlags     uint32
	Token             Token               // if set, runs new process in the security context represented by the token
	ProcessAttributes *SecurityAttributes // if set, applies these security attributes as the descriptor for the new process
	ThreadAttributes  *SecurityAttributes // if set, applies these security attributes as the descriptor for the main thread of the new process
}

var zeroProcAttr ProcAttr
var zeroSysProcAttr SysProcAttr

func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle uintptr, err error) {
	if len(argv0) == 0 {
		return 0, 0, EWINDOWS
	}
	if attr == nil {
		attr = &zeroProcAttr
	}
	sys := attr.Sys
	if sys == nil {
		sys = &zeroSysProcAttr
	}

	if len(attr.Files) > 3 {
		return 0, 0, EWINDOWS
	}
	if len(attr.Files) < 3 {
		return 0, 0, EINVAL
	}

	if len(attr.Dir) != 0 {
		// StartProcess assumes that argv0 is relative to attr.Dir,
		// because it implies Chdir(attr.Dir) before executing argv0.
		// Windows CreateProcess assumes the opposite: it looks for
		// argv0 relative to the current directory, and, only once the new
		// process is started, it does Chdir(attr.Dir). We are adjusting
		// for that difference here by making argv0 absolute.
		var err error
		argv0, err = joinExeDirAndFName(attr.Dir, argv0)
		if err != nil {
			return 0, 0, err
		}
	}
	argv0p, err := UTF16PtrFromString(argv0)
	if err != nil {
		return 0, 0, err
	}

	var cmdline string
	// Windows CreateProcess takes the command line as a single string:
	// use attr.CmdLine if set, else build the command line by escaping
	// and joining each argument with spaces
	if sys.CmdLine != "" {
		cmdline = sys.CmdLine
	} else {
		cmdline = makeCmdLine(argv)
	}

	var argvp *uint16
	if len(cmdline) != 0 {
		argvp, err = UTF16PtrFromString(cmdline)
		if err != nil {
			return 0, 0, err
		}
	}

	var dirp *uint16
	if len(attr.Dir) != 0 {
		dirp, err = UTF16PtrFromString(attr.Dir)
		if err != nil {
			return 0, 0, err
		}
	}

	// Acquire the fork lock so that no other threads
	// create new fds that are not yet close-on-exec
	// before we fork.
	ForkLock.Lock()
	defer ForkLock.Unlock()

	p, _ := GetCurrentProcess()
	fd := make([]Handle, len(attr.Files))
	for i := range attr.Files {
		if attr.Files[i] > 0 {
			err := DuplicateHandle(p, Handle(attr.Files[i]), p, &fd[i], 0, true, DUPLICATE_SAME_ACCESS)
			if err != nil {
				return 0, 0, err
			}
			defer CloseHandle(Handle(fd[i]))
		}
	}
	si := new(StartupInfo)
	si.Cb = uint32(unsafe.Sizeof(*si))
	si.Flags = STARTF_USESTDHANDLES
	if sys.HideWindow {
		si.Flags |= STARTF_USESHOWWINDOW
		si.ShowWindow = SW_HIDE
	}
	si.StdInput = fd[0]
	si.StdOutput = fd[1]
	si.StdErr = fd[2]

	pi := new(ProcessInformation)

	flags := sys.CreationFlags | CREATE_UNICODE_ENVIRONMENT
	if sys.Token != 0 {
		err = CreateProcessAsUser(sys.Token, argv0p, argvp, sys.ProcessAttributes, sys.ThreadAttributes, true, flags, createEnvBlock(attr.Env), dirp, si, pi)
	} else {
		err = CreateProcess(argv0p, argvp, sys.ProcessAttributes, sys.ThreadAttributes, true, flags, createEnvBlock(attr.Env), dirp, si, pi)
	}
	if err != nil {
		return 0, 0, err
	}
	defer CloseHandle(Handle(pi.Thread))

	return int(pi.ProcessId), uintptr(pi.Process), nil
}

func Exec(argv0 string, argv []string, envv []string) (err error) {
	return EWINDOWS
}
<commit_msg>syscall: rewrite Windows makeCmdLine to use []byte<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Fork, exec, wait, etc.

package syscall

import (
	"sync"
	"unicode/utf16"
	"unsafe"
)

var ForkLock sync.RWMutex

// EscapeArg rewrites command line argument s as prescribed
// in https://msdn.microsoft.com/en-us/library/ms880421.
// This function returns "" (2 double quotes) if s is empty.
// Alternatively, these transformations are done:
// - every back slash (\) is doubled, but only if immediately
//   followed by double quote (");
// - every double quote (") is escaped by back slash (\);
// - finally, s is wrapped with double quotes (arg -> "arg"),
//   but only if there is space or tab inside s.
func EscapeArg(s string) string {
	for i := 0; i < len(s); i++ {
		switch s[i] {
		case '"', '\\', ' ', '\t':
			// Some escaping required.
			b := make([]byte, 0, len(s)+2)
			b = appendEscapeArg(b, s)
			return string(b)
		}
	}
	return s
}

// appendEscapeArg escapes the string s, as per escapeArg,
// appends the result to b, and returns the updated slice.
func appendEscapeArg(b []byte, s string) []byte {
	if len(s) == 0 {
		return append(b, `""`...)
	}

	needsBackslash := false
	hasSpace := false
	for i := 0; i < len(s); i++ {
		switch s[i] {
		case '"', '\\':
			needsBackslash = true
		case ' ', '\t':
			hasSpace = true
		}
	}

	if !needsBackslash && !hasSpace {
		// No special handling required; normal case.
		return append(b, s...)
	}
	if !needsBackslash {
		// hasSpace is true, so we need to quote the string.
		b = append(b, '"')
		b = append(b, s...)
		return append(b, '"')
	}

	if hasSpace {
		b = append(b, '"')
	}
	slashes := 0
	for i := 0; i < len(s); i++ {
		c := s[i]
		switch c {
		default:
			slashes = 0
		case '\\':
			slashes++
		case '"':
			for ; slashes > 0; slashes-- {
				b = append(b, '\\')
			}
			b = append(b, '\\')
		}
		b = append(b, c)
	}
	if hasSpace {
		for ; slashes > 0; slashes-- {
			b = append(b, '\\')
		}
		b = append(b, '"')
	}

	return b
}

// makeCmdLine builds a command line out of args by escaping "special"
// characters and joining the arguments with spaces.
func makeCmdLine(args []string) string {
	var b []byte
	for _, v := range args {
		if len(b) > 0 {
			b = append(b, ' ')
		}
		b = appendEscapeArg(b, v)
	}
	return string(b)
}

// createEnvBlock converts an array of environment strings into
// the representation required by CreateProcess: a sequence of NUL
// terminated strings followed by a nil.
// Last bytes are two UCS-2 NULs, or four NUL bytes.
func createEnvBlock(envv []string) *uint16 {
	if len(envv) == 0 {
		return &utf16.Encode([]rune("\x00\x00"))[0]
	}
	length := 0
	for _, s := range envv {
		length += len(s) + 1
	}
	length += 1

	b := make([]byte, length)
	i := 0
	for _, s := range envv {
		l := len(s)
		copy(b[i:i+l], []byte(s))
		copy(b[i+l:i+l+1], []byte{0})
		i = i + l + 1
	}
	copy(b[i:i+1], []byte{0})

	return &utf16.Encode([]rune(string(b)))[0]
}

func CloseOnExec(fd Handle) {
	SetHandleInformation(Handle(fd), HANDLE_FLAG_INHERIT, 0)
}

func SetNonblock(fd Handle, nonblocking bool) (err error) {
	return nil
}

// FullPath retrieves the full path of the specified file.
func FullPath(name string) (path string, err error) {
	p, err := UTF16PtrFromString(name)
	if err != nil {
		return "", err
	}
	n := uint32(100)
	for {
		buf := make([]uint16, n)
		n, err = GetFullPathName(p, uint32(len(buf)), &buf[0], nil)
		if err != nil {
			return "", err
		}
		if n <= uint32(len(buf)) {
			return UTF16ToString(buf[:n]), nil
		}
	}
}

func isSlash(c uint8) bool {
	return c == '\\' || c == '/'
}

func normalizeDir(dir string) (name string, err error) {
	ndir, err := FullPath(dir)
	if err != nil {
		return "", err
	}
	if len(ndir) > 2 && isSlash(ndir[0]) && isSlash(ndir[1]) {
		// dir cannot have \\server\share\path form
		return "", EINVAL
	}
	return ndir, nil
}

func volToUpper(ch int) int {
	if 'a' <= ch && ch <= 'z' {
		ch += 'A' - 'a'
	}
	return ch
}

func joinExeDirAndFName(dir, p string) (name string, err error) {
	if len(p) == 0 {
		return "", EINVAL
	}
	if len(p) > 2 && isSlash(p[0]) && isSlash(p[1]) {
		// \\server\share\path form
		return p, nil
	}
	if len(p) > 1 && p[1] == ':' {
		// has drive letter
		if len(p) == 2 {
			return "", EINVAL
		}
		if isSlash(p[2]) {
			return p, nil
		} else {
			d, err := normalizeDir(dir)
			if err != nil {
				return "", err
			}
			if volToUpper(int(p[0])) == volToUpper(int(d[0])) {
				return FullPath(d + "\\" + p[2:])
			} else {
				return FullPath(p)
			}
		}
	} else {
		// no drive letter
		d, err := normalizeDir(dir)
		if err != nil {
			return "", err
		}
		if isSlash(p[0]) {
			return FullPath(d[:2] + p)
		} else {
			return FullPath(d + "\\" + p)
		}
	}
}

type ProcAttr struct {
	Dir   string
	Env   []string
	Files []uintptr
	Sys   *SysProcAttr
}

type SysProcAttr struct {
	HideWindow        bool
	CmdLine           string // used if non-empty, else the windows command line is built by escaping the arguments passed to StartProcess
	CreationFlags     uint32
	Token             Token               // if set, runs new process in the security context represented by the token
	ProcessAttributes *SecurityAttributes // if set, applies these security attributes as the descriptor for the new process
	ThreadAttributes  *SecurityAttributes // if set, applies these security attributes as the descriptor for the main thread of the new process
}

var zeroProcAttr ProcAttr
var zeroSysProcAttr SysProcAttr

func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle uintptr, err error) {
	if len(argv0) == 0 {
		return 0, 0, EWINDOWS
	}
	if attr == nil {
		attr = &zeroProcAttr
	}
	sys := attr.Sys
	if sys == nil {
		sys = &zeroSysProcAttr
	}

	if len(attr.Files) > 3 {
		return 0, 0, EWINDOWS
	}
	if len(attr.Files) < 3 {
		return 0, 0, EINVAL
	}

	if len(attr.Dir) != 0 {
		// StartProcess assumes that argv0 is relative to attr.Dir,
		// because it implies Chdir(attr.Dir) before executing argv0.
		// Windows CreateProcess assumes the opposite: it looks for
		// argv0 relative to the current directory, and, only once the new
		// process is started, it does Chdir(attr.Dir). We are adjusting
		// for that difference here by making argv0 absolute.
		var err error
		argv0, err = joinExeDirAndFName(attr.Dir, argv0)
		if err != nil {
			return 0, 0, err
		}
	}
	argv0p, err := UTF16PtrFromString(argv0)
	if err != nil {
		return 0, 0, err
	}

	var cmdline string
	// Windows CreateProcess takes the command line as a single string:
	// use attr.CmdLine if set, else build the command line by escaping
	// and joining each argument with spaces
	if sys.CmdLine != "" {
		cmdline = sys.CmdLine
	} else {
		cmdline = makeCmdLine(argv)
	}

	var argvp *uint16
	if len(cmdline) != 0 {
		argvp, err = UTF16PtrFromString(cmdline)
		if err != nil {
			return 0, 0, err
		}
	}

	var dirp *uint16
	if len(attr.Dir) != 0 {
		dirp, err = UTF16PtrFromString(attr.Dir)
		if err != nil {
			return 0, 0, err
		}
	}

	// Acquire the fork lock so that no other threads
	// create new fds that are not yet close-on-exec
	// before we fork.
	ForkLock.Lock()
	defer ForkLock.Unlock()

	p, _ := GetCurrentProcess()
	fd := make([]Handle, len(attr.Files))
	for i := range attr.Files {
		if attr.Files[i] > 0 {
			err := DuplicateHandle(p, Handle(attr.Files[i]), p, &fd[i], 0, true, DUPLICATE_SAME_ACCESS)
			if err != nil {
				return 0, 0, err
			}
			defer CloseHandle(Handle(fd[i]))
		}
	}
	si := new(StartupInfo)
	si.Cb = uint32(unsafe.Sizeof(*si))
	si.Flags = STARTF_USESTDHANDLES
	if sys.HideWindow {
		si.Flags |= STARTF_USESHOWWINDOW
		si.ShowWindow = SW_HIDE
	}
	si.StdInput = fd[0]
	si.StdOutput = fd[1]
	si.StdErr = fd[2]

	pi := new(ProcessInformation)

	flags := sys.CreationFlags | CREATE_UNICODE_ENVIRONMENT
	if sys.Token != 0 {
		err = CreateProcessAsUser(sys.Token, argv0p, argvp, sys.ProcessAttributes, sys.ThreadAttributes, true, flags, createEnvBlock(attr.Env), dirp, si, pi)
	} else {
		err = CreateProcess(argv0p, argvp, sys.ProcessAttributes, sys.ThreadAttributes, true, flags, createEnvBlock(attr.Env), dirp, si, pi)
	}
	if err != nil {
		return 0, 0, err
	}
	defer CloseHandle(Handle(pi.Thread))

	return int(pi.ProcessId), uintptr(pi.Process), nil
}

func Exec(argv0 string, argv []string, envv []string) (err error) {
	return EWINDOWS
}
<|endoftext|>