<commit_before>// csvsplit: Split a .csv into multiple files.
// https://github.com/JeffPaine/csvsplit
package main

import (
	"encoding/csv"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"path/filepath"
)

var (
	flagRecords = flag.Int("records", 0, "The number of records per output file")
	flagInput   = flag.String("input", "", "Filename of the input file to split (leave blank to use stdin)")
	flagOutput  = flag.String("output", "", "Filename / path of the output file (leave blank for current directory)")
	flagHeaders = flag.Int("headers", 0, "Number of header lines in the input file to preserve in each output file")
)

func main() {
	flag.Parse()

	// Sanity check flags
	if *flagRecords < 1 || *flagHeaders < 0 || *flagHeaders >= *flagRecords {
		flag.Usage()
		os.Exit(1)
	}

	// Get input from a given file or stdin
	var r *csv.Reader
	if *flagInput != "" {
		f, err := os.Open(*flagInput)
		if err != nil {
			log.Fatal(err)
		}
		defer f.Close()
		r = csv.NewReader(f)
	} else {
		r = csv.NewReader(os.Stdin)
	}

	var recs [][]string
	count := 1
	for {
		record, err := r.Read()
		if err == io.EOF {
			break
		} else if err != nil {
			log.Fatal(err)
		}

		recs = append(recs, record)
		if len(recs) == *flagRecords {
			save(&recs, count)
			// Reset records to include just the header lines (if any)
			recs = recs[:*flagHeaders]
			count++
		}
	}
	if len(recs) > 0 {
		save(&recs, count)
	}
}

// save() saves the given *[][]string of csv data to a .csv file. Files are named
// sequentially in the form of 001.csv, 002.csv, etc.
func save(recs *[][]string, c int) {
	name := fmt.Sprintf("%v%03d%v", *flagOutput, c, ".csv")

	// Make sure we don't overwrite existing files
	if _, err := os.Stat(name); err == nil {
		log.Fatal("file exists: ", name)
	}

	// If a directory is specified, make sure that directory exists
	if filepath.Dir(*flagOutput) != "." {
		_, err := os.Stat(filepath.Dir(*flagOutput))
		if err != nil {
			log.Fatalf("no such directory '%v'", *flagOutput)
		}
	}

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

	w := csv.NewWriter(f)
	w.WriteAll(*recs)
}
<commit_msg>Add comment<commit_after>// csvsplit: Split a .csv into multiple files.
// https://github.com/JeffPaine/csvsplit
package main

import (
	"encoding/csv"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"path/filepath"
)

var (
	flagRecords = flag.Int("records", 0, "The number of records per output file")
	flagInput   = flag.String("input", "", "Filename of the input file to split (leave blank to use stdin)")
	flagOutput  = flag.String("output", "", "Filename / path of the output file (leave blank for current directory)")
	flagHeaders = flag.Int("headers", 0, "Number of header lines in the input file to preserve in each output file")
)

func main() {
	flag.Parse()

	// Sanity check flags
	if *flagRecords < 1 || *flagHeaders < 0 || *flagHeaders >= *flagRecords {
		flag.Usage()
		os.Exit(1)
	}

	// Get input from a given file or stdin
	var r *csv.Reader
	if *flagInput != "" {
		f, err := os.Open(*flagInput)
		if err != nil {
			log.Fatal(err)
		}
		defer f.Close()
		r = csv.NewReader(f)
	} else {
		r = csv.NewReader(os.Stdin)
	}

	// Read the input .csv file line by line. Save to a new file after reaching
	// the amount of records prescribed by the -records flag.
	var recs [][]string
	count := 1
	for {
		record, err := r.Read()
		if err == io.EOF {
			break
		} else if err != nil {
			log.Fatal(err)
		}

		recs = append(recs, record)
		if len(recs) == *flagRecords {
			save(&recs, count)
			// Reset records to include just the header lines (if any)
			recs = recs[:*flagHeaders]
			count++
		}
	}
	if len(recs) > 0 {
		save(&recs, count)
	}
}

// save() saves the given *[][]string of csv data to a .csv file. Files are named
// sequentially in the form of 001.csv, 002.csv, etc.
func save(recs *[][]string, c int) {
	name := fmt.Sprintf("%v%03d%v", *flagOutput, c, ".csv")

	// Make sure we don't overwrite existing files
	if _, err := os.Stat(name); err == nil {
		log.Fatal("file exists: ", name)
	}

	// If a directory is specified, make sure that directory exists
	if filepath.Dir(*flagOutput) != "." {
		_, err := os.Stat(filepath.Dir(*flagOutput))
		if err != nil {
			log.Fatalf("no such directory '%v'", *flagOutput)
		}
	}

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

	w := csv.NewWriter(f)
	w.WriteAll(*recs)
}
<|endoftext|>


<commit_before>package pyradebug

import (
	"errors"
	"fmt"
	"runtime"
	"strings"
	"sync"
)

type PyraDebug struct {
	Enable  bool
	Debug   bool
	lck     sync.Mutex
	history map[string]*GoroutineInfo
}

type GoroutineInfo struct {
	Id     string
	Name   string
	Status string
}

func InitPyraDebug() *PyraDebug {
	pd := &PyraDebug{}
	pd.history = make(map[string]*GoroutineInfo)
	return pd
}

func GetGoroutineId() string {
	b1 := make([]byte, 50)
	runtime.Stack(b1, false)
	s1 := string(b1)
	as1 := strings.Split(s1, "\n")
	s2 := as1[0]
	s3 := s2[:len(s2)-11][10:]
	return s3
}

func (pd *PyraDebug) SetGoroutineName(name string) {
	if !pd.Enable {
		return
	}
	if pd.Debug {
		fmt.Printf("PyraDebug.SetGoroutineName %s\n", name)
	}
	id := GetGoroutineId()
	pd.lck.Lock()
	defer pd.lck.Unlock()
	// pd.history = append(pd.history, &GoroutineInfo{id: id, name: name})
	_, ok := pd.history[id]
	if ok {
		panic(errors.New("Goroutine name is set twice"))
	}
	pd.history[id] = &GoroutineInfo{Id: id, Name: name}
}

func parseFirstLine(s2 string) (id string, status string) {
	i1 := strings.Index(s2, "[")
	id = s2[:i1-1]
	i2 := strings.Index(s2, "]")
	status = s2[i1+1 : i2]
	return id, status
}

func (pd *PyraDebug) ListGoroutines(bufferSize int) (result []*GoroutineInfo) {
	if pd.Debug {
		fmt.Printf("PyraDebug.ListGoroutines %v\n", pd.history)
	}
	b1 := make([]byte, bufferSize)
	runtime.Stack(b1, true)
	s1 := string(b1)
	as1 := strings.Split(s1, "\n")
	gs := [][]string{nil}
	for _, s := range as1 {
		if s == "" {
			gs = append(gs, nil)
		} else {
			gs[len(gs)-1] = append(gs[len(gs)-1], s)
		}
	}

	for _, as2 := range gs {
		if len(as2) == 0 {
			continue
		}
		id, status := parseFirstLine(as2[0])
		result = append(result, &GoroutineInfo{Id: id, Status: status})
	}

	pd.GiveNames(result)

	return result
}
func (pd *PyraDebug) GiveNames(a1 []*GoroutineInfo) {
	pd.lck.Lock()
	defer pd.lck.Unlock()

	for _, gi := range a1 {
		gi2 := pd.history[gi.Id]
		if gi2 != nil {
			gi.Name = gi2.Name
		}
	}
}
<commit_msg>debug 2<commit_after>package pyradebug

import (
	"errors"
	"fmt"
	"runtime"
	"strings"
	"sync"
)

type PyraDebug struct {
	Enable  bool
	Debug   bool
	lck     sync.Mutex
	history map[string]*GoroutineInfo
}

type GoroutineInfo struct {
	Id     string
	Name   string
	Status string
}

func InitPyraDebug() *PyraDebug {
	pd := &PyraDebug{}
	pd.history = make(map[string]*GoroutineInfo)
	return pd
}

func GetGoroutineId() string {
	b1 := make([]byte, 50)
	runtime.Stack(b1, false)
	s1 := string(b1)
	as1 := strings.Split(s1, "\n")
	s2 := as1[0]
	s3 := s2[:len(s2)-11][10:]
	return s3
}

func (pd *PyraDebug) SetGoroutineName(name string) {
	if !pd.Enable {
		return
	}
	id := GetGoroutineId()
	if pd.Debug {
		fmt.Printf("PyraDebug.SetGoroutineName id:%s name:%s\n", id, name)
	}
	pd.lck.Lock()
	defer pd.lck.Unlock()
	// pd.history = append(pd.history, &GoroutineInfo{id: id, name: name})
	_, ok := pd.history[id]
	if ok {
		panic(errors.New("Goroutine name is set twice"))
	}
	pd.history[id] = &GoroutineInfo{Id: id, Name: name}
}

func parseFirstLine(s2 string) (id string, status string) {
	i1 := strings.Index(s2, "[")
	id = s2[:i1-1]
	i2 := strings.Index(s2, "]")
	status = s2[i1+1 : i2]
	return id, status
}

