From patchwork Thu Apr 20 08:13:45 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Abdiel Janulgue X-Patchwork-Id: 9689837 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id EAFC960326 for ; Thu, 20 Apr 2017 08:15:14 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DAB1E2845C for ; Thu, 20 Apr 2017 08:15:14 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CF68E28464; Thu, 20 Apr 2017 08:15:14 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 5547D2845C for ; Thu, 20 Apr 2017 08:15:14 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 41EA66E32C; Thu, 20 Apr 2017 08:15:13 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga06.intel.com (mga06.intel.com [134.134.136.31]) by gabe.freedesktop.org (Postfix) with ESMTPS id 63B746E0E0 for ; Thu, 20 Apr 2017 08:15:11 +0000 (UTC) Received: from orsmga003.jf.intel.com ([10.7.209.27]) by orsmga104.jf.intel.com with ESMTP; 20 Apr 2017 01:15:11 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.37,225,1488873600"; d="scan'208";a="959064130" Received: from skylake-nuc.fi.intel.com ([10.237.72.145]) by orsmga003.jf.intel.com with ESMTP; 20 Apr 2017 01:15:09 -0700 From: Abdiel Janulgue To: intel-gfx@lists.freedesktop.org Date: Thu, 20 Apr 2017 11:13:45 +0300 Message-Id: <1492676028-15372-1-git-send-email-abdiel.janulgue@linux.intel.com> X-Mailer: git-send-email 2.7.4 Cc: Daniel Vetter Subject: [Intel-gfx] [i-g-t PATCH 1/4] lib/igt_core: Add igt_exec helpers X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP Support executing external processes with the goal of capturing its standard streams to the igt logging infrastructure in addition to its exit status. Cc: Daniel Vetter Cc: Petri Latvala Signed-off-by: Abdiel Janulgue --- lib/igt_core.c | 151 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/igt_core.h | 3 ++ 2 files changed, 154 insertions(+) diff --git a/lib/igt_core.c b/lib/igt_core.c index 403b942..8a7ba0d 100644 --- a/lib/igt_core.c +++ b/lib/igt_core.c @@ -2073,3 +2073,154 @@ FILE *__igt_fopen_data(const char* igt_srcdir, const char* igt_datadir, return fp; } + +struct output_pipe { + int output_fd; + int save_fd; + int read_fd; + int write_fd; + bool redirected; + enum igt_log_level log_level; +}; + +static bool redirect_output(struct output_pipe *p, int output_fd, + enum igt_log_level level) +{ + int fds[2], flags; + + if (pipe(fds) == -1) + return false; + + if ((flags = fcntl(fds[0], F_GETFL) == -1)) + return false; + + flags |= O_NONBLOCK; + if (fcntl(fds[0], F_SETFL, flags) == -1) + return false; + + /* save output */ + if ((p->save_fd = dup(output_fd)) == -1) + return false; + + /* Redirect output to our buffer */ + if (dup2(fds[1], output_fd) == -1) + return false; + + p->output_fd = output_fd; + p->read_fd = fds[0]; + p->write_fd = fds[1]; + p->redirected = true; + p->log_level = level; + + return true; +} + +static bool unredirect_output(struct output_pipe *p) +{ + close(p->write_fd); + if (dup2(p->save_fd, p->output_fd) == -1) + return false; + close(p->save_fd); + + p->redirected = false; + + return true; +} + +/** + * igt_exec: + * + * Executes the shell command specified in @command and capture its stdout and + * stderr to igt_log or igt_warn respectively. + * + * Returns: The exit status of the executed process. -1 for failure. + */ +int igt_exec(const char *command) +{ +#define OUT 0 +#define ERR 1 + struct output_pipe op[2]; + int i, sel_fd, status; + fd_set fds; + struct timeval timeout = { .tv_sec = 0, .tv_usec = 0 }; + char buf[PIPE_BUF]; + + if (!redirect_output(&op[OUT], STDOUT_FILENO, IGT_LOG_INFO)) + return -1; + if (!redirect_output(&op[ERR], STDERR_FILENO, IGT_LOG_WARN)) + return -1; + + if ((status = system(command)) == -1) + return -1; + + FD_ZERO(&fds); + FD_SET(op[OUT].read_fd, &fds); + FD_SET(op[ERR].read_fd, &fds); + + sel_fd = max(op[OUT].read_fd, op[ERR].read_fd); + if (select(sel_fd + 1, &fds, NULL, NULL, &timeout) == -1) + return -1; + + for (i = 0; i < ARRAY_SIZE(op); i++) { + struct output_pipe *current = &op[i]; + + if (!FD_ISSET(current->read_fd, &fds)) { + close(current->read_fd); + if (!unredirect_output(current)) + return -1; + continue; + } + + memset(buf, 0, sizeof(buf)); + while (read(current->read_fd, buf, sizeof(buf)) > 0) { + if (current->redirected) { + if (!unredirect_output(current)) + return -1; + } + igt_log(IGT_LOG_DOMAIN, current->log_level, + "[cmd] %s", buf); + memset(buf, 0, sizeof(buf)); + } + close(current->read_fd); + } + + return WEXITSTATUS(status); +} + +/** + * igt_exec_quiet: + * Similar to igt_exec(), except redirect output to /dev/null + * + * Returns: The exit status of the executed process. -1 for failure. + */ +int igt_exec_quiet(const char *command) +{ + int stderr_fd_copy, stdout_fd_copy, status, nullfd; + + /* redirect */ + if ((nullfd = open("/dev/null", O_WRONLY)) == -1) + return -1; + if ((stdout_fd_copy = dup(STDOUT_FILENO)) == -1) + return -1; + if ((stderr_fd_copy = dup(STDERR_FILENO)) == -1) + return -1; + + if (dup2(nullfd, STDOUT_FILENO) == -1) + return -1; + if (dup2(nullfd, STDERR_FILENO) == -1) + return -1; + + if ((status = system(command)) == -1) + return -1; + + /* restore */ + if (dup2(stdout_fd_copy, STDOUT_FILENO) == -1) + return -1; + if (dup2(stderr_fd_copy, STDERR_FILENO) == -1) + return -1; + + close(stdout_fd_copy); + close(stderr_fd_copy); + + return WEXITSTATUS(status); +} diff --git a/lib/igt_core.h b/lib/igt_core.h index 51b98d8..6d4cf60 100644 --- a/lib/igt_core.h +++ b/lib/igt_core.h @@ -918,4 +918,7 @@ FILE *__igt_fopen_data(const char* igt_srcdir, const char* igt_datadir, #define igt_fopen_data(filename) \ __igt_fopen_data(IGT_SRCDIR, IGT_DATADIR, filename) +int igt_exec(const char *command); +int igt_exec_quiet(const char *command); + #endif /* IGT_CORE_H */