Code reorganization

This commit is contained in:
Nate Choe
2022-03-30 17:39:55 -05:00
parent 266a087655
commit 26c0eaca15
7 changed files with 241 additions and 160 deletions

View File

@@ -18,200 +18,75 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <pwd.h>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>
#include <pthread.h>
#include <swebs/util.h>
#include <swebs/setup.h>
#include <swebs/runner.h>
#include <swebs/sockets.h>
#include <swebs/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", pid);
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;
int backlog = 100;
char shouldDaemonize = 0;
char *pidfile = "/run/swebs.pid";
Sitefile *site;
Listener *listener;
int processes;
int *pending, (*notify)[2];
int *pending, pendingid, (*notify)[2];
pthread_t *threads;
int i;
for (;;) {
int c = getopt(argc, argv, "o:j:s:b:c:Bp:hl");
if (c == -1)
break;
switch (c) {
case 'o':
logout = optarg;
break;
case 'j':
processes = atoi(optarg);
break;
case 's':
sitefile = optarg;
break;
case 'b':
backlog = atoi(optarg);
break;
case 'B':
shouldDaemonize = 1;
break;
case 'p':
pidfile = optarg;
break;
case 'l':
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",
setup(argc, argv, &site, &listener, &processes);
"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':
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)",
" -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 '?':
fprintf(stderr, "-h for help\n");
exit(EXIT_FAILURE);
}
}
if (sitefile == NULL) {
fprintf(stderr, "No sitefile configured\n");
pendingid = smalloc(sizeof(int) * (processes - 1));
if (pendingid < 0) {
createLog("smalloc() failed");
exit(EXIT_FAILURE);
}
site = parseSitefile(sitefile);
if (site == NULL) {
fprintf(stderr, "Invalid sitefile %s\n", sitefile);
pending = saddr(pendingid);;
if (pending == NULL) {
createLog("saddr() failed");
exit(EXIT_FAILURE);
}
memset(pending, 0, sizeof(int) * (processes - 1));
switch (site->type) {
case TCP: default:
listener = createListener(TCP, site->port, backlog);
break;
case TLS:
initTLS();
listener = createListener(TLS, site->port, backlog,
site->key, site->cert);
break;
}
if (listener == NULL) {
fprintf(stderr, "Failed to create socket\n");
exit(EXIT_FAILURE);
}
if (shouldDaemonize)
daemonize(pidfile);
if (initLogging(logout)) {
fprintf(stderr, "Couldn't open logs file %s\n", logout);
exit(EXIT_FAILURE);
}
{
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");
root = getpwnam("root");
if (root == NULL) {
createLog("Couldn't find root user, quitting");
exit(EXIT_FAILURE);
}
if (geteuid() == root->pw_uid) {
createLog("swebs should not be run as root");
exit(EXIT_FAILURE);
}
}
signal(SIGPIPE, SIG_IGN);
pending = calloc(processes - 1, sizeof(int));
notify = malloc(sizeof(int[2]) * (processes - 1));
threads = malloc(sizeof(pthread_t) * (processes - 1));
if (threads == NULL)
if (notify == NULL) {
createLog("malloc() failed");
exit(EXIT_FAILURE);
}
threads = malloc(sizeof(pthread_t) * (processes - 1));
if (threads == NULL) {
createLog("malloc() failed");
exit(EXIT_FAILURE);
}
for (i = 0; i < processes - 1; i++) {
RunnerArgs *args = malloc(sizeof(RunnerArgs));
if (args == NULL)
if (args == NULL) {
createLog("malloc() failed");
exit(EXIT_FAILURE);
if (pipe(notify[i]))
}
if (pipe(notify[i])) {
createLog("pipe() failed");
exit(EXIT_FAILURE);
}
args->site = site;
args->pending = pending;
args->pendingid = pendingid;
args->notify = notify[i][0];
args->id = i;
pthread_create(threads + i, NULL,
(void*(*)(void*)) runServer, args);
}
signal(SIGPIPE, SIG_IGN);
createLog("swebs started");
for (;;) {
@@ -228,7 +103,7 @@ NULL
if (pending[i] < pending[lowestThread])
lowestThread = i;
if (write(notify[lowestThread][1], &stream, sizeof(&stream))
< sizeof(&stream))
< sizeof(&stream))
continue;
}