Branch data Line data Source code
1 : : /*-
2 : : * Copyright (c) 2019 Baptiste Daroussin <bapt@FreeBSD.org>
3 : : * All rights reserved.
4 : : *
5 : : * Redistribution and use in source and binary forms, with or without
6 : : * modification, are permitted provided that the following conditions
7 : : * are met:
8 : : * 1. Redistributions of source code must retain the above copyright
9 : : * notice, this list of conditions and the following disclaimer
10 : : * in this position and unchanged.
11 : : * 2. Redistributions in binary form must reproduce the above copyright
12 : : * notice, this list of conditions and the following disclaimer in the
13 : : * documentation and/or other materials provided with the distribution.
14 : : *
15 : : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
16 : : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 : : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 : : * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
19 : : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 : : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 : : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 : : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 : : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 : : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 : : */
26 : :
27 : : #include "pkg_config.h"
28 : :
29 : : #ifdef HAVE_SYS_PROCCTL_H
30 : : #include <sys/procctl.h>
31 : : #endif
32 : :
33 : : #include <sys/types.h>
34 : : #include <sys/wait.h>
35 : :
36 : : #include <errno.h>
37 : : #include <poll.h>
38 : : #include <xstring.h>
39 : : #include <err.h>
40 : : #include <stdio.h>
41 : :
42 : : #include "pkg.h"
43 : : #include "private/pkg.h"
44 : : #include "private/event.h"
45 : : #include "private/lua.h"
46 : :
47 : : extern char **environ;
48 : :
49 : : int
50 : 2474 : pkg_lua_script_run(struct pkg * const pkg, pkg_lua_script type, bool upgrade)
51 : : {
52 : 2474 : int ret = EPKG_OK;
53 : : struct pkg_lua_script *lscript;
54 : : int pstat;
55 : : #ifdef PROC_REAP_KILL
56 : : bool do_reap;
57 : : pid_t mypid;
58 : : struct procctl_reaper_status info;
59 : : struct procctl_reaper_kill killemall;
60 : : #endif
61 : : int cur_pipe[2];
62 : 2474 : char *line = NULL;
63 : :
64 [ + + ]: 2474 : if (pkg->lua_scripts[type] == NULL)
65 : 2386 : return (EPKG_OK);
66 : :
67 [ - + ]: 88 : if (!pkg_object_bool(pkg_config_get("RUN_SCRIPTS"))) {
68 : 0 : return (EPKG_OK);
69 : : }
70 : :
71 : : #ifdef PROC_REAP_KILL
72 : 88 : mypid = getpid();
73 : 88 : do_reap = procctl(P_PID, mypid, PROC_REAP_ACQUIRE, NULL) == 0;
74 : : #endif
75 : :
76 [ + + ]: 188 : LL_FOREACH(pkg->lua_scripts[type], lscript) {
77 [ - + ]: 100 : if (get_socketpair(cur_pipe) == -1) {
78 : 0 : pkg_emit_errno("pkg_lua_script_script", "socketpair");
79 : 0 : goto cleanup;
80 : : }
81 : 100 : pid_t pid = fork();
82 [ - + ]: 100 : if (pid == 0) {
83 : : static const luaL_Reg pkg_lib[] = {
84 : : { "print_msg", lua_print_msg },
85 : : { "prefixed_path", lua_prefix_path },
86 : : { "filecmp", lua_pkg_filecmp },
87 : : { "copy", lua_pkg_copy },
88 : : { "stat", lua_stat },
89 : : { "readdir", lua_readdir },
90 : : { "exec", lua_exec },
91 : : { NULL, NULL },
92 : : };
93 : 0 : close(cur_pipe[0]);
94 : 0 : lua_State *L = luaL_newstate();
95 : 0 : luaL_openlibs( L );
96 : 0 : lua_atpanic(L, (lua_CFunction)stack_dump );
97 : 0 : lua_pushinteger(L, cur_pipe[1]);
98 : 0 : lua_setglobal(L, "msgfd");
99 : 0 : lua_pushlightuserdata(L, pkg);
100 : 0 : lua_setglobal(L, "package");
101 : 0 : lua_pushinteger(L, pkg->rootfd);
102 : 0 : lua_setglobal(L, "rootfd");
103 : 0 : lua_pushstring(L, pkg->prefix);
104 : 0 : lua_setglobal(L, "pkg_prefix");
105 : 0 : lua_pushstring(L, pkg->name);
106 : 0 : lua_setglobal(L, "pkg_name");
107 : 0 : if (ctx.pkg_rootdir == NULL)
108 : 0 : ctx.pkg_rootdir = "/";
109 : 0 : lua_pushstring(L, ctx.pkg_rootdir);
110 : 0 : lua_setglobal(L, "pkg_rootdir");
111 : 0 : lua_pushboolean(L, (upgrade));
112 : 0 : lua_setglobal(L, "pkg_upgrade");
113 : 0 : luaL_newlib(L, pkg_lib);
114 : 0 : lua_setglobal(L, "pkg");
115 : 0 : lua_override_ios(L, true);
116 : :
117 : : /* parse and set arguments of the line is in the comments */
118 : 0 : if (STARTS_WITH(lscript->script, "-- args: ")) {
119 : 0 : char *walk, *begin, *line = NULL;
120 : 0 : int spaces, argc = 0;
121 : 0 : char **args = NULL;
122 : :
123 : 0 : walk = strchr(lscript->script, '\n');
124 : 0 : begin = lscript->script + strlen("-- args: ");
125 : 0 : line = xstrndup(begin, walk - begin);
126 : 0 : spaces = pkg_utils_count_spaces(line);
127 : 0 : args = xmalloc((spaces + 1)* sizeof(char *));
128 : 0 : walk = xstrdup(line);
129 [ # # ]: 0 : while (walk != NULL) {
130 : 0 : args[argc++] = pkg_utils_tokenize(&walk);
131 : : }
132 : 0 : lua_args_table(L, args, argc);
133 : 0 : }
134 : :
135 : 0 : pkg_debug(3, "Scripts: executing lua\n--- BEGIN ---\n%s\nScripts: --- END ---", lscript->script);
136 : 0 : if (luaL_dostring(L, lscript->script)) {
137 : 0 : pkg_emit_error("Failed to execute lua script: %s", lua_tostring(L, -1));
138 : 0 : lua_close(L);
139 : 0 : _exit(1);
140 : : }
141 : :
142 [ # # ]: 0 : if (lua_tonumber(L, -1) != 0) {
143 : 0 : lua_close(L);
144 : 0 : _exit(1);
145 : : }
146 : :
147 : 0 : lua_close(L);
148 : 0 : _exit(0);
149 [ - + ]: 100 : } else if (pid < 0) {
150 : 0 : pkg_emit_errno("Cannot fork", "lua_script");
151 : 0 : ret = EPKG_FATAL;
152 : 0 : goto cleanup;
153 : : }
154 : :
155 : 100 : close(cur_pipe[1]);
156 : :
157 : 100 : ret = pkg_script_run_child(pid, &pstat, cur_pipe[0], "lua");
158 : 188 : }
159 : :
160 : :
161 : : cleanup:
162 : : #ifdef PROC_REAP_KILL
163 : : /*
164 : : * If the prior PROCCTL_REAP_ACQUIRE call failed, the kernel
165 : : * probably doesn't support this, so don't try.
166 : : */
167 [ - + ]: 88 : if (!do_reap)
168 : 0 : return (ret);
169 : :
170 : 88 : procctl(P_PID, mypid, PROC_REAP_STATUS, &info);
171 : 88 : if (info.rs_children != 0) {
172 : 0 : killemall.rk_sig = SIGKILL;
173 : 0 : killemall.rk_flags = 0;
174 : 0 : if (procctl(P_PID, mypid, PROC_REAP_KILL, &killemall) != 0) {
175 : 0 : pkg_errno("%s", "Fail to kill all processes");
176 : 0 : }
177 : 0 : }
178 : 88 : procctl(P_PID, mypid, PROC_REAP_RELEASE, NULL);
179 : : #endif
180 : 88 : free(line);
181 : :
182 : 88 : return (ret);
183 : 2474 : }
184 : :
185 : : ucl_object_t *
186 : 84 : pkg_lua_script_to_ucl(struct pkg_lua_script *scripts)
187 : : {
188 : : struct pkg_lua_script *script;
189 : : ucl_object_t *array;
190 : :
191 : 84 : array = ucl_object_typed_new(UCL_ARRAY);
192 [ + + ]: 180 : LL_FOREACH(scripts, script) {
193 : 192 : ucl_array_append(array, ucl_object_fromstring_common(script->script,
194 : 96 : strlen(script->script), UCL_STRING_RAW|UCL_STRING_TRIM));
195 : 96 : }
196 : :
197 : 84 : return (array);
198 : : }
199 : :
200 : : int
201 : 256 : pkg_lua_script_from_ucl(struct pkg *pkg, const ucl_object_t *obj, pkg_lua_script type)
202 : : {
203 : : struct pkg_lua_script *lscript;
204 : : const ucl_object_t *cur;
205 : 256 : ucl_object_iter_t it = NULL;
206 : :
207 [ + + ]: 544 : while ((cur = ucl_iterate_object(obj, &it, true))) {
208 [ - + ]: 288 : if (ucl_object_type(cur) != UCL_STRING) {
209 : 0 : pkg_emit_error("lua scripts be strings");
210 : 0 : return (EPKG_FATAL);
211 : : }
212 : 288 : lscript = xcalloc(1, sizeof(*lscript));
213 : 288 : lscript->script = xstrdup(ucl_object_tostring(cur));
214 [ + + ]: 288 : DL_APPEND(pkg->lua_scripts[type], lscript);
215 : : }
216 : 256 : return (EPKG_OK);
217 : 256 : }
218 : :
|