ddat interop with dat js cable interop with cabal js ddat's frontend = dat-thang cable fe = cable-thang dillo support based on cel's dillo-dat bootstrap node xplatform support Signed-off-by: divo <418@cryspace.space>
119 lines
3.1 KiB
C
119 lines
3.1 KiB
C
#define _POSIX_C_SOURCE 200809L
|
|
#include <arpa/inet.h>
|
|
#include <errno.h>
|
|
#include <netinet/in.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/types.h>
|
|
#include <sys/wait.h>
|
|
#include <unistd.h>
|
|
|
|
static int connect_local(unsigned short port)
|
|
{
|
|
struct sockaddr_in address;
|
|
int fd = socket(AF_INET, SOCK_STREAM, 0);
|
|
if (fd < 0) return -1;
|
|
memset(&address, 0, sizeof(address));
|
|
address.sin_family = AF_INET;
|
|
address.sin_port = htons(port);
|
|
address.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
|
if (connect(fd, (struct sockaddr *)&address, sizeof(address))) {
|
|
close(fd);
|
|
return -1;
|
|
}
|
|
return fd;
|
|
}
|
|
|
|
static int send_all(int fd, const char *data, size_t length)
|
|
{
|
|
while (length) {
|
|
ssize_t sent = send(fd, data, length, 0);
|
|
if (sent < 0 && errno == EINTR) continue;
|
|
if (sent <= 0) return -1;
|
|
data += sent;
|
|
length -= (size_t)sent;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int request_page(unsigned short port, const char *url)
|
|
{
|
|
const char *key = "abcdef1234567890";
|
|
char request[4096], buffer[4096];
|
|
int fd, n;
|
|
int length = snprintf(request, sizeof(request),
|
|
"<cmd='auth' msg='%s' '>\n<cmd='open_url' url='%s' '>", key, url);
|
|
if (length < 0 || (size_t)length >= sizeof(request)) return -1;
|
|
fd = connect_local(port);
|
|
if (fd < 0) return -1;
|
|
if (send_all(fd, request, (size_t)length) || shutdown(fd, SHUT_WR)) {
|
|
close(fd);
|
|
return -1;
|
|
}
|
|
while ((n = (int)recv(fd, buffer, sizeof(buffer), 0)) > 0) {
|
|
if (fwrite(buffer, 1, (size_t)n, stdout) != (size_t)n) {
|
|
close(fd);
|
|
return -1;
|
|
}
|
|
}
|
|
close(fd);
|
|
if (n < 0) return -1;
|
|
return fflush(stdout) ? -1 : 0;
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
struct sockaddr_in address;
|
|
socklen_t address_length = sizeof(address);
|
|
unsigned short port;
|
|
int listener;
|
|
pid_t child;
|
|
int status, fd;
|
|
if (argc != 3) {
|
|
fprintf(stderr, "usage: %s DPI-HELPER URL\n", argv[0]);
|
|
return 2;
|
|
}
|
|
listener = socket(AF_INET, SOCK_STREAM, 0);
|
|
if (listener < 0) { perror("socket"); return 1; }
|
|
memset(&address, 0, sizeof(address));
|
|
address.sin_family = AF_INET;
|
|
address.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
|
address.sin_port = 0;
|
|
if (bind(listener, (struct sockaddr *)&address, sizeof(address)) ||
|
|
listen(listener, 8) || getsockname(listener, (struct sockaddr *)&address, &address_length)) {
|
|
perror("bind/listen"); close(listener); return 1;
|
|
}
|
|
port = ntohs(address.sin_port);
|
|
child = fork();
|
|
if (child < 0) { perror("fork"); close(listener); return 1; }
|
|
if (!child) {
|
|
if (dup2(listener, STDIN_FILENO) < 0) _exit(126);
|
|
close(listener);
|
|
execl(argv[1], argv[1], (char *)NULL);
|
|
perror("exec"); _exit(127);
|
|
}
|
|
close(listener);
|
|
if (request_page(port, argv[2])) {
|
|
perror("request page");
|
|
kill(child, SIGTERM);
|
|
waitpid(child, NULL, 0);
|
|
return 1;
|
|
}
|
|
fd = connect_local(port);
|
|
{
|
|
const char *bye = "<cmd='auth' msg='abcdef1234567890' '>\n<cmd='DpiBye' '>";
|
|
if (fd < 0 || send_all(fd, bye, strlen(bye))) {
|
|
perror("send DpiBye");
|
|
kill(child, SIGTERM);
|
|
waitpid(child, NULL, 0);
|
|
return 1;
|
|
}
|
|
}
|
|
shutdown(fd, SHUT_WR);
|
|
close(fd);
|
|
if (waitpid(child, &status, 0) < 0) { perror("waitpid"); return 1; }
|
|
return WIFEXITED(status) ? WEXITSTATUS(status) : 1;
|
|
}
|