tst_run_cmd.c revision e63337a09474e594900efab91d1a3fc7fa332f2e
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>
284bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev#include "test.h"
294bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev
30bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh#define OPEN_MODE	(S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
31bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh#define OPEN_FLAGS	(O_WRONLY | O_APPEND | O_CREAT)
32bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh
33bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikhvoid tst_run_cmd_fds(void (cleanup_fn)(void),
34e63337a09474e594900efab91d1a3fc7fa332f2eStanislav Kholmanskikh		const char *const argv[],
35bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh		int stdout_fd,
36bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh		int stderr_fd)
374bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev{
384bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev	if (argv == NULL || argv[0] == NULL) {
394bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev		tst_brkm(TBROK, cleanup_fn,
404bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev			"argument list is empty at %s:%d", __FILE__, __LINE__);
414bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev	}
424bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev
434bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev	pid_t pid = vfork();
444bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev	if (pid == -1) {
454bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev		tst_brkm(TBROK | TERRNO, cleanup_fn, "vfork failed at %s:%d",
464bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev			__FILE__, __LINE__);
474bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev	}
48bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh	if (!pid) {
49bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh		/* redirecting stdout and stderr if needed */
50bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh		if (stdout_fd != -1) {
51bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh			close(STDOUT_FILENO);
52bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh			dup2(stdout_fd, STDOUT_FILENO);
53bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh		}
54bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh
55bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh		if (stderr_fd != -1) {
56bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh			close(STDERR_FILENO);
57bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh			dup2(stderr_fd, STDERR_FILENO);
58bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh		}
59bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh
60e63337a09474e594900efab91d1a3fc7fa332f2eStanislav Kholmanskikh		_exit(execvp(argv[0], (char *const *)argv));
61bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh	}
624bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev
634bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev	int ret = -1;
644bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev	if (waitpid(pid, &ret, 0) != pid) {
654bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev		tst_brkm(TBROK, cleanup_fn, "waitpid failed at %s:%d",
664bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev			__FILE__, __LINE__);
674bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev	}
684bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev
694bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev	if (!WIFEXITED(ret) || WEXITSTATUS(ret) != 0) {
704bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev		tst_brkm(TBROK, cleanup_fn, "failed to exec cmd '%s' at %s:%d",
714bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev			argv[0], __FILE__, __LINE__);
724bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev	}
734bc55ecaa76244f3ba28a91f4fb8b3dac9c744acAlexey Kodanev}
74bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh
75bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikhvoid tst_run_cmd(void (cleanup_fn)(void),
76e63337a09474e594900efab91d1a3fc7fa332f2eStanislav Kholmanskikh		const char *const argv[],
77bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh		const char *stdout_path,
78bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh		const char *stderr_path)
79bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh{
80bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh	int stdout_fd = -1;
81bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh	int stderr_fd = -1;
82bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh
83bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh	if (stdout_path != NULL) {
84bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh		stdout_fd = open(stdout_path,
85bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh				OPEN_FLAGS, OPEN_MODE);
86bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh
87bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh		if (stdout_fd == -1)
88bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh			tst_resm(TWARN | TERRNO,
89bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh				"open() on %s failed at %s:%d",
90bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh				stdout_path, __FILE__, __LINE__);
91bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh	}
92bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh
93bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh	if (stderr_path != NULL) {
94bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh		stderr_fd = open(stderr_path,
95bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh				OPEN_FLAGS, OPEN_MODE);
96bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh
97bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh		if (stderr_fd == -1)
98bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh			tst_resm(TWARN | TERRNO,
99bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh				"open() on %s failed at %s:%d",
100bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh				stderr_path, __FILE__, __LINE__);
101bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh	}
102bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh
103bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh	tst_run_cmd_fds(cleanup_fn, argv, stdout_fd, stderr_fd);
104bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh
105bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh	if ((stdout_fd != -1) && (close(stdout_fd) == -1))
106bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh		tst_resm(TWARN | TERRNO,
107bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh			"close() on %s failed at %s:%d",
108bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh			stdout_path, __FILE__, __LINE__);
109bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh
110bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh	if ((stderr_fd != -1) && (close(stderr_fd) == -1))
111bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh		tst_resm(TWARN | TERRNO,
112bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh			"close() on %s failed at %s:%d",
113bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh			stderr_path, __FILE__, __LINE__);
114bee0a9469641d3cc8d29853abb4ba10883b30ba6Stanislav kholmanskikh}
115