// This file is part of Snownews - A lightweight console RSS newsreader // // Copyright (c) 2003-2004 Oliver Feiler // // Snownews is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License version 3 // as published by the Free Software Foundation. // // Snownews 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 Snownews. If not, see http://www.gnu.org/licenses/. #include "filters.h" #include "uiutil.h" #include "conv.h" //---------------------------------------------------------------------- static int pipe_command_buf (const char* command, char** argv, const void* inbuf, size_t inbuf_size, char** outbuf, unsigned* outbuf_size); //---------------------------------------------------------------------- // Load output of local script. Must be valid RSS. int FilterExecURL (struct feed* cur_ptr) { char* command = strdup (cur_ptr->feedurl); char* freeme = command; strsep (&command, ":"); char buf[BUFSIZ]; snprintf (buf, sizeof (buf), _("Loading \"%s\""), command); UIStatus (buf, 0, 0); FILE* scriptoutput = popen (command, "r"); free (freeme); if (!scriptoutput) return -1; cur_ptr->content_length = 0; cur_ptr->xmltext = realloc (cur_ptr->xmltext, cur_ptr->content_length + 1); cur_ptr->xmltext[cur_ptr->content_length] = '\0'; while (!feof (scriptoutput) && fgets (buf, sizeof (buf), scriptoutput)) { size_t br = strlen (buf); cur_ptr->xmltext = realloc (cur_ptr->xmltext, cur_ptr->content_length + br + 1); memcpy (&cur_ptr->xmltext[cur_ptr->content_length], buf, br + 1); cur_ptr->content_length += br; } pclose (scriptoutput); // Set title and link structure to something. // To the feedurl in this case so the program shows something // as placeholder instead of crash. if (cur_ptr->title == NULL) cur_ptr->title = strdup (cur_ptr->feedurl); if (cur_ptr->link == NULL) cur_ptr->link = strdup (cur_ptr->feedurl); return 0; } int FilterPipeNG (struct feed* cur_ptr) { if (cur_ptr->perfeedfilter == NULL) return -1; char* data = malloc (cur_ptr->content_length + 1); memcpy (data, cur_ptr->xmltext, cur_ptr->content_length); data[cur_ptr->content_length] = 0; free (cur_ptr->xmltext); cur_ptr->xmltext = NULL; cur_ptr->content_length = 0; char* filter = strdup (cur_ptr->perfeedfilter); char* command = strsep (&filter, " "); char** options = malloc (sizeof (char*)); size_t nopts = 0; options[nopts++] = command; for (;;) { options = realloc (options, sizeof (char*) * (nopts + 1)); if (!(options[nopts++] = strsep (&filter, " "))) break; } int rc = pipe_command_buf (command, options, data, cur_ptr->content_length, &cur_ptr->xmltext, &cur_ptr->content_length); free (data); free (command); free (options); // options[i] contains only pointers! return rc; } static int pipe_command_buf (const char* command, char** argv, const void* inbuf, size_t inbuf_size, char** outbuf, unsigned* outbuf_size) { enum { READ_END, WRITE_END, N_ENDS }; int input_pipe[N_ENDS], output_pipe[N_ENDS]; if (0 != pipe (input_pipe)) { perror ("Couldn't create input pipe"); return -1; } if (0 != pipe (output_pipe)) { close (input_pipe[READ_END]); close (input_pipe[WRITE_END]); perror ("Couldn't create output pipe"); return -1; } int result = fork(); if (result < 0) { close (input_pipe[READ_END]); close (input_pipe[WRITE_END]); close (output_pipe[READ_END]); close (output_pipe[WRITE_END]); perror ("fork"); return -1; } else if (result == 0) { close (output_pipe[WRITE_END]); close (input_pipe[READ_END]); if (0 > dup2 (output_pipe[READ_END], STDIN_FILENO)) { perror ("dup2 error on output_pipe"); exit (EXIT_FAILURE); } close (output_pipe[READ_END]); if (0 > dup2 (input_pipe[WRITE_END], STDOUT_FILENO)) { perror ("dup2 error on input_pipe"); exit (EXIT_FAILURE); } close (input_pipe[WRITE_END]); if (0 > execvp (command, argv)) { char tmp[PATH_MAX]; snprintf (tmp, sizeof (tmp), "Exec of \"%s\" failed", command); perror (tmp); } exit (EXIT_FAILURE); } else { close (output_pipe[READ_END]); close (input_pipe[WRITE_END]); write (output_pipe[WRITE_END], inbuf, inbuf_size); close (output_pipe[WRITE_END]); char* buf = NULL, *buf_cur = NULL; int buf_size = 0, bytes_read = 0; do { buf_size += BUFSIZ; buf = realloc (buf, buf_size + 1); buf_cur = buf + buf_size - BUFSIZ; result = read (input_pipe[READ_END], buf_cur, BUFSIZ); if (result > 0) { bytes_read += result; if (result < BUFSIZ) { buf_size -= (BUFSIZ - result); buf = realloc (buf, buf_size + 1); break; } } else if (result < 0) { free (buf); buf = NULL; return -1; } } while (result > 0); close (input_pipe[READ_END]); if (bytes_read == 0) { free (buf); return -1; } else { buf[buf_size] = '\0'; *outbuf = buf; *outbuf_size = buf_size; } } return 0; }