func (pd *PyraDebug) ListGoroutines(bufferSize int) (result []*GoroutineInfo) {
	if pd.Debug {
		fmt.Printf("PyraDebug.ListGoroutines %#v\n", pd.history)
	}
	b1 := make([]byte, bufferSize)
	runtime.Stack(b1, true)
	s1 := string(b1)
	as1 := strings.Split(s1, "\n")
	gs := [][]string{nil}
	for _, s := range as1 {
		if s == "" {
			gs = append(gs, nil)
		} else {
			gs[len(gs)-1] = append(gs[len(gs)-1], s)
		}
	}

	for _, as2 := range gs {
		if len(as2) == 0 {
			continue
		}
		id, status := parseFirstLine(as2[0])
		result = append(result, &GoroutineInfo{Id: id, Status: status})
	}

	pd.GiveNames(result)

	return result
}
func (pd *PyraDebug) GiveNames(a1 []*GoroutineInfo) {
	pd.lck.Lock()
	defer pd.lck.Unlock()

	for _, gi := range a1 {
		gi2 := pd.history[gi.Id]
		if gi2 != nil {
			gi.Name = gi2.Name
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"io"
	"launchpad.net/goamz/aws"
	"launchpad.net/goamz/s3"
	"log"
	"os"
	"path/filepath"
	"sync"
	"sync/atomic"
)

var (
	waitGroup   sync.WaitGroup
	fileQueue   chan *s3.Key
	syncedFiles uint64
	syncedBytes uint64
	totalFiles  uint64

	awsAccessKey  string
	awsSecretKey  string
	awsBucket     string
	awsRegion     = "eu-west-1"
	localRootPath string
	workerCount   = 8
)

func listBucket() {
	bucket := newBucketConnection()
	marker := ""

	for {
		sourceList, err := bucket.List("", "", marker, 1000)
		if err != nil {
			log.Fatal(err)
		}

		for i := 0; i < len(sourceList.Contents); i++ {
			key := sourceList.Contents[i]
			fileQueue <- &key
		}

		if !sourceList.IsTruncated {
			break
		}

		lastIndex := len(sourceList.Contents) - 1
		lastKey := sourceList.Contents[lastIndex]
		marker = lastKey.Key
	}
}

func fileWorker(fileQueue chan *s3.Key) {
	bucket := newBucketConnection()

	for {
		key := <-fileQueue
		if key == nil {
			waitGroup.Done()
			break
		}

		processKey(bucket, key)
	}
}

func processKey(bucket *s3.Bucket, key *s3.Key) {
	defer atomic.AddUint64(&totalFiles, 1)

	localFilePath := filepath.Join(localRootPath, key.Key)

	if checkFilePresence(localFilePath) {
		size := fileSize(localFilePath)

		if size == key.Size {
			log.Printf("Skipped %v", key.Key)
			return
		}

		log.Printf("Mismatched size for %v (expecting %d bytes, got %d bytes)", key.Key, key.Size, size)
	}

	// Make the dir if it doesn't exist
	dirPath := filepath.Dir(localFilePath)
	err := os.MkdirAll(dirPath, 0777)
	if err != nil {
		log.Fatal(err)
	}

	fileWriter, err := os.Create(localFilePath)
	defer fileWriter.Close()
	if err != nil {
		log.Fatal(err)
	}

	bucketReader, err := bucket.GetReader(key.Key)
	defer bucketReader.Close()
	if err != nil {
		log.Fatal(err)
	}

	bytes, err := io.Copy(fileWriter, bucketReader)
	if err != nil {
		log.Fatal(err)
	}

	atomic.AddUint64(&syncedBytes, uint64(bytes))
	atomic.AddUint64(&syncedFiles, 1)

	log.Printf("Fetched %v (%d bytes)", key.Key, bytes)
}

func checkFilePresence(path string) (bool) {
	file, err := os.Open(path)
	if err != nil {
		if os.IsNotExist(err) {
			return false
		}

		log.Fatal(err)
	}

	file.Close()
	return true
}

func fileSize(path string) (int64) {
	info, err := os.Stat(path)
	if err != nil {
		log.Fatal(err)
	}

	return info.Size()
}

func newBucketConnection() (bucket *s3.Bucket) {
	auth := aws.Auth{AccessKey: awsAccessKey, SecretKey: awsSecretKey}
	s3Conn := s3.New(auth, aws.Regions[awsRegion])
	return s3Conn.Bucket(awsBucket)
}

func initFlags() {
	flag.StringVar(&awsAccessKey, "access-key", "", "AWS Access Key")
	flag.StringVar(&awsSecretKey, "secret-key", "", "AWS Secret Key")
	flag.StringVar(&awsBucket, "bucket", "", "S3 Bucket")
	flag.StringVar(&awsRegion, "region", awsRegion, "S3 Region")

	flag.Parse()
	args := flag.Args()

	if len(args) > 0 {
		localRootPath = args[0]
	}

	if localRootPath == "" {
		log.Fatal("No destination provided.")
	}

	// If the provided path isn't absolute, make it so
	if !filepath.IsAbs(localRootPath) {
		workingDir, err := os.Getwd()
		if err != nil {
			log.Fatal(err)
		}

		localRootPath = filepath.Join(workingDir, localRootPath)
	}

	fileInfo, err := os.Stat(localRootPath)
	if os.IsNotExist(err) {
		log.Fatal("Destination not found.")
	}

	if !fileInfo.IsDir() {
		log.Fatal("Destination is not a directory.")
	}
}

func main() {
	initFlags()

	fileQueue = make(chan *s3.Key, 2000)

	log.Printf("Starting bucket sync from %v to %v", awsBucket, localRootPath)

	startWorkers()
	listBucket()
	stopWorkers()

	log.Printf("Synced %v/%v seen files, updated %v bytes", syncedFiles, totalFiles, syncedBytes)
}

func startWorkers() {
	for i := 0; i < workerCount; i++ {
		waitGroup.Add(1)
		go fileWorker(fileQueue)
	}
}

func stopWorkers() {
	// Shutdown the workers by sending them a nil
	for i := 0; i < workerCount; i++ {
		fileQueue <- nil
	}

	// Wait for everything to finish up
	waitGroup.Wait()
}
<commit_msg>Put file I/O through single thread.<commit_after>package main

import (
	"flag"
	"io"
	"launchpad.net/goamz/aws"
	"launchpad.net/goamz/s3"
	"log"
	"os"
	"path/filepath"
	"sync"
	"sync/atomic"
)

var (
	fileQueue         chan *s3.Key
	fileWaitGroup     sync.WaitGroup
	downloadQueue     chan *s3.Key
	downloadWaitGroup sync.WaitGroup
	syncedFiles       uint64
	syncedBytes       uint64
	totalFiles        uint64
	totalBytes        uint64

	awsAccessKey  string
	awsSecretKey  string
	awsBucket     string
	awsRegion     = "eu-west-1"
	localRootPath string

	downloadConcurrency = 8
	fileConcurrency     = 1
)

func listBucket() {
	bucket := newBucketConnection()
	marker := ""

	for {
		sourceList, err := bucket.List("", "", marker, 1000)
		if err != nil {
			log.Fatal(err)
		}

		for i := 0; i < len(sourceList.Contents); i++ {
			key := sourceList.Contents[i]
			fileQueue <- &key
		}

		if !sourceList.IsTruncated {
			break
		}

		lastIndex := len(sourceList.Contents) - 1
		lastKey := sourceList.Contents[lastIndex]
		marker = lastKey.Key
	}
}

func fileWorker() {
	for {
		key := <-fileQueue
		if key == nil {
			fileWaitGroup.Done()
			break
		}

		checkKey(key)
	}
}

func downloadWorker() {
	bucket := newBucketConnection()

	for {
		key := <-downloadQueue
		if key == nil {
			downloadWaitGroup.Done()
			break
		}

		downloadKey(bucket, key)
	}
}

func checkKey(key *s3.Key) {
	defer atomic.AddUint64(&totalFiles, 1)
	defer atomic.AddUint64(&totalBytes, uint64(key.Size))

	path := pathForKey(key)

	if checkFilePresence(path) {
		size := fileSize(path)

		if size == key.Size {
			log.Printf("Skipped %v", key.Key)
			return
		}

		log.Printf("Mismatched size for %v (expecting %d bytes, got %d bytes)", key.Key, key.Size, size)
	}

	downloadQueue <- key
}

func downloadKey(bucket *s3.Bucket, key *s3.Key) {
	path := pathForKey(key)

	// Make the dir if it doesn't exist
	dirPath := filepath.Dir(path)
	err := os.MkdirAll(dirPath, 0777)
	if err != nil {
		log.Fatal(err)
	}

	fileWriter, err := os.Create(path)
	defer fileWriter.Close()
	if err != nil {
		log.Fatal(err)
	}

	bucketReader, err := bucket.GetReader(key.Key)
	defer bucketReader.Close()
	if err != nil {
		log.Fatal(err)
	}

	bytes, err := io.Copy(fileWriter, bucketReader)
	if err != nil {
		log.Fatal(err)
	}

	atomic.AddUint64(&syncedBytes, uint64(bytes))
	atomic.AddUint64(&syncedFiles, 1)

	log.Printf("Fetched %v (%d bytes)", key.Key, bytes)
}

func checkFilePresence(path string) bool {
	file, err := os.Open(path)
	if err != nil {
		if os.IsNotExist(err) {
			return false
		}

		log.Fatal(err)
	}

	file.Close()
	return true
}

func fileSize(path string) int64 {
	info, err := os.Stat(path)
	if err != nil {
		log.Fatal(err)
	}

	return info.Size()
}

func pathForKey(key *s3.Key) string {
	return filepath.Join(localRootPath, key.Key)
}

func newBucketConnection() (bucket *s3.Bucket) {
	auth := aws.Auth{AccessKey: awsAccessKey, SecretKey: awsSecretKey}
	s3Conn := s3.New(auth, aws.Regions[awsRegion])
	return s3Conn.Bucket(awsBucket)
}

func initFlags() {
	flag.StringVar(&awsAccessKey, "access-key", "", "AWS Access Key")
	flag.StringVar(&awsSecretKey, "secret-key", "", "AWS Secret Key")
	flag.StringVar(&awsBucket, "bucket", "", "S3 Bucket")
	flag.StringVar(&awsRegion, "region", awsRegion, "S3 Region")

	flag.Parse()
	args := flag.Args()

	if len(args) > 0 {
		localRootPath = args[0]
	}

	if localRootPath == "" {
		log.Fatal("No destination provided.")
	}

	// If the provided path isn't absolute, make it so
	if !filepath.IsAbs(localRootPath) {
		workingDir, err := os.Getwd()
		if err != nil {
			log.Fatal(err)
		}

		localRootPath = filepath.Join(workingDir, localRootPath)
	}

	fileInfo, err := os.Stat(localRootPath)
	if os.IsNotExist(err) {
		log.Fatal("Destination not found.")
	}

	if !fileInfo.IsDir() {
		log.Fatal("Destination is not a directory.")
	}
}

func main() {
	initFlags()

	fileQueue = make(chan *s3.Key, 10000)
	downloadQueue = make(chan *s3.Key, 10000)

	log.Printf("Starting bucket sync from %v to %v", awsBucket, localRootPath)

	startWorkers()
	listBucket()
	stopWorkers()

	log.Printf("Synced %v/%v seen files, updated %v/%v bytes", syncedFiles, totalFiles, syncedBytes, totalBytes)
}

func startWorkers() {
	for i := 0; i < fileConcurrency; i++ {
		fileWaitGroup.Add(1)
		go fileWorker()
	}

	for i := 0; i < downloadConcurrency; i++ {
		downloadWaitGroup.Add(1)
		go downloadWorker()
	}
}

func stopWorkers() {
	// We shutdown the workers by sending them a nil
	for i := 0; i < fileConcurrency; i++ {
		fileQueue <- nil
	}

	fileWaitGroup.Wait()

	for i := 0; i < downloadConcurrency; i++ {
		downloadQueue <- nil
	}

	downloadWaitGroup.Wait()
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"
	// "os/exec"
	"time"
)

func main() {
	//Check for our command line configuration flags
	var (
		backupPathPtr = flag.String("backupPath", "~/", "The base directory where the openshift backups will be stored.")
	)
	flag.Parse()
	fmt.Println("Running openshift-backup with backup path set to ", *backupPathPtr)

	//Get the name of the directory where we want to save this backup
	weekdays := []string{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}
	directory := weekdays[time.Now().Weekday()]

	//Create the backup directory if it does not exist
	fi, err := os.Stat(directory)
	if err != nil {
		fmt.Println("Creating directory named", directory)
		// create folder
		os.Mkdir(directory, 0600)
	} else {
		fmt.Println("Folder exists!: ", fi.Name())
	}

	//Define our openshift command

}
<commit_msg>Setting up user's home directory path. Creating a function to create directories. Creating folder to store all back ups in.<commit_after>package main

import (
	"flag"
	"fmt"
	"os"
	"os/user"
	// "os/exec"
	"log"
	"time"
)

func main() {
	// Get Users home directory
	user, err := user.Current()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(user.HomeDir)

	//Check for our command line configuration flags
	var (
		backupPathPtr = flag.String("backupPath", user.HomeDir, "The base directory where the openshift backups will be stored.")
	)
	flag.Parse()
	fmt.Println("Running openshift-backup with backup path set to ", *backupPathPtr)

	// Set Path
	path := *backupPathPtr + "/" + "OpenShiftBackUps"

	// Create OpenShiftBackUps directory
	createDir(path, 0700)

	//Get the name of the directory where we want to save this backup
	weekdays := []string{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}
	directory := weekdays[time.Now().Weekday()]

	dirPath := path + "/" + directory

	//Create the backup directory if it does not exist
	createDir(dirPath, 0600)

	//Define our openshift command

}

func createDir(name string, perm os.FileMode) error {
	fi, err := os.Stat(name)
	if err != nil {
		fmt.Println("Creating directory named", name)

		// create folder
		err = os.Mkdir(name, perm)
		if err != nil {
			fmt.Println("Couldn't create directory: ", err)

			return err
		}

	} else {
		fmt.Println("Folder exists!: ", fi.Name())

	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"encoding/json"
	"fmt"
	"log"
	"os"
	"regexp"
	"strconv"
	"strings"
)

var pattern = regexp.MustCompile(`^(MemFree|Buffers|Cached): + (\d+) kB`)

func gradient(shades uint, max_value uint) func(val uint) string {
	var (
		colors              = make([]string, shades)
		breakpoints         = make([]uint, shades-1)
		step                = max_value / shades
		scale       float32 = 255 / (float32(max_value) / 2)
	)

	color := func(val uint) string {
		switch {
		case val < step:
			// red
			return "#FF0000"
		case val >= step*(shades-1):
			// green
			return "#00FF00"
		case val < max_value/2:
			// red-ish
			return fmt.Sprintf("#FF%02X00", uint(float32(val)*scale))
		default:
			// green-ish
			return fmt.Sprintf("#%02XFF00", uint(255-(float32(val)-float32(max_value/2-step))*scale))
		}
	}

	for i := uint(0); i < shades-1; i++ {
		breakpoints[i] = step * (i + 1)
	}

	for i := uint(0); i < shades; i++ {
		colors[i] = color(step * i)
	}

	out := func(val uint) string {
		if val <= breakpoints[0] {
			return colors[0]
		} else if val > breakpoints[len(breakpoints)-1] {
			return colors[len(colors)-1]
		}

		for i := 0; i < len(breakpoints); i++ {
			if val > breakpoints[i] && val <= breakpoints[i+1] {
				return colors[i+1]
			}
		}

		panic("gradient")
	}

	return out
}

func getFreeMemory() (freeMemory uint) {
	file, err := os.Open("/proc/meminfo")

	if err != nil {
		log.Println(err)
		freeMemory = 0
		return
	}

	defer file.Close()

	scanner := bufio.NewScanner(file)

	for scanner.Scan() {
		line := scanner.Text()

		if pattern.MatchString(line) {
			memory := (pattern.FindAllStringSubmatch(line, -1)[0][2])
			tmp, err := strconv.ParseUint(memory, 10, 32)

			if err != nil {
				log.Println(err)
				continue
			}

			freeMemory += uint(tmp)
		}
	}

	// Return free memory in MB.
	freeMemory /= 1024
	return
}

func main() {
	type Element struct {
		FullText            string `json:"full_text"`
		ShortText           string `json:"short_text,omitempty"`
		Color               string `json:"color,omitempty"`
		MinWidth            string `json:"min_width,omitempty"`
		Align               string `json:"align,omitempty"`
		Name                string `json:"name"`
		Instance            string `json:"instance,omitempty"`
		Urgent              string `json:"urgent,omitempty"`
		Separator           string `json:"separator,omitempty"`
		SeparatorBlockWidth string `json:"separator_block_width,omitempty"`
	}

	var (
		buffer   bytes.Buffer
		status   []Element
		colorize = gradient(4, 1024)
	)

	scanner := bufio.NewScanner(os.Stdin)

	// Skip the first line which contains the version header.
	if scanner.Scan() {
		if _, err := buffer.WriteString(scanner.Text()); err != nil {
			log.Fatal(err)
		}
	}

	// The second line contains the start of the infinite array.
	if scanner.Scan() {
		if _, err := buffer.WriteString(scanner.Text()); err != nil {
			log.Fatal(err)
		}
	}

	for scanner.Scan() {
		line, prefix := scanner.Text(), ""

		// Remember the comma at the beginning of the line.
		if strings.HasPrefix(line, ",") {
			line, prefix = line[1:], ","
		}

		if _, err := buffer.WriteString(prefix); err != nil {
			log.Println(err)
			continue
		}

		freeMemory := getFreeMemory()

		memoryElement := Element{
			FullText: fmt.Sprintf("Mem: %d MB", freeMemory),
			Name:     "mem_info",
			Color:    colorize(freeMemory),
		}

		dec := json.NewDecoder(strings.NewReader(line))

		if err := dec.Decode(&status); err != nil {
			log.Println(err)
			continue
		}

		// Prepend the memory element.
		status = append([]Element{memoryElement}, status...)

		out, err := json.Marshal(status)

		if err != nil {
			log.Println(err)
			continue
		}

		buffer.Write(out)
		buffer.WriteTo(os.Stdout)

		// Reset output.
		status = []Element{}
	}
}
<commit_msg>do not panic on failed color determination<commit_after>package main

import (
	"bufio"
	"bytes"
	"encoding/json"
	"fmt"
	"log"
	"os"
	"regexp"
	"strconv"
	"strings"
)

var pattern = regexp.MustCompile(`^(MemFree|Buffers|Cached): + (\d+) kB`)

func gradient(shades uint, max_value uint) func(val uint) string {
	var (
		colors              = make([]string, shades)
		breakpoints         = make([]uint, shades-1)
		step                = max_value / shades
		scale       float32 = 255 / (float32(max_value) / 2)
	)

	color := func(val uint) string {
		switch {
		case val < step:
			// red
			return "#FF0000"
		case val >= step*(shades-1):
			// green
			return "#00FF00"
		case val < max_value/2:
			// red-ish
			return fmt.Sprintf("#FF%02X00", uint(float32(val)*scale))
		default:
			// green-ish
			return fmt.Sprintf("#%02XFF00", uint(255-(float32(val)-float32(max_value/2-step))*scale))
		}
	}

	for i := uint(0); i < shades-1; i++ {
		breakpoints[i] = step * (i + 1)
	}

	for i := uint(0); i < shades; i++ {
		colors[i] = color(step * i)
	}

	out := func(val uint) string {
		if val <= breakpoints[0] {
			return colors[0]
		} else if val > breakpoints[len(breakpoints)-1] {
			return colors[len(colors)-1]
		}

		for i := 0; i < len(breakpoints); i++ {
			if val > breakpoints[i] && val <= breakpoints[i+1] {
				return colors[i+1]
			}
		}

		log.Println("failed to determine color")
		return ""
	}

	return out
}

func getFreeMemory() (freeMemory uint) {
	file, err := os.Open("/proc/meminfo")

	if err != nil {
		log.Println(err)
		freeMemory = 0
		return
	}

	defer file.Close()

	scanner := bufio.NewScanner(file)

	for scanner.Scan() {
		line := scanner.Text()

		if pattern.MatchString(line) {
			memory := (pattern.FindAllStringSubmatch(line, -1)[0][2])
			tmp, err := strconv.ParseUint(memory, 10, 32)

			if err != nil {
				log.Println(err)
				continue
			}

			freeMemory += uint(tmp)
		}
	}

	// Return free memory in MB.
	freeMemory /= 1024
	return
}

func main() {
	type Element struct {
		FullText            string `json:"full_text"`
		ShortText           string `json:"short_text,omitempty"`
		Color               string `json:"color,omitempty"`
		MinWidth            string `json:"min_width,omitempty"`
		Align               string `json:"align,omitempty"`
		Name                string `json:"name"`
		Instance            string `json:"instance,omitempty"`
		Urgent              string `json:"urgent,omitempty"`
		Separator           string `json:"separator,omitempty"`
		SeparatorBlockWidth string `json:"separator_block_width,omitempty"`
	}

	var (
		buffer   bytes.Buffer
		status   []Element
		colorize = gradient(4, 1024)
	)

	scanner := bufio.NewScanner(os.Stdin)

	// Skip the first line which contains the version header.
	if scanner.Scan() {
		if _, err := buffer.WriteString(scanner.Text()); err != nil {
			log.Fatal(err)
		}
	}

	// The second line contains the start of the infinite array.
	if scanner.Scan() {
		if _, err := buffer.WriteString(scanner.Text()); err != nil {
			log.Fatal(err)
		}
	}

	for scanner.Scan() {
		line, prefix := scanner.Text(), ""

		// Remember the comma at the beginning of the line.
		if strings.HasPrefix(line, ",") {
			line, prefix = line[1:], ","
		}

		if _, err := buffer.WriteString(prefix); err != nil {
			log.Println(err)
			continue
		}

		freeMemory := getFreeMemory()

		memoryElement := Element{
			FullText: fmt.Sprintf("Mem: %d MB", freeMemory),
			Name:     "mem_info",
			Color:    colorize(freeMemory),
		}

		dec := json.NewDecoder(strings.NewReader(line))

		if err := dec.Decode(&status); err != nil {
			log.Println(err)
			continue
		}

		// Prepend the memory element.
		status = append([]Element{memoryElement}, status...)

		out, err := json.Marshal(status)

		if err != nil {
			log.Println(err)
			continue
		}

		buffer.Write(out)
		buffer.WriteTo(os.Stdout)

		// Reset output.
		status = []Element{}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"flag"
	"fmt"
	"log"
	"os"
	"os/exec"
	"os/signal"
	"strings"
	"sync"
	"syscall"
	"time"

	"gopkg.in/fsnotify.v1"
)

var (
	filesFlag = flag.String("f", "", "files and directories to watch, split by ':'")
	sigFlag   = flag.String("s", "HUP", "signal to send on change")
	delayFlag = flag.Duration("d", 3*time.Second, "time to wait after change before signalling child")
)

func signalByName(name string) (sig os.Signal, err error) {
	var ok bool
	if sig, ok = signals[strings.ToUpper(name)]; !ok {
		err = errors.New(fmt.Sprintf("unknown signal: %s", name))
	}
	return
}

func signalDebounce(process *os.Process, sig os.Signal, delay time.Duration) *sync.Cond {
	var m sync.Mutex
	cond := sync.NewCond(&m)
	cond.L.Lock()

	go func() {
		// continulously wait for a Broadcast event
		// then sleep, and pass along the signal to the process
		// The sleep causes the signals to effectively be debounced.
		// Note: this isn't a true debounce. We don't want to trigger
		// immediately on the first event. We explicitly want to wait
		// _then_ trigger.
		for {
			cond.Wait()
			time.Sleep(delay)
			if process != nil {
				log.Println("==> signalling child")
				process.Signal(sig)
			}
		}
	}()

	return cond
}

func usageAndExit(s interface{}) {
	fmt.Println(s)
	flag.Usage()
	os.Exit(1)
}

func usage() {
	fmt.Fprintf(os.Stderr, "usage: blart [flags] [command]\n")
	flag.PrintDefaults()
}

func init() {
	flag.Usage = usage
	flag.Parse()
}

func main() {
	sig, err := signalByName(*sigFlag)
	if err != nil {
		usageAndExit(err)
	}

	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		usageAndExit(err)
	}
	defer watcher.Close()

	if *filesFlag == "" {
		usageAndExit("no files to watch")
	}

	if len(flag.Args()) == 0 {
		usageAndExit("no command specified")
	}

	// start watching files for changes
	for _, file := range strings.Split(*filesFlag, ":") {
		err = watcher.Add(file)
		// if a file doesn't exist that you're trying to watch at this
		// point, it's likely a config error, and we should bail
		if err != nil {
			usageAndExit(err)
		}
	}

	cmd := exec.Command(flag.Args()[0], flag.Args()[1:]...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	err = cmd.Start()
	if err != nil {
		usageAndExit(err)
	}

	fmt.Println("==> starting child", strings.Join(flag.Args(), " "))

	done := make(chan struct{})
	go func() {
		cmd.Wait()
		done <- struct{}{}
	}()

	go func() {
		var event fsnotify.Event
		var err error

		// Create wrapper to debounce the signal events
		cond := signalDebounce(cmd.Process, sig, *delayFlag)

		for {
			select {
			case event = <-watcher.Events:
				log.Println("==> detected change in", event.Name)
				// Broadcase to the sync.Cond that an event has happened.
				// magic happens inside signalDebounce
				cond.Broadcast()
				if event.Op&fsnotify.Rename == fsnotify.Rename {
					// File was renamed, so remove the old watch,
					// and add a new one
					watcher.Remove(event.Name)
					watcher.Add(event.Name)
				}
			case err = <-watcher.Errors:
				log.Println("==> error:", err)
			}
		}
	}()

	// Listen to signals send to parent, and pass along to the child
	c := make(chan os.Signal, 1)
	signal.Notify(c)
	go func() {
		var sig os.Signal
		for {
			sig = <-c
			cmd.Process.Signal(sig)
			switch sig {
			case os.Interrupt, os.Kill, syscall.SIGTERM:
				countdown := 5 * time.Second

				fmt.Println("==> attempting to shut down cleanly")
				fmt.Printf("==> waiting up to %s for child to exit\n", countdown)

				// try and wait for the child to shut down before killing
				select {
				case <-done:
				case <-time.After(countdown):
				}

				// it hasn't shut down yet, so attempt to SIGKILL
				fmt.Println("==> attempting to now kill child")
				cmd.Process.Signal(os.Kill)

				select {
				case <-done:
				case <-time.After(time.Second):
				}

				// still hasn't exited, so killing self
				fmt.Println("==> now committing suicide")
				os.Exit(1)
			}
		}
	}()

	<-done
}
<commit_msg>0.1.0<commit_after>package main

import (
	"errors"
	"flag"
	"fmt"
	"log"
	"os"
	"os/exec"
	"os/signal"
	"runtime"
	"strings"
	"sync"
	"syscall"
	"time"

	"gopkg.in/fsnotify.v1"
)

const Version = "0.1.0"

var (
	filesFlag = flag.String("f", "", "files and directories to watch, split by ':'")
	sigFlag   = flag.String("s", "HUP", "signal to send on change")
	delayFlag = flag.Duration("d", 3*time.Second, "time to wait after change before signalling child")
)

func signalByName(name string) (sig os.Signal, err error) {
	var ok bool
	if sig, ok = signals[strings.ToUpper(name)]; !ok {
		err = errors.New(fmt.Sprintf("unknown signal: %s", name))
	}
	return
}

func signalDebounce(process *os.Process, sig os.Signal, delay time.Duration) *sync.Cond {
	var m sync.Mutex
	cond := sync.NewCond(&m)
	cond.L.Lock()

	go func() {
		// continulously wait for a Broadcast event
		// then sleep, and pass along the signal to the process
		// The sleep causes the signals to effectively be debounced.
		// Note: this isn't a true debounce. We don't want to trigger
		// immediately on the first event. We explicitly want to wait
		// _then_ trigger.
		for {
			cond.Wait()
			time.Sleep(delay)
			if process != nil {
				log.Println("==> signalling child")
				process.Signal(sig)
			}
		}
	}()

	return cond
}

func usageAndExit(s interface{}) {
	fmt.Printf("!! %s\n", s)
	flag.Usage()
	fmt.Println()
	fmt.Printf("%s version: %s (%s on %s/%s; %s)\n", os.Args[0], Version, runtime.Version(), runtime.GOOS, runtime.GOARCH, runtime.Compiler)
	os.Exit(1)
}

func usage() {
	fmt.Fprintf(os.Stderr, "usage: blart [flags] [command]\n")
	flag.PrintDefaults()
}

func init() {
	flag.Usage = usage
	flag.Parse()
}

func main() {
	sig, err := signalByName(*sigFlag)
	if err != nil {
		usageAndExit(err)
	}

	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		usageAndExit(err)
	}
	defer watcher.Close()

	if *filesFlag == "" {
		usageAndExit("no files to watch")
	}

	if len(flag.Args()) == 0 {
		usageAndExit("no command specified")
	}

	// start watching files for changes
	for _, file := range strings.Split(*filesFlag, ":") {
		err = watcher.Add(file)
		// if a file doesn't exist that you're trying to watch at this
		// point, it's likely a config error, and we should bail
		if err != nil {
			usageAndExit(err)
		}
	}

	cmd := exec.Command(flag.Args()[0], flag.Args()[1:]...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	err = cmd.Start()
	if err != nil {
		usageAndExit(err)
	}

	fmt.Println("==> starting child", strings.Join(flag.Args(), " "))

	done := make(chan struct{})
	go func() {
		cmd.Wait()
		done <- struct{}{}
	}()

	go func() {
		var event fsnotify.Event
		var err error

		// Create wrapper to debounce the signal events
		cond := signalDebounce(cmd.Process, sig, *delayFlag)

		for {
			select {
			case event = <-watcher.Events:
				log.Println("==> detected change in", event.Name)
				// Broadcase to the sync.Cond that an event has happened.
				// magic happens inside signalDebounce
				cond.Broadcast()
				if event.Op&fsnotify.Rename == fsnotify.Rename {
					// File was renamed, so remove the old watch,
					// and add a new one
					watcher.Remove(event.Name)
					watcher.Add(event.Name)
				}
			case err = <-watcher.Errors:
				log.Println("==> error:", err)
			}
		}
	}()

	// Listen to signals send to parent, and pass along to the child
	c := make(chan os.Signal, 1)
	signal.Notify(c)
	go func() {
		var sig os.Signal
		for {
			sig = <-c
			cmd.Process.Signal(sig)
			switch sig {
			case os.Interrupt, os.Kill, syscall.SIGTERM:
				countdown := 5 * time.Second

				fmt.Println("==> attempting to shut down cleanly")
				fmt.Printf("==> waiting up to %s for child to exit\n", countdown)

				// try and wait for the child to shut down before killing
				select {
				case <-done:
				case <-time.After(countdown):
				}

				// it hasn't shut down yet, so attempt to SIGKILL
				fmt.Println("==> attempting to now kill child")
				cmd.Process.Signal(os.Kill)

				select {
				case <-done:
				case <-time.After(time.Second):
				}

				// still hasn't exited, so killing self
				fmt.Println("==> now committing suicide")
				os.Exit(1)
			}
		}
	}()

	<-done
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 Matt Jibson <matt.jibson@gmail.com>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package main

import (
	"bytes"
	"flag"
	"fmt"
	"go/ast"
	"go/format"
	"go/parser"
	"go/printer"
	"go/token"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"strconv"
	"strings"

	"golang.org/x/tools/go/ast/astutil"
)

const dirMode os.FileMode = 0755

var (
	dryrun       = flag.Bool("n", false, "don't perform any action, instead print them")
	create       = flag.Bool("c", false, "create the third party directory if needed")
	relative     = flag.Bool("r", false, "use a relative third party directory (needed on App Engine)")
	verbose      = flag.Bool("v", false, "print actions")
	thirdParty   = flag.String("d", "_third_party", "name of third party directory")
	flagUpdate   = flag.Bool("u", false, "update (go get -d -u) used packages")
	includeTests = flag.Bool("t", false, "import dependencies for _test.go files")

	relpath, gopath, ThirdParty string
)

func main() {
	flag.Parse()
	if *dryrun {
		*verbose = true
	}

	ThirdParty = filepath.Base(*thirdParty)
	if ThirdParty != *thirdParty {
		log.Fatal("third party directory cannot contain path separators")
	}
	if *create {
		os.Mkdir(ThirdParty, dirMode)
	}
	if _, err := os.Open(ThirdParty); err != nil {
		log.Fatalf("could not open %s directory: run with -c or create it manually", ThirdParty)
	}

	pwd, err := os.Getwd()
	if err != nil {
		log.Fatal(err)
	}
	var importSites []string
	for _, s := range filepath.SplitList(os.Getenv("GOPATH")) {
		s, err := filepath.Abs(s)
		if err != nil {
			log.Fatal(err)
		}
		s, err = filepath.EvalSymlinks(s)
		if err != nil {
			log.Fatal(err)
		}
		if sf, err := os.Open(filepath.Join(s, "src")); err == nil {
			names, err := sf.Readdirnames(0)
			if err == nil {
				for _, name := range names {
					importSites = append(importSites, name)
				}
			}
		}
		if !strings.HasPrefix(pwd, s) {
			continue
		}
		gopath = s
		relpath = strings.TrimPrefix(pwd, filepath.Join(s, "src")+string(os.PathSeparator))
		break
	}
	if relpath == "" {
		log.Fatal("couldn't determine current directory relative to $GOPATH")
	}

	if *verbose {
		log.Println("using GOPATH:", gopath)
		log.Println("using relative path:", relpath)
	}
	updated := make(map[string]bool)
	for {
		update(updated)
		if !rewriteImports(importSites) {
			break
		}
	}
}

func update(updated map[string]bool) {
	paths := make(map[string]struct{})
	reltp := ThirdParty + "/"
	if !*relative {
		reltp = filepath.ToSlash(relpath) + "/" + reltp
	}
	filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
		if err != nil || info.IsDir() {
			return nil
		}
		if !*includeTests && strings.HasSuffix(path, "_test.go") {
			return nil
		}
		fset := token.NewFileSet()
		f, err := parser.ParseFile(fset, path, nil, parser.ParseComments)
		if err != nil {
			return nil
		}
		for _, im := range f.Imports {
			v := im.Path.Value[1 : len(im.Path.Value)-1]
			if !strings.HasPrefix(v, reltp) {
				continue
			}
			paths[strings.TrimPrefix(v, reltp)] = struct{}{}
		}
		return nil
	})
	for k := range paths {
		fpath := filepath.Join(gopath, "src", k)
		if *flagUpdate && !updated[k] {
			updated[k] = true
			if *verbose {
				log.Printf("go get -d -u %v", k)
			}
			if !*dryrun {
				out, err := exec.Command("go", "get", "-d", "-u", k).CombinedOutput()
				if len(out) > 0 {
					log.Println(string(out))
				}
				if err != nil {
					log.Println("go get", k, "err:", err)
				}
			}
		}
		f, err := os.Open(fpath)
		if err != nil {
			log.Printf("%s required, but could not be found at %s", k, fpath)
			continue
		}
		files, err := f.Readdir(0)
		if err != nil {
			log.Fatal(err)
		}
		f.Close()
		for _, source := range files {
			if source.IsDir() || strings.HasPrefix(source.Name(), ".") {
				continue
			}
			spath := filepath.Join(f.Name(), source.Name())
			destdir := filepath.Join(ThirdParty, k)
			dest := filepath.Join(destdir, source.Name())
			if err := os.MkdirAll(destdir, dirMode); err != nil {
				log.Fatal(err)
			}
			dst, err := os.Open(dest)
			created := false
			newer := false
			if os.IsNotExist(err) {
				if *verbose {
					log.Println("create", dest)
				}
				created = true
			} else if err != nil {
				log.Fatal(err)
			} else {
				destination, err := dst.Stat()
				if err != nil {
					log.Fatal(err)
				}
				newer = source.ModTime().After(destination.ModTime())
				dst.Close()
			}
			if created || newer {
				if *verbose {
					log.Printf("copy %s -> %s\n", spath, dest)
				}
				if !*dryrun {
					b, err := ioutil.ReadFile(spath)
					if err != nil {
						log.Fatal(err)
					}
					if filepath.Ext(spath) == ".go" {
						b, err = fixImportCheck(b, path.Join(relpath, destdir))
						if err != nil {
							log.Fatal(err)
						}
					}
					if err := ioutil.WriteFile(dest, b, source.Mode()); err != nil {
						log.Fatal(err)
					}
				}
			}
		}
	}
}

func fixImportCheck(body []byte, importPath string) ([]byte, error) {
	fset := token.NewFileSet()
	// todo: see if we can restrict the mode some more
	f, err := parser.ParseFile(fset, "", body, parser.ParseComments)
	if err != nil {
		log.Fatal(err)
	}
	var after *ast.CommentGroup
	var pos token.Pos = token.Pos(len(body))
	for _, v := range f.Comments {
		text := strings.TrimSpace(v.Text())
		if v.Pos() > f.Package && v.Pos() < pos && strings.HasPrefix(text, "import") {
			pos = v.Pos()
			after = v
		}
	}
	if after != nil && bytes.IndexByte(body[f.Package:pos], '\n') == -1 {
		comment := fmt.Sprintf(`// import "%s"`, importPath)
		buf := new(bytes.Buffer)
		buf.Write(body[:after.Pos()-1])
		buf.WriteString(comment)
		buf.Write(body[after.End()-1:])
		body = buf.Bytes()
	}
	return body, nil
}

func rewriteImports(importSites []string) (rewritten bool) {
	filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
		if err != nil || info.IsDir() {
			return nil
		}
		fset := token.NewFileSet()
		f, err := parser.ParseFile(fset, path, nil, parser.ParseComments)
		if err != nil {
			return nil
		}
		for _, im := range f.Imports {
			for _, site := range importSites {
				v, err := strconv.Unquote(im.Path.Value)
				if err != nil {
					log.Fatal(err)
				}
				// don't replace ourself
				if v == relpath || strings.HasPrefix(v, relpath+"/") {
					if *verbose {
						log.Printf("skipping %s because it is in %s\n", v, relpath)
					}
					continue
				}
				if strings.HasPrefix(v, site+"/") {
					target := ThirdParty + "/" + v
					if !*relative {
						target = filepath.ToSlash(relpath) + "/" + target
					}
					if *verbose {
						log.Printf("rewrite %s: %s -> %s\n", path, v, target)
					}
					if *dryrun {
						break
					}
					if !astutil.RewriteImport(fset, f, v, target) {
						log.Fatalf("%s: could not rewrite %s", path, im.Path.Value)
					}
					rewritten = true
					break
				}
			}
		}
		var buf bytes.Buffer
		if err := printer.Fprint(&buf, fset, f); err != nil {
			log.Fatal(err)
		}
		fb, err := format.Source(buf.Bytes())
		if err != nil {
			log.Fatal(err)
		}
		if err := ioutil.WriteFile(path, fb, info.Mode()); err != nil {
			log.Fatal(err)
		}
		return nil
	})
	return
}
<commit_msg>Drive letter and path separator issues on Windows.<commit_after>/*
 * Copyright (c) 2014 Matt Jibson <matt.jibson@gmail.com>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package main

import (
	"bytes"
	"flag"
	"fmt"
	"go/ast"
	"go/format"
	"go/parser"
	"go/printer"
	"go/token"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"strconv"
	"strings"

	"golang.org/x/tools/go/ast/astutil"
)

const dirMode os.FileMode = 0755

var (
	dryrun       = flag.Bool("n", false, "don't perform any action, instead print them")
	create       = flag.Bool("c", false, "create the third party directory if needed")
	relative     = flag.Bool("r", false, "use a relative third party directory (needed on App Engine)")
	verbose      = flag.Bool("v", false, "print actions")
	thirdParty   = flag.String("d", "_third_party", "name of third party directory")
	flagUpdate   = flag.Bool("u", false, "update (go get -d -u) used packages")
	includeTests = flag.Bool("t", false, "import dependencies for _test.go files")

	relpath, gopath, ThirdParty string
)

func main() {
	flag.Parse()
	if *dryrun {
		*verbose = true
	}

	ThirdParty = filepath.Base(*thirdParty)
	if ThirdParty != *thirdParty {
		log.Fatal("third party directory cannot contain path separators")
	}
	if *create {
		os.Mkdir(ThirdParty, dirMode)
	}
	if _, err := os.Open(ThirdParty); err != nil {
		log.Fatalf("could not open %s directory: run with -c or create it manually", ThirdParty)
	}

	pwd, err := os.Getwd()
	if err != nil {
		log.Fatal(err)
	}
	// Under certain circumstances Getwd and EvalSymlinks return different case drive letter on Windows.
	// To ensure a match in the loop below, do an Evalsymlink on pwd too.
	pwd, err = filepath.EvalSymlinks(pwd)
	if err != nil {
		log.Fatal(err)
	}
	var importSites []string
	for _, s := range filepath.SplitList(os.Getenv("GOPATH")) {
		s, err := filepath.Abs(s)
		if err != nil {
			log.Fatal(err)
		}
		s, err = filepath.EvalSymlinks(s)
		if err != nil {
			log.Fatal(err)
		}
		if sf, err := os.Open(filepath.Join(s, "src")); err == nil {
			names, err := sf.Readdirnames(0)
			if err == nil {
				for _, name := range names {
					importSites = append(importSites, name)
				}
			}
		}
		if !strings.HasPrefix(pwd, s) {
			continue
		}
		gopath = s
		relpath = filepath.ToSlash(strings.TrimPrefix(pwd, filepath.Join(s, "src")+string(os.PathSeparator)))
		break
	}
	if relpath == "" {
		log.Fatal("couldn't determine current directory relative to $GOPATH")
	}

	if *verbose {
		log.Println("using GOPATH:", gopath)
		log.Println("using relative path:", relpath)
	}
	updated := make(map[string]bool)
	for {
		update(updated)
		if !rewriteImports(importSites) {
			break
		}
	}
}

func update(updated map[string]bool) {
	paths := make(map[string]struct{})
	reltp := ThirdParty + "/"
	if !*relative {
		reltp = filepath.ToSlash(relpath) + "/" + reltp
	}
	filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
		if err != nil || info.IsDir() {
			return nil
		}
		if !*includeTests && strings.HasSuffix(path, "_test.go") {
			return nil
		}
		fset := token.NewFileSet()
		f, err := parser.ParseFile(fset, path, nil, parser.ParseComments)
		if err != nil {
			return nil
		}
		for _, im := range f.Imports {
			v := im.Path.Value[1 : len(im.Path.Value)-1]
			if !strings.HasPrefix(v, reltp) {
				continue
			}
			paths[strings.TrimPrefix(v, reltp)] = struct{}{}
		}
		return nil
	})
	for k := range paths {
		fpath := filepath.Join(gopath, "src", k)
		if *flagUpdate && !updated[k] {
			updated[k] = true
			if *verbose {
				log.Printf("go get -d -u %v", k)
			}
			if !*dryrun {
				out, err := exec.Command("go", "get", "-d", "-u", k).CombinedOutput()
				if len(out) > 0 {
					log.Println(string(out))
				}
				if err != nil {
					log.Println("go get", k, "err:", err)
				}
			}
		}
		f, err := os.Open(fpath)
		if err != nil {
			log.Printf("%s required, but could not be found at %s", k, fpath)
			continue
		}
		files, err := f.Readdir(0)
		if err != nil {
			log.Fatal(err)
		}
		f.Close()
		for _, source := range files {
			if source.IsDir() || strings.HasPrefix(source.Name(), ".") {
				continue
			}
			spath := filepath.Join(f.Name(), source.Name())
			destdir := filepath.Join(ThirdParty, k)
			dest := filepath.Join(destdir, source.Name())
			if err := os.MkdirAll(destdir, dirMode); err != nil {
				log.Fatal(err)
			}
			dst, err := os.Open(dest)
			created := false
			newer := false
			if os.IsNotExist(err) {
				if *verbose {
					log.Println("create", dest)
				}
				created = true
			} else if err != nil {
				log.Fatal(err)
			} else {
				destination, err := dst.Stat()
				if err != nil {
					log.Fatal(err)
				}
				newer = source.ModTime().After(destination.ModTime())
				dst.Close()
			}
			if created || newer {
				if *verbose {
					log.Printf("copy %s -> %s\n", spath, dest)
				}
				if !*dryrun {
					b, err := ioutil.ReadFile(spath)
					if err != nil {
						log.Fatal(err)
					}
					if filepath.Ext(spath) == ".go" {
						b, err = fixImportCheck(b, filepath.ToSlash(path.Join(relpath, destdir)))
						if err != nil {
							log.Fatal(err)
						}
					}
					if err := ioutil.WriteFile(dest, b, source.Mode()); err != nil {
						log.Fatal(err)
					}
				}
			}
		}
	}
}

func fixImportCheck(body []byte, importPath string) ([]byte, error) {
	fset := token.NewFileSet()
	// todo: see if we can restrict the mode some more
	f, err := parser.ParseFile(fset, "", body, parser.ParseComments)
	if err != nil {
		log.Fatal(err)
	}
	var after *ast.CommentGroup
	var pos token.Pos = token.Pos(len(body))
	for _, v := range f.Comments {
		text := strings.TrimSpace(v.Text())
		if v.Pos() > f.Package && v.Pos() < pos && strings.HasPrefix(text, "import") {
			pos = v.Pos()
			after = v
		}
	}
	if after != nil && bytes.IndexByte(body[f.Package:pos], '\n') == -1 {
		comment := fmt.Sprintf(`// import "%s"`, importPath)
		buf := new(bytes.Buffer)
		buf.Write(body[:after.Pos()-1])
		buf.WriteString(comment)
		buf.Write(body[after.End()-1:])
		body = buf.Bytes()
	}
	return body, nil
}

func rewriteImports(importSites []string) (rewritten bool) {
	filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
		if err != nil || info.IsDir() {
			return nil
		}
		fset := token.NewFileSet()
		f, err := parser.ParseFile(fset, path, nil, parser.ParseComments)
		if err != nil {
			return nil
		}
		for _, im := range f.Imports {
			for _, site := range importSites {
				v, err := strconv.Unquote(im.Path.Value)
				if err != nil {
					log.Fatal(err)
				}
				// don't replace ourself
				if v == relpath || strings.HasPrefix(v, relpath+"/") {
					if *verbose {
						log.Printf("skipping %s because it is in %s\n", v, relpath)
					}
					continue
				}
				if strings.HasPrefix(v, site+"/") {
					target := ThirdParty + "/" + v
					if !*relative {
						target = filepath.ToSlash(relpath) + "/" + target
					}
					if *verbose {
						log.Printf("rewrite %s: %s -> %s\n", path, v, target)
					}
					if *dryrun {
						break
					}
					if !astutil.RewriteImport(fset, f, v, target) {
						log.Fatalf("%s: could not rewrite %s", path, im.Path.Value)
					}
					rewritten = true
					break
				}
			}
		}
		var buf bytes.Buffer
		if err := printer.Fprint(&buf, fset, f); err != nil {
			log.Fatal(err)
		}
		fb, err := format.Source(buf.Bytes())
		if err != nil {
			log.Fatal(err)
		}
		if err := ioutil.WriteFile(path, fb, info.Mode()); err != nil {
			log.Fatal(err)
		}
		return nil
	})
	return
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"html/template"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/exec"
	"time"
)

var streams []stream
var commands []*exec.Cmd

type stream struct {
	Name   string
	Stream string
	Image  string
}

func main() {
	//Read in urls of webcams from configuration file
	data, err := ioutil.ReadFile("streams.json")
	if err != nil {
		panic(err)
	}

	if err := json.Unmarshal(data, &streams); err != nil {
		panic(err)
	}

	//Startup webserver to listen to commands to execute video player
	http.HandleFunc("/", serveIndex)
	http.HandleFunc("/all", serveAll)
	http.HandleFunc("/pick", serveOne)
	http.HandleFunc("/stop", serveStop)
	// showAll()
	log.Println("server started...")
	log.Fatal(http.ListenAndServe(":2000", nil))
}

func renderWebsite(w http.ResponseWriter) {
	const tpl = `
<!DOCTYPE html>

		<meta charset="UTF-8">
		<title>Zoo Cam Viewer</title>

All

Stop

		{{range .Streams}}
{{ .Name }}

{{else}}
no streams
{{end}}

`
	t, err := template.New("webpage").Parse(tpl)
	if err != nil {
		panic(err)
	}
	t.Execute(w, struct{ Streams []stream }{Streams: streams})
}

func serveIndex(w http.ResponseWriter, r *http.Request) {
	//Serve up basic website with icons to choose from with "all" option
	renderWebsite(w)
}

func serveAll(w http.ResponseWriter, r *http.Request) {
	//Close all existing processes, and fire up all the videos
	showAll()
	renderWebsite(w)
}

func serveOne(w http.ResponseWriter, r *http.Request) {
	//Close all existing processes, and fire up the single video passed in
	name := r.FormValue("name")
	log.Println("got stream name of " + name)
	for _, stream := range streams {
		if stream.Name == name {
			log.Println("Starting stream " + stream.Name)
			showOne(stream)
		}
	}
	renderWebsite(w)
}

func serveStop(w http.ResponseWriter, r *http.Request) {
	killAll()
	renderWebsite(w)
}

func showAll() {
	killAll()
	width := 1920
	height := 1080
	streamCount := len(streams)

	//Determine how many streams we have to make even boxed grids
	boxes := 1
	for ; boxes*boxes < streamCount; boxes++ {
	}

	startWidth := 0
	startHeight := 0
	widthStep := width / boxes
	heightStep := height / boxes
	//We now have a box X box width screen (say 3x3), so split the screen appropriately
	for index, s := range streams {
		endWidth := startWidth + ((index + 1) * widthStep)
		endHeight := startHeight + ((index + 1) * heightStep)
		log.Printf("end width is %v and end height is %v\n", endWidth, endHeight)
		log.Printf("dimensions of window: %v,%v,%v,%v", startWidth, startHeight, endWidth, endHeight)
		cmd := exec.Command("omxplayer", "--win", fmt.Sprintf("%v,%v,%v,%v", startWidth, startHeight, endWidth, endHeight), s.Stream)
		// cmd := exec.Command("mplayer", s.Stream)
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
		commands = append(commands, cmd)
		cmd.Start()
		time.Sleep(5 * time.Second)
	}
}

func showOne(s stream) {
	killAll()
	//Startup in fullscreen
	cmd := exec.Command("omxplayer", "-b", s.Stream)
	// cmd := exec.Command("mplayer", s.Stream)
	cmd.Start()
	commands = append(commands, cmd)
}

func killAll() {
	log.Println("killing all existing streams")
	for _, proc := range commands {
		proc.Process.Kill()
	}
}
<commit_msg>fixing box calculations<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"html/template"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/exec"
	"time"
)

var streams []stream
var commands []*exec.Cmd

type stream struct {
	Name   string
	Stream string
	Image  string
}

func main() {
	//Read in urls of webcams from configuration file
	data, err := ioutil.ReadFile("streams.json")
	if err != nil {
		panic(err)
	}

	if err := json.Unmarshal(data, &streams); err != nil {
		panic(err)
	}

	//Startup webserver to listen to commands to execute video player
	http.HandleFunc("/", serveIndex)
	http.HandleFunc("/all", serveAll)
	http.HandleFunc("/pick", serveOne)
	http.HandleFunc("/stop", serveStop)
	// showAll()
	log.Println("server started...")
	log.Fatal(http.ListenAndServe(":2000", nil))
}

func renderWebsite(w http.ResponseWriter) {
	const tpl = `
<!DOCTYPE html>

		<meta charset="UTF-8">
		<title>Zoo Cam Viewer</title>

All

Stop

		{{range .Streams}}
{{ .Name }}

{{else}}
no streams
{{end}}

`
	t, err := template.New("webpage").Parse(tpl)
	if err != nil {
		panic(err)
	}
	t.Execute(w, struct{ Streams []stream }{Streams: streams})
}

func serveIndex(w http.ResponseWriter, r *http.Request) {
	//Serve up basic website with icons to choose from with "all" option
	renderWebsite(w)
}

func serveAll(w http.ResponseWriter, r *http.Request) {
	//Close all existing processes, and fire up all the videos
	showAll()
	renderWebsite(w)
}

func serveOne(w http.ResponseWriter, r *http.Request) {
	//Close all existing processes, and fire up the single video passed in
	name := r.FormValue("name")
	log.Println("got stream name of " + name)
	for _, stream := range streams {
		if stream.Name == name {
			log.Println("Starting stream " + stream.Name)
			showOne(stream)
		}
	}
	renderWebsite(w)
}

func serveStop(w http.ResponseWriter, r *http.Request) {
	killAll()
	renderWebsite(w)
}

func showAll() {
	killAll()
	width := 1920
	height := 1080
	streamCount := len(streams)

	//Determine how many streams we have to make even boxed grids
	boxes := 1
	for ; boxes*boxes < streamCount; boxes++ {
	}

	startWidth := 0
	startHeight := 0
	widthStep := width / boxes
	heightStep := height / boxes
	//We now have a box X box width screen (say 3x3), so split the screen appropriately
	for index, s := range streams {
		endWidth := startWidth + ((index + 1) * widthStep)
		endHeight := startHeight + ((index + 1) * heightStep)
		log.Printf("end width is %v and end height is %v\n", endWidth, endHeight)
		log.Printf("dimensions of window: %v,%v,%v,%v", startWidth, startHeight, endWidth, endHeight)
		cmd := exec.Command("omxplayer", "--win", fmt.Sprintf("%v,%v,%v,%v", startWidth, startHeight, endWidth, endHeight), s.Stream)
		// cmd := exec.Command("mplayer", s.Stream)
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
		commands = append(commands, cmd)
		cmd.Start()
		time.Sleep(5 * time.Second)
		startWidth = endWidth
		startHeight = endHeight
	}
}

func showOne(s stream) {
	killAll()
	//Startup in fullscreen
	cmd := exec.Command("omxplayer", "-b", s.Stream)
	// cmd := exec.Command("mplayer", s.Stream)
	cmd.Start()
	commands = append(commands, cmd)
}

func killAll() {
	log.Println("killing all existing streams")
	for _, proc := range commands {
		proc.Process.Kill()
	}
}
<|endoftext|>


<commit_before>/*
(BSD 2-clause license)

Copyright (c) 2014, Shawn Webb
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/
package main

import (
    /*
    "log"
    "time"
    */
    "fmt"
    "database/sql"
    _ "github.com/go-sql-driver/mysql"
    "github.com/coopernurse/gorp"
    /* "github.com/virtbsd/VirtualMachine" */
    "github.com/virtbsd/jail"
    "github.com/virtbsd/network"
)

