From fd50e8e12b93661b637cb277579e7a0f3362a3e0 Mon Sep 17 00:00:00 2001
From: Darien Raymond <admin@v2ray.com>
Date: Mon, 3 Oct 2016 11:18:24 +0200
Subject: [PATCH] allow stdin as input source

---
 shell/point/config.go           |  8 +++++---
 shell/point/config_json.go      | 15 ++++-----------
 shell/point/config_json_test.go | 11 +++++++++--
 shell/point/main/main.go        | 17 ++++++++++++++++-
 4 files changed, 34 insertions(+), 17 deletions(-)

diff --git a/shell/point/config.go b/shell/point/config.go
index 7c047d5b..d4b72e87 100644
--- a/shell/point/config.go
+++ b/shell/point/config.go
@@ -1,6 +1,8 @@
 package point
 
 import (
+	"io"
+
 	"v2ray.com/core/app/dns"
 	"v2ray.com/core/app/router"
 	"v2ray.com/core/common"
@@ -75,15 +77,15 @@ type Config struct {
 	TransportConfig *transport.Config
 }
 
-type ConfigLoader func(init string) (*Config, error)
+type ConfigLoader func(input io.Reader) (*Config, error)
 
 var (
 	configLoader ConfigLoader
 )
 
-func LoadConfig(init string) (*Config, error) {
+func LoadConfig(input io.Reader) (*Config, error) {
 	if configLoader == nil {
 		return nil, common.ErrBadConfiguration
 	}
-	return configLoader(init)
+	return configLoader(input)
 }
diff --git a/shell/point/config_json.go b/shell/point/config_json.go
index 739db174..afc66b84 100644
--- a/shell/point/config_json.go
+++ b/shell/point/config_json.go
@@ -5,8 +5,7 @@ package point
 import (
 	"encoding/json"
 	"errors"
-	"io/ioutil"
-	"os"
+	"io"
 	"strings"
 
 	"v2ray.com/core/app/dns"
@@ -260,16 +259,10 @@ func (this *OutboundDetourConfig) UnmarshalJSON(data []byte) error {
 	return nil
 }
 
-func JsonLoadConfig(file string) (*Config, error) {
-	fixedFile := os.ExpandEnv(file)
-	rawConfig, err := ioutil.ReadFile(fixedFile)
-	if err != nil {
-		log.Error("Point: Failed to read server config file (", file, "): ", file, err)
-		return nil, err
-	}
-
+func JsonLoadConfig(input io.Reader) (*Config, error) {
 	jsonConfig := &Config{}
-	err = json.Unmarshal(rawConfig, jsonConfig)
+	decoder := json.NewDecoder(input)
+	err := decoder.Decode(jsonConfig)
 	if err != nil {
 		log.Error("Point: Failed to load server config: ", err)
 		return nil, err
diff --git a/shell/point/config_json_test.go b/shell/point/config_json_test.go
index 199c8469..6b073fc9 100644
--- a/shell/point/config_json_test.go
+++ b/shell/point/config_json_test.go
@@ -4,6 +4,7 @@ package point_test
 
 import (
 	"encoding/json"
+	"io"
 	"os"
 	"path/filepath"
 	"testing"
@@ -14,13 +15,19 @@ import (
 	"v2ray.com/core/testing/assert"
 )
 
+func OpenFile(file string, assert *assert.Assert) io.Reader {
+	input, err := os.Open(file)
+	assert.Error(err).IsNil()
+	return input
+}
+
 func TestClientSampleConfig(t *testing.T) {
 	assert := assert.On(t)
 
 	GOPATH := os.Getenv("GOPATH")
 	baseDir := filepath.Join(GOPATH, "src", "v2ray.com", "core", "tools", "release", "config")
 
-	pointConfig, err := LoadConfig(filepath.Join(baseDir, "vpoint_socks_vmess.json"))
+	pointConfig, err := LoadConfig(OpenFile(filepath.Join(baseDir, "vpoint_socks_vmess.json"), assert))
 	assert.Error(err).IsNil()
 
 	assert.Pointer(pointConfig.InboundConfig).IsNotNil()
@@ -40,7 +47,7 @@ func TestServerSampleConfig(t *testing.T) {
 	GOPATH := os.Getenv("GOPATH")
 	baseDir := filepath.Join(GOPATH, "src", "v2ray.com", "core", "tools", "release", "config")
 
-	pointConfig, err := LoadConfig(filepath.Join(baseDir, "vpoint_vmess_freedom.json"))
+	pointConfig, err := LoadConfig(OpenFile(filepath.Join(baseDir, "vpoint_vmess_freedom.json"), assert))
 	assert.Error(err).IsNil()
 
 	assert.Pointer(pointConfig.InboundConfig).IsNotNil()
diff --git a/shell/point/main/main.go b/shell/point/main/main.go
index d1217f36..c3fe6f7b 100644
--- a/shell/point/main/main.go
+++ b/shell/point/main/main.go
@@ -3,6 +3,7 @@ package main
 import (
 	"flag"
 	"fmt"
+	"io"
 	"os"
 	"os/signal"
 	"path/filepath"
@@ -38,6 +39,7 @@ var (
 	logLevel   = flag.String("loglevel", "warning", "Level of log info to be printed to console, available value: debug, info, warning, error")
 	version    = flag.Bool("version", false, "Show current version of V2Ray.")
 	test       = flag.Bool("test", false, "Test config file only, without launching V2Ray server.")
+	format     = flag.String("format", "json", "Format of input file.")
 )
 
 func init() {
@@ -68,7 +70,20 @@ func startV2Ray() *point.Point {
 		log.Error("Config file is not set.")
 		return nil
 	}
-	config, err := point.LoadConfig(configFile)
+	var configInput io.Reader
+	if configFile == "stdin:" {
+		configInput = os.Stdin
+	} else {
+		fixedFile := os.ExpandEnv(configFile)
+		file, err := os.Open(fixedFile)
+		if err != nil {
+			log.Error("Config file not readable: ", err)
+			return nil
+		}
+		defer file.Close()
+		configInput = file
+	}
+	config, err := point.LoadConfig(configInput)
 	if err != nil {
 		log.Error("Failed to read config file (", configFile, "): ", configFile, err)
 		return nil