func RunModule(module Module) { var output types.Value = nil defer func() { var result = 0 if r := recover(); r != nil { result = 1 if output == nil { output = types.Map{ types.Keyword("success"): types.Bool(false), types.Keyword("error"): types.String(fmt.Sprint(r)), } } } if output == nil { output = types.Map{ types.Keyword("success"): types.Bool(true), } } fmt.Println(edn.DumpString(output)) os.Exit(result) }() var input types.Value = nil var err error = nil if module.TakesInput() { input, err = edn.ParseReader(bufio.NewReader(os.Stdin)) } if err != nil { panic(err) } output, err = module.Exec(input) if err != nil { panic(err) } }
func (self GatherFacts) Exec(_ types.Value) (types.Value, error) { var result types.Map = make(types.Map) result[types.Keyword("os")] = types.String(runtime.GOOS) result[types.Keyword("arch")] = types.String(runtime.GOARCH) var interfaces, err = net.Interfaces() if err != nil { return nil, err } var netifs = make(types.Vector, len(interfaces)) for i, iface := range interfaces { var facemap = make(types.Map) facemap[types.Keyword("name")] = types.String(iface.Name) facemap[types.Keyword("mac-address")] = types.String(iface.HardwareAddr.String()) facemap[types.Keyword("loopback?")] = types.Bool(iface.Flags&net.FlagLoopback != 0) var addrs, err = iface.Addrs() if err != nil { return nil, err } var v4list = (*types.List)(list.New()) var v6list = (*types.List)(list.New()) for _, addr := range addrs { var addrmap = make(types.Map) switch ip := addr.(type) { case *net.IPAddr: var v4 = ip.IP.To4() addrmap[types.Keyword("address")] = types.String(ip.IP.String()) if v4 != nil { v4list.Insert(addrmap) } else { v6list.Insert(addrmap) } break case *net.IPNet: var v4 = ip.IP.To4() addrmap[types.Keyword("address")] = types.String(ip.IP.String()) size, bits := ip.Mask.Size() addrmap[types.Keyword("prefix-length")] = types.Int(size) addrmap[types.Keyword("bit-length")] = types.Int(bits) if v4 != nil { v4list.Insert(addrmap) } else { v6list.Insert(addrmap) } break } } facemap[types.Keyword("ipv4-addresses")] = v4list facemap[types.Keyword("ipv6-addresses")] = v6list netifs[i] = facemap } result[types.Keyword("network-interfaces")] = netifs return result, nil }
func (this HashFile) Exec(input types.Value) (out types.Value, err error) { var inputMap types.Map if i, ok := input.(types.Map); ok { inputMap = i } else { err = errors.New(fmt.Sprintf("expected a map as input, got a %T", input)) return } var hashName string var hashNameElement = inputMap[types.Keyword("hash")] if hashNameElement == nil { hashName = "sha256" } else if h, ok := hashNameElement.(types.String); ok { hashName = string(h) } else if k, ok := hashNameElement.(types.Keyword); ok { hashName = string(k) } else if s, ok := hashNameElement.(types.Symbol); ok { hashName = string(s) } else { err = errors.New(":hash must be a string, keyword, or symbol if specified") return } hashName = strings.ToLower(hashName) var hash hash.Hash if hashName == "md5" { hash = md5.New() } else if hashName == "sha" || hashName == "sha1" || hashName == "sha-1" { hash = sha1.New() } else if hashName == "sha224" || hashName == "sha-224" { hash = sha256.New224() } else if hashName == "sha256" || hashName == "sha-256" { hash = sha256.New() } else if hashName == "sha384" || hashName == "sha-384" { hash = sha512.New384() } else if hashName == "sha512/224" || hashName == "sha-512/224" { hash = sha512.New512_224() } else if hashName == "sha512/256" || hashName == "sha-512/256" { hash = sha512.New512_256() } else if hashName == "sha512" || hashName == "sha-512" { hash = sha512.New() } else { err = errors.New(fmt.Sprint("unknown hash name: ", hashName)) return } var fileName string var fileElem = inputMap[types.Keyword("file")] if fileElem == nil { err = errors.New(":file argument is required") return } else if f, ok := fileElem.(types.String); ok { fileName = string(f) } else { err = errors.New(":file argument must be a string") return } file, err := os.Open(fileName) if err != nil { return } hashOut := bufio.NewWriterSize(hash, hash.BlockSize()) wrote, err := io.Copy(hashOut, file) hashOut.Flush() if err != nil { return } out = types.Map{ types.Keyword("success"): types.Bool(true), types.Keyword("size"): types.Int(wrote), types.Keyword("file"): types.String(fileName), types.Keyword("hash"): types.Keyword(hashName), types.Keyword("digest"): types.String(fmt.Sprintf("%x", hash.Sum(nil))), } return }
func (yyrcvr *yyParserImpl) Parse(yylex yyLexer, result *yySymType) int { var yyn int var yylval yySymType var yyVAL yySymType var yyDollar []yySymType _ = yyDollar // silence set and not used yyS := make([]yySymType, yyMaxDepth) Nerrs := 0 /* number of errors */ Errflag := 0 /* error recovery flag */ yystate := 0 yychar := -1 yytoken := -1 // yychar translated into internal numbering yyrcvr.lookahead = func() int { return yychar } defer func() { // Make sure we report no lookahead when not parsing. yystate = -1 yychar = -1 yytoken = -1 }() yyp := -1 goto yystack ret0: return 0 ret1: return 1 yystack: /* put a state and value onto the stack */ if yyDebug >= 4 { __yyfmt__.Printf("char %v in %v\n", yyTokname(yytoken), yyStatname(yystate)) } yyp++ if yyp >= len(yyS) { nyys := make([]yySymType, len(yyS)*2) copy(nyys, yyS) yyS = nyys } yyS[yyp] = yyVAL yyS[yyp].yys = yystate yynewstate: yyn = yyPact[yystate] if yyn <= yyFlag { goto yydefault /* simple state */ } if yychar < 0 { yychar, yytoken = yylex1(yylex, &yylval) } yyn += yytoken if yyn < 0 || yyn >= yyLast { goto yydefault } yyn = yyAct[yyn] if yyChk[yyn] == yytoken { /* valid shift */ yychar = -1 yytoken = -1 yyVAL = yylval yystate = yyn if Errflag > 0 { Errflag-- } goto yystack } yydefault: /* default state action */ yyn = yyDef[yystate] if yyn == -2 { if yychar < 0 { yychar, yytoken = yylex1(yylex, &yylval) } /* look through exception table */ xi := 0 for { if yyExca[xi+0] == -1 && yyExca[xi+1] == yystate { break } xi += 2 } for xi += 2; ; xi += 2 { yyn = yyExca[xi+0] if yyn < 0 || yyn == yytoken { break } } yyn = yyExca[xi+1] if yyn < 0 { goto ret0 } } if yyn == 0 { /* error ... attempt to resume parsing */ switch Errflag { case 0: /* brand new error */ yylex.Error(yyErrorMessage(yystate, yytoken)) Nerrs++ if yyDebug >= 1 { __yyfmt__.Printf("%s", yyStatname(yystate)) __yyfmt__.Printf(" saw %s\n", yyTokname(yytoken)) } fallthrough case 1, 2: /* incompletely recovered error ... try again */ Errflag = 3 /* find a state where "error" is a legal shift action */ for yyp >= 0 { yyn = yyPact[yyS[yyp].yys] + yyErrCode if yyn >= 0 && yyn < yyLast { yystate = yyAct[yyn] /* simulate a shift of "error" */ if yyChk[yystate] == yyErrCode { goto yystack } } /* the current p has no shift on "error", pop stack */ if yyDebug >= 2 { __yyfmt__.Printf("error recovery pops state %d\n", yyS[yyp].yys) } yyp-- } /* there is no state on the stack with an error shift ... abort */ goto ret1 case 3: /* no shift yet; clobber input char */ if yyDebug >= 2 { __yyfmt__.Printf("error recovery discards %s\n", yyTokname(yytoken)) } if yytoken == yyEofCode { goto ret1 } yychar = -1 yytoken = -1 goto yynewstate /* try again in the same state */ } } /* reduction by production yyn */ if yyDebug >= 2 { __yyfmt__.Printf("reduce %v in:\n\t%v\n", yyn, yyStatname(yystate)) } yynt := yyn yypt := yyp _ = yypt // guard against "declared and not used" yyp -= yyR2[yyn] // yyp is now the index of $0. Perform the default action. Iff the // reduced production is ε, $1 is possibly out of range. if yyp+1 >= len(yyS) { nyys := make([]yySymType, len(yyS)*2) copy(nyys, yyS) yyS = nyys } yyVAL = yyS[yyp+1] /* consult goto table to find next state */ yyn = yyR1[yyn] yyg := yyPgo[yyn] yyj := yyg + yyS[yyp].yys + 1 if yyj >= yyLast { yystate = yyAct[yyg] } else { yystate = yyAct[yyj] if yyChk[yystate] != -yyn { yystate = yyAct[yyg] } } // dummy call; replaced with literal code switch yynt { case 1: yyDollar = yyS[yypt-3 : yypt+1] //line parser.y:41 { result.v = yyDollar[2].v } case 2: yyDollar = yyS[yypt-1 : yypt+1] //line parser.y:42 { yylex.Error("empty input") } case 4: yyDollar = yyS[yypt-4 : yypt+1] //line parser.y:47 { yyVAL.v = types.TaggedValue{string(yyDollar[2].v.(types.Symbol)), yyDollar[4].v} } case 24: yyDollar = yyS[yypt-1 : yypt+1] //line parser.y:80 { yyVAL.v = types.Value(new(types.List)) } case 25: yyDollar = yyS[yypt-4 : yypt+1] //line parser.y:81 { yyDollar[1].v.(*types.List).Insert(yyDollar[3].v) } case 26: yyDollar = yyS[yypt-1 : yypt+1] //line parser.y:87 { yyVAL.v = types.Bool(true) } case 27: yyDollar = yyS[yypt-1 : yypt+1] //line parser.y:88 { yyVAL.v = types.Bool(false) } case 28: yyDollar = yyS[yypt-1 : yypt+1] //line parser.y:92 { yyVAL.v = types.Value(nil) } case 37: yyDollar = yyS[yypt-4 : yypt+1] //line parser.y:129 { set := types.Sequence(types.Set{}) values := types.Sequence(yyDollar[3].v.(*types.List)) yyVAL.v = set.Into(values) } case 38: yyDollar = yyS[yypt-3 : yypt+1] //line parser.y:137 { yyVAL.k = yyDollar[1].v yyVAL.v = yyDollar[3].v } case 39: yyDollar = yyS[yypt-1 : yypt+1] //line parser.y:138 { yylex.Error("Map literal must contain an even number of forms") } case 40: yyDollar = yyS[yypt-1 : yypt+1] //line parser.y:142 { yyVAL.v = types.Map{} } case 41: yyDollar = yyS[yypt-3 : yypt+1] //line parser.y:144 { yyDollar[1].v.(types.Map)[yyDollar[2].k] = yyDollar[2].v } case 42: yyDollar = yyS[yypt-3 : yypt+1] //line parser.y:150 { yyVAL = yyDollar[2] } case 43: yyDollar = yyS[yypt-3 : yypt+1] //line parser.y:154 { yyVAL = yyDollar[2] } case 44: yyDollar = yyS[yypt-3 : yypt+1] //line parser.y:159 { vec := types.Sequence(types.Vector{}) values := types.Sequence(yyDollar[2].v.(*types.List)) yyVAL.v = vec.Into(values) } } goto yystack /* stack new state and value */ }
// The command module takes as input a map, and runs that command. // // Parameters in the input map are: // :command, a list or vector, giving the command to run. Required. // :env, a map of names to values; if specified, these are added to the environment when running the command; optional // :input, a string to pass to the command's stdin; optional func (this Command) Exec(input types.Value) (output types.Value, err error) { var command []string var commandMap types.Map if m, ok := input.(types.Map); ok { commandMap = m } else { err = errors.New("input must be a map") return } var commandEntry = commandMap[types.Keyword("command")] if commandEntry == nil { err = errors.New("require at least :command in input") return } else if l, ok := commandEntry.(*types.List); ok { var list = (*list.List)(l) command = make([]string, list.Len()) var i = 0 for e := list.Front(); e != nil; e = e.Next() { if elem, ok := e.Value.(types.String); ok { command[i] = string(elem) i++ } else { err = errors.New(":command must be a list of strings") return } } } else if v, ok := commandEntry.(types.Vector); ok { var vect = ([]types.Value)(v) command = make([]string, len(vect)) for i, e := range vect { if elem, ok := e.(types.String); ok { command[i] = string(elem) } else { err = errors.New(":command must be a vector of strings") return } } } else { err = errors.New("expected a list or vector as :command") return } var cmd = exec.Command(command[0], command[1:]...) var envEntry = commandMap[types.Keyword("env")] if envEntry != nil { if e, ok := envEntry.(types.Map); ok { var env = make([]string, len(e)) var i = 0 for k := range e { v := e[k] if kk, ok := k.(types.String); ok && len(kk) > 0 { if vv, ok := v.(types.String); ok && len(vv) > 0 { env[i] = fmt.Sprint(string(kk), "=", string(vv)) } else { err = errors.New(":env values must be nonempty strings") return } } else { err = errors.New(":env keys must be nonempty strings") return } i++ } cmd.Env = env } else { err = errors.New(":env must be a map if specified") return } } var stdinEntry = commandMap[types.Keyword("input")] if stdinEntry != nil { if stdin, ok := stdinEntry.(types.String); ok { cmd.Stdin = strings.NewReader(string(stdin)) } else { err = errors.New(":input must be a string if specified") return } } var stderr = new(bytes.Buffer) var stdout = new(bytes.Buffer) cmd.Stderr = stderr cmd.Stdout = stdout err = cmd.Run() if err != nil { output = types.Map{ types.Keyword("success"): types.Bool(false), types.Keyword("err"): types.String(stderr.String()), types.Keyword("out"): types.String(stdout.String()), types.Keyword("system-time"): types.Float(cmd.ProcessState.SystemTime().Seconds()), types.Keyword("user-time"): types.Float(cmd.ProcessState.UserTime().Seconds()), } return } output = types.Map{ types.Keyword("success"): types.Bool(true), types.Keyword("err"): types.String(stderr.String()), types.Keyword("out"): types.String(stdout.String()), types.Keyword("system-time"): types.Float(cmd.ProcessState.SystemTime().Seconds()), types.Keyword("user-time"): types.Float(cmd.ProcessState.UserTime().Seconds()), } return }
func (this Shell) Exec(input types.Value) (output types.Value, err error) { var commandMap types.Map if m, ok := input.(types.Map); ok { commandMap = m } else { err = errors.New("input must be a map") return } var command string var commandEntry = commandMap[types.Keyword("command")] if commandEntry == nil { err = errors.New(":command argument is required") return } else if c, ok := commandEntry.(types.String); ok { command = string(c) } else { err = errors.New(":command must be a string") return } var shell = "/bin/sh" shellEntry := commandMap[types.Keyword("shell")] if shellEntry != nil { if s, ok := shellEntry.(types.String); ok { shell = string(s) } else { err = errors.New(":shell must be a string if specified") return } } cmd := exec.Command(shell, "-c", command) var envEntry = commandMap[types.Keyword("env")] if envEntry != nil { if e, ok := envEntry.(types.Map); ok { var env = make([]string, len(e)) var i = 0 for k := range e { v := e[k] if kk, ok := k.(types.String); ok && len(kk) > 0 { if vv, ok := v.(types.String); ok && len(vv) > 0 { env[i] = fmt.Sprint(string(kk), "=", string(vv)) } else { err = errors.New(":env values must be nonempty strings") return } } else { err = errors.New(":env keys must be nonempty strings") return } i++ } cmd.Env = env } else { err = errors.New(":env must be a map if specified") return } } inputEntry := commandMap[types.Keyword("input")] if inputEntry != nil { if i, ok := inputEntry.(types.String); ok { cmd.Stdin = strings.NewReader(string(i)) } else { err = errors.New(":input must be a string if specified") } } var stderr = new(bytes.Buffer) var stdout = new(bytes.Buffer) cmd.Stderr = stderr cmd.Stdout = stdout err = cmd.Run() if err != nil { output = types.Map{ types.Keyword("success"): types.Bool(false), types.Keyword("err"): types.String(stderr.String()), types.Keyword("out"): types.String(stdout.String()), types.Keyword("system-time"): types.Float(cmd.ProcessState.SystemTime().Seconds()), types.Keyword("user-time"): types.Float(cmd.ProcessState.UserTime().Seconds()), } return } output = types.Map{ types.Keyword("success"): types.Bool(true), types.Keyword("err"): types.String(stderr.String()), types.Keyword("out"): types.String(stdout.String()), types.Keyword("system-time"): types.Float(cmd.ProcessState.SystemTime().Seconds()), types.Keyword("user-time"): types.Float(cmd.ProcessState.UserTime().Seconds()), } return }
// Lex runs the lexer. Always returns 0. // When the -s option is given, this function is not generated; // instead, the NN_FUN macro runs the lexer. func (yylex *lexer) Lex(lval *yySymType) int { OUTER0: for { switch yylex.next(0) { case 0: { return tWhitespace } case 1: { return tOpenBracket } case 2: { return tCloseBracket } case 3: { return tOpenBrace } case 4: { return tCloseBrace } case 5: { return tOpenParen } case 6: { return tCloseParen } case 7: { return tOctothorpe } case 8: { return tNil } case 9: { lval.v = types.Bool(true) return tTrue } case 10: { lval.v = types.Bool(false) return tFalse } case 11: { lval.v = types.Character('\n') return tCharacter } case 12: { lval.v = types.Character('\r') return tCharacter } case 13: { lval.v = types.Character('\t') return tCharacter } case 14: { lval.v = types.Character(' ') return tCharacter } case 15: { panic("Unicode characters are currently unimplemented") } case 16: { s := yylex.Text()[1:] ch, _, _ := strings.NewReader(s).ReadRune() lval.v = types.Character(ch) return tCharacter } case 17: { lval.v = types.Keyword(yylex.Text()[1:]) return tKeyword } case 18: { s := yylex.Text() lval.v = types.String(s[1 : len(s)-1]) return tString } case 19: { lval.v = types.Symbol(yylex.Text()) return tSymbol } case 20: { lval.v = types.ParseBigInt(yylex.Text()) return tBigInteger } case 21: { lval.v = types.ParseFloat(yylex.Text()) return tFloat } case 22: { lval.v = types.ParseInt(yylex.Text()) return tInteger } case 23: { lval.v = types.ParseFloat(yylex.Text()) return tFloat } case 24: { lval.v = types.ParseFloat(yylex.Text()) return tFloat } case 25: { lval.v = types.ParseFloat(yylex.Text()) return tFloat } case 26: { lval.v = types.ParseRational(yylex.Text()) return tRational } case 27: { // (This rule must be last) // Unmatched token... return -1 } default: break OUTER0 } continue } yylex.pop() return 0 }