var db *gorp.DbMap

func main() {
    db = initDb()
    myjail := jail.GetJail(db, map[string]interface{} { "uuid": "bcf95990-98f7-11e3-b9f2-18037319526c" })
    if myjail == nil {
        fmt.Printf("Jail not found\n");
    } else {
        err := myjail.Validate()
        if err != nil {
            panic(err)
        }

        fmt.Printf("%+v\n", myjail)
        fmt.Printf("Path: \"%s\"\n", myjail.Path)
    }
}

func initDb() *gorp.DbMap {
    db, err := sql.Open("mysql", "virtbsd:v1rtbsd!@unix(/tmp/mysql.sock)/virtbsd_db?loc=Local")
    if err != nil {
        return nil
    }

    dbmap := &gorp.DbMap{Db: db, Dialect: gorp.MySQLDialect{"InnoDB", "UTF8"}}

    dbmap.AddTable(jail.Jail{}).SetKeys(false, "UUID")
    dbmap.AddTable(network.Network{}).SetKeys(false, "UUID")
    dbmap.AddTable(network.NetworkDevice{}).SetKeys(false, "UUID")
    dbmap.AddTable(network.NetworkPhysical{})
    dbmap.AddTable(network.DeviceAddress{})
    dbmap.AddTable(network.DeviceOption{})
    dbmap.AddTable(jail.MountPoint{})
    dbmap.AddTable(jail.JailOption{})

    if err = dbmap.CreateTablesIfNotExists(); err != nil {
        panic(err)
    }

    return dbmap
}
<commit_msg>Test booting up test jail<commit_after>/*
(BSD 2-clause license)

Copyright (c) 2014, Shawn Webb
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/
package main

import (
    /*
    "log"
    "time"
    */
    "fmt"
    "database/sql"
    _ "github.com/go-sql-driver/mysql"
    "github.com/coopernurse/gorp"
    /* "github.com/virtbsd/VirtualMachine" */
    "github.com/virtbsd/jail"
    "github.com/virtbsd/network"
)

