Path: blob/main/lib/libc/tests/gen/posix_spawn_test.c
39491 views
/*-1* Copyright (c) 2011 Jilles Tjoelker2* All rights reserved.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12*13* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND14* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE15* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE16* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE17* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL18* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS19* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)20* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT21* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY22* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF23* SUCH DAMAGE.24*/2526/*27* Test program for posix_spawn() and posix_spawnp() as specified by28* IEEE Std. 1003.1-2008.29*/3031#include <sys/param.h>32#include <sys/stat.h>33#include <sys/wait.h>34#include <errno.h>35#include <fcntl.h>36#include <stdio.h>37#include <stdlib.h>38#include <string.h>39#include <spawn.h>4041#include <atf-c.h>4243static const char true_script[] =44"#!/usr/bin/env\n"45"/usr/bin/true\n";4647char *myenv[2] = { "answer=42", NULL };4849ATF_TC_WITHOUT_HEAD(posix_spawn_simple_test);50ATF_TC_BODY(posix_spawn_simple_test, tc)51{52char *myargs[4];53int error, status;54pid_t pid, waitres;5556/* Make sure we have no child processes. */57while (waitpid(-1, NULL, 0) != -1)58;59ATF_REQUIRE_MSG(errno == ECHILD, "errno was not ECHILD: %d", errno);6061/* Simple test. */62myargs[0] = "sh";63myargs[1] = "-c";64myargs[2] = "exit $answer";65myargs[3] = NULL;66error = posix_spawnp(&pid, myargs[0], NULL, NULL, myargs, myenv);67ATF_REQUIRE(error == 0);68waitres = waitpid(pid, &status, 0);69ATF_REQUIRE(waitres == pid);70ATF_REQUIRE(WIFEXITED(status) && WEXITSTATUS(status) == 42);71}7273ATF_TC_WITHOUT_HEAD(posix_spawn_no_such_command_negative_test);74ATF_TC_BODY(posix_spawn_no_such_command_negative_test, tc)75{76char *myargs[4];77int error, status;78pid_t pid, waitres;7980/*81* If the executable does not exist, the function shall either fail82* and not create a child process or succeed and create a child83* process that exits with status 127.84*/85myargs[0] = "/var/empty/nonexistent";86myargs[1] = NULL;87error = posix_spawn(&pid, myargs[0], NULL, NULL, myargs, myenv);88if (error == 0) {89waitres = waitpid(pid, &status, 0);90ATF_REQUIRE(waitres == pid);91ATF_REQUIRE(WIFEXITED(status) && WEXITSTATUS(status) == 127);92} else {93ATF_REQUIRE(error == ENOENT);94waitres = waitpid(-1, NULL, 0);95ATF_REQUIRE(waitres == -1 && errno == ECHILD);96}97}9899ATF_TC_WITHOUT_HEAD(posix_spawnp_enoexec_fallback);100ATF_TC_BODY(posix_spawnp_enoexec_fallback, tc)101{102char buf[FILENAME_MAX];103char *myargs[2];104int error, status;105pid_t pid, waitres;106107snprintf(buf, sizeof(buf), "%s/spawnp_enoexec.sh",108atf_tc_get_config_var(tc, "srcdir"));109myargs[0] = buf;110myargs[1] = NULL;111error = posix_spawnp(&pid, myargs[0], NULL, NULL, myargs, myenv);112ATF_REQUIRE(error == 0);113waitres = waitpid(pid, &status, 0);114ATF_REQUIRE(waitres == pid);115ATF_REQUIRE(WIFEXITED(status) && WEXITSTATUS(status) == 42);116}117118ATF_TC_WITHOUT_HEAD(posix_spawnp_enoexec_fallback_null_argv0);119ATF_TC_BODY(posix_spawnp_enoexec_fallback_null_argv0, tc)120{121char buf[FILENAME_MAX];122char *myargs[1];123int error;124pid_t pid;125126snprintf(buf, sizeof(buf), "%s/spawnp_enoexec.sh",127atf_tc_get_config_var(tc, "srcdir"));128myargs[0] = NULL;129error = posix_spawnp(&pid, buf, NULL, NULL, myargs, myenv);130ATF_REQUIRE(error == EINVAL);131}132133ATF_TC(posix_spawnp_eacces);134ATF_TC_HEAD(posix_spawnp_eacces, tc)135{136atf_tc_set_md_var(tc, "descr", "Verify EACCES behavior in posix_spawnp");137atf_tc_set_md_var(tc, "require.user", "unprivileged");138}139ATF_TC_BODY(posix_spawnp_eacces, tc)140{141const struct spawnp_eacces_tc {142const char *pathvar;143int error_expected;144} spawnp_eacces_tests[] = {145{ ".", EACCES }, /* File exists, but not +x */146{ "unsearchable", ENOENT }, /* File exists, dir not +x */147};148char *myargs[2] = { "eacces", NULL };149int error;150151error = mkdir("unsearchable", 0755);152ATF_REQUIRE(error == 0);153error = symlink("/usr/bin/true", "unsearchable/eacces");154ATF_REQUIRE(error == 0);155156(void)chmod("unsearchable", 0444);157158/* this will create a non-executable file */159atf_utils_create_file("eacces", true_script);160161for (size_t i = 0; i < nitems(spawnp_eacces_tests); i++) {162const struct spawnp_eacces_tc *tc = &spawnp_eacces_tests[i];163pid_t pid;164165error = setenv("PATH", tc->pathvar, 1);166ATF_REQUIRE_EQ(0, error);167168error = posix_spawnp(&pid, myargs[0], NULL, NULL, myargs,169myenv);170ATF_CHECK_INTEQ_MSG(tc->error_expected, error,171"path '%s'", tc->pathvar);172}173}174175ATF_TP_ADD_TCS(tp)176{177178ATF_TP_ADD_TC(tp, posix_spawn_simple_test);179ATF_TP_ADD_TC(tp, posix_spawn_no_such_command_negative_test);180ATF_TP_ADD_TC(tp, posix_spawnp_enoexec_fallback);181ATF_TP_ADD_TC(tp, posix_spawnp_enoexec_fallback_null_argv0);182ATF_TP_ADD_TC(tp, posix_spawnp_eacces);183184return (atf_no_error());185}186187188