14bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev/* 24bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev * Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved. 34bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev * 44bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev * This program is free software; you can redistribute it and/or 54bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev * modify it under the terms of the GNU General Public License as 64bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev * published by the Free Software Foundation; either version 2 of 74bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev * the License, or (at your option) any later version. 84bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev * 94bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev * This program is distributed in the hope that it would be useful, 104bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev * but WITHOUT ANY WARRANTY; without even the implied warranty of 114bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 124bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev * GNU General Public License for more details. 134bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev * 144bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev * You should have received a copy of the GNU General Public License 154bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev * along with this program; if not, write the Free Software Foundation, 164bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 174bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev * 184bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev * Author: Alexey Kodanev <alexey.kodanev@oracle.com> 194bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev * 204bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev */ 214bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev 22bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh#include <errno.h> 234bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev#include <sys/types.h> 24bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh#include <sys/stat.h> 254bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev#include <sys/wait.h> 26bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh#include <fcntl.h> 274bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev#include <unistd.h> 28989d3063aee442c001fac7a61dc6f1b0e9050768Cyril Hrubis#include <signal.h> 294bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev#include "test.h" 304bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev 31bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh#define OPEN_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) 32bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh#define OPEN_FLAGS (O_WRONLY | O_APPEND | O_CREAT) 33bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh 34bbdb9f78378c7e038f463efa39d2470e1c51ad54Cyril Hrubisint tst_run_cmd_fds_(void (cleanup_fn)(void), 35e63337a09474e594900efab91d1a3fc7fa332f2eStanislav Kholmanskikh const char *const argv[], 36bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh int stdout_fd, 37a648a4d00896726b2bd4e7eb914f8955fe225595Stanislav Kholmanskikh int stderr_fd, 38a648a4d00896726b2bd4e7eb914f8955fe225595Stanislav Kholmanskikh int pass_exit_val) 394bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev{ 40a648a4d00896726b2bd4e7eb914f8955fe225595Stanislav Kholmanskikh int rc; 41a648a4d00896726b2bd4e7eb914f8955fe225595Stanislav Kholmanskikh 424bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev if (argv == NULL || argv[0] == NULL) { 434bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev tst_brkm(TBROK, cleanup_fn, 444bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev "argument list is empty at %s:%d", __FILE__, __LINE__); 454bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev } 464bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev 47989d3063aee442c001fac7a61dc6f1b0e9050768Cyril Hrubis /* 48989d3063aee442c001fac7a61dc6f1b0e9050768Cyril Hrubis * The tst_sig() install poisoned signal handlers for all signals the 49989d3063aee442c001fac7a61dc6f1b0e9050768Cyril Hrubis * test is not expected to get. 50989d3063aee442c001fac7a61dc6f1b0e9050768Cyril Hrubis * 51989d3063aee442c001fac7a61dc6f1b0e9050768Cyril Hrubis * So we temporarily disable the handler for sigchild we get after our 52989d3063aee442c001fac7a61dc6f1b0e9050768Cyril Hrubis * child exits so that we don't have to disable it in each test that 53989d3063aee442c001fac7a61dc6f1b0e9050768Cyril Hrubis * uses this interface. 54989d3063aee442c001fac7a61dc6f1b0e9050768Cyril Hrubis */ 55989d3063aee442c001fac7a61dc6f1b0e9050768Cyril Hrubis void *old_handler = signal(SIGCHLD, SIG_DFL); 56989d3063aee442c001fac7a61dc6f1b0e9050768Cyril Hrubis 574bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev pid_t pid = vfork(); 584bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev if (pid == -1) { 594bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev tst_brkm(TBROK | TERRNO, cleanup_fn, "vfork failed at %s:%d", 604bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev __FILE__, __LINE__); 614bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev } 62bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh if (!pid) { 63bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh /* redirecting stdout and stderr if needed */ 64bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh if (stdout_fd != -1) { 65bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh close(STDOUT_FILENO); 66bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh dup2(stdout_fd, STDOUT_FILENO); 67bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh } 68bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh 69bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh if (stderr_fd != -1) { 70bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh close(STDERR_FILENO); 71bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh dup2(stderr_fd, STDERR_FILENO); 72bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh } 73bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh 743d2deae3a823b33d5d6886f3ee0565329407af7fCyril Hrubis if (execvp(argv[0], (char *const *)argv)) { 753d2deae3a823b33d5d6886f3ee0565329407af7fCyril Hrubis if (errno == ENOENT) 763d2deae3a823b33d5d6886f3ee0565329407af7fCyril Hrubis _exit(255); 773d2deae3a823b33d5d6886f3ee0565329407af7fCyril Hrubis } 783d2deae3a823b33d5d6886f3ee0565329407af7fCyril Hrubis _exit(254); 79bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh } 804bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev 814bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev int ret = -1; 824bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev if (waitpid(pid, &ret, 0) != pid) { 83989d3063aee442c001fac7a61dc6f1b0e9050768Cyril Hrubis tst_brkm(TBROK | TERRNO, cleanup_fn, "waitpid failed at %s:%d", 844bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev __FILE__, __LINE__); 854bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev } 864bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev 87989d3063aee442c001fac7a61dc6f1b0e9050768Cyril Hrubis signal(SIGCHLD, old_handler); 88989d3063aee442c001fac7a61dc6f1b0e9050768Cyril Hrubis 89a648a4d00896726b2bd4e7eb914f8955fe225595Stanislav Kholmanskikh if (!WIFEXITED(ret)) { 904bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev tst_brkm(TBROK, cleanup_fn, "failed to exec cmd '%s' at %s:%d", 914bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev argv[0], __FILE__, __LINE__); 924bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev } 93a648a4d00896726b2bd4e7eb914f8955fe225595Stanislav Kholmanskikh 94a648a4d00896726b2bd4e7eb914f8955fe225595Stanislav Kholmanskikh rc = WEXITSTATUS(ret); 95a648a4d00896726b2bd4e7eb914f8955fe225595Stanislav Kholmanskikh 96a648a4d00896726b2bd4e7eb914f8955fe225595Stanislav Kholmanskikh if ((!pass_exit_val) && rc) 97a648a4d00896726b2bd4e7eb914f8955fe225595Stanislav Kholmanskikh tst_brkm(TBROK, cleanup_fn, 98a648a4d00896726b2bd4e7eb914f8955fe225595Stanislav Kholmanskikh "'%s' exited with a non-zero code %d at %s:%d", 99a648a4d00896726b2bd4e7eb914f8955fe225595Stanislav Kholmanskikh argv[0], rc, __FILE__, __LINE__); 100a648a4d00896726b2bd4e7eb914f8955fe225595Stanislav Kholmanskikh 101a648a4d00896726b2bd4e7eb914f8955fe225595Stanislav Kholmanskikh return rc; 1024bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev} 103bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh 104bbdb9f78378c7e038f463efa39d2470e1c51ad54Cyril Hrubisint tst_run_cmd_(void (cleanup_fn)(void), 105e63337a09474e594900efab91d1a3fc7fa332f2eStanislav Kholmanskikh const char *const argv[], 106bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh const char *stdout_path, 107a648a4d00896726b2bd4e7eb914f8955fe225595Stanislav Kholmanskikh const char *stderr_path, 108a648a4d00896726b2bd4e7eb914f8955fe225595Stanislav Kholmanskikh int pass_exit_val) 109bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh{ 110bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh int stdout_fd = -1; 111bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh int stderr_fd = -1; 112a648a4d00896726b2bd4e7eb914f8955fe225595Stanislav Kholmanskikh int rc; 113bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh 114bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh if (stdout_path != NULL) { 115bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh stdout_fd = open(stdout_path, 116bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh OPEN_FLAGS, OPEN_MODE); 117bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh 118bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh if (stdout_fd == -1) 119bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh tst_resm(TWARN | TERRNO, 120bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh "open() on %s failed at %s:%d", 121bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh stdout_path, __FILE__, __LINE__); 122bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh } 123bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh 124bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh if (stderr_path != NULL) { 125bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh stderr_fd = open(stderr_path, 126bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh OPEN_FLAGS, OPEN_MODE); 127bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh 128bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh if (stderr_fd == -1) 129bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh tst_resm(TWARN | TERRNO, 130bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh "open() on %s failed at %s:%d", 131bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh stderr_path, __FILE__, __LINE__); 132bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh } 133bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh 134a648a4d00896726b2bd4e7eb914f8955fe225595Stanislav Kholmanskikh rc = tst_run_cmd_fds(cleanup_fn, argv, stdout_fd, stderr_fd, 135a648a4d00896726b2bd4e7eb914f8955fe225595Stanislav Kholmanskikh pass_exit_val); 136bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh 137bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh if ((stdout_fd != -1) && (close(stdout_fd) == -1)) 138bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh tst_resm(TWARN | TERRNO, 139bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh "close() on %s failed at %s:%d", 140bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh stdout_path, __FILE__, __LINE__); 141bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh 142bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh if ((stderr_fd != -1) && (close(stderr_fd) == -1)) 143bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh tst_resm(TWARN | TERRNO, 144bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh "close() on %s failed at %s:%d", 145bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh stderr_path, __FILE__, __LINE__); 146a648a4d00896726b2bd4e7eb914f8955fe225595Stanislav Kholmanskikh 147a648a4d00896726b2bd4e7eb914f8955fe225595Stanislav Kholmanskikh return rc; 148bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh} 149a83cbb8ce3db1a0c0bc90dafa669a97bb5632768George Wang 150a83cbb8ce3db1a0c0bc90dafa669a97bb5632768George Wangint tst_system(const char *command) 151a83cbb8ce3db1a0c0bc90dafa669a97bb5632768George Wang{ 152a83cbb8ce3db1a0c0bc90dafa669a97bb5632768George Wang int ret = 0; 153a83cbb8ce3db1a0c0bc90dafa669a97bb5632768George Wang 154a83cbb8ce3db1a0c0bc90dafa669a97bb5632768George Wang /* 155a83cbb8ce3db1a0c0bc90dafa669a97bb5632768George Wang *Temporarily disable SIGCHLD of user defined handler, so the 156a83cbb8ce3db1a0c0bc90dafa669a97bb5632768George Wang *system(3) function will not cause unexpected SIGCHLD signal 157a83cbb8ce3db1a0c0bc90dafa669a97bb5632768George Wang *callback function for test cases. 158a83cbb8ce3db1a0c0bc90dafa669a97bb5632768George Wang */ 159a83cbb8ce3db1a0c0bc90dafa669a97bb5632768George Wang void *old_handler = signal(SIGCHLD, SIG_DFL); 160a83cbb8ce3db1a0c0bc90dafa669a97bb5632768George Wang 161a83cbb8ce3db1a0c0bc90dafa669a97bb5632768George Wang ret = system(command); 162a83cbb8ce3db1a0c0bc90dafa669a97bb5632768George Wang 163a83cbb8ce3db1a0c0bc90dafa669a97bb5632768George Wang signal(SIGCHLD, old_handler); 164a83cbb8ce3db1a0c0bc90dafa669a97bb5632768George Wang return ret; 165a83cbb8ce3db1a0c0bc90dafa669a97bb5632768George Wang} 166