var db *gorp.DbMap

func main() {
    db = initDb()
    myjail := jail.GetJail(db, map[string]interface{} { "uuid": "bcf95990-98f7-11e3-b9f2-18037319526c" })
    if myjail == nil {
        fmt.Printf("Jail not found\n");
    } else {
        err := myjail.Validate()
        if err != nil {
            panic(err)
        }

        if err = myjail.PrepareHostNetworking(); err != nil {
            panic(err);
        }
        if err = myjail.Start(); err != nil {
            panic(err);
        }
        if err = myjail.PrepareGuestNetworking(); err != nil {
            panic(err);
        }
    }
}

func initDb() *gorp.DbMap {
    db, err := sql.Open("mysql", "virtbsd:v1rtbsd!@unix(/tmp/mysql.sock)/virtbsd_db?loc=Local")
    if err != nil {
        return nil
    }

    dbmap := &gorp.DbMap{Db: db, Dialect: gorp.MySQLDialect{"InnoDB", "UTF8"}}

    dbmap.AddTable(jail.Jail{}).SetKeys(false, "UUID")
    dbmap.AddTable(network.Network{}).SetKeys(false, "UUID")
    dbmap.AddTable(network.NetworkDevice{}).SetKeys(false, "UUID")
    dbmap.AddTable(network.NetworkPhysical{})
    dbmap.AddTable(network.DeviceAddress{})
    dbmap.AddTable(network.DeviceOption{})
    dbmap.AddTable(network.Route{})
    dbmap.AddTable(jail.MountPoint{})
    dbmap.AddTable(jail.JailOption{})

    if err = dbmap.CreateTablesIfNotExists(); err != nil {
        panic(err)
    }

    return dbmap
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strings"

	log "github.com/Sirupsen/logrus"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/ec2metadata"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/aws/aws-sdk-go/service/iam"
)

