Skip to main content

addfd

Function addfd 

Source
pub fn addfd(
    forked: i32,
    save: &mut [i32; 10],
    mfds: &mut [Option<Box<multio>>; 10],
    fd1: i32,
    fd2: i32,
    rflag: i32,
    varid: Option<&str>,
)
Expand description

Port of static void addfd(int forked, int *save, struct multio **mfds, int fd1, int fd2, int rflag, char *varid) from Src/exec.c:2397.

C body (~100 lines, three branches):

if (varid) {
    /* {varid}>file form — move fd above 10 and bind $varid to it */
} else if (!mfds[fd1] || unset(MULTIOS)) {
    /* new multio OR MULTIOS off — first redir on this fd */
} else {
    /* additional redir on a fd that's already a multio (split or extend) */
}

Register fd2 (already-open) as a redirection target for fd1. Three branches: varid writes the moved fd to $varid and bumps fdtable[fd1] = FDT_EXTERNAL; new-multio path saves the original fd1 (when !forked) and stamps mfds[fd1] as a single-entry struct; extend-multio path either splits a ct=1 stream into a pipe + 2 fds via mpipe, or appends another fd to an already-split stream (re-allocating mfds for fd1 past the MULTIOUNIT boundary).

multio.fds is now Vec<i32> (zsh_h.rs:1397) so the C hrealloc at c:2485 maps to Vec::push; MULTIOUNIT is no longer a hard cap (still 8 for the initial allocation, grown on demand thereafter).

fdtable[fdN] |= FDT_SAVED_MASK at c:2440 — Rust fdtable_set stores the int value but doesn’t expose a bitwise-OR setter; we re-read + OR + re-store as two atomic-feeling steps.