1 /*@ S-nail - a mail user agent derived from Berkeley Mail. 2 *@ Child process handling, direct (pipe streams are in file-streams.h). 3 * 4 * Copyright (c) 2012 - 2020 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>. 5 * SPDX-License-Identifier: ISC 6 * 7 * Permission to use, copy, modify, and/or distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 #ifndef mx_CHILD_H 20 #define mx_CHILD_H 21 22 #include <mx/nail.h> 23 24 #define mx_HEADER 25 #include <su/code-in.h> 26 27 struct mx_child_ctx; 28 29 /* */ 30 #define mx_CHILD_MAXARGS 3 /* xxx vector */ 31 32 enum mx_child_flags{ 33 mx_CHILD_NONE = 0, 34 /* Ensure the forked child has started running (as opposed to the default 35 * success which only remarks "fork(2) has returned successfully") */ 36 mx_CHILD_SPAWN_CONTROL = 1u<<0, 37 /* On top of SPAWN_CONTROL, wait until the child called execve */ 38 mx_CHILD_SPAWN_CONTROL_LINGER = 1u<<1, 39 /* run(): handle all the lifetime, and wait etc., return final status */ 40 mx_CHILD_RUN_WAIT_LIFE = 1u<<2, 41 42 /* Child uses terminal and requires termios handling */ 43 mx__CHILD_JOBCTL = 1u<<8 44 }; 45 46 /* mx_child_ctx_setup() to zero out */ 47 struct mx_child_ctx{ 48 /* Output: */ 49 s32 cc_pid; /* Filled upon successful start (when not waited..) */ 50 s32 cc_exit_status; /* WEXITSTATUS(); -WEXITSTATUS() if !WIFEXITED */ 51 /* err_no() on failure; with SPAWN_CONTROL it could be set to errors that 52 * happen in the child, too; set to ERR_CHILD when there was error and there 53 * was no error */ 54 s32 cc_error; 55 u32 cc_flags; /* child_flags */ 56 /* Input: the arguments are all optional */ 57 /* Signals must be handled by the caller. If this is set, then it is 58 * a sigset_t*: the signals to ignore in the new process. 59 * SIGINT is enabled unless it is in the mask. */ 60 void *cc_mask; /* In fact a sigset_t XXX su_sigset! */ 61 s32 cc_fds[2]; /* A real FD, or _FD_PASS or _FD_NULL XXX sz[2] */ 62 char const *cc_cmd; /* The command to run, */ 63 char const *cc_args[mx_CHILD_MAXARGS]; /* and its optional arguments */ 64 /* NIL or NIL terminated array; Note: is modified if set! */ 65 char const **cc_env_addon; /* TODO su_dict */ 66 sz cc__cpipe[2]; 67 }; 68 69 /* Slots in .cc_fds */ 70 #define mx_CHILD_FD_IN 0 71 #define mx_CHILD_FD_OUT 1 72 73 /* Special file descriptors for .cc_fds */ 74 #define mx_CHILD_FD_PASS (-1) 75 #define mx_CHILD_FD_NULL (-2) 76 77 /* At program startup: initialize controller (panic on failure) */ 78 EXPORT void mx_child_controller_setup(void); 79 80 /* Initialize (zero out etc.). The .cc_fds are set to CHILD_FD_PASS */ 81 EXPORT void mx_child_ctx_setup(struct mx_child_ctx *ccp); 82 83 /* Start and run a command, with optional arguments and splicing of stdin and 84 * stdout, as defined by the ctx_setup()d ccp, return whether the process has 85 * been started successfully. 86 * With RUN_WAIT_LIFE the return value also indicates whether the parent has 87 * child_wait()ed successfully, i.e., whether the child has terminated 88 * already; .cc_exit_status etc. can be examined for more. 89 * Otherwise _signal(), _forget() and _wait() can be used on ccp */ 90 EXPORT boole mx_child_run(struct mx_child_ctx *ccp); 91 92 /* Fork a child process, "enable" the below functions upon success. 93 * With SPAWN_CONTROL the parent will linger until the child has called 94 * in_child_setup() or even (with SPAWN_CONTROL_LINGER) until it execve's. 95 * Children can start children themselves, but we do not care about termios 96 * XXX or child handling no more in recursive levels */ 97 EXPORT boole mx_child_fork(struct mx_child_ctx *ccp); 98 99 /* Setup an image in the child; signals are still blocked before that! */ 100 EXPORT void mx_child_in_child_setup(struct mx_child_ctx *ccp); 101 102 /* This can only be used if SPAWN_CONTROL_LINGER had been used. 103 * It will pass err up to the parent, and close the control pipe. 104 * It does not exit the program */ 105 EXPORT void mx_child_in_child_exec_failed(struct mx_child_ctx *ccp, s32 err); 106 107 /* Send a signal to a managed process, return 0 on success, a negative value 108 * if the process does no(t) (longer) exist, or an error constant */ 109 EXPORT s32 mx_child_signal(struct mx_child_ctx *ccp, s32 sig); 110 111 /* Loose any knowledge we might have regarding ccp. 112 * Neither waiting nor any other status report will be available. 113 * This must not be used in conjunction with FD_PASS. */ 114 EXPORT void mx_child_forget(struct mx_child_ctx *ccp); 115 116 /* Wait on the child and return whether ccp was a known child and has been 117 * waited for successfully; examine ccp for error / status */ 118 EXPORT boole mx_child_wait(struct mx_child_ctx *ccp); 119 120 #include <su/code-ou.h> 121 #endif /* mx_CHILD_H */ 122 /* s-it-mode */ 123