func shellEncode(key, value string, output io.Writer) {
	key = strings.ToUpper(key)
	key = strings.Replace(key, ":", "_", -1)
	key = strings.Replace(key, "-", "_", -1)
	fmt.Fprintf(output, "AWS_%s=%s\n", strings.Replace(strings.ToUpper(key), ":", "_", -1), value)
}

func init() {
	log.SetOutput(os.Stderr)
}

func main() {
	session := session.New()
	metadata := ec2metadata.New(session)
	f, err := os.Create("/etc/aws")
	if err != nil {
		log.Panicf("Failed to create file /etc/aws, %v", err)
	}
	defer f.Close()
	writer := bufio.NewWriter(f)

	var instanceID string
	if metadata.Available() {
		instanceID, err = metadata.GetMetadata("instance-id")
		if err != nil {
			log.Panicf("Failed to fetch instance-id, %v", err)
		}
		shellEncode("INSTANCE_ID", instanceID, writer)

		az, err := metadata.GetMetadata("placement/availability-zone")
		if err != nil {
			log.Panicf("Failed to fetch availablity-zone, %v", err)
		}
		shellEncode("AVAILABLITY_ZONE", az, writer)

		region, err := metadata.Region()
		if err != nil {
			log.Panicf("Failed to fetch Region, %v", err)
		}
		shellEncode("REGION", region, writer)
		session = session.Copy(&aws.Config{Region: aws.String(region)})
	} else {
		instanceID = os.Args[1]
	}

	iamClient := iam.New(session)
	aliases, err := iamClient.ListAccountAliases(&iam.ListAccountAliasesInput{})
	if err != nil {
		log.Panicf("Failed to ListAccountAliases, %v", err)
	}

	for _, alias := range aliases.AccountAliases {
		shellEncode("ACCOUNT_ALIAS", *alias, writer)
	}

	log.Info("Describing instances")
	ec2Client := ec2.New(session)
	resp, err := ec2Client.DescribeInstances(&ec2.DescribeInstancesInput{
		InstanceIds: []*string{
			aws.String(instanceID),
		},
	})
	if err != nil {
		log.Panicf("Failed to DescribeInstances, %v", err)
	}

	for _, res := range resp.Reservations {
		for _, inst := range res.Instances {
			log.Infof("Instance ID: %s", *inst.InstanceId)
			for _, tag := range inst.Tags {
				shellEncode("Tag_"+*tag.Key, *tag.Value, writer)
			}
		}
	}

	writer.Flush()
}
<commit_msg>Writing values to buffer prior to creating file<commit_after>package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"os"
	"strings"

	log "github.com/Sirupsen/logrus"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/ec2metadata"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/aws/aws-sdk-go/service/iam"
)

