1*387f9dfdSAndroid Build Coastguard Worker /*
2*387f9dfdSAndroid Build Coastguard Worker * Copyright 2016 GitHub, Inc
3*387f9dfdSAndroid Build Coastguard Worker *
4*387f9dfdSAndroid Build Coastguard Worker * Based on lua.c, the Lua C Interpreter
5*387f9dfdSAndroid Build Coastguard Worker * Copyright (C) 1994-2012 Lua.org, PUC-Rio. All rights reserved.
6*387f9dfdSAndroid Build Coastguard Worker *
7*387f9dfdSAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining
8*387f9dfdSAndroid Build Coastguard Worker * a copy of this software and associated documentation files (the
9*387f9dfdSAndroid Build Coastguard Worker * "Software"), to deal in the Software without restriction, including
10*387f9dfdSAndroid Build Coastguard Worker * without limitation the rights to use, copy, modify, merge, publish,
11*387f9dfdSAndroid Build Coastguard Worker * distribute, sublicense, and/or sell copies of the Software, and to
12*387f9dfdSAndroid Build Coastguard Worker * permit persons to whom the Software is furnished to do so, subject to
13*387f9dfdSAndroid Build Coastguard Worker * the following conditions:
14*387f9dfdSAndroid Build Coastguard Worker *
15*387f9dfdSAndroid Build Coastguard Worker * The above copyright notice and this permission notice shall be
16*387f9dfdSAndroid Build Coastguard Worker * included in all copies or substantial portions of the Software.
17*387f9dfdSAndroid Build Coastguard Worker *
18*387f9dfdSAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19*387f9dfdSAndroid Build Coastguard Worker * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20*387f9dfdSAndroid Build Coastguard Worker * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21*387f9dfdSAndroid Build Coastguard Worker * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22*387f9dfdSAndroid Build Coastguard Worker * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23*387f9dfdSAndroid Build Coastguard Worker * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24*387f9dfdSAndroid Build Coastguard Worker * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25*387f9dfdSAndroid Build Coastguard Worker */
26*387f9dfdSAndroid Build Coastguard Worker #include <signal.h>
27*387f9dfdSAndroid Build Coastguard Worker #include <stdio.h>
28*387f9dfdSAndroid Build Coastguard Worker #include <stdlib.h>
29*387f9dfdSAndroid Build Coastguard Worker #include <string.h>
30*387f9dfdSAndroid Build Coastguard Worker #include <unistd.h>
31*387f9dfdSAndroid Build Coastguard Worker
32*387f9dfdSAndroid Build Coastguard Worker #include "lauxlib.h"
33*387f9dfdSAndroid Build Coastguard Worker #include "lua.h"
34*387f9dfdSAndroid Build Coastguard Worker #include "lualib.h"
35*387f9dfdSAndroid Build Coastguard Worker
36*387f9dfdSAndroid Build Coastguard Worker static lua_State *globalL = NULL;
37*387f9dfdSAndroid Build Coastguard Worker static const char *progname = NULL;
38*387f9dfdSAndroid Build Coastguard Worker
lstop(lua_State * L,lua_Debug * ar)39*387f9dfdSAndroid Build Coastguard Worker static void lstop(lua_State *L, lua_Debug *ar) {
40*387f9dfdSAndroid Build Coastguard Worker (void)ar; /* unused arg. */
41*387f9dfdSAndroid Build Coastguard Worker lua_sethook(L, NULL, 0, 0);
42*387f9dfdSAndroid Build Coastguard Worker luaL_error(L, "interrupted!");
43*387f9dfdSAndroid Build Coastguard Worker }
44*387f9dfdSAndroid Build Coastguard Worker
laction(int i)45*387f9dfdSAndroid Build Coastguard Worker static void laction(int i) {
46*387f9dfdSAndroid Build Coastguard Worker signal(i, SIG_DFL);
47*387f9dfdSAndroid Build Coastguard Worker lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
48*387f9dfdSAndroid Build Coastguard Worker }
49*387f9dfdSAndroid Build Coastguard Worker
l_message(const char * pname,const char * msg)50*387f9dfdSAndroid Build Coastguard Worker static void l_message(const char *pname, const char *msg) {
51*387f9dfdSAndroid Build Coastguard Worker if (pname)
52*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "%s: ", pname);
53*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "%s\n", msg);
54*387f9dfdSAndroid Build Coastguard Worker fflush(stderr);
55*387f9dfdSAndroid Build Coastguard Worker }
56*387f9dfdSAndroid Build Coastguard Worker
report(lua_State * L,int status)57*387f9dfdSAndroid Build Coastguard Worker static int report(lua_State *L, int status) {
58*387f9dfdSAndroid Build Coastguard Worker if (status && !lua_isnil(L, -1)) {
59*387f9dfdSAndroid Build Coastguard Worker const char *msg = lua_tostring(L, -1);
60*387f9dfdSAndroid Build Coastguard Worker if (msg == NULL)
61*387f9dfdSAndroid Build Coastguard Worker msg = "(error object is not a string)";
62*387f9dfdSAndroid Build Coastguard Worker l_message(progname, msg);
63*387f9dfdSAndroid Build Coastguard Worker lua_pop(L, 1);
64*387f9dfdSAndroid Build Coastguard Worker }
65*387f9dfdSAndroid Build Coastguard Worker return status;
66*387f9dfdSAndroid Build Coastguard Worker }
67*387f9dfdSAndroid Build Coastguard Worker
traceback(lua_State * L)68*387f9dfdSAndroid Build Coastguard Worker static int traceback(lua_State *L) {
69*387f9dfdSAndroid Build Coastguard Worker if (!lua_isstring(L, 1)) /* 'message' not a string? */
70*387f9dfdSAndroid Build Coastguard Worker return 1; /* keep it intact */
71*387f9dfdSAndroid Build Coastguard Worker lua_getglobal(L, "debug");
72*387f9dfdSAndroid Build Coastguard Worker if (!lua_istable(L, -1)) {
73*387f9dfdSAndroid Build Coastguard Worker lua_pop(L, 1);
74*387f9dfdSAndroid Build Coastguard Worker return 1;
75*387f9dfdSAndroid Build Coastguard Worker }
76*387f9dfdSAndroid Build Coastguard Worker lua_getfield(L, -1, "traceback");
77*387f9dfdSAndroid Build Coastguard Worker if (!lua_isfunction(L, -1)) {
78*387f9dfdSAndroid Build Coastguard Worker lua_pop(L, 2);
79*387f9dfdSAndroid Build Coastguard Worker return 1;
80*387f9dfdSAndroid Build Coastguard Worker }
81*387f9dfdSAndroid Build Coastguard Worker lua_pushvalue(L, 1); /* pass error message */
82*387f9dfdSAndroid Build Coastguard Worker lua_pushinteger(L, 2); /* skip this function and traceback */
83*387f9dfdSAndroid Build Coastguard Worker lua_call(L, 2, 1); /* call debug.traceback */
84*387f9dfdSAndroid Build Coastguard Worker return 1;
85*387f9dfdSAndroid Build Coastguard Worker }
86*387f9dfdSAndroid Build Coastguard Worker
docall(lua_State * L,int narg,int clear)87*387f9dfdSAndroid Build Coastguard Worker static int docall(lua_State *L, int narg, int clear) {
88*387f9dfdSAndroid Build Coastguard Worker int status;
89*387f9dfdSAndroid Build Coastguard Worker int base = lua_gettop(L) - narg; /* function index */
90*387f9dfdSAndroid Build Coastguard Worker lua_pushcfunction(L, traceback); /* push traceback function */
91*387f9dfdSAndroid Build Coastguard Worker lua_insert(L, base); /* put it under chunk and args */
92*387f9dfdSAndroid Build Coastguard Worker signal(SIGINT, laction);
93*387f9dfdSAndroid Build Coastguard Worker status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base);
94*387f9dfdSAndroid Build Coastguard Worker signal(SIGINT, SIG_DFL);
95*387f9dfdSAndroid Build Coastguard Worker lua_remove(L, base); /* remove traceback function */
96*387f9dfdSAndroid Build Coastguard Worker /* force a complete garbage collection in case of errors */
97*387f9dfdSAndroid Build Coastguard Worker if (status != 0)
98*387f9dfdSAndroid Build Coastguard Worker lua_gc(L, LUA_GCCOLLECT, 0);
99*387f9dfdSAndroid Build Coastguard Worker return status;
100*387f9dfdSAndroid Build Coastguard Worker }
101*387f9dfdSAndroid Build Coastguard Worker
dolibrary(lua_State * L,const char * name,int clear)102*387f9dfdSAndroid Build Coastguard Worker static int dolibrary(lua_State *L, const char *name, int clear) {
103*387f9dfdSAndroid Build Coastguard Worker lua_getglobal(L, "require");
104*387f9dfdSAndroid Build Coastguard Worker lua_pushstring(L, name);
105*387f9dfdSAndroid Build Coastguard Worker return report(L, docall(L, 1, clear));
106*387f9dfdSAndroid Build Coastguard Worker }
107*387f9dfdSAndroid Build Coastguard Worker
108*387f9dfdSAndroid Build Coastguard Worker struct Smain {
109*387f9dfdSAndroid Build Coastguard Worker int argc;
110*387f9dfdSAndroid Build Coastguard Worker char **argv;
111*387f9dfdSAndroid Build Coastguard Worker int status;
112*387f9dfdSAndroid Build Coastguard Worker };
113*387f9dfdSAndroid Build Coastguard Worker
pushargv(lua_State * L,char ** argv,int argc,int offset)114*387f9dfdSAndroid Build Coastguard Worker static void pushargv(lua_State *L, char **argv, int argc, int offset) {
115*387f9dfdSAndroid Build Coastguard Worker int i, j;
116*387f9dfdSAndroid Build Coastguard Worker lua_createtable(L, argc, 0);
117*387f9dfdSAndroid Build Coastguard Worker for (i = offset, j = 1; i < argc; i++, j++) {
118*387f9dfdSAndroid Build Coastguard Worker lua_pushstring(L, argv[i]);
119*387f9dfdSAndroid Build Coastguard Worker lua_rawseti(L, -2, j);
120*387f9dfdSAndroid Build Coastguard Worker }
121*387f9dfdSAndroid Build Coastguard Worker }
122*387f9dfdSAndroid Build Coastguard Worker
pmain(lua_State * L)123*387f9dfdSAndroid Build Coastguard Worker static int pmain(lua_State *L) {
124*387f9dfdSAndroid Build Coastguard Worker struct Smain *s = (struct Smain *)lua_touserdata(L, 1);
125*387f9dfdSAndroid Build Coastguard Worker globalL = L;
126*387f9dfdSAndroid Build Coastguard Worker
127*387f9dfdSAndroid Build Coastguard Worker lua_gc(L, LUA_GCSTOP, 0);
128*387f9dfdSAndroid Build Coastguard Worker luaL_openlibs(L);
129*387f9dfdSAndroid Build Coastguard Worker lua_gc(L, LUA_GCRESTART, 0);
130*387f9dfdSAndroid Build Coastguard Worker
131*387f9dfdSAndroid Build Coastguard Worker s->status = dolibrary(L, "bcc", 0);
132*387f9dfdSAndroid Build Coastguard Worker if (s->status)
133*387f9dfdSAndroid Build Coastguard Worker return 0;
134*387f9dfdSAndroid Build Coastguard Worker
135*387f9dfdSAndroid Build Coastguard Worker lua_pushstring(L, progname);
136*387f9dfdSAndroid Build Coastguard Worker lua_setglobal(L, "BCC_STANDALONE");
137*387f9dfdSAndroid Build Coastguard Worker
138*387f9dfdSAndroid Build Coastguard Worker pushargv(L, s->argv, s->argc, 1);
139*387f9dfdSAndroid Build Coastguard Worker lua_setglobal(L, "arg");
140*387f9dfdSAndroid Build Coastguard Worker
141*387f9dfdSAndroid Build Coastguard Worker s->status = report(L, docall(L, 0, 1));
142*387f9dfdSAndroid Build Coastguard Worker return 0;
143*387f9dfdSAndroid Build Coastguard Worker }
144*387f9dfdSAndroid Build Coastguard Worker
main(int argc,char ** argv)145*387f9dfdSAndroid Build Coastguard Worker int main(int argc, char **argv) {
146*387f9dfdSAndroid Build Coastguard Worker int status;
147*387f9dfdSAndroid Build Coastguard Worker struct Smain s;
148*387f9dfdSAndroid Build Coastguard Worker lua_State *L = lua_open(); /* create state */
149*387f9dfdSAndroid Build Coastguard Worker
150*387f9dfdSAndroid Build Coastguard Worker if (L == NULL) {
151*387f9dfdSAndroid Build Coastguard Worker l_message(argv[0], "cannot create state: not enough memory");
152*387f9dfdSAndroid Build Coastguard Worker return EXIT_FAILURE;
153*387f9dfdSAndroid Build Coastguard Worker }
154*387f9dfdSAndroid Build Coastguard Worker
155*387f9dfdSAndroid Build Coastguard Worker if (geteuid() != 0) {
156*387f9dfdSAndroid Build Coastguard Worker l_message(argv[0], "bcc-lua must be ran as root");
157*387f9dfdSAndroid Build Coastguard Worker return EXIT_FAILURE;
158*387f9dfdSAndroid Build Coastguard Worker }
159*387f9dfdSAndroid Build Coastguard Worker
160*387f9dfdSAndroid Build Coastguard Worker progname = argv[0];
161*387f9dfdSAndroid Build Coastguard Worker s.argc = argc;
162*387f9dfdSAndroid Build Coastguard Worker s.argv = argv;
163*387f9dfdSAndroid Build Coastguard Worker s.status = 0;
164*387f9dfdSAndroid Build Coastguard Worker
165*387f9dfdSAndroid Build Coastguard Worker status = lua_cpcall(L, &pmain, &s);
166*387f9dfdSAndroid Build Coastguard Worker report(L, status);
167*387f9dfdSAndroid Build Coastguard Worker lua_close(L);
168*387f9dfdSAndroid Build Coastguard Worker
169*387f9dfdSAndroid Build Coastguard Worker return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS;
170*387f9dfdSAndroid Build Coastguard Worker }
171