Reorganized responseutil.c and made the entire program ANSI and POSIX compliant

This commit is contained in:
Nate Choe
2022-02-13 22:54:19 -06:00
parent b91bb8614d
commit 2105f00965
17 changed files with 395 additions and 294 deletions

View File

@@ -21,7 +21,7 @@
#include <string.h>
#include <assert.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdarg.h>
#include <pwd.h>
#include <fcntl.h>
@@ -36,14 +36,55 @@
#include <sockets.h>
#include <sitefile.h>
static void daemonize(char *pidfile) {
pid_t pid;
FILE *pidout;
pid = fork();
switch (pid) {
case -1:
exit(EXIT_FAILURE);
case 0:
break;
default:
pidout = fopen(pidfile, "w");
fprintf(pidout, "%d\n", getpid());
fclose(pidout);
exit(EXIT_SUCCESS);
}
if (setsid() < 0)
exit(EXIT_FAILURE);
}
static void printLongMessage(char *first, ...) {
va_list ap;
va_start(ap, first);
puts(first);
for (;;) {
char *nextarg = va_arg(ap, char *);
if (nextarg == NULL)
break;
puts(nextarg);
}
va_end(ap);
}
int main(int argc, char **argv) {
char *logout = "/var/log/swebs.log";
char *sitefile = NULL;
int processes = sysconf(_SC_NPROCESSORS_ONLN) + 1;
uint16_t port = 443;
int backlog = 100;
bool shouldDaemonize = false;
char shouldDaemonize = 0;
char *pidfile = "/run/swebs.pid";
Sitefile *site;
Listener *listener;
int *pending, (*notify)[2];
pthread_t *threads;
int i;
for (;;) {
int c = getopt(argc, argv, "o:j:s:p:b:c:BP:hl");
if (c == -1)
@@ -65,39 +106,41 @@ int main(int argc, char **argv) {
backlog = atoi(optarg);
break;
case 'B':
shouldDaemonize = true;
shouldDaemonize = 1;
break;
case 'P':
pidfile = optarg;
break;
case 'l':
printf(
"swebs Copyright (C) 2022 Nate Choe\n"
"This is free software, and you are welcome to redistribute under certain\n"
"conditions, but comes with ABSOLUTELY NO WARRANTY. For more details see the\n"
"GNU General Public License Version 3\n"
"\n"
"This program dynamically links with:\n"
" gnutls (gnutls.org)\n"
"\n"
"For any complaints, email me at natechoe9@gmail.com\n"
"I'm a programmer not a lawyer, so there's a good chance I accidentally\n"
"violated the LGPL.\n"
printLongMessage(
"swebs Copyright (C) 2022 Nate Choe",
"This is free software, and you are welcome to redistribute under certain",
"conditions, but comes with ABSOLUTELY NO WARRANTY. For more details see the",
"GNU General Public License Version 3\n",
"This program dynamically links with:",
" gnutls (gnutls.org)\n",
"For any complaints, email me at natechoe9@gmail.com",
"I'm a programmer not a lawyer, so there's a good chance I accidentally",
"violated the LGPL.",
NULL
);
exit(EXIT_SUCCESS);
case 'h':
printf(
"Usage: swebs [options]\n"
" -o [out] Set the log file (default: /var/log/swebs.log)\n"
" -j [cores] Use that many cores (default: $(nproc)+1)\n"
" -s [site file] Use that site file (required)\n"
" -p [port] Set the port (default: 443)\n"
" -b [backlog] Set the socket backlog (default: 100)\n"
" -B Run swebs in the background and daemonize\n"
" -P [pidfile] Specify PID file if daemonizing\n"
" (defualt: /run/swebs.pid)\n"
" -l Show some legal details\n"
" -h Show this help message\n"
printLongMessage(
"Usage: swebs [options]",
" -o [out] Set the log file (default: /var/log/swebs.log)",
" -j [cores] Use that many cores (default: $(nproc)+1)",
" -s [site file] Use that site file (required)",
" -p [port] Set the port (default: 443)",
" -b [backlog] Set the socket backlog (default: 100)",
" -B Run swebs in the background and daemonize",
" -P [pidfile] Specify PID file if daemonizing",
" (defualt: /run/swebs.pid)",
" -l Show some legal details",
" -h Show this help message",
NULL
);
exit(EXIT_SUCCESS);
case '?':
@@ -111,13 +154,12 @@ int main(int argc, char **argv) {
fprintf(stderr, "No sitefile configured\n");
exit(EXIT_FAILURE);
}
Sitefile *site = parseSitefile(sitefile);
site = parseSitefile(sitefile);
if (site == NULL) {
fprintf(stderr, "Invalid sitefile %s\n", sitefile);
exit(EXIT_FAILURE);
}
Listener *listener;
switch (site->type) {
case TCP: default:
listener = createListener(TCP, port, backlog);
@@ -133,13 +175,8 @@ int main(int argc, char **argv) {
exit(EXIT_FAILURE);
}
if (shouldDaemonize) {
if (daemon(1, 0) < 0)
exit(EXIT_FAILURE);
FILE *pid = fopen(pidfile, "w");
fprintf(pid, "%d\n", getpid());
fclose(pid);
}
if (shouldDaemonize)
daemonize(pidfile);
if (initLogging(logout)) {
fprintf(stderr, "Couldn't open logs file %s\n", logout);
@@ -147,13 +184,14 @@ int main(int argc, char **argv) {
}
{
struct passwd *swebs = getpwnam("swebs");
struct passwd *swebs, *root;
swebs = getpwnam("swebs");
if (swebs == NULL)
createLog("Couldn't find swebs user");
else
if (seteuid(swebs->pw_uid))
createLog("seteuid() failed");
struct passwd *root = getpwnam("root");
root = getpwnam("root");
if (root == NULL) {
createLog("Couldn't find root user, quitting");
exit(EXIT_FAILURE);
@@ -164,18 +202,18 @@ int main(int argc, char **argv) {
}
}
int *pending = calloc(processes - 1, sizeof(int));
int (*notify)[2] = malloc(sizeof(int[2]) * (processes - 1));
pthread_t *threads = malloc(sizeof(pthread_t) * (processes - 1));
pending = calloc(processes - 1, sizeof(int));
notify = malloc(sizeof(int[2]) * (processes - 1));
threads = malloc(sizeof(pthread_t) * (processes - 1));
if (threads == NULL)
exit(EXIT_FAILURE);
for (int i = 0; i < processes - 1; i++) {
if (pipe(notify[i]))
exit(EXIT_FAILURE);
for (i = 0; i < processes - 1; i++) {
RunnerArgs *args = malloc(sizeof(RunnerArgs));
if (args == NULL)
exit(EXIT_FAILURE);
if (pipe(notify[i]))
exit(EXIT_FAILURE);
args->site = site;
args->pending = pending;
args->notify = notify[i][0];
@@ -188,21 +226,19 @@ int main(int argc, char **argv) {
for (;;) {
Stream *stream = acceptStream(listener, O_NONBLOCK);
int lowestThread;
if (stream == NULL) {
createLog("Accepting a stream failed");
continue;
}
int lowestThread = 0;
int lowestCount = pending[0];
for (int i = 1; i < processes - 1; i++) {
if (pending[i] < lowestCount) {
lowestThread = 0;
for (i = 1; i < processes - 1; i++)
if (pending[i] < pending[lowestThread])
lowestThread = i;
lowestCount = pending[i];
}
}
if (write(notify[lowestThread][1], &stream, sizeof(&stream))
< sizeof(&stream))
exit(EXIT_FAILURE);
}
}