func shellEncode(key, value string, output io.Writer) {
	key = strings.ToUpper(key)
	key = strings.Replace(key, ":", "_", -1)
	key = strings.Replace(key, "-", "_", -1)
	fmt.Fprintf(output, "AWS_%s=%s\n", strings.Replace(strings.ToUpper(key), ":", "_", -1), value)
}

func init() {
	log.SetOutput(os.Stderr)
}

func main() {
	session := session.New()
	metadata := ec2metadata.New(session)
	var buffer bytes.Buffer
	var err error

	writer := bufio.NewWriter(&buffer)

	var instanceID string
	if metadata.Available() {
		instanceID, err = metadata.GetMetadata("instance-id")
		if err != nil {
			log.Panicf("Failed to fetch instance-id, %v", err)
		}
		shellEncode("INSTANCE_ID", instanceID, writer)

		az, err := metadata.GetMetadata("placement/availability-zone")
		if err != nil {
			log.Panicf("Failed to fetch availablity-zone, %v", err)
		}
		shellEncode("AVAILABLITY_ZONE", az, writer)

		region, err := metadata.Region()
		if err != nil {
			log.Panicf("Failed to fetch Region, %v", err)
		}
		shellEncode("REGION", region, writer)
		session = session.Copy(&aws.Config{Region: aws.String(region)})
	} else {
		instanceID = os.Args[1]
	}

	iamClient := iam.New(session)
	aliases, err := iamClient.ListAccountAliases(&iam.ListAccountAliasesInput{})
	if err != nil {
		log.Panicf("Failed to ListAccountAliases, %v", err)
	}

	for _, alias := range aliases.AccountAliases {
		shellEncode("ACCOUNT_ALIAS", *alias, writer)
	}

	log.Info("Describing instances")
	ec2Client := ec2.New(session)
	resp, err := ec2Client.DescribeInstances(&ec2.DescribeInstancesInput{
		InstanceIds: []*string{
			aws.String(instanceID),
		},
	})
	if err != nil {
		log.Panicf("Failed to DescribeInstances, %v", err)
	}

	for _, res := range resp.Reservations {
		for _, inst := range res.Instances {
			log.Infof("Instance ID: %s", *inst.InstanceId)
			for _, tag := range inst.Tags {
				shellEncode("Tag_"+*tag.Key, *tag.Value, writer)
			}
		}
	}

	writer.Flush()

	f, err := os.Create("/etc/aws")
	if err != nil {
		log.Panicf("Failed to create file /etc/aws, %v", err)
	}
	defer f.Close()

	f.Write(buffer.Bytes())
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"html/template"
	"image/jpeg"
	"log"
	"net"
	"net/http"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"strconv"
	"strings"

	"github.com/nfnt/resize"
	"github.com/pyk/byten"
	"github.com/skratchdot/open-golang/open"
)

type media struct {
	Filename string
	Fileinfo os.FileInfo
}

func in(slice []string, str string) bool {
	for _, s := range slice {
		if s == str {
			return true
		}
	}
	return false
}

var acceptedImageExt = []string{".jpg", ".jpeg", ".mp4", ".png"}
var dirThumbs = fmt.Sprintf("%s%s", os.Getenv("HOME"), "/.cache/lk")
var dirPath = "."
var version = "master"
var showVersionFlag = flag.Bool("version", false, "Show version")
var port = flag.Int("port", 0, "listen port")
var openbrowser = flag.Bool("openbrowser", false, "Open in browser")

func hostname() string {
	hostname, _ := os.Hostname()
	// If hostname does not have dots (i.e. not fully qualified), then return zeroconf address for LAN browsing
	if strings.Split(hostname, ".")[0] == hostname {
		return hostname + ".local"
	}
	return hostname
}

func main() {

	flag.Parse()

	if *showVersionFlag {
		fmt.Println("https://github.com/kaihendry/lk", version)
		os.Exit(0)
	}

	directory := flag.Arg(0)
	dirPath, _ = filepath.Abs(directory)

	// Getting rid of /../ etc
	dirPath = path.Clean(dirPath)

	// Don't allow path under dirPath to be viewed
	http.Handle("/o/", http.StripPrefix(path.Join("/o", dirPath), http.FileServer(http.Dir(dirPath))))
	http.HandleFunc("/favicon.ico", http.NotFound)

	http.HandleFunc("/", index)
	http.HandleFunc("/t/", thumb)

	// http://stackoverflow.com/a/33985208/4534
	eport := os.Getenv("PORT")
	if eport != "" {
		*port, _ = strconv.Atoi(eport)
	}
	ln, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))
	if err != nil {
		log.Panic(err)
	}

	if a, ok := ln.Addr().(*net.TCPAddr); ok {
		host := fmt.Sprintf("http://%s:%d", hostname(), a.Port)
		fmt.Println("Serving from", host)
		if *openbrowser {
			open.Start(host)
		}
	}
	if err := http.Serve(ln, nil); err != nil {
		log.Panic(err)
	}

}

func thumb(w http.ResponseWriter, r *http.Request) {

	// Path cleaning
	requestedPath := path.Clean(r.URL.Path[2:])

	// Make sure you can't go under the dirPath
	if !strings.HasPrefix(requestedPath, dirPath) {
		http.NotFound(w, r)
		return
	}

	thumbPath := filepath.Join(dirThumbs, requestedPath)
	if _, err := os.Stat(thumbPath); err != nil {
		log.Println("THUMB:", thumbPath, "does not exist")
		srcPath := requestedPath
		if _, err := os.Stat(srcPath); err != nil {
			log.Println("ORIGINAL", srcPath, "does not exist")
			http.NotFound(w, r)
			return
		}

		log.Println("Must generate thumb for", srcPath)
		err := genthumb(srcPath, thumbPath)
		if err != nil {
			http.Error(w, err.Error(), 400)
			return
		}
		log.Println("Created thumb", thumbPath)
	}
	w.Header().Set("Content-Type", "image/jpeg")
	http.ServeFile(w, r, thumbPath)
}

func findmedia(m *[]media) func(filename string, f os.FileInfo, err error) error {
	return func(filename string, f os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		base := filepath.Base(filename)
		if strings.HasPrefix(base, ".") || strings.HasPrefix(base, "_") {
			// Skip hidden files
			return nil
		}
		// log.Printf("Visited: %s\n", filename)
		if !f.IsDir() && in(acceptedImageExt, strings.ToLower(path.Ext(filename))) {
			// log.Printf("Adding: %s\n%+v\n", filename, f)
			*m = append(*m, media{filename, f})
		}
		return nil
	}
}

func index(w http.ResponseWriter, r *http.Request) {

	srcPath := filepath.Join(dirPath, r.URL.Path)

	var m []media
	err := filepath.Walk(srcPath, findmedia(&m))
	if err != nil {
		log.Println(err)
	}

	t := template.New("medialist")

	template.Must(t.Funcs(template.FuncMap{"matchType": matchType, "size": byten.Size}).Parse(`<!DOCTYPE html>

<meta charset="utf-8" />

{{ range .Media }}

{{if . | matchType ".jpg"}}
{{else if . | matchType ".png"}}
{{else if . | matchType ".mp4"}}<video title="{{ .Fileinfo.Size | size }}" poster="t{{.Filename}}" preload=none controls src=o{{.Filename}}>Video: {{.Filename}}</video>
{{else}}{{.}}
{{end}}

{{ end }}

By lk {{ .Version }}

`))

	err = t.Execute(w, struct {
		Media   []media
		Version string
	}{
		Media:   m,
		Version: version,
	})

	if err != nil {
		panic(err)
	}

	log.Printf("%s %s %s %s\n", r.RemoteAddr, r.Method, r.URL, r.UserAgent())

}

func matchType(ext string, m media) bool {
	return strings.ToLower(ext) == strings.ToLower(path.Ext(m.Filename))
}

func genJPGthumb(src string, dst string) (err error) {

	// First if vipsthumbnail is around, use that, because it's crazy fast
	path, err := exec.LookPath("vipsthumbnail")
	if err == nil {
		out, err := exec.Command(path, "-t", "-s", "460x460", "-o", dst, src).CombinedOutput()
		if err != nil {
			fmt.Printf("The output is %s\n", out)
			return err
		}
		return err
	}

	file, err := os.Open(src)
	if err != nil {
		return err
	}
	defer file.Close()

	img, err := jpeg.Decode(file)
	if err != nil {
		return err
	}

	m := resize.Thumbnail(460, 460, img, resize.NearestNeighbor)

	out, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer out.Close()

	// write new image to file
	jpeg.Encode(out, m, nil)

	return
}

func genthumb(src string, dst string) (err error) {

	dir, _ := filepath.Split(dst)
	err = os.MkdirAll(dir, 0700)
	if err != nil {
		return err
	}

	switch mediatype := strings.ToLower(path.Ext(src)); mediatype {
	case ".jpg":
		return genJPGthumb(src, dst)
	default:
		path, err := exec.LookPath("ffmpeg")
		if err == nil {
			out, err := exec.Command(path, "-y", "-ss", "0.5", "-i", src, "-vframes", "1", "-f", "image2", dst).CombinedOutput()
			if err != nil {
				log.Printf("The output is %s\n", out)
				return err
			}
			return err
		}
		return fmt.Errorf("unknown mediatype: %s", mediatype)
	}

	return

}
<commit_msg>Show largest media first<commit_after>package main

