/* * xexec_cmd.c - Part of AFD, an automatic file distribution program. * Copyright (c) 1999 - 2021 Holger Kiehl * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "afddefs.h" DESCR__S_M3 /* ** NAME ** xexec_cmd - executes a shell command ** ** SYNOPSIS ** void xexec_cmd(char *cmd) ** ** DESCRIPTION ** xexec_cmd() executes a command specified in 'cmd' by calling ** /bin/sh -c 'cmd', and returns after the command has been ** completed. All output is written to the text widget cmd_output. ** ** RETURN VALUES ** Returns INCORRECT when it fails to execute the command 'cmd'. ** In buffer will be the results of STDOUT and STDERR. ** ** AUTHOR ** H.Kiehl ** ** HISTORY ** 05.12.1999 H.Kiehl Created ** */ DESCR__E_M3 #include #include /* strlen() */ #include /* exit() */ #include /* read(), close(), STDOUT_FILENO, */ /* STDERR_FILENO */ #include /* O_NONBLOCK */ #include #include /* wait() */ #include #include #include #include "show_cmd.h" #define READ 0 #define WRITE 1 /* External global variables. */ extern int cmd_fd, go_to_beginning, no_repeat_button; extern pid_t cmd_pid; extern Display *display; extern Widget appshell, cmd_output; extern XmTextPosition wpr_position; extern XtInputId cmd_input_id; /* Local function prototypes. */ static void read_data(XtPointer, int *, XtInputId *); /*############################# xexec_cmd() #############################*/ void xexec_cmd(char *cmd) { int channels[2]; if (cmd_pid > 0) { if (wait(NULL) == -1) { (void)fprintf(stderr, "wait() error : %s (%s %d)\n", strerror(errno), __FILE__, __LINE__); exit(INCORRECT); } cmd_pid = 0; if (close(cmd_fd) == -1) { (void)fprintf(stderr, "close() error : %s (%s %d)\n", strerror(errno), __FILE__, __LINE__); } } if (pipe(channels) == -1) { (void)fprintf(stderr, "pipe() error : %s (%s %d)\n", strerror(errno), __FILE__, __LINE__); exit(INCORRECT); } switch (cmd_pid = fork()) { case -1: /* Failed to fork. */ (void)fprintf(stderr, "fork() error : %s (%s %d)\n", strerror(errno), __FILE__, __LINE__); exit(INCORRECT); case 0 : /* Child process. */ (void)close(channels[READ]); dup2(channels[WRITE], STDOUT_FILENO); dup2(channels[WRITE], STDERR_FILENO); (void)execl("/bin/sh", "sh", "-c", cmd, (char *)0); _exit(INCORRECT); default: /* Parent process. */ (void)close(channels[WRITE]); cmd_fd = channels[READ]; cmd_input_id = XtAppAddInput(XtWidgetToApplicationContext(appshell), channels[READ], (XtPointer)XtInputReadMask, (XtInputCallbackProc)read_data, (XtPointer)NULL); } return; } /*++++++++++++++++++++++++++++ read_data() ++++++++++++++++++++++++++++++*/ static void read_data(XtPointer client_data, int *fd, XtInputId *id) { int n; char buffer[4096 + 1]; if ((n = read(*fd, buffer, 4096)) > 0) { buffer[n] = '\0'; XmTextInsert(cmd_output, wpr_position, buffer); wpr_position += n; if (go_to_beginning == NO) { XmTextShowPosition(cmd_output, wpr_position); } XFlush(display); } else if (n == 0) { if (no_repeat_button == NO) { buffer[0] = '>'; buffer[1] = '\0'; XmTextInsert(cmd_output, wpr_position, buffer); } if (go_to_beginning == NO) { XmTextShowPosition(cmd_output, wpr_position); } else { XmTextShowPosition(cmd_output, 0); } XFlush(display); if (cmd_pid > 0) { if (wait(NULL) == -1) { (void)fprintf(stderr, "wait() error : %s (%s %d)\n", strerror(errno), __FILE__, __LINE__); exit(INCORRECT); } cmd_pid = 0; } wpr_position = 0; if (cmd_input_id != 0L) { XtRemoveInput(cmd_input_id); cmd_input_id = 0L; if (close(cmd_fd) == -1) { (void)fprintf(stderr, "close() error : %s (%s %d)\n", strerror(errno), __FILE__, __LINE__); } } } return; }