/* * Copyright (c) 2003 Benedikt Meurer (benedikt.meurer@unix-ag.uni-siegen.de) * 2004 Jean-François Wauthy (pollux@xfce.org) * * 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 Library 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H #include #endif /* !HAVE_CONFIG_H */ #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_SYS_WAIT_H #include #endif #include #ifdef HAVE_STDLIB_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #include "filter.h" /* create a new filter */ XfprintFilter * xfprint_filter_new(const gchar *command) { XfprintFilter *filter; g_return_val_if_fail(command != NULL, NULL); filter = g_new0(XfprintFilter, 1); filter->argc = 0; filter->argv = g_new0(gchar *, 40); filter->size = 40; filter->argv[0] = g_path_get_basename(command); filter->command = g_strdup(command); return(filter); } /* free a filter and all memory associated with it */ void xfprint_filter_free(XfprintFilter *filter) { gchar **p; g_return_if_fail(filter != NULL); for (p = filter->argv; *p; p++) g_free(*p); g_free(filter->argv); g_free(filter->command); g_free(filter); } /* add a new command line option to the filter */ void xfprint_filter_add(XfprintFilter *filter, const gchar *format, ...) { va_list ap; g_return_if_fail(filter != NULL); g_return_if_fail(format != NULL); if (++filter->argc < filter->size) { va_start(ap, format); filter->argv[filter->argc] = g_strdup_vprintf(format, ap); va_end(ap); } else { g_warning( "Unable to add another option. Dynamic resizing " "no implemented yet."); } } XfprintFilterList * xfprint_filterlist_new(void) { return(g_new0(XfprintFilterList, 1)); } /* free a list of filters (frees the filters itself too) */ void xfprint_filterlist_free(XfprintFilterList *filters) { g_return_if_fail(filters != NULL); g_list_foreach(filters->filters, (GFunc)xfprint_filter_free, NULL); g_list_free(filters->filters); g_free(filters); } void xfprint_filterlist_append(XfprintFilterList *filters, XfprintFilter *filter) { g_return_if_fail(filter != NULL); g_return_if_fail(filters != NULL); filters->filters = g_list_append(filters->filters, filter); } void xfprint_filterlist_prepend(XfprintFilterList *filters, XfprintFilter *filter) { g_return_if_fail(filter != NULL); g_return_if_fail(filters != NULL); filters->filters = g_list_prepend(filters->filters, filter); } static XfprintFilter * xfprint_filterlist_first(XfprintFilterList *filters) { g_return_val_if_fail(filters != NULL, NULL); filters->cursor = g_list_first(filters->filters); return(filters->cursor ? (XfprintFilter *)filters->cursor->data : NULL); } static XfprintFilter * xfprint_filterlist_next(XfprintFilterList *filters) { g_return_val_if_fail(filters != NULL, NULL); if (filters->cursor) filters->cursor = g_list_next(filters->cursor); return(filters->cursor ? (XfprintFilter *)filters->cursor->data : NULL); } int xfprint_filterlist_execute(XfprintFilterList *filters, int input, int output, int error) { XfprintFilter *filter; int status; int fd[2]; int outfd; pid_t pid; filter = xfprint_filterlist_first(filters); for (; filter; filter = xfprint_filterlist_next(filters)) { if (pipe(fd) < 0) return(-1); if ((pid = fork()) < 0) { return(-1); } else if (pid == 0) { (void)close(fd[0]); /* connect the last processes stdout to output */ if (!g_list_next(filters->cursor)) outfd = output; else outfd = fd[1]; if (input != STDIN_FILENO) (void)dup2(input, STDIN_FILENO); if (outfd != STDOUT_FILENO) (void)dup2(outfd, STDOUT_FILENO); if (error != STDERR_FILENO) (void)dup2(error, STDERR_FILENO); (void)execvp(filter->command, filter->argv); _exit(127); } (void)close(input); (void)close(fd[1]); input = fd[0]; } (void)close(input); while ((pid = waitpid(-1, &status, 0)) >= 0) { if (!WIFEXITED(status)) return(status); else if (WEXITSTATUS(status)) return(WEXITSTATUS(status)); } if (pid < 0 && errno != ECHILD) return(-1); return(0); }