import (
	"flag"
	"fmt"
	"html/template"
	"image/jpeg"
	"log"
	"net"
	"net/http"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"sort"
	"strconv"
	"strings"

	"github.com/nfnt/resize"
	"github.com/pyk/byten"
	"github.com/skratchdot/open-golang/open"
)

type media struct {
	Filename string
	Fileinfo os.FileInfo
}

func in(slice []string, str string) bool {
	for _, s := range slice {
		if s == str {
			return true
		}
	}
	return false
}

var acceptedImageExt = []string{".jpg", ".jpeg", ".mp4", ".png"}
var dirThumbs = fmt.Sprintf("%s%s", os.Getenv("HOME"), "/.cache/lk")
var dirPath = "."
var version = "master"
var showVersionFlag = flag.Bool("version", false, "Show version")
var port = flag.Int("port", 0, "listen port")
var openbrowser = flag.Bool("openbrowser", false, "Open in browser")

func hostname() string {
	hostname, _ := os.Hostname()
	// If hostname does not have dots (i.e. not fully qualified), then return zeroconf address for LAN browsing
	if strings.Split(hostname, ".")[0] == hostname {
		return hostname + ".local"
	}
	return hostname
}

func main() {

	flag.Parse()

	if *showVersionFlag {
		fmt.Println("https://github.com/kaihendry/lk", version)
		os.Exit(0)
	}

	directory := flag.Arg(0)
	dirPath, _ = filepath.Abs(directory)

	// Getting rid of /../ etc
	dirPath = path.Clean(dirPath)

	// Don't allow path under dirPath to be viewed
	http.Handle("/o/", http.StripPrefix(path.Join("/o", dirPath), http.FileServer(http.Dir(dirPath))))
	http.HandleFunc("/favicon.ico", http.NotFound)

	http.HandleFunc("/", index)
	http.HandleFunc("/t/", thumb)

	// http://stackoverflow.com/a/33985208/4534
	eport := os.Getenv("PORT")
	if eport != "" {
		*port, _ = strconv.Atoi(eport)
	}
	ln, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))
	if err != nil {
		log.Panic(err)
	}

	if a, ok := ln.Addr().(*net.TCPAddr); ok {
		host := fmt.Sprintf("http://%s:%d", hostname(), a.Port)
		fmt.Println("Serving from", host)
		if *openbrowser {
			open.Start(host)
		}
	}
	if err := http.Serve(ln, nil); err != nil {
		log.Panic(err)
	}

}

func thumb(w http.ResponseWriter, r *http.Request) {

	// Path cleaning
	requestedPath := path.Clean(r.URL.Path[2:])

	// Make sure you can't go under the dirPath
	if !strings.HasPrefix(requestedPath, dirPath) {
		http.NotFound(w, r)
		return
	}

	thumbPath := filepath.Join(dirThumbs, requestedPath)
	if _, err := os.Stat(thumbPath); err != nil {
		log.Println("THUMB:", thumbPath, "does not exist")
		srcPath := requestedPath
		if _, err := os.Stat(srcPath); err != nil {
			log.Println("ORIGINAL", srcPath, "does not exist")
			http.NotFound(w, r)
			return
		}

		log.Println("Must generate thumb for", srcPath)
		err := genthumb(srcPath, thumbPath)
		if err != nil {
			http.Error(w, err.Error(), 400)
			return
		}
		log.Println("Created thumb", thumbPath)
	}
	w.Header().Set("Content-Type", "image/jpeg")
	http.ServeFile(w, r, thumbPath)
}

func findmedia(m *[]media) func(filename string, f os.FileInfo, err error) error {
	return func(filename string, f os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		base := filepath.Base(filename)
		if strings.HasPrefix(base, ".") || strings.HasPrefix(base, "_") {
			// Skip hidden files
			return nil
		}
		// log.Printf("Visited: %s\n", filename)
		if !f.IsDir() && in(acceptedImageExt, strings.ToLower(path.Ext(filename))) {
			// log.Printf("Adding: %s\n%+v\n", filename, f)
			*m = append(*m, media{filename, f})
		}
		return nil
	}
}

func index(w http.ResponseWriter, r *http.Request) {

	srcPath := filepath.Join(dirPath, r.URL.Path)

	var m []media
	err := filepath.Walk(srcPath, findmedia(&m))
	if err != nil {
		log.Println(err)
	}

	// Largest file first
	sort.Slice(m, func(i, j int) bool {
		return m[i].Fileinfo.Size() > m[j].Fileinfo.Size()
	})

	t := template.New("medialist")

	template.Must(t.Funcs(template.FuncMap{"matchType": matchType, "size": byten.Size}).Parse(`<!DOCTYPE html>

<meta charset="utf-8" />

{{ range .Media }}

{{if . | matchType ".jpg"}}
{{else if . | matchType ".png"}}
{{else if . | matchType ".mp4"}}<video title="{{ .Fileinfo.Size | size }}" poster="t{{.Filename}}" preload=none controls src=o{{.Filename}}>Video: {{.Filename}}</video>
{{else}}{{.}}
{{end}}

{{ end }}

By lk {{ .Version }}

`))

	err = t.Execute(w, struct {
		Media   []media
		Version string
	}{
		Media:   m,
		Version: version,
	})

	if err != nil {
		panic(err)
	}

	log.Printf("%s %s %s %s\n", r.RemoteAddr, r.Method, r.URL, r.UserAgent())

}

func matchType(ext string, m media) bool {
	return strings.ToLower(ext) == strings.ToLower(path.Ext(m.Filename))
}

func genJPGthumb(src string, dst string) (err error) {

	// First if vipsthumbnail is around, use that, because it's crazy fast
	path, err := exec.LookPath("vipsthumbnail")
	if err == nil {
		out, err := exec.Command(path, "-t", "-s", "460x460", "-o", dst, src).CombinedOutput()
		if err != nil {
			fmt.Printf("Command output is %s\n", out)
			return err
		}
		return err
	}

	file, err := os.Open(src)
	if err != nil {
		return err
	}
	defer file.Close()

	img, err := jpeg.Decode(file)
	if err != nil {
		return err
	}

	m := resize.Thumbnail(460, 460, img, resize.NearestNeighbor)

	out, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer out.Close()

	// write new image to file
	jpeg.Encode(out, m, nil)

	return
}

func genthumb(src string, dst string) (err error) {

	dir, _ := filepath.Split(dst)
	err = os.MkdirAll(dir, 0700)
	if err != nil {
		return err
	}

	switch mediatype := strings.ToLower(path.Ext(src)); mediatype {
	case ".jpg":
		return genJPGthumb(src, dst)
	default:
		path, err := exec.LookPath("ffmpeg")
		if err == nil {
			out, err := exec.Command(path, "-y", "-ss", "0.5", "-i", src, "-vframes", "1", "-f", "image2", dst).CombinedOutput()
			if err != nil {
				log.Printf("Command output is %s\n", out)
				return err
			}
			return err
		}
		return fmt.Errorf("unknown mediatype: %s", mediatype)
	}

	return

}
<|endoftext|>


<commit_before>package main

import (
	"encoding/gob"
	"errors"
	"flag"
	"fmt"
	"io"
	"net"
	"os"
	"os/exec"
	"os/signal"
	"runtime"
	"syscall"
	"unsafe"
)

var (
	modshell32         = syscall.NewLazyDLL("shell32.dll")
	procShellExecuteEx = modshell32.NewProc("ShellExecuteExW")
)

const (
	SEE_MASK_NOCLOSEPROCESS = 0x00000040
)

const (
	ERROR_BAD_FORMAT = 11
)

const (
	SE_ERR_FNF             = 2
	SE_ERR_PNF             = 3
	SE_ERR_ACCESSDENIED    = 5
	SE_ERR_OOM             = 8
	SE_ERR_DLLNOTFOUND     = 32
	SE_ERR_SHARE           = 26
	SE_ERR_ASSOCINCOMPLETE = 27
	SE_ERR_DDETIMEOUT      = 28
	SE_ERR_DDEFAIL         = 29
	SE_ERR_DDEBUSY         = 30
	SE_ERR_NOASSOC         = 31
)

type (
	DWORD     uint32
	HANDLE    uintptr
	HINSTANCE HANDLE
	HKEY      HANDLE
	HWND      HANDLE
	ULONG     uint32
	LPCTSTR   uintptr
	LPVOID    uintptr
)

type SHELLEXECUTEINFO struct {
	cbSize         DWORD
	fMask          ULONG
	hwnd           HWND
	lpVerb         LPCTSTR
	lpFile         LPCTSTR
	lpParameters   LPCTSTR
	lpDirectory    LPCTSTR
	nShow          int
	hInstApp       HINSTANCE
	lpIDList       LPVOID
	lpClass        LPCTSTR
	hkeyClass      HKEY
	dwHotKey       DWORD
	hIconOrMonitor HANDLE
	hProcess       HANDLE
}

func ShellExecuteAndWait(hwnd HWND, lpOperation, lpFile, lpParameters, lpDirectory string, nShowCmd int) error {
	var lpctstrVerb, lpctstrParameters, lpctstrDirectory LPCTSTR
	if len(lpOperation) != 0 {
		lpctstrVerb = LPCTSTR(unsafe.Pointer(syscall.StringToUTF16Ptr(lpOperation)))
	}
	if len(lpParameters) != 0 {
		lpctstrParameters = LPCTSTR(unsafe.Pointer(syscall.StringToUTF16Ptr(lpParameters)))
	}
	if len(lpDirectory) != 0 {
		lpctstrDirectory = LPCTSTR(unsafe.Pointer(syscall.StringToUTF16Ptr(lpDirectory)))
	}
	i := &SHELLEXECUTEINFO{
		fMask:        SEE_MASK_NOCLOSEPROCESS,
		hwnd:         hwnd,
		lpVerb:       lpctstrVerb,
		lpFile:       LPCTSTR(unsafe.Pointer(syscall.StringToUTF16Ptr(lpFile))),
		lpParameters: lpctstrParameters,
		lpDirectory:  lpctstrDirectory,
		nShow:        nShowCmd,
	}
	i.cbSize = DWORD(unsafe.Sizeof(*i))
	return ShellExecuteEx(i)
}

func ShellExecuteEx(pExecInfo *SHELLEXECUTEINFO) error {
	ret, _, _ := procShellExecuteEx.Call(uintptr(unsafe.Pointer(pExecInfo)))
	if ret == 1 && pExecInfo.fMask&SEE_MASK_NOCLOSEPROCESS != 0 {
		s, e := syscall.WaitForSingleObject(syscall.Handle(pExecInfo.hProcess), syscall.INFINITE)
		switch s {
		case syscall.WAIT_OBJECT_0:
			break
		case syscall.WAIT_FAILED:
			return os.NewSyscallError("WaitForSingleObject", e)
		default:
			return errors.New("Unexpected result from WaitForSingleObject")
		}
	}
	errorMsg := ""
	if pExecInfo.hInstApp != 0 && pExecInfo.hInstApp <= 32 {
		switch int(pExecInfo.hInstApp) {
		case SE_ERR_FNF:
			errorMsg = "The specified file was not found"
		case SE_ERR_PNF:
			errorMsg = "The specified path was not found"
		case ERROR_BAD_FORMAT:
			errorMsg = "The .exe file is invalid (non-Win32 .exe or error in .exe image)"
		case SE_ERR_ACCESSDENIED:
			errorMsg = "The operating system denied access to the specified file"
		case SE_ERR_ASSOCINCOMPLETE:
			errorMsg = "The file name association is incomplete or invalid"
		case SE_ERR_DDEBUSY:
			errorMsg = "The DDE transaction could not be completed because other DDE transactions were being processed"
		case SE_ERR_DDEFAIL:
			errorMsg = "The DDE transaction failed"
		case SE_ERR_DDETIMEOUT:
			errorMsg = "The DDE transaction could not be completed because the request timed out"
		case SE_ERR_DLLNOTFOUND:
			errorMsg = "The specified DLL was not found"
		case SE_ERR_NOASSOC:
			errorMsg = "There is no application associated with the given file name extension"
		case SE_ERR_OOM:
			errorMsg = "There was not enough memory to complete the operation"
		case SE_ERR_SHARE:
			errorMsg = "A sharing violation occurred"
		default:
			errorMsg = fmt.Sprintf("Unknown error occurred with error code %v", pExecInfo.hInstApp)
		}
	} else {
		return nil
	}
	return errors.New(errorMsg)
}

type Message struct {
	Type string
	Exit int
	Data []byte
}

func msgWrite(enc *gob.Encoder, typ string) io.WriteCloser {
	r, w := io.Pipe()
	go func() {
		defer r.Close()
		var b [256]byte
		for {
			n, err := r.Read(b[:])
			if err != nil {
				break
			}
			enc.Encode(&Message{Type: typ, Exit: 0, Data: b[:n]})
		}
	}()
	return w
}

