Repository: SerenityOS/serenity
File: Userland/Libraries/LibC/spawn.cpp (C++)

Code before:
            }
        }

        // FIXME: POSIX_SPAWN_SETSCHEDULER
    }

    if (file_actions) {
        for (auto const& action : file_actions->state->actions) {
            if (action() < 0) {
                perror("posix_spawn file action");
                _exit(127);
            }
        }
    }

    exec(path, argv, envp);
    perror("posix_spawn exec");
    _exit(127);
}

extern "C" int posix_spawn_syscall(
    pid_t* out_pid,
    char const* path,
    char* const argv[],
    char* const envp[])
{
    if (!path || !argv || !argv[0])
        return EINVAL;

    Syscall::SC_posix_spawn_params posix_spawn_params;

    // 1. Prepare path (Syscall::StringArgument)
    posix_spawn_params.path.characters = path;
    posix_spawn_params.path.length = strlen(path);

    // 2. Prepare argv (Syscall::StringListArgument)
    //    This requires iterating argv, calling strlen on each, and storing them in a
    //    temporary array of Syscall::StringArgument.
    Vector<Syscall::StringArgument, 32> argv_string_args; // Max 32 args for temp buffer
    size_t argc = 0;
    for (argc = 0; argv[argc] != nullptr; ++argc) {
        if (argc >= argv_string_args.capacity()) { // Or a saner general limit
            // E2BIG if too many arguments for our temporary buffer or system limits
            return E2BIG;
        }
        argv_string_args.unchecked_append({ argv[argc], strlen(argv[argc]) });
    }
    posix_spawn_params.arguments.strings = argv_string_args.is_empty() ? nullptr : argv_string_args.data();
    posix_spawn_params.arguments.length = argv_string_args.size();

    // 3. Prepare envp (Syscall::StringListArgument)

Review comment (suggestion):
The `extern "C"` should be unnecessary. This code is already wrapped in an `extern "C"` block. But do we even want this function to be public? I would rather make this a `static` implementation detail.

Also, we typically don't format argument lists like this. Please keep them in one line.

Code after:
            }
        }

        // FIXME: POSIX_SPAWN_SETSCHEDULER
    }

    if (file_actions) {
        for (auto const& action : file_actions->state->actions) {
            if (action() < 0) {
                perror("posix_spawn file action");
                _exit(127);
            }
        }
    }

    exec(path, argv, envp);
    perror("posix_spawn exec");
    _exit(127);
}

static ErrorOr<pid_t> posix_spawn_syscall(char const* path, char* const argv[], char* const envp[])
{
    if (!path || !argv || !argv[0])
        return EINVAL;

    Syscall::SC_posix_spawn_params posix_spawn_params;

    posix_spawn_params.path.characters = path;
    posix_spawn_params.path.length = strlen(path);

    Vector<Syscall::StringArgument, 32> argv_string_args;
    for (size_t argc = 0; argv[argc] != nullptr; ++argc)
        TRY(argv_string_args.try_append({ argv[argc], strlen(argv[argc]) }));

    posix_spawn_params.arguments.strings = argv_string_args.is_empty() ? nullptr : argv_string_args.data();
    posix_spawn_params.arguments.length = argv_string_args.size();

    Vector<Syscall::StringArgument, 32> envp_string_args;
    if (envp) {
        for (size_t envc = 0; envp[envc] != nullptr; ++envc)
            TRY(envp_string_args.try_append({ envp[envc], strlen(envp[envc]) }));
    }

    posix_spawn_params.environment.strings = envp_string_args.is_empty() ? nullptr : envp_string_args.data();
    posix_spawn_params.environment.length = envp_string_args.size();

    posix_spawn_params.attr_data = nullptr;
    posix_spawn_params.attr_data_size = 0;

    posix_spawn_params.serialized_file_actions_data = nullptr;
    posix_spawn_params.serialized_file_actions_data_size = 0;