1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <csignal>
17 #include <cstdio>
18 #include <dirent.h>
19 #include <fcntl.h>
20 #include <js_native_api.h>
21 #include <js_native_api_types.h>
22 #include <node_api.h>
23 #include <spawn.h>
24 #include <sys/stat.h>
25 #include <unistd.h>
26
27 #define FAIL (-1)
28 #define SUCCESS 0
29 #define PARAM_0 0
30 #define PARAM_1 1
31 #define PARAM_256 256
32 #define PARAM_0777 0777
33 #define PARAM_MINUS_1 (-1)
34 #define BAD_FD (-1)
35
PosixSpawn(napi_env env, napi_callback_info info)36 static napi_value PosixSpawn(napi_env env, napi_callback_info info)
37 {
38 size_t argc = PARAM_1;
39 napi_value args[1] = {nullptr};
40 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
41 int param;
42 napi_get_value_int32(env, args[0], ¶m);
43
44 int ret;
45 pid_t pid;
46 if (param == PARAM_0) {
47 posix_spawnattr_t attr;
48 posix_spawnattr_init(&attr);
49 const char *argv[] = {"sh", "-c", "echo", nullptr};
50 ret = posix_spawn(&pid, "/bin/sh", nullptr, &attr, (char *const *)argv, nullptr);
51 posix_spawnattr_destroy(&attr);
52 } else {
53 ret = posix_spawn(&pid, "unexitfile", nullptr, nullptr, nullptr, nullptr);
54 }
55
56 if (ret != SUCCESS) {
57 ret = FAIL;
58 }
59 napi_value result = nullptr;
60 napi_create_int32(env, ret, &result);
61 return result;
62 }
63
PosixSpawnFileActionsAddclose(napi_env env, napi_callback_info info)64 static napi_value PosixSpawnFileActionsAddclose(napi_env env, napi_callback_info info)
65 {
66 size_t argc = PARAM_1;
67 napi_value args[1] = {nullptr};
68 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
69 int param;
70 napi_get_value_int32(env, args[0], ¶m);
71
72 int ret;
73 posix_spawn_file_actions_t actions;
74 posix_spawn_file_actions_init(&actions);
75 if (param == PARAM_0) {
76 int p[2];
77 pipe(p);
78 ret = posix_spawn_file_actions_addclose(&actions, p[0]);
79 close(p[1]);
80 close(p[0]);
81 } else {
82 ret = posix_spawn_file_actions_addclose(&actions, BAD_FD);
83 }
84 posix_spawn_file_actions_destroy(&actions);
85 if (ret != PARAM_0) {
86 ret = FAIL;
87 }
88
89 napi_value result = nullptr;
90 napi_create_int32(env, ret, &result);
91 return result;
92 }
93
PosixSpawnFileActionsAddDup2(napi_env env, napi_callback_info info)94 static napi_value PosixSpawnFileActionsAddDup2(napi_env env, napi_callback_info info)
95 {
96 size_t argc = PARAM_1;
97 napi_value args[1] = {nullptr};
98 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
99 int param;
100 napi_get_value_int32(env, args[0], ¶m);
101
102 int ret;
103 posix_spawn_file_actions_t actions;
104 if (param == PARAM_0) {
105 posix_spawn_file_actions_init(&actions);
106 ret = posix_spawn_file_actions_adddup2(&actions, SUCCESS, SUCCESS);
107 posix_spawn_file_actions_destroy(&actions);
108 } else {
109 ret = posix_spawn_file_actions_adddup2(&actions, BAD_FD, BAD_FD);
110 }
111 if (ret != SUCCESS) {
112 ret = FAIL;
113 }
114
115 napi_value result = nullptr;
116 napi_create_int32(env, ret, &result);
117 return result;
118 }
119
PosixSpawnFileActionsAddOpen(napi_env env, napi_callback_info info)120 static napi_value PosixSpawnFileActionsAddOpen(napi_env env, napi_callback_info info)
121 {
122 char path[] = "/data/storage/el2/base/files/fzl.txt";
123 size_t argc = PARAM_1;
124 napi_value args[1] = {nullptr};
125 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
126 int param;
127 napi_get_value_int32(env, args[0], ¶m);
128
129 int ret;
130 posix_spawn_file_actions_t actions;
131 if (param == PARAM_0) {
132 int fd = open(path, O_CREAT, PARAM_0777);
133 posix_spawn_file_actions_init(&actions);
134 ret = posix_spawn_file_actions_addopen(&actions, fd, path, O_CREAT, S_IXGRP);
135 posix_spawn_file_actions_destroy(&actions);
136 close(fd);
137 remove(path);
138 } else {
139 ret = posix_spawn_file_actions_addopen(&actions, BAD_FD, path, O_CREAT, S_IXGRP);
140 }
141 if (ret != SUCCESS) {
142 ret = FAIL;
143 }
144
145 napi_value result = nullptr;
146 napi_create_int32(env, ret, &result);
147 return result;
148 }
149
PosixSpawnFileActionsDestroy(napi_env env, napi_callback_info info)150 static napi_value PosixSpawnFileActionsDestroy(napi_env env, napi_callback_info info)
151 {
152 size_t argc = PARAM_1;
153 napi_value args[1] = {nullptr};
154 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
155 int param;
156 napi_get_value_int32(env, args[0], ¶m);
157
158 int ret = FAIL;
159 if (param == PARAM_0) {
160 posix_spawn_file_actions_t actions;
161 posix_spawn_file_actions_init(&actions);
162 ret = posix_spawn_file_actions_destroy(&actions);
163 }
164
165 napi_value result = nullptr;
166 napi_create_int32(env, ret, &result);
167 return result;
168 }
169
PosixSpawnFileActionsInit(napi_env env, napi_callback_info info)170 static napi_value PosixSpawnFileActionsInit(napi_env env, napi_callback_info info)
171 {
172 size_t argc = PARAM_1;
173 napi_value args[1] = {nullptr};
174 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
175 int param;
176 napi_get_value_int32(env, args[0], ¶m);
177
178 int ret = FAIL;
179 if (param == PARAM_0) {
180 posix_spawn_file_actions_t actions;
181 ret = posix_spawn_file_actions_init(&actions);
182 posix_spawn_file_actions_destroy(&actions);
183 }
184
185 napi_value result = nullptr;
186 napi_create_int32(env, ret, &result);
187 return result;
188 }
189
PosixSpawnAttrDestroy(napi_env env, napi_callback_info info)190 static napi_value PosixSpawnAttrDestroy(napi_env env, napi_callback_info info)
191 {
192 size_t argc = PARAM_1;
193 napi_value args[1] = {nullptr};
194 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
195 int param;
196 napi_get_value_int32(env, args[0], ¶m);
197
198 int ret = FAIL;
199 if (param == PARAM_0) {
200 posix_spawnattr_t attr;
201 posix_spawnattr_init(&attr);
202 ret = posix_spawnattr_destroy(&attr);
203 }
204
205 napi_value result = nullptr;
206 napi_create_int32(env, ret, &result);
207 return result;
208 }
209
PosixSpawnAttrGetflags(napi_env env, napi_callback_info info)210 static napi_value PosixSpawnAttrGetflags(napi_env env, napi_callback_info info)
211 {
212 size_t argc = PARAM_1;
213 napi_value args[1] = {nullptr};
214 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
215 int param;
216 napi_get_value_int32(env, args[0], ¶m);
217
218 int ret = FAIL;
219 posix_spawnattr_t attr;
220 if (param == PARAM_0) {
221 short flags = PARAM_0;
222 posix_spawnattr_init(&attr);
223 posix_spawnattr_setflags(&attr, POSIX_SPAWN_RESETIDS);
224 ret = posix_spawnattr_getflags(&attr, &flags);
225 posix_spawnattr_destroy(&attr);
226 }
227
228 napi_value result = nullptr;
229 napi_create_int32(env, ret, &result);
230 return result;
231 }
232
PosixSpawnAttrGetpGroup(napi_env env, napi_callback_info info)233 static napi_value PosixSpawnAttrGetpGroup(napi_env env, napi_callback_info info)
234 {
235 size_t argc = PARAM_1;
236 napi_value args[1] = {nullptr};
237 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
238 int param;
239 napi_get_value_int32(env, args[0], ¶m);
240
241 int ret = FAIL;
242 if (param == PARAM_0) {
243 posix_spawnattr_t spawnattr;
244 pid_t group = PARAM_MINUS_1;
245 posix_spawnattr_init(&spawnattr);
246 ret = posix_spawnattr_getpgroup(&spawnattr, &group);
247 posix_spawnattr_destroy(&spawnattr);
248 }
249
250 napi_value result = nullptr;
251 napi_create_int32(env, ret, &result);
252 return result;
253 }
254
PosixSpawnAttrGetSigDefault(napi_env env, napi_callback_info info)255 static napi_value PosixSpawnAttrGetSigDefault(napi_env env, napi_callback_info info)
256 {
257 size_t argc = PARAM_1;
258 napi_value args[1] = {nullptr};
259 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
260 int param;
261 napi_get_value_int32(env, args[0], ¶m);
262
263 int ret = FAIL;
264 if (param == PARAM_0) {
265 posix_spawnattr_t spawnattr;
266 sigset_t sigset;
267 posix_spawnattr_init(&spawnattr);
268 ret = posix_spawnattr_getsigdefault(&spawnattr, &sigset);
269 posix_spawnattr_destroy(&spawnattr);
270 }
271
272 napi_value result = nullptr;
273 napi_create_int32(env, ret, &result);
274 return result;
275 }
276
PosixSpawnAttrGetSigMask(napi_env env, napi_callback_info info)277 static napi_value PosixSpawnAttrGetSigMask(napi_env env, napi_callback_info info)
278 {
279 size_t argc = PARAM_1;
280 napi_value args[1] = {nullptr};
281 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
282 int param;
283 napi_get_value_int32(env, args[0], ¶m);
284
285 int ret = FAIL;
286 if (param == PARAM_0) {
287 posix_spawnattr_t spawnattr;
288 sigset_t mask;
289 posix_spawnattr_init(&spawnattr);
290 ret = posix_spawnattr_getsigmask(&spawnattr, &mask);
291 posix_spawnattr_destroy(&spawnattr);
292 }
293
294 napi_value result = nullptr;
295 napi_create_int32(env, ret, &result);
296 return result;
297 }
298
PosixSpawnAttrInit(napi_env env, napi_callback_info info)299 static napi_value PosixSpawnAttrInit(napi_env env, napi_callback_info info)
300 {
301 size_t argc = PARAM_1;
302 napi_value args[1] = {nullptr};
303 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
304 int param;
305 napi_get_value_int32(env, args[0], ¶m);
306
307 int ret = FAIL;
308 if (param == PARAM_0) {
309 posix_spawnattr_t attr;
310 ret = posix_spawnattr_init(&attr);
311 posix_spawnattr_destroy(&attr);
312 }
313
314 napi_value result = nullptr;
315 napi_create_int32(env, ret, &result);
316 return result;
317 }
318
PosixSpawnAttrSetFlags(napi_env env, napi_callback_info info)319 static napi_value PosixSpawnAttrSetFlags(napi_env env, napi_callback_info info)
320 {
321 size_t argc = PARAM_1;
322 napi_value args[1] = {nullptr};
323 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
324 int param;
325 napi_get_value_int32(env, args[0], ¶m);
326
327 int ret;
328 posix_spawnattr_t spawnattr;
329 posix_spawnattr_init(&spawnattr);
330 if (param == PARAM_0) {
331 ret = posix_spawnattr_setflags(&spawnattr, POSIX_SPAWN_RESETIDS);
332 } else {
333 ret = posix_spawnattr_setflags(&spawnattr, PARAM_256);
334 }
335 posix_spawnattr_destroy(&spawnattr);
336 if (ret != PARAM_0) {
337 ret = FAIL;
338 }
339
340 napi_value result = nullptr;
341 napi_create_int32(env, ret, &result);
342 return result;
343 }
344
PosixSpawnAttrSetPGroup(napi_env env, napi_callback_info info)345 static napi_value PosixSpawnAttrSetPGroup(napi_env env, napi_callback_info info)
346 {
347 size_t argc = PARAM_1;
348 napi_value args[1] = {nullptr};
349 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
350 int param;
351 napi_get_value_int32(env, args[0], ¶m);
352
353 int ret = FAIL;
354 if (param == PARAM_0) {
355 posix_spawnattr_t attr;
356 pid_t group = PARAM_MINUS_1;
357 posix_spawnattr_init(&attr);
358 ret = posix_spawnattr_setpgroup(&attr, group);
359 posix_spawnattr_destroy(&attr);
360 }
361
362 napi_value result = nullptr;
363 napi_create_int32(env, ret, &result);
364 return result;
365 }
366
PosixSpawnAttrSetSigDefault(napi_env env, napi_callback_info info)367 static napi_value PosixSpawnAttrSetSigDefault(napi_env env, napi_callback_info info)
368 {
369 size_t argc = PARAM_1;
370 napi_value args[1] = {nullptr};
371 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
372 int param;
373 napi_get_value_int32(env, args[0], ¶m);
374
375 int ret = FAIL;
376 if (param == PARAM_0) {
377 posix_spawnattr_t attr;
378 sigset_t sigset;
379 sigemptyset(&sigset);
380 sigaddset(&sigset, SIGCHLD);
381 posix_spawnattr_init(&attr);
382 ret = posix_spawnattr_setsigdefault(&attr, &sigset);
383 posix_spawnattr_destroy(&attr);
384 }
385
386 napi_value result = nullptr;
387 napi_create_int32(env, ret, &result);
388 return result;
389 }
390
PosixSpawnAttrSetSigMask(napi_env env, napi_callback_info info)391 static napi_value PosixSpawnAttrSetSigMask(napi_env env, napi_callback_info info)
392 {
393 size_t argc = PARAM_1;
394 napi_value args[1] = {nullptr};
395 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
396 int param;
397 napi_get_value_int32(env, args[0], ¶m);
398
399 int ret = FAIL;
400 if (param == PARAM_0) {
401 posix_spawnattr_t attr;
402 sigset_t sigset;
403 sigemptyset(&sigset);
404 sigaddset(&sigset, SIGCHLD);
405 posix_spawnattr_init(&attr);
406 ret = posix_spawnattr_setsigmask(&attr, &sigset);
407 posix_spawnattr_destroy(&attr);
408 }
409
410 napi_value result = nullptr;
411 napi_create_int32(env, ret, &result);
412 return result;
413 }
414
PosixSpawnP(napi_env env, napi_callback_info info)415 static napi_value PosixSpawnP(napi_env env, napi_callback_info info)
416 {
417 size_t argc = PARAM_1;
418 napi_value args[1] = {nullptr};
419 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
420 int param;
421 napi_get_value_int32(env, args[0], ¶m);
422
423 int ret;
424 pid_t pid;
425 if (param == PARAM_0) {
426 pid = getpid();
427 posix_spawnattr_t attr;
428 posix_spawnattr_init(&attr);
429 const char *argv[] = {"/bin/echo", "hello", nullptr};
430 ret = posix_spawnp(&pid, "echo", nullptr, &attr, (char *const *)argv, nullptr);
431 posix_spawnattr_destroy(&attr);
432 } else {
433 ret = posix_spawn(&pid, "unexitfile", nullptr, nullptr, nullptr, nullptr);
434 }
435
436 if (ret != SUCCESS) {
437 ret = FAIL;
438 }
439 napi_value result = nullptr;
440 napi_create_int32(env, ret, &result);
441 return result;
442 }
443
Init(napi_env env, napi_value exports)444 EXTERN_C_START static napi_value Init(napi_env env, napi_value exports)
445 {
446 napi_property_descriptor desc[] = {
447 {"posixSpawn", nullptr, PosixSpawn, nullptr, nullptr, nullptr, napi_default, nullptr},
448 {"posixSpawnFileActionsAddClose", nullptr, PosixSpawnFileActionsAddclose, nullptr, nullptr, nullptr,
449 napi_default, nullptr},
450 {"posixSpawnFileActionsAdddup2", nullptr, PosixSpawnFileActionsAddDup2, nullptr, nullptr, nullptr, napi_default,
451 nullptr},
452 {"posixSpawnFileActionsAddopen", nullptr, PosixSpawnFileActionsAddOpen, nullptr, nullptr, nullptr, napi_default,
453 nullptr},
454 {"posixSpawnFileActionsDestroy", nullptr, PosixSpawnFileActionsDestroy, nullptr, nullptr, nullptr, napi_default,
455 nullptr},
456 {"posixSpawnFileActionsInit", nullptr, PosixSpawnFileActionsInit, nullptr, nullptr, nullptr, napi_default,
457 nullptr},
458 {"posixSpawnAttrDestroy", nullptr, PosixSpawnAttrDestroy, nullptr, nullptr, nullptr, napi_default, nullptr},
459 {"posixSpawnAttrGetFlags", nullptr, PosixSpawnAttrGetflags, nullptr, nullptr, nullptr, napi_default, nullptr},
460 {"posixSpawnAttrGetpGroup", nullptr, PosixSpawnAttrGetpGroup, nullptr, nullptr, nullptr, napi_default, nullptr},
461 {"posixSpawnAttrGetSigDefault", nullptr, PosixSpawnAttrGetSigDefault, nullptr, nullptr, nullptr, napi_default,
462 nullptr},
463 {"posixSpawnAttrGetSigMask", nullptr, PosixSpawnAttrGetSigMask, nullptr, nullptr, nullptr, napi_default,
464 nullptr},
465 {"posixSpawnAttrInit", nullptr, PosixSpawnAttrInit, nullptr, nullptr, nullptr, napi_default, nullptr},
466 {"posixSpawnAttrSetFlags", nullptr, PosixSpawnAttrSetFlags, nullptr, nullptr, nullptr, napi_default, nullptr},
467 {"posixSpawnAttrSetPGroup", nullptr, PosixSpawnAttrSetPGroup, nullptr, nullptr, nullptr, napi_default, nullptr},
468 {"posixSpawnAttrSetSigDefault", nullptr, PosixSpawnAttrSetSigDefault, nullptr, nullptr, nullptr, napi_default,
469 nullptr},
470 {"posixSpawnAttrSetSigMask", nullptr, PosixSpawnAttrSetSigMask, nullptr, nullptr, nullptr, napi_default,
471 nullptr},
472 {"posixSpawnP", nullptr, PosixSpawnP, nullptr, nullptr, nullptr, napi_default, nullptr}};
473 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
474 return exports;
475 }
476 EXTERN_C_END
477
478 static napi_module demoModule = {
479 .nm_version = 1,
480 .nm_flags = 0,
481 .nm_filename = "spawnndk1",
482 .nm_register_func = Init,
483 .nm_modname = "libspawnndk1",
484 .nm_priv = ((void *)0),
485 .reserved = {0},
486 };
487
RegisterModule(void)488 extern "C" __attribute__((constructor)) void RegisterModule(void) { napi_module_register(&demoModule); }