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