mirror of
https://github.com/openai/codex.git
synced 2026-09-15 12:08:01 +00:00
build(zsh): add patched zsh build script and wrapper origin patch
This commit is contained in:
126
scripts/build-patched-zsh.sh
Executable file
126
scripts/build-patched-zsh.sh
Executable file
@@ -0,0 +1,126 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Build the Codex-patched zsh used by shell-tool-mcp.
|
||||
#
|
||||
# Defaults are intentionally override-friendly:
|
||||
# CODEX_REPO Codex repo root containing shell-tool-mcp/patches
|
||||
# ZSH_SRC_DIR Working clone location for zsh source
|
||||
# INSTALL_PREFIX Install prefix for make install
|
||||
# JOBS Parallel jobs for make
|
||||
# ZSH_REMOTE Upstream zsh remote
|
||||
# INSTALL_DOCS Set to 1 to run full `make install` (includes manpages)
|
||||
|
||||
ZSH_COMMIT="77045ef899e53b9598bebc5a41db93a548a40ca6"
|
||||
ZSH_REMOTE="${ZSH_REMOTE:-https://git.code.sf.net/p/zsh/code}"
|
||||
INSTALL_PREFIX="${INSTALL_PREFIX:-$HOME/.local/codex-zsh-${ZSH_COMMIT:0:7}}"
|
||||
|
||||
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
resolve_codex_repo() {
|
||||
if [[ -n "${CODEX_REPO:-}" ]]; then
|
||||
printf '%s\n' "$CODEX_REPO"
|
||||
return
|
||||
fi
|
||||
|
||||
# Most reliable when this script is run from inside the codex repo.
|
||||
local from_script
|
||||
from_script="$(cd -- "$SCRIPT_DIR/.." && pwd)"
|
||||
if [[ -f "$from_script/shell-tool-mcp/patches/zsh-exec-wrapper.patch" ]]; then
|
||||
printf '%s\n' "$from_script"
|
||||
return
|
||||
fi
|
||||
|
||||
# Common local workspace layouts.
|
||||
if [[ -f "$HOME/repos/codex/shell-tool-mcp/patches/zsh-exec-wrapper.patch" ]]; then
|
||||
printf '%s\n' "$HOME/repos/codex"
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ -f "$HOME/code/codex/shell-tool-mcp/patches/zsh-exec-wrapper.patch" ]]; then
|
||||
printf '%s\n' "$HOME/code/codex"
|
||||
return
|
||||
fi
|
||||
|
||||
echo "Could not locate codex repo. Set CODEX_REPO=/path/to/codex." >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
resolve_zsh_src_dir() {
|
||||
if [[ -n "${ZSH_SRC_DIR:-}" ]]; then
|
||||
printf '%s\n' "$ZSH_SRC_DIR"
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ -d "$HOME/repos/zsh/.git" ]]; then
|
||||
printf '%s\n' "$HOME/repos/zsh"
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ -d "$HOME/code/zsh/.git" ]]; then
|
||||
printf '%s\n' "$HOME/code/zsh"
|
||||
return
|
||||
fi
|
||||
|
||||
# Fallback for users without an existing clone.
|
||||
printf '%s\n' "$HOME/src/zsh-code"
|
||||
}
|
||||
|
||||
CODEX_REPO="$(resolve_codex_repo)"
|
||||
ZSH_SRC_DIR="$(resolve_zsh_src_dir)"
|
||||
PATCH_FILE="$CODEX_REPO/shell-tool-mcp/patches/zsh-exec-wrapper.patch"
|
||||
|
||||
if [[ ! -f "$PATCH_FILE" ]]; then
|
||||
echo "Patch file not found: $PATCH_FILE" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z "${JOBS:-}" ]]; then
|
||||
if command -v nproc >/dev/null 2>&1; then
|
||||
JOBS="$(nproc)"
|
||||
elif command -v sysctl >/dev/null 2>&1; then
|
||||
JOBS="$(sysctl -n hw.ncpu)"
|
||||
else
|
||||
JOBS=4
|
||||
fi
|
||||
fi
|
||||
|
||||
mkdir -p "$(dirname -- "$ZSH_SRC_DIR")"
|
||||
|
||||
if [[ ! -d "$ZSH_SRC_DIR/.git" ]]; then
|
||||
git clone "$ZSH_REMOTE" "$ZSH_SRC_DIR"
|
||||
fi
|
||||
|
||||
git -C "$ZSH_SRC_DIR" fetch --depth 1 origin "$ZSH_COMMIT"
|
||||
git -C "$ZSH_SRC_DIR" checkout --detach -f "$ZSH_COMMIT"
|
||||
git -C "$ZSH_SRC_DIR" reset --hard "$ZSH_COMMIT"
|
||||
|
||||
if git -C "$ZSH_SRC_DIR" apply --reverse --check "$PATCH_FILE" >/dev/null 2>&1; then
|
||||
echo "Patch already applied: $PATCH_FILE"
|
||||
else
|
||||
git -C "$ZSH_SRC_DIR" apply --check "$PATCH_FILE"
|
||||
git -C "$ZSH_SRC_DIR" apply "$PATCH_FILE"
|
||||
fi
|
||||
|
||||
(
|
||||
cd "$ZSH_SRC_DIR"
|
||||
./Util/preconfig
|
||||
./configure --prefix="$INSTALL_PREFIX"
|
||||
make -j"$JOBS"
|
||||
if [[ "${INSTALL_DOCS:-0}" == "1" ]]; then
|
||||
make install
|
||||
else
|
||||
make install.bin
|
||||
fi
|
||||
)
|
||||
|
||||
cat <<OUT
|
||||
|
||||
Built patched zsh successfully.
|
||||
Binary:
|
||||
$INSTALL_PREFIX/bin/zsh
|
||||
|
||||
Quick checks:
|
||||
$INSTALL_PREFIX/bin/zsh --version
|
||||
$INSTALL_PREFIX/bin/zsh -fc '/bin/echo smoke-zsh'
|
||||
OUT
|
||||
@@ -1,34 +1,228 @@
|
||||
diff --git a/Src/exec.c b/Src/exec.c
|
||||
index 27bca11..baea760 100644
|
||||
index 27bca110c..c1770f6d2 100644
|
||||
--- a/Src/exec.c
|
||||
+++ b/Src/exec.c
|
||||
@@ -507,7 +507,9 @@ zexecve(char *pth, char **argv, char **newenvp)
|
||||
@@ -507,7 +507,12 @@ zexecve(char *pth, char **argv, char **newenvp)
|
||||
{
|
||||
int eno;
|
||||
static char buf[PATH_MAX * 2+1];
|
||||
- char **eep;
|
||||
+ char **eep, **exec_argv;
|
||||
+ char **eep, **exec_argv, **wrapper_envp;
|
||||
+ char *orig_pth = pth;
|
||||
+ char *exec_wrapper;
|
||||
+ char wrapper_origin_buf[64];
|
||||
+ int wrapper_origin_len;
|
||||
+ int wrapper_envc, wrapper_origin_idx;
|
||||
|
||||
unmetafy(pth, NULL);
|
||||
for (eep = argv; *eep; eep++)
|
||||
@@ -526,8 +528,17 @@ zexecve(char *pth, char **argv, char **newenvp)
|
||||
@@ -526,8 +531,51 @@ zexecve(char *pth, char **argv, char **newenvp)
|
||||
|
||||
if (newenvp == NULL)
|
||||
newenvp = environ;
|
||||
+ exec_argv = argv;
|
||||
+ /* Use the command env by default; wrapper mode may replace this with an
|
||||
+ * explicitly rebuilt envp so origin metadata is guaranteed to be present
|
||||
+ * even when execve does not use the process-global environ. */
|
||||
+ wrapper_envp = newenvp;
|
||||
+ if ((exec_wrapper = getenv("EXEC_WRAPPER")) &&
|
||||
+ *exec_wrapper && !inblank(*exec_wrapper)) {
|
||||
+ /* zexecve callers provide spare argv slots before argv[0] for
|
||||
+ * interpreter dispatch; reuse those slots to trampoline through the
|
||||
+ * wrapper binary while preserving the original target path. */
|
||||
+ exec_argv = argv - 2;
|
||||
+ exec_argv[0] = exec_wrapper;
|
||||
+ exec_argv[1] = orig_pth;
|
||||
+ wrapper_origin_len = sprintf(wrapper_origin_buf,
|
||||
+ "CODEX_ZSH_SIDECAR_WRAPPER_ORIGIN=%d",
|
||||
+ zsh_exec_wrapper_origin);
|
||||
+ if (wrapper_origin_len > 0 &&
|
||||
+ wrapper_origin_len < (int)sizeof(wrapper_origin_buf)) {
|
||||
+ wrapper_envc = 0;
|
||||
+ wrapper_origin_idx = -1;
|
||||
+ for (eep = newenvp; *eep; eep++) {
|
||||
+ if (strncmp(*eep, "CODEX_ZSH_SIDECAR_WRAPPER_ORIGIN=",
|
||||
+ sizeof("CODEX_ZSH_SIDECAR_WRAPPER_ORIGIN=") - 1) == 0)
|
||||
+ wrapper_origin_idx = wrapper_envc;
|
||||
+ wrapper_envc++;
|
||||
+ }
|
||||
+ wrapper_envp = zalloc((wrapper_envc + 2) * sizeof(char *));
|
||||
+ if (wrapper_origin_idx >= 0) {
|
||||
+ for (wrapper_envc = 0; newenvp[wrapper_envc]; wrapper_envc++)
|
||||
+ wrapper_envp[wrapper_envc] =
|
||||
+ wrapper_envc == wrapper_origin_idx ?
|
||||
+ wrapper_origin_buf : newenvp[wrapper_envc];
|
||||
+ wrapper_envp[wrapper_envc] = NULL;
|
||||
+ } else {
|
||||
+ for (wrapper_envc = 0; newenvp[wrapper_envc]; wrapper_envc++)
|
||||
+ wrapper_envp[wrapper_envc] = newenvp[wrapper_envc];
|
||||
+ wrapper_envp[wrapper_envc++] = wrapper_origin_buf;
|
||||
+ wrapper_envp[wrapper_envc] = NULL;
|
||||
+ }
|
||||
+ }
|
||||
+ pth = exec_wrapper;
|
||||
+ }
|
||||
winch_unblock();
|
||||
- execve(pth, argv, newenvp);
|
||||
+ execve(pth, exec_argv, newenvp);
|
||||
+ execve(pth, exec_argv, wrapper_envp);
|
||||
+ pth = orig_pth;
|
||||
|
||||
/* If the execve returns (which in general shouldn't happen), *
|
||||
* then check for an errno equal to ENOEXEC. This errno is set *
|
||||
diff --git a/Src/init.c b/Src/init.c
|
||||
index 20b8cc7fd..b6d5c9c9a 100644
|
||||
--- a/Src/init.c
|
||||
+++ b/Src/init.c
|
||||
@@ -59,6 +59,9 @@ int underscoreused;
|
||||
/**/
|
||||
int sourcelevel;
|
||||
|
||||
+/**/
|
||||
+int zsh_exec_wrapper_origin = EXEC_WRAPPER_ORIGIN_USER_COMMAND;
|
||||
+
|
||||
/* the shell tty fd */
|
||||
|
||||
/**/
|
||||
@@ -1450,14 +1453,25 @@ init_signals(void)
|
||||
void
|
||||
run_init_scripts(void)
|
||||
{
|
||||
+ int old_origin;
|
||||
+
|
||||
noerrexit = NOERREXIT_EXIT | NOERREXIT_RETURN | NOERREXIT_SIGNAL;
|
||||
+ zsh_exec_wrapper_origin = EXEC_WRAPPER_ORIGIN_USER_COMMAND;
|
||||
|
||||
if (EMULATION(EMULATE_KSH|EMULATE_SH)) {
|
||||
- if (islogin)
|
||||
+ if (islogin) {
|
||||
+ old_origin = zsh_exec_wrapper_origin;
|
||||
+ zsh_exec_wrapper_origin = EXEC_WRAPPER_ORIGIN_LOGIN_STARTUP;
|
||||
source("/etc/profile");
|
||||
+ zsh_exec_wrapper_origin = old_origin;
|
||||
+ }
|
||||
if (unset(PRIVILEGED)) {
|
||||
- if (islogin)
|
||||
+ if (islogin) {
|
||||
+ old_origin = zsh_exec_wrapper_origin;
|
||||
+ zsh_exec_wrapper_origin = EXEC_WRAPPER_ORIGIN_LOGIN_STARTUP;
|
||||
sourcehome(".profile");
|
||||
+ zsh_exec_wrapper_origin = old_origin;
|
||||
+ }
|
||||
|
||||
if (interact) {
|
||||
noerrs = 2;
|
||||
@@ -1467,16 +1481,26 @@ run_init_scripts(void)
|
||||
if (!parsestr(&s)) {
|
||||
singsub(&s);
|
||||
noerrs = 0;
|
||||
+ old_origin = zsh_exec_wrapper_origin;
|
||||
+ zsh_exec_wrapper_origin = EXEC_WRAPPER_ORIGIN_RC_STARTUP;
|
||||
source(s);
|
||||
+ zsh_exec_wrapper_origin = old_origin;
|
||||
}
|
||||
}
|
||||
noerrs = 0;
|
||||
}
|
||||
- } else
|
||||
+ } else {
|
||||
+ old_origin = zsh_exec_wrapper_origin;
|
||||
+ zsh_exec_wrapper_origin = EXEC_WRAPPER_ORIGIN_LOGIN_STARTUP;
|
||||
source("/etc/suid_profile");
|
||||
+ zsh_exec_wrapper_origin = old_origin;
|
||||
+ }
|
||||
} else {
|
||||
#ifdef GLOBAL_ZSHENV
|
||||
+ old_origin = zsh_exec_wrapper_origin;
|
||||
+ zsh_exec_wrapper_origin = EXEC_WRAPPER_ORIGIN_RC_STARTUP;
|
||||
source(GLOBAL_ZSHENV);
|
||||
+ zsh_exec_wrapper_origin = old_origin;
|
||||
#endif
|
||||
|
||||
if (isset(RCS) && unset(PRIVILEGED))
|
||||
@@ -1492,33 +1516,61 @@ run_init_scripts(void)
|
||||
}
|
||||
}
|
||||
|
||||
+ old_origin = zsh_exec_wrapper_origin;
|
||||
+ zsh_exec_wrapper_origin = EXEC_WRAPPER_ORIGIN_RC_STARTUP;
|
||||
sourcehome(".zshenv");
|
||||
+ zsh_exec_wrapper_origin = old_origin;
|
||||
}
|
||||
if (islogin) {
|
||||
#ifdef GLOBAL_ZPROFILE
|
||||
- if (isset(RCS) && isset(GLOBALRCS))
|
||||
+ if (isset(RCS) && isset(GLOBALRCS)) {
|
||||
+ old_origin = zsh_exec_wrapper_origin;
|
||||
+ zsh_exec_wrapper_origin = EXEC_WRAPPER_ORIGIN_LOGIN_STARTUP;
|
||||
source(GLOBAL_ZPROFILE);
|
||||
+ zsh_exec_wrapper_origin = old_origin;
|
||||
+ }
|
||||
#endif
|
||||
- if (isset(RCS) && unset(PRIVILEGED))
|
||||
+ if (isset(RCS) && unset(PRIVILEGED)) {
|
||||
+ old_origin = zsh_exec_wrapper_origin;
|
||||
+ zsh_exec_wrapper_origin = EXEC_WRAPPER_ORIGIN_LOGIN_STARTUP;
|
||||
sourcehome(".zprofile");
|
||||
+ zsh_exec_wrapper_origin = old_origin;
|
||||
+ }
|
||||
}
|
||||
if (interact) {
|
||||
#ifdef GLOBAL_ZSHRC
|
||||
- if (isset(RCS) && isset(GLOBALRCS))
|
||||
+ if (isset(RCS) && isset(GLOBALRCS)) {
|
||||
+ old_origin = zsh_exec_wrapper_origin;
|
||||
+ zsh_exec_wrapper_origin = EXEC_WRAPPER_ORIGIN_RC_STARTUP;
|
||||
source(GLOBAL_ZSHRC);
|
||||
+ zsh_exec_wrapper_origin = old_origin;
|
||||
+ }
|
||||
#endif
|
||||
- if (isset(RCS) && unset(PRIVILEGED))
|
||||
+ if (isset(RCS) && unset(PRIVILEGED)) {
|
||||
+ old_origin = zsh_exec_wrapper_origin;
|
||||
+ zsh_exec_wrapper_origin = EXEC_WRAPPER_ORIGIN_RC_STARTUP;
|
||||
sourcehome(".zshrc");
|
||||
+ zsh_exec_wrapper_origin = old_origin;
|
||||
+ }
|
||||
}
|
||||
if (islogin) {
|
||||
#ifdef GLOBAL_ZLOGIN
|
||||
- if (isset(RCS) && isset(GLOBALRCS))
|
||||
+ if (isset(RCS) && isset(GLOBALRCS)) {
|
||||
+ old_origin = zsh_exec_wrapper_origin;
|
||||
+ zsh_exec_wrapper_origin = EXEC_WRAPPER_ORIGIN_LOGIN_STARTUP;
|
||||
source(GLOBAL_ZLOGIN);
|
||||
+ zsh_exec_wrapper_origin = old_origin;
|
||||
+ }
|
||||
#endif
|
||||
- if (isset(RCS) && unset(PRIVILEGED))
|
||||
+ if (isset(RCS) && unset(PRIVILEGED)) {
|
||||
+ old_origin = zsh_exec_wrapper_origin;
|
||||
+ zsh_exec_wrapper_origin = EXEC_WRAPPER_ORIGIN_LOGIN_STARTUP;
|
||||
sourcehome(".zlogin");
|
||||
+ zsh_exec_wrapper_origin = old_origin;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
+ zsh_exec_wrapper_origin = EXEC_WRAPPER_ORIGIN_USER_COMMAND;
|
||||
noerrexit = 0;
|
||||
nohistsave = 0;
|
||||
}
|
||||
diff --git a/Src/zsh.h b/Src/zsh.h
|
||||
index 5bda04e88..c0750cf45 100644
|
||||
--- a/Src/zsh.h
|
||||
+++ b/Src/zsh.h
|
||||
@@ -2215,6 +2215,14 @@ enum source_return {
|
||||
SOURCE_ERROR = 2
|
||||
};
|
||||
|
||||
+enum exec_wrapper_origin {
|
||||
+ EXEC_WRAPPER_ORIGIN_USER_COMMAND = 0,
|
||||
+ EXEC_WRAPPER_ORIGIN_LOGIN_STARTUP = 1,
|
||||
+ EXEC_WRAPPER_ORIGIN_RC_STARTUP = 2
|
||||
+};
|
||||
+
|
||||
+extern int zsh_exec_wrapper_origin;
|
||||
+
|
||||
enum noerrexit_bits {
|
||||
/* Suppress ERR_EXIT and traps: global */
|
||||
NOERREXIT_EXIT = 1,
|
||||
|
||||
Reference in New Issue
Block a user