Example #1
0
// exec shell commands with text to STDIN
func execShell(shellCmd, input string, varsNames []string, userID, chatID int, userName, userDisplayName string, cacheTTL *cache.MemoryTTL) (result []byte) {
	cacheKey := shellCmd + "/" + input
	if cacheTTL != nil {
		cacheData, err := cacheTTL.Get(cacheKey)
		if err != cache.ErrNotFound && err != nil {
			log.Print(err)
		} else if err == nil {
			// cache hit
			return cacheData.([]byte)
		}
	}

	shell, params := "sh", []string{"-c", shellCmd}
	if runtime.GOOS == "windows" {
		shell, params = "cmd", []string{"/C", shellCmd}
	}
	osExecCommand := exec.Command(shell, params...)
	osExecCommand.Stderr = os.Stderr

	// copy variables from parent process
	for _, envRaw := range os.Environ() {
		osExecCommand.Env = append(osExecCommand.Env, envRaw)
	}

	if input != "" {
		if len(varsNames) > 0 {
			// set user input to shell vars
			arguments := regexp.MustCompile(`\s+`).Split(input, len(varsNames))
			for i, arg := range arguments {
				osExecCommand.Env = append(osExecCommand.Env, fmt.Sprintf("%s=%s", varsNames[i], arg))
			}
		} else {
			// write user input to STDIN
			stdin, err := osExecCommand.StdinPipe()
			if err == nil {
				io.WriteString(stdin, input)
				stdin.Close()
			} else {
				log.Print("get STDIN error: ", err)
			}
		}
	}

	// set S2T_* env vars
	s2tVariables := [...]struct{ name, value string }{
		{"S2T_LOGIN", userName},
		{"S2T_USERID", strconv.Itoa(userID)},
		{"S2T_USERNAME", userDisplayName},
		{"S2T_CHATID", strconv.Itoa(userID)},
	}
	for _, row := range s2tVariables {
		osExecCommand.Env = append(osExecCommand.Env, fmt.Sprintf("%s=%s", row.name, row.value))
	}

	shellOut, err := osExecCommand.Output()
	if err != nil {
		log.Print("exec error: ", err)
		result = []byte(fmt.Sprintf("exec error: %s", err))
	} else {
		result = shellOut
	}

	if cacheTTL != nil {
		err := cacheTTL.Set(cacheKey, result)
		if err != nil {
			log.Print(err)
		}
	}

	return result
}