Ken Van Hoeylandt f8172446fd
App loading improvements and more (#675)
- External apps can opt into automatic cleanup when they exit, including tracked tasks, threads, files, directories, and memory.
- App-relative file paths resolve against the app’s working directory, with `.` and `..` normalized.
- The shell identifies ELF binaries that cannot be executed instead of treating them as scripts.
- Shared icon fonts now offer distinct default and large sizes, with updated icons across the interface.
- ESP32 apps can load additional ELF formats when address mirroring is enabled.
- Terminal colors render clearly on monochrome displays, and toolbar buttons have cleaner styling.
- GPS settings safely refresh their device list when their window is hidden or its widgets are destroyed.
2026-10-06 07:45:58 +02:00

102 lines
4.4 KiB
C

// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <stdbool.h>
#include <stddef.h>
#include <sys/poll.h>
#ifdef __cplusplus
extern "C" {
#endif
struct stat;
struct termios;
/**
* App-instance behavior for libc calls, used by the platform modules' libc wraps
* (app-esp32-module, app-posix-module).
*
* Each app_libc_try_*() function returns false when the call has nothing to do with an app instance
* (not called from an app's task, or not an app fd), so the caller falls through to the real libc
* function. When it returns true, the call was handled: *out_result holds the return value, and errno
* is set on failure. A closed app fd fails with EBADF, so it never reaches a real fd of the same number.
*/
/** Handles ioctl(fd, TIOCGWINSZ, struct winsize*) for an app fd. */
bool app_libc_try_window_size(int fd, unsigned long request, void* arg, int* out_result);
/** @param[out] out_result @a buf on success, NULL on failure */
bool app_libc_try_getcwd(char* buf, size_t size, char** out_result);
bool app_libc_try_chdir(const char* path, int* out_result);
/**
* Resolves @a path against the calling app instance's cwd, for the path-based libc calls: the platform's
* libc has no per-app cwd.
* On ESP32, ".", ".." and empty segments are collapsed too, also in an absolute path, since FATFS doesn't support them.
* On POSIX, the path is kept as written, so trailing separators and ".." through symlinks keep their meaning.
* Returns false for a NULL or empty @a path, which the caller then passes on as-is.
* @param[out] buf receives the resolved path
* @param[out] out_path @a buf on success, NULL when the resolved path doesn't fit (errno is set to ENAMETOOLONG)
*/
bool app_libc_try_resolve_path(const char* path, char* buf, size_t size, const char** out_path);
/** App fds report as character devices, which also makes isatty() true for them. */
bool app_libc_try_fstat(int fd, struct stat* st, int* out_result);
/**
* App fd input is always raw and unechoed, and a written '\n' also returns the cursor.
* The input flags are per app instance: ICRNL (on by default, like a terminal) makes stdin read '\r' as '\n'.
*/
bool app_libc_try_tcgetattr(int fd, struct termios* t, int* out_result);
/** Stores the input flags (c_iflag, of which ICRNL is applied). Other settings are accepted without effect. */
bool app_libc_try_tcsetattr(int fd, const struct termios* t, int* out_result);
/** Signal numbers an app can register a handler for are 1 to APP_LIBC_SIGNAL_COUNT - 1. */
#define APP_LIBC_SIGNAL_COUNT 32
typedef void (*AppLibcSignalHandler)(int sig);
/**
* Records @a handler for @a sig in the calling app instance, called when a signal is delivered (see
* app/signal.h). SIGKILL, SIGSTOP and out-of-range signals fail with EINVAL.
* @param[out] out_previous the previously registered handler, or SIG_ERR on failure
*/
bool app_libc_try_signal(int sig, AppLibcSignalHandler handler, AppLibcSignalHandler* out_previous);
/**
* Sends @a sig to the app instance @a pid via app_signal_send(), never to the process.
* A @a sig of 0 only checks that @a pid exists. SIGKILL, SIGSTOP and out-of-range signals fail
* with EINVAL. A @a pid that is not a running app instance fails with ESRCH, including pid <= 0,
* since there are no process groups.
*/
bool app_libc_try_kill(int pid, int sig, int* out_result);
/** The calling app instance's AppInstanceId. */
bool app_libc_try_getpid(int* out_result);
/** The AppInstanceId of the calling app instance's parent, or 0 for a top-level launch. */
bool app_libc_try_getppid(int* out_result);
/** Sleeps the calling app instance. Fails with EINTR when a signal is pending or arrives (see app/signal.h). */
bool app_libc_try_usleep(unsigned long usec, int* out_result);
/**
* Sleeps the calling app instance. Returns early when a signal is pending or arrives (see app/signal.h).
* @param[out] out_result the whole seconds not slept, 0 when not interrupted
*/
bool app_libc_try_sleep(unsigned int seconds, unsigned int* out_result);
typedef int (*AppLibcPollFunction)(struct pollfd* fds, nfds_t nfds, int timeout);
/**
* Handles poll() when @a fds contains an app fd. Other fds are checked with @a real_poll.
* Closed app fds report POLLNVAL. Fails with EINTR when a signal is pending (see app/signal.h).
*/
bool app_libc_try_poll(struct pollfd* fds, nfds_t nfds, int timeout, AppLibcPollFunction real_poll, int* out_result);
#ifdef __cplusplus
}
#endif