1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-09-27 02:56:18 -04:00
elinks/src/protocol/file/mailcap.c
Witold Filipczyk 541303cbff [modules] Additional function getname
When non NULL it will be return module name and version.
2024-09-26 16:19:26 +02:00

151 lines
3.1 KiB
C

/* Internal "mailcap's copiousoutput" protocol implementation */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h> /* OS/2 needs this after sys/types.h */
#endif
#include <sys/stat.h> /* OS/2 needs this after sys/types.h */
#ifdef HAVE_FCNTL_H
#include <fcntl.h> /* OS/2 needs this after sys/types.h */
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "elinks.h"
#include "config/options.h"
#include "cookies/cookies.h"
#include "intl/libintl.h"
#include "mime/backend/common.h"
#include "network/connection.h"
#include "network/progress.h"
#include "network/socket.h"
#include "osdep/osdep.h"
#include "osdep/sysname.h"
#include "protocol/common.h"
#include "protocol/file/mailcap.h"
#include "protocol/http/http.h"
#include "protocol/uri.h"
#include "terminal/terminal.h"
#include "util/conv.h"
#include "util/env.h"
#include "util/string.h"
struct module mailcap_protocol_module = struct_module(
/* name: */ N_("Mailcap"),
/* options: */ NULL,
/* hooks: */ NULL,
/* submodules: */ NULL,
/* data: */ NULL,
/* init: */ NULL,
/* done: */ NULL,
/* getname: */ NULL
);
#ifdef HAVE_FORK
static void
get_request(struct connection *conn)
{
struct read_buffer *rb = alloc_read_buffer(conn->socket);
if (!rb) return;
memcpy(rb->data, "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\n\r\n", 45);
rb->length = 45;
rb->freespace -= 45;
conn->unrestartable = 1;
conn->socket->state = SOCKET_END_ONCLOSE;
read_from_socket(conn->socket, rb, connection_state(S_SENT),
http_got_header);
}
#endif
void
mailcap_protocol_handler(struct connection *conn)
{
#ifdef HAVE_FORK
char *script, *ref;
pid_t pid;
struct connection_state state = connection_state(S_OK);
int pipe_read[2], check;
/* security checks */
if (!conn->referrer || conn->referrer->protocol != PROTOCOL_MAILCAP) {
goto bad;
}
ref = get_uri_string(conn->referrer, URI_DATA);
if (!ref) {
goto bad;
}
check = strcmp(ref, "elmailcap");
mem_free(ref);
if (check) goto bad;
script = get_uri_string(conn->uri, URI_DATA);
if (!script) {
state = connection_state(S_OUT_OF_MEM);
goto end2;
}
if (c_pipe(pipe_read)) {
state = connection_state_for_errno(errno);
goto end1;
}
pid = fork();
if (pid < 0) {
state = connection_state_for_errno(errno);
goto end0;
}
if (!pid) {
if (dup2(pipe_read[1], STDOUT_FILENO) < 0) {
_exit(2);
}
close_all_non_term_fd();
close(STDERR_FILENO);
if (execl("/bin/sh", "/bin/sh", "-c", script, (char *) NULL)) {
_exit(3);
}
} else { /* ELinks */
mem_free(script);
if (!init_http_connection_info(conn, 1, 0, 1)) {
close(pipe_read[0]); close(pipe_read[1]);
return;
}
close(pipe_read[1]);
conn->socket->fd = pipe_read[0];
conn->data_socket->fd = -1;
conn->cgi = 1;
set_nonblocking_fd(conn->socket->fd);
get_request(conn);
return;
}
end0:
close(pipe_read[0]); close(pipe_read[1]);
end1:
mem_free(script);
end2:
abort_connection(conn, state);
return;
bad:
#endif
abort_connection(conn, connection_state(S_BAD_URL));
}