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