188 lines
5.3 KiB
C
188 lines
5.3 KiB
C
// This file is part of Snownews - A lightweight console RSS newsreader
|
|
//
|
|
// Copyright (c) 2003-2004 Oliver Feiler <kiza@kcore.de>
|
|
//
|
|
// 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;
|
|
}
|