Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/pkg
Path: blob/main/libpkg/lua_scripts.c
2645 views
1
/*-
2
* Copyright (c) 2019-2025 Baptiste Daroussin <[email protected]>
3
*
4
* SPDX-License-Identifier: BSD-2-Clause
5
*/
6
7
#if __has_include(<sys/procctl.h>)
8
#include <sys/procctl.h>
9
#endif
10
11
#include <sys/types.h>
12
#include <sys/wait.h>
13
14
#include <errno.h>
15
#include <poll.h>
16
#include <xstring.h>
17
#include <err.h>
18
#include <stdio.h>
19
20
#include "pkg.h"
21
#include "private/pkg.h"
22
#include "private/event.h"
23
#include "private/lua.h"
24
25
extern char **environ;
26
27
int
28
pkg_lua_script_run(struct pkg * const pkg, pkg_lua_script type, bool upgrade)
29
{
30
int ret = EPKG_OK;
31
int pstat;
32
#ifdef PROC_REAP_KILL
33
bool do_reap;
34
pid_t mypid;
35
struct procctl_reaper_status info;
36
struct procctl_reaper_kill killemall;
37
#endif
38
int cur_pipe[2];
39
char *line = NULL;
40
41
if (vec_len(&pkg->lua_scripts[type]) == 0)
42
return (EPKG_OK);
43
44
if (!pkg_object_bool(pkg_config_get("RUN_SCRIPTS"))) {
45
return (EPKG_OK);
46
}
47
48
#ifdef PROC_REAP_KILL
49
mypid = getpid();
50
do_reap = procctl(P_PID, mypid, PROC_REAP_ACQUIRE, NULL) == 0;
51
#endif
52
53
vec_foreach(pkg->lua_scripts[type], i) {
54
char *script = pkg->lua_scripts[type].d[i];
55
if (get_socketpair(cur_pipe) == -1) {
56
pkg_emit_errno("pkg_lua_script_script", "socketpair");
57
goto cleanup;
58
}
59
pid_t pid = fork();
60
if (pid == 0) {
61
static const luaL_Reg pkg_lib[] = {
62
{ "print_msg", lua_print_msg },
63
{ "prefixed_path", lua_prefix_path },
64
{ "filecmp", lua_pkg_filecmp },
65
{ "copy", lua_pkg_copy },
66
{ "stat", lua_stat },
67
{ "readdir", lua_readdir },
68
{ "exec", lua_exec },
69
{ "symlink", lua_pkg_symlink },
70
{ "metalog_copy", lua_metalog_copy },
71
{ NULL, NULL },
72
};
73
close(cur_pipe[0]);
74
lua_State *L = luaL_newstate();
75
luaL_openlibs( L );
76
lua_atpanic(L, (lua_CFunction)stack_dump );
77
lua_pushinteger(L, cur_pipe[1]);
78
lua_setglobal(L, "msgfd");
79
lua_pushlightuserdata(L, pkg);
80
lua_setglobal(L, "package");
81
lua_pushinteger(L, pkg->rootfd);
82
lua_setglobal(L, "rootfd");
83
lua_pushstring(L, pkg->prefix);
84
lua_setglobal(L, "pkg_prefix");
85
lua_pushstring(L, pkg->name);
86
lua_setglobal(L, "pkg_name");
87
if (ctx.pkg_rootdir == NULL)
88
ctx.pkg_rootdir = "/";
89
lua_pushstring(L, ctx.pkg_rootdir);
90
lua_setglobal(L, "pkg_rootdir");
91
if (ctx.metalog != NULL) {
92
lua_pushstring(L, ctx.metalog);
93
lua_setglobal(L, "pkg_metalog");
94
}
95
lua_pushboolean(L, (upgrade));
96
lua_setglobal(L, "pkg_upgrade");
97
luaL_newlib(L, pkg_lib);
98
lua_setglobal(L, "pkg");
99
lua_override_ios(L, true);
100
101
/* parse and set arguments of the line is in the comments */
102
if (STARTS_WITH(script, "-- args: ")) {
103
char *walk, *begin, *line = NULL;
104
int spaces, argc = 0;
105
char **args = NULL;
106
107
walk = strchr(script, '\n');
108
begin = script + strlen("-- args: ");
109
line = xstrndup(begin, walk - begin);
110
spaces = pkg_utils_count_spaces(line);
111
args = xmalloc((spaces + 1)* sizeof(char *));
112
walk = xstrdup(line);
113
while (walk != NULL) {
114
args[argc++] = pkg_utils_tokenize(&walk);
115
}
116
lua_args_table(L, args, argc);
117
}
118
119
pkg_debug(3, "Scripts: executing lua\n--- BEGIN ---\n%s\nScripts: --- END ---", script);
120
if (luaL_dostring(L, script)) {
121
pkg_emit_error("Failed to execute lua script: %s", lua_tostring(L, -1));
122
lua_close(L);
123
_exit(1);
124
}
125
126
if (lua_tonumber(L, -1) != 0) {
127
lua_close(L);
128
_exit(1);
129
}
130
131
lua_close(L);
132
_exit(0);
133
} else if (pid < 0) {
134
pkg_emit_errno("Cannot fork", "lua_script");
135
ret = EPKG_FATAL;
136
goto cleanup;
137
}
138
139
close(cur_pipe[1]);
140
141
ret = pkg_script_run_child(pid, &pstat, cur_pipe[0], "lua");
142
}
143
144
145
cleanup:
146
#ifdef PROC_REAP_KILL
147
/*
148
* If the prior PROCCTL_REAP_ACQUIRE call failed, the kernel
149
* probably doesn't support this, so don't try.
150
*/
151
if (!do_reap)
152
return (ret);
153
154
procctl(P_PID, mypid, PROC_REAP_STATUS, &info);
155
if (info.rs_children != 0) {
156
killemall.rk_sig = SIGKILL;
157
killemall.rk_flags = 0;
158
if (procctl(P_PID, mypid, PROC_REAP_KILL, &killemall) != 0) {
159
pkg_errno("%s", "Fail to kill all processes");
160
}
161
}
162
procctl(P_PID, mypid, PROC_REAP_RELEASE, NULL);
163
#endif
164
free(line);
165
166
return (ret);
167
}
168
169
ucl_object_t *
170
pkg_lua_script_to_ucl(charv_t *scripts)
171
{
172
ucl_object_t *array;
173
174
array = ucl_object_typed_new(UCL_ARRAY);
175
vec_foreach(*scripts, i)
176
ucl_array_append(array, ucl_object_fromstring_common(scripts->d[i],
177
strlen(scripts->d[i]), UCL_STRING_RAW|UCL_STRING_TRIM));
178
179
return (array);
180
}
181
182
int
183
pkg_lua_script_from_ucl(struct pkg *pkg, const ucl_object_t *obj, pkg_lua_script type)
184
{
185
const ucl_object_t *cur;
186
ucl_object_iter_t it = NULL;
187
188
while ((cur = ucl_iterate_object(obj, &it, true))) {
189
if (ucl_object_type(cur) != UCL_STRING) {
190
pkg_emit_error("lua scripts be strings");
191
return (EPKG_FATAL);
192
}
193
vec_push(&pkg->lua_scripts[type], xstrdup(ucl_object_tostring(cur)));
194
}
195
return (EPKG_OK);
196
}
197
198
199