Connect to unix sockets to interface with user-written programs.

This commit is contained in:
Qc Na 2023-03-10 17:43:14 +01:00
parent f647ff347a
commit 2afaf5510b
Signed by: qcna
GPG Key ID: 3C818AEF6447D77F
5 changed files with 74 additions and 7 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
*.o
vger
unit_test

4
main.c
View File

@ -88,10 +88,10 @@ main(int argc, char **argv)
/* *** from here, cgi didn't run *** */
/* check if path available */
check_path(path, sizeof(path));
struct stat sb = check_path(path, sizeof(path));
/* regular file to stdout */
display_file(path);
display_file(path, sb);
stop(EXIT_SUCCESS, NULL);
}

View File

@ -1,3 +1,6 @@
#ifndef utils_h_INCLUDED
#define utils_h_INCLUDED
void getsubexp(const char *, regmatch_t, char *);
void echdir(const char *);
void epledge(const char *, const char *);
@ -6,3 +9,5 @@ int esetenv(const char *, const char *, int);
size_t esnprintf(char *, size_t, const char *, ...);
size_t print_file(FILE *fd);
void set_errmsg(const char *, ...);
#endif // utils_h_INCLUDED

67
vger.c
View File

@ -1,6 +1,8 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <ctype.h>
#include <dirent.h>
@ -175,20 +177,77 @@ set_rootdir(const char *chroot_dir, const char *cgi_dir, const char *user)
}
ssize_t
display_file(const char *path)
display_file(const char *path, struct stat sb)
{
FILE *fd = NULL;
const char *file_mime;
size_t pathlen = strlen(path);
/*
* special case : path ends with "/". The user requested a dir
*/
if ((path[strlen(path)-1] == '/') && (doautoidx)) {
if ((path[pathlen-1] == '/') && (doautoidx)) {
/* no index.gmi, so display autoindex if enabled */
_datasiz += autoindex(path);
return _datasiz;
}
if (S_ISSOCK(sb.st_mode)) {
/* I got these numbers off of a Stack Overflow answer, so take them with a grain of salt. */
#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined( __NetBSD__) || defined(__DragonFly__)
if(pathlen > 104) {
#elif defined(__linux__)
if(pathlen > 108) {
#else
#error "I don't know the max path length of a unix socket for this system!"
#endif
/* If the name is too long. */
status(40, "%s", "socket name is too long");
return _datasiz;
}
/* Create the socket address (a filename, really). */
struct sockaddr_un addr;
memset(&addr, 0, sizeof(struct sockaddr_un));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, path, pathlen);
/* Allocate a UNIX domain socket. */
int sock = socket(AF_UNIX, SOCK_STREAM, 0);
/* Connect to the desired socket. */
int ret = connect(sock, (const struct sockaddr *) &addr, sizeof(struct sockaddr_un));
if (ret == -1) {
status(43, "%s", "unable to connect to socket");
return _datasiz;
}
/* TODO: Move this to its own function. */
file_mime = get_file_mime(path, default_mime);
if (strcmp(file_mime, "text/gemini") == 0)
status(20, "%s; %s", file_mime, lang);
else
status(20, "%s", file_mime);
/* Read data until the socket is closed. */
char buffer[BUFSIZ];
for (;;) {
ret = read(sock, buffer, BUFSIZ);
if (ret == -1) {
_datasiz += fprintf(stdout, "\n\n\nsocket read error: %i\n", errno);
break;
} else if (ret == 0) {
break; /* end of file */
} else {
fwrite(buffer, 1, ret, stdout);
}
}
/* We're done! */
close(sock);
return _datasiz;
}
/* open the file requested */
if ((fd = fopen(path, "r")) != NULL) {
file_mime = get_file_mime(path, default_mime);
@ -398,7 +457,7 @@ remove_double_dot(char *request)
memmove(request, pos + 3, strlen(pos) + 1 - 3); /* "/.." = 3 */
}
void
struct stat
check_path(char *path, size_t pathsiz)
{
struct stat sb = {0};
@ -427,6 +486,8 @@ check_path(char *path, size_t pathsiz)
if (stat(tmp, &sb) == 0)
esnprintf(path, pathsiz, "%s", tmp);
}
return sb;
}
void

4
vger.h
View File

@ -42,8 +42,8 @@ static char _request[GEMINI_REQUEST_MAX] = {'\0'};
ssize_t autoindex(const char *);
void cgi(const char *);
char * read_request(char *);
void check_path(char *, size_t);
ssize_t display_file(const char *);
struct stat check_path(char *, size_t);
ssize_t display_file(const char *, struct stat);
int do_cgi(const char *, const char *, const char *, const char *);
void drop_privileges(const char *);
void set_rootdir(const char *, const char *, const char *);