func client(addr string) int {
	conn, err := net.Dial("tcp", addr)
	if err != nil {
		fmt.Fprintf(os.Stderr, "cannot find executable: %v\n", os.Args[0])
		return 1
	}
	defer conn.Close()

	enc := gob.NewEncoder(conn)
	dec := gob.NewDecoder(conn)

	outw := msgWrite(enc, "stdout")
	defer outw.Close()
	errw := msgWrite(enc, "stderr")
	defer errw.Close()

	cmd := exec.Command(flag.Arg(0), flag.Args()[1:]...)
	inw, err := cmd.StdinPipe()
	if err != nil {
		fmt.Fprintf(os.Stderr, "cannot find executable: %v\n", os.Args[0])
		return 1
	}
	defer inw.Close()
	cmd.Stdout = outw
	cmd.Stderr = errw

	go func() {
		defer inw.Close()
	in_loop:
		for {
			var msg Message
			err = dec.Decode(&msg)
			if err != nil {
				return
			}
			switch msg.Type {
			case "close":
				break in_loop
			case "ctrlc":
				if runtime.GOOS == "windows" {
					cmd.Process.Kill()
				} else {
					cmd.Process.Signal(os.Interrupt)
				}
			case "stdin":
				inw.Write(msg.Data)
			}
		}
	}()

	err = cmd.Run()

	code := 1
	if err != nil {
		if status, ok := cmd.ProcessState.Sys().(syscall.WaitStatus); ok {
			code = status.ExitStatus()
		}
	} else {
		code = 0
	}
	enc.Encode(&Message{Type: "exit", Exit: code})
	return 0
}

func makeCmdLine(args []string) string {
	var s string
	for _, v := range args {
		if s != "" {
			s += " "
		}
		s += syscall.EscapeArg(v)
	}
	return s
}

func server() int {
	lis, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		fmt.Fprintf(os.Stderr, "cannot find executable: %v\n", os.Args[0])
		return 1
	}
	defer lis.Close()

	exe, err := os.Executable()
	if err != nil {
		fmt.Fprintf(os.Stderr, "cannot find executable: %v\n", os.Args[0])
		return 1
	}
	args := []string{"-mode", lis.Addr().String()}
	args = append(args, flag.Args()...)

	var conn net.Conn
	go func() {
		err = ShellExecuteAndWait(0, "runas", exe, makeCmdLine(args), "", syscall.SW_HIDE)
		if err != nil {
			lis.Close()
		}
	}()

	conn, err = lis.Accept()
	if err != nil {
		fmt.Fprintf(os.Stderr, "cannot execute command: %v\n", makeCmdLine(flag.Args()))
		return 1
	}
	defer conn.Close()

	enc := gob.NewEncoder(conn)

	sc := make(chan os.Signal, 1)
	signal.Notify(sc, os.Interrupt)
	go func() {
		for range sc {
			enc.Encode(&Message{Type: "ctrlc"})
		}
	}()
	defer close(sc)

	go func() {
		return
		var b [256]byte
		for {
			n, err := os.Stdin.Read(b[:])
			if err != nil {
				enc.Encode(&Message{Type: "close"})
				break
			}
			enc.Encode(&Message{Type: "stdin", Data: b[:n]})
		}
	}()

	dec := gob.NewDecoder(conn)
	for {
		var msg Message
		err = dec.Decode(&msg)
		if err != nil {
			fmt.Fprintf(os.Stderr, "cannot execute command: %v\n", makeCmdLine(flag.Args()))
			return 1
		}
		switch msg.Type {
		case "stdout":
			os.Stdout.Write(msg.Data)
		case "stderr":
			os.Stderr.Write(msg.Data)
		case "exit":
			return msg.Exit
		}
	}
	return 0
}

func main() {
	var mode string
	flag.StringVar(&mode, "mode", "", "mode")
	flag.Parse()
	if mode != "" {
		os.Exit(client(mode))
	}
	os.Exit(server())
}
<commit_msg>cosmetic change<commit_after>package main

import (
	"encoding/gob"
	"errors"
	"flag"
	"fmt"
	"io"
	"net"
	"os"
	"os/exec"
	"os/signal"
	"runtime"
	"syscall"
	"unsafe"
)

var (
	modshell32         = syscall.NewLazyDLL("shell32.dll")
	procShellExecuteEx = modshell32.NewProc("ShellExecuteExW")
)

const (
	SEE_MASK_NOCLOSEPROCESS = 0x00000040
)

const (
	ERROR_BAD_FORMAT = 11
)

const (
	SE_ERR_FNF             = 2
	SE_ERR_PNF             = 3
	SE_ERR_ACCESSDENIED    = 5
	SE_ERR_OOM             = 8
	SE_ERR_DLLNOTFOUND     = 32
	SE_ERR_SHARE           = 26
	SE_ERR_ASSOCINCOMPLETE = 27
	SE_ERR_DDETIMEOUT      = 28
	SE_ERR_DDEFAIL         = 29
	SE_ERR_DDEBUSY         = 30
	SE_ERR_NOASSOC         = 31
)

type (
	DWORD     uint32
	HANDLE    uintptr
	HINSTANCE HANDLE
	HKEY      HANDLE
	HWND      HANDLE
	ULONG     uint32
	LPCTSTR   uintptr
	LPVOID    uintptr
)

type SHELLEXECUTEINFO struct {
	cbSize         DWORD
	fMask          ULONG
	hwnd           HWND
	lpVerb         LPCTSTR
	lpFile         LPCTSTR
	lpParameters   LPCTSTR
	lpDirectory    LPCTSTR
	nShow          int
	hInstApp       HINSTANCE
	lpIDList       LPVOID
	lpClass        LPCTSTR
	hkeyClass      HKEY
	dwHotKey       DWORD
	hIconOrMonitor HANDLE
	hProcess       HANDLE
}

func ShellExecuteAndWait(hwnd HWND, lpOperation, lpFile, lpParameters, lpDirectory string, nShowCmd int) error {
	var lpctstrVerb, lpctstrParameters, lpctstrDirectory LPCTSTR
	if len(lpOperation) != 0 {
		lpctstrVerb = LPCTSTR(unsafe.Pointer(syscall.StringToUTF16Ptr(lpOperation)))
	}
	if len(lpParameters) != 0 {
		lpctstrParameters = LPCTSTR(unsafe.Pointer(syscall.StringToUTF16Ptr(lpParameters)))
	}
	if len(lpDirectory) != 0 {
		lpctstrDirectory = LPCTSTR(unsafe.Pointer(syscall.StringToUTF16Ptr(lpDirectory)))
	}
	i := &SHELLEXECUTEINFO{
		fMask:        SEE_MASK_NOCLOSEPROCESS,
		hwnd:         hwnd,
		lpVerb:       lpctstrVerb,
		lpFile:       LPCTSTR(unsafe.Pointer(syscall.StringToUTF16Ptr(lpFile))),
		lpParameters: lpctstrParameters,
		lpDirectory:  lpctstrDirectory,
		nShow:        nShowCmd,
	}
	i.cbSize = DWORD(unsafe.Sizeof(*i))
	return ShellExecuteEx(i)
}

func ShellExecuteEx(pExecInfo *SHELLEXECUTEINFO) error {
	ret, _, _ := procShellExecuteEx.Call(uintptr(unsafe.Pointer(pExecInfo)))
	if ret == 1 && pExecInfo.fMask&SEE_MASK_NOCLOSEPROCESS != 0 {
		s, e := syscall.WaitForSingleObject(syscall.Handle(pExecInfo.hProcess), syscall.INFINITE)
		switch s {
		case syscall.WAIT_OBJECT_0:
			break
		case syscall.WAIT_FAILED:
			return os.NewSyscallError("WaitForSingleObject", e)
		default:
			return errors.New("Unexpected result from WaitForSingleObject")
		}
	}
	errorMsg := ""
	if pExecInfo.hInstApp != 0 && pExecInfo.hInstApp <= 32 {
		switch int(pExecInfo.hInstApp) {
		case SE_ERR_FNF:
			errorMsg = "The specified file was not found"
		case SE_ERR_PNF:
			errorMsg = "The specified path was not found"
		case ERROR_BAD_FORMAT:
			errorMsg = "The .exe file is invalid (non-Win32 .exe or error in .exe image)"
		case SE_ERR_ACCESSDENIED:
			errorMsg = "The operating system denied access to the specified file"
		case SE_ERR_ASSOCINCOMPLETE:
			errorMsg = "The file name association is incomplete or invalid"
		case SE_ERR_DDEBUSY:
			errorMsg = "The DDE transaction could not be completed because other DDE transactions were being processed"
		case SE_ERR_DDEFAIL:
			errorMsg = "The DDE transaction failed"
		case SE_ERR_DDETIMEOUT:
			errorMsg = "The DDE transaction could not be completed because the request timed out"
		case SE_ERR_DLLNOTFOUND:
			errorMsg = "The specified DLL was not found"
		case SE_ERR_NOASSOC:
			errorMsg = "There is no application associated with the given file name extension"
		case SE_ERR_OOM:
			errorMsg = "There was not enough memory to complete the operation"
		case SE_ERR_SHARE:
			errorMsg = "A sharing violation occurred"
		default:
			errorMsg = fmt.Sprintf("Unknown error occurred with error code %v", pExecInfo.hInstApp)
		}
	} else {
		return nil
	}
	return errors.New(errorMsg)
}

type msg struct {
	name string
	exit int
	data []byte
}

func msgWrite(enc *gob.Encoder, typ string) io.WriteCloser {
	r, w := io.Pipe()
	go func() {
		defer r.Close()
		var b [256]byte
		for {
			n, err := r.Read(b[:])
			if err != nil {
				break
			}
			enc.Encode(&msg{name: typ, data: b[:n]})
		}
	}()
	return w
}

func client(addr string) int {
	conn, err := net.Dial("tcp", addr)
	if err != nil {
		fmt.Fprintf(os.Stderr, "cannot find executable: %v\n", os.Args[0])
		return 1
	}
	defer conn.Close()

	enc := gob.NewEncoder(conn)
	dec := gob.NewDecoder(conn)

	outw := msgWrite(enc, "stdout")
	defer outw.Close()
	errw := msgWrite(enc, "stderr")
	defer errw.Close()

	cmd := exec.Command(flag.Arg(0), flag.Args()[1:]...)
	inw, err := cmd.StdinPipe()
	if err != nil {
		fmt.Fprintf(os.Stderr, "cannot find executable: %v\n", os.Args[0])
		return 1
	}
	defer inw.Close()
	cmd.Stdout = outw
	cmd.Stderr = errw

	go func() {
		defer inw.Close()
	in_loop:
		for {
			var m msg
			err = dec.Decode(&m)
			if err != nil {
				return
			}
			switch m.name {
			case "close":
				break in_loop
			case "ctrlc":
				if runtime.GOOS == "windows" {
					cmd.Process.Kill()
				} else {
					cmd.Process.Signal(os.Interrupt)
				}
			case "stdin":
				inw.Write(m.data)
			}
		}
	}()

	err = cmd.Run()

	code := 1
	if err != nil {
		if status, ok := cmd.ProcessState.Sys().(syscall.WaitStatus); ok {
			code = status.ExitStatus()
		}
	} else {
		code = 0
	}
	enc.Encode(&msg{name: "exit", exit: code})
	return 0
}

func makeCmdLine(args []string) string {
	var s string
	for _, v := range args {
		if s != "" {
			s += " "
		}
		s += syscall.EscapeArg(v)
	}
	return s
}

func server() int {
	lis, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		fmt.Fprintf(os.Stderr, "cannot find executable: %v\n", os.Args[0])
		return 1
	}
	defer lis.Close()

	exe, err := os.Executable()
	if err != nil {
		fmt.Fprintf(os.Stderr, "cannot find executable: %v\n", os.Args[0])
		return 1
	}
	args := []string{"-mode", lis.Addr().String()}
	args = append(args, flag.Args()...)

	var conn net.Conn
	go func() {
		err = ShellExecuteAndWait(0, "runas", exe, makeCmdLine(args), "", syscall.SW_HIDE)
		if err != nil {
			lis.Close()
		}
	}()

	conn, err = lis.Accept()
	if err != nil {
		fmt.Fprintf(os.Stderr, "cannot execute command: %v\n", makeCmdLine(flag.Args()))
		return 1
	}
	defer conn.Close()

	enc := gob.NewEncoder(conn)

	sc := make(chan os.Signal, 1)
	signal.Notify(sc, os.Interrupt)
	go func() {
		for range sc {
			enc.Encode(&msg{name: "ctrlc"})
		}
	}()
	defer close(sc)

	go func() {
		return
		var b [256]byte
		for {
			n, err := os.Stdin.Read(b[:])
			if err != nil {
				enc.Encode(&msg{name: "close"})
				break
			}
			enc.Encode(&msg{name: "stdin", data: b[:n]})
		}
	}()

	dec := gob.NewDecoder(conn)
	for {
		var m msg
		err = dec.Decode(&m)
		if err != nil {
			fmt.Fprintf(os.Stderr, "cannot execute command: %v\n", makeCmdLine(flag.Args()))
			return 1
		}
		switch m.name {
		case "stdout":
			os.Stdout.Write(m.data)
		case "stderr":
			os.Stderr.Write(m.data)
		case "exit":
			return m.exit
		}
	}
	return 0
}

func main() {
	var mode string
	flag.StringVar(&mode, "mode", "", "mode")
	flag.Parse()
	if mode != "" {
		os.Exit(client(mode))
	}
	os.Exit(server())
}
<|endoftext|>