// 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 }