xref: /freebsd/contrib/dialog/prgbox.c (revision a96ef4501919d7ac08e94e98dc34b0bdd744802b)
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