17a1c0d96SNathan Whitehorn /*
2*a96ef450SBaptiste Daroussin * $Id: prgbox.c,v 1.14 2019/07/25 00:07:15 tom Exp $
37a1c0d96SNathan Whitehorn *
47a1c0d96SNathan Whitehorn * prgbox.c -- implements the prg box
57a1c0d96SNathan Whitehorn *
6*a96ef450SBaptiste Daroussin * Copyright 2011-2016,2019 Thomas E. Dickey
77a1c0d96SNathan Whitehorn *
87a1c0d96SNathan Whitehorn * This program is free software; you can redistribute it and/or modify
9682c9e0fSNathan Whitehorn * it under the terms of the GNU Lesser General Public License, version 2.1
10682c9e0fSNathan Whitehorn * as published by the Free Software Foundation.
117a1c0d96SNathan Whitehorn *
127a1c0d96SNathan Whitehorn * This program is distributed in the hope that it will be useful, but
137a1c0d96SNathan Whitehorn * WITHOUT ANY WARRANTY; without even the implied warranty of
147a1c0d96SNathan Whitehorn * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
157a1c0d96SNathan Whitehorn * Lesser General Public License for more details.
167a1c0d96SNathan Whitehorn *
177a1c0d96SNathan Whitehorn * You should have received a copy of the GNU Lesser General Public
187a1c0d96SNathan Whitehorn * License along with this program; if not, write to
197a1c0d96SNathan Whitehorn * Free Software Foundation, Inc.
207a1c0d96SNathan Whitehorn * 51 Franklin St., Fifth Floor
217a1c0d96SNathan Whitehorn * Boston, MA 02110, USA.
227a1c0d96SNathan Whitehorn */
237a1c0d96SNathan Whitehorn
247a1c0d96SNathan Whitehorn #include <dialog.h>
257a1c0d96SNathan Whitehorn
262a3e3873SBaptiste Daroussin static void
reapchild(int sig)272a3e3873SBaptiste Daroussin reapchild(int sig)
282a3e3873SBaptiste Daroussin {
292a3e3873SBaptiste Daroussin (void) sig;
302a3e3873SBaptiste Daroussin }
312a3e3873SBaptiste Daroussin
327a1c0d96SNathan Whitehorn /*
337a1c0d96SNathan Whitehorn * Open a pipe which ties stderr and stdout together.
347a1c0d96SNathan Whitehorn */
35f4f33ea0SBaptiste Daroussin FILE *
dlg_popen(const char * command,const char * type)367a1c0d96SNathan Whitehorn dlg_popen(const char *command, const char *type)
377a1c0d96SNathan Whitehorn {
387a1c0d96SNathan Whitehorn FILE *result = 0;
397a1c0d96SNathan Whitehorn int fd[2];
407a1c0d96SNathan Whitehorn
41*a96ef450SBaptiste Daroussin if ((*type == 'r' || *type == 'w') && pipe(fd) == 0) {
42*a96ef450SBaptiste Daroussin char *blob;
43*a96ef450SBaptiste Daroussin
442a3e3873SBaptiste Daroussin switch (fork()) {
457a1c0d96SNathan Whitehorn case -1: /* Error. */
467a1c0d96SNathan Whitehorn (void) close(fd[0]);
477a1c0d96SNathan Whitehorn (void) close(fd[1]);
487a1c0d96SNathan Whitehorn break;
497a1c0d96SNathan Whitehorn case 0: /* child. */
507a1c0d96SNathan Whitehorn if (*type == 'r') {
517a1c0d96SNathan Whitehorn if (fd[1] != STDOUT_FILENO) {
527a1c0d96SNathan Whitehorn (void) dup2(fd[1], STDOUT_FILENO);
537a1c0d96SNathan Whitehorn (void) close(fd[1]);
547a1c0d96SNathan Whitehorn }
557a1c0d96SNathan Whitehorn (void) dup2(STDOUT_FILENO, STDERR_FILENO);
567a1c0d96SNathan Whitehorn (void) close(fd[0]);
577a1c0d96SNathan Whitehorn } else {
587a1c0d96SNathan Whitehorn if (fd[0] != STDIN_FILENO) {
597a1c0d96SNathan Whitehorn (void) dup2(fd[0], STDIN_FILENO);
607a1c0d96SNathan Whitehorn (void) close(fd[0]);
617a1c0d96SNathan Whitehorn }
627a1c0d96SNathan Whitehorn (void) close(fd[1]);
637a1c0d96SNathan Whitehorn (void) close(STDERR_FILENO);
647a1c0d96SNathan Whitehorn }
657a1c0d96SNathan Whitehorn /*
667a1c0d96SNathan Whitehorn * Bourne shell needs "-c" option to force it to use only the
677a1c0d96SNathan Whitehorn * given command. Also, it needs the command to be parsed into
687a1c0d96SNathan Whitehorn * tokens.
697a1c0d96SNathan Whitehorn */
70f4f33ea0SBaptiste Daroussin if ((blob = malloc(10 + strlen(command))) != 0) {
71*a96ef450SBaptiste Daroussin char **argv;
72f4f33ea0SBaptiste Daroussin sprintf(blob, "sh -c \"%s\"", command);
732a3e3873SBaptiste Daroussin argv = dlg_string_to_argv(blob);
742a3e3873SBaptiste Daroussin execvp("sh", argv);
752a3e3873SBaptiste Daroussin }
767a1c0d96SNathan Whitehorn _exit(127);
777a1c0d96SNathan Whitehorn /* NOTREACHED */
787a1c0d96SNathan Whitehorn default: /* parent */
797a1c0d96SNathan Whitehorn if (*type == 'r') {
807a1c0d96SNathan Whitehorn result = fdopen(fd[0], type);
817a1c0d96SNathan Whitehorn (void) close(fd[1]);
827a1c0d96SNathan Whitehorn } else {
837a1c0d96SNathan Whitehorn result = fdopen(fd[1], type);
847a1c0d96SNathan Whitehorn (void) close(fd[0]);
857a1c0d96SNathan Whitehorn }
867a1c0d96SNathan Whitehorn break;
877a1c0d96SNathan Whitehorn }
887a1c0d96SNathan Whitehorn }
897a1c0d96SNathan Whitehorn
907a1c0d96SNathan Whitehorn return result;
917a1c0d96SNathan Whitehorn }
927a1c0d96SNathan Whitehorn
937a1c0d96SNathan Whitehorn /*
947a1c0d96SNathan Whitehorn * Display text from a pipe in a scrolling window.
957a1c0d96SNathan Whitehorn */
967a1c0d96SNathan Whitehorn int
dialog_prgbox(const char * title,const char * cprompt,const char * command,int height,int width,int pauseopt)977a1c0d96SNathan Whitehorn dialog_prgbox(const char *title,
987a1c0d96SNathan Whitehorn const char *cprompt,
997a1c0d96SNathan Whitehorn const char *command,
1007a1c0d96SNathan Whitehorn int height,
1017a1c0d96SNathan Whitehorn int width,
1027a1c0d96SNathan Whitehorn int pauseopt)
1037a1c0d96SNathan Whitehorn {
1047a1c0d96SNathan Whitehorn int code;
1057a1c0d96SNathan Whitehorn FILE *fp;
1062a3e3873SBaptiste Daroussin void (*oldreaper) (int) = signal(SIGCHLD, reapchild);
1077a1c0d96SNathan Whitehorn
1087a1c0d96SNathan Whitehorn fp = dlg_popen(command, "r");
1097a1c0d96SNathan Whitehorn if (fp == NULL)
1107a1c0d96SNathan Whitehorn dlg_exiterr("pipe open failed: %s", command);
1117a1c0d96SNathan Whitehorn
1127a1c0d96SNathan Whitehorn code = dlg_progressbox(title, cprompt, height, width, pauseopt, fp);
1137a1c0d96SNathan Whitehorn
1147a1c0d96SNathan Whitehorn pclose(fp);
1152a3e3873SBaptiste Daroussin signal(SIGCHLD, oldreaper);
1167a1c0d96SNathan Whitehorn
1177a1c0d96SNathan Whitehorn return code;
1187a1c0d96SNathan Whitehorn }
119