SafeAPI Backend POSIX
POSIX/Linux OAL backend for safeAPIFreamwork
Toggle main menu visibility
Loading...
Searching...
No Matches
sapi_posix_backend_reboot.c
Go to the documentation of this file.
1
/* _XOPEN_SOURCE 700 (implies _POSIX_C_SOURCE 200809L) rather than
2
* _POSIX_C_SOURCE alone: setenv()/putenv() below are XSI extensions, not
3
* base POSIX. */
4
#define _XOPEN_SOURCE 700
5
55
#include "
safeapi/posix_backend/sapi_posix_backend.h
"
56
57
#include <limits.h>
58
#include <stdbool.h>
59
#include <stdio.h>
60
#include <stdlib.h>
61
#include <unistd.h>
62
63
#if defined(__APPLE__)
64
#include <mach-o/dyld.h>
65
#endif
66
67
extern
char
**environ;
68
70
/* No dynamic allocation (REQ-OAL-REBOOT-001's fixed-storage convention,
71
* project-wide "no malloc/free/realloc" rule) - a fixed-capacity static
72
* array of pointers, not copies of the strings themselves (see
73
* sapi_posix_backend_reboot_set_argv()'s own doc for why storing the
74
* pointers is sufficient). +1 slot for the NULL terminator execv()
75
* requires. */
76
#define SAPI_POSIX_REBOOT_MAX_ARGV 8U
77
79
85
static
bool
resolve_self_exe_path
(
char
*out_path,
size_t
out_path_size,
const
char
*argv0);
86
static
sapi_status_t backend_request(uint16_t reason_code);
87
89
static
char
*
s_registered_argv
[
SAPI_POSIX_REBOOT_MAX_ARGV
+ 1U];
90
static
bool
s_argv_registered =
false
;
91
static
const
sapi_reboot_backend_t s_posix_reboot_backend = { backend_request };
92
94
95
97
void
sapi_posix_backend_reboot_set_argv
(
int
argc,
char
*
const
argv[])
98
{
99
int
count = (argc < 0) ? 0 : argc;
100
int
i;
101
102
if
(count > (
int
)
SAPI_POSIX_REBOOT_MAX_ARGV
)
103
{
104
count = (int)
SAPI_POSIX_REBOOT_MAX_ARGV
;
105
}
106
for
(i = 0; i < count; i++)
107
{
108
s_registered_argv
[i] = argv[i];
109
}
110
s_registered_argv
[count] = NULL;
111
s_argv_registered =
true
;
112
}
113
114
const
sapi_reboot_backend_t *
sapi_posix_backend_reboot
(
void
)
115
{
116
return
&s_posix_reboot_backend;
117
}
118
119
120
/****Local functions ****/
121
122
static
bool
resolve_self_exe_path
(
char
*out_path,
size_t
out_path_size,
const
char
*argv0)
123
{
124
#if defined(__APPLE__)
125
uint32_t size = (uint32_t)out_path_size;
126
127
if
(_NSGetExecutablePath(out_path, &size) == 0)
128
{
129
return
true
;
130
}
131
/* size now holds the required buffer length, but out_path_size is a
132
* fixed compile-time buffer here (PATH_MAX) - if that was not enough,
133
* there is nothing more this stand-in backend can do. */
134
(void)argv0;
135
return
false
;
136
#elif defined(__linux__)
137
ssize_t written = readlink(
"/proc/self/exe"
, out_path, out_path_size - 1U);
138
139
if
((written <= 0) || ((
size_t
)written >= out_path_size))
140
{
141
(void)argv0;
142
return
false
;
143
}
144
out_path[written] =
'\0'
;
145
return
true
;
146
#else
147
/* Unknown UNIX: best effort only - argv0 may not be a resolvable path
148
* (e.g. found via $PATH), which is an honest, documented limitation of
149
* this fallback branch, not silently hidden. */
150
if
((argv0 == NULL) || (out_path_size == 0U))
151
{
152
return
false
;
153
}
154
(void)snprintf(out_path, out_path_size,
"%s"
, argv0);
155
return
true
;
156
#endif
157
}
158
159
static
sapi_status_t backend_request(uint16_t reason_code)
160
{
161
char
reason_env[32];
162
int
written;
163
char
self_path[PATH_MAX];
164
165
written = snprintf(reason_env,
sizeof
(reason_env),
"SAPI_REBOOT_REASON_CODE=%u"
, (
unsigned
int
)reason_code);
166
if
((written > 0) && ((
size_t
)written <
sizeof
(reason_env)))
167
{
168
(void)putenv(reason_env);
169
}
170
171
/* No argv0 threaded through to this backend (see file header) - the
172
* unknown-UNIX fallback branch of resolve_self_exe_path() simply will
173
* not have one to fall back to and returns false, same as any other
174
* unresolvable-path case. */
175
if
(!
resolve_self_exe_path
(self_path,
sizeof
(self_path), NULL))
176
{
177
return
SAPI_STATUS_NOT_SUPPORTED;
178
}
179
180
/* Prefer the caller's own original argv (sapi_posix_backend_
181
* reboot_set_argv()) if registered, so a re-exec resumes with
182
* whatever command-line arguments the caller's own main() depends on
183
* - see this file's own header and sapi_posix_backend.h's doc.
184
* Otherwise fall back to a self-contained placeholder argv[0]; the
185
* kernel/loader resolves the actual executable from self_path either
186
* way, not from argv[0]'s string content. */
187
if
(s_argv_registered)
188
{
189
(void)execv(self_path,
s_registered_argv
);
190
}
191
else
192
{
193
char
*
const
argv_stub[] = { (
char
*)
"sapi-reboot"
, NULL };
194
195
(void)execv(self_path, argv_stub);
196
}
197
198
/* Reached only if execv() failed. */
199
return
SAPI_STATUS_NOT_SUPPORTED;
200
}
sapi_posix_backend.h
Real POSIX/Linux backend for every OAL service (ADR-018).
sapi_posix_backend_reboot
const sapi_reboot_backend_t * sapi_posix_backend_reboot(void)
The POSIX sapi_reboot backend (execv() re-exec of the current process image, self-path resolved porta...
Definition
sapi_posix_backend_reboot.c:114
sapi_posix_backend_reboot_set_argv
void sapi_posix_backend_reboot_set_argv(int argc, char *const argv[])
Registers the original process argv[] the POSIX reboot backend should re-exec with (instead of its ow...
Definition
sapi_posix_backend_reboot.c:97
SAPI_POSIX_REBOOT_MAX_ARGV
#define SAPI_POSIX_REBOOT_MAX_ARGV
Definition
sapi_posix_backend_reboot.c:76
s_registered_argv
static char * s_registered_argv[SAPI_POSIX_REBOOT_MAX_ARGV+1U]
Definition
sapi_posix_backend_reboot.c:89
resolve_self_exe_path
static bool resolve_self_exe_path(char *out_path, size_t out_path_size, const char *argv0)
Definition
sapi_posix_backend_reboot.c:122
src
sapi_posix_backend_reboot.c
Generated by
1.18.0