xref: /aosp_15_r20/external/bcc/src/lua/src/main.c (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
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