Skip to content

Commit

Permalink
build: Improve portability for non-Linux systems.
Browse files Browse the repository at this point in the history
This addresses compilation and build issues with
non-Linux systems, FreeBSD in particular.

The core BBS now builds successfully on FreeBSD
for me; some functionality is missing (namely
UUID functionality in utils.c and much functionality
in system.c). Most modules should compile as well,
though dependencies are not all addressed.
  • Loading branch information
InterLinked1 committed Nov 24, 2023
1 parent f3ad32d commit 3b479c6
Show file tree
Hide file tree
Showing 38 changed files with 415 additions and 93 deletions.
49 changes: 28 additions & 21 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,22 @@ CFLAGS = -Wall -Werror -Wunused -Wextra -Wparentheses -Wconversion -Wdangling-el
EXE = lbbs
PREFIX = /usr/local
BINDIR = $(PREFIX)/bin
LIBS = -lrt -lm -ldl -lbfd -lbsd -lcap -lcrypt -lssl -lcrypto -lcurl -lreadline -luuid -rdynamic
UNAME_S := $(shell uname -s)

export UNAME_S

LIBS = -lrt -lm -ldl

LIBS += -lbfd -lcrypt -lssl -lcrypto -lcurl -lreadline -luuid -rdynamic

ifeq ($(UNAME_S),Linux)
LIBS += -lbsd -lcap
endif

ifeq ($(UNAME_S),FreeBSD)
LIBS += -lexecinfo -lintl
endif

RM = rm -f
LN = ln
INSTALL = install
Expand Down Expand Up @@ -101,14 +116,17 @@ modinstall: $(MOD_SUBDIR)
done

extinstall:
@if [ ! -d /var/lib ]; then\
mkdir /var/lib;\
fi
@if [ ! -d /var/lib/lbbs ]; then\
mkdir /var/lib/lbbs;\
fi
@if [ ! -d /var/lib/lbbs/external ]; then\
mkdir /var/lib/lbbs/external;\
fi
$(SUBMAKE) --no-builtin-rules -C external install
ln -s --force /var/lib/lbbs/external/rsysop /usr/local/sbin/rsysop
ln -s -f /var/lib/lbbs/external/rsysop /usr/local/sbin/rsysop

scripts :
@if [ ! -d /var/lib/lbbs ]; then\
Expand Down Expand Up @@ -145,28 +163,17 @@ doxygen :
# apt-get install -y doxygen graphviz
doxygen Doxyfile.in

# only do these checks if we're actually running a valgrind target
valgrindver:
# --show-error-list is only available in valgrind 3.15.0+: https://valgrind.org/docs/manual/dist.news.html
VALGRIND_VERSION_MAJOR = $(shell valgrind --version | cut -d'-' -f2 | cut -d'.' -f1)
VALGRIND_VERSION_MINOR = $(shell valgrind --version | cut -d'-' -f2 | cut -d'.' -f2)
ifeq ($(shell test $(VALGRIND_VERSION_MAJOR) -ge 3 -a $(VALGRIND_VERSION_MINOR) -ge 15; echo $$?),0)
VALGRIND = valgrind --show-error-list=yes --keep-debuginfo=yes
else
VALGRIND = valgrind --keep-debuginfo=yes
endif

valgrindfg : valgrindver
$(VALGRIND) --leak-check=full --track-fds=yes --track-origins=yes --show-leak-kinds=all --suppressions=valgrind.supp /usr/sbin/$(EXE) -cb
valgrindfg :
@scripts/valgrind.sh "valgrindfg"

valgrind : valgrindver
$(VALGRIND) --leak-check=full --track-fds=yes --track-origins=yes --show-leak-kinds=all --suppressions=valgrind.supp --log-fd=9 /usr/sbin/$(EXE) -cb 9>valgrind.txt
valgrind :
@scripts/valgrind.sh "valgrind"

valgrindsupp : valgrindver
$(VALGRIND) --leak-check=full --track-fds=yes --track-origins=yes --show-leak-kinds=all --suppressions=valgrind.supp --gen-suppressions=all --log-fd=9 /usr/sbin/$(EXE) -cb 9>valgrind.txt
valgrindsupp :
@scripts/valgrind.sh "valgrindsupp"

helgrind : valgrindver
$(VALGRIND) --tool=helgrind /usr/sbin/$(EXE) -c
helgrind :
@scripts/valgrind.sh "helgrind"

.PHONY: all
.PHONY: bbs
Expand Down
7 changes: 6 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ At the console, press :code:`?` or :code:`h` for a list of available commands. Y

Some configuration of the BBS will be needed before you can use it. Consult the sample configs in :code:`/etc/lbbs` for an overview of settings you may need to configure. At a minimum, you will need to add a menu to the BBS (:code:`menus.conf`).

LBBS is best run on a modern version of Debian Linux (Debian 11 or 12). It should also compile on most other commonly used Linux distros. A recent version of gcc is required (e.g. >= 11). Note that LBBS likely is not currently portable to non-Linux systems, e.g. BSD or UNIX. It likely won't be a lot of work to make it more portable, but that work hasn't been done yet since I only test and run BBSes on Linux. Additionally, LBBS requires gcc to compile, since it uses some gcc-specific compiler extensions.
LBBS is best run on a modern version of Debian Linux (Debian 11 or 12). It should also compile on most other commonly used Linux distros. A recent version of gcc is required (e.g. >= 11).
The BBS core should compile and install on FreeBSD, but not all module dependencies may be available and some functionality may be degraded.

**WARNING: Do not run the BBS as root!** Create a non-root user and configure the BBS to run as that instead. See :code:`lbbs -?` or :code:`/etc/lbbs/bbs.conf` to configure the run user and run group.

Expand Down Expand Up @@ -128,6 +129,10 @@ Config files go in :code:`/etc/lbbs` and are as follows:

* :code:`menus.conf` - BBS menus, menu items and options. **This is the heart of LBBS configuration.**

* :code:`mod_asterisk_ami.conf` - Asterisk Manager Interface

* :code:`mod_asterisk_queues.conf` - Asterisk queues integration

* :code:`mod_auth_mysql.conf` - MySQL/MariaDB auth provider module config

* :code:`mod_auth_static.conf` - Static user configuration (intended for development and testing)
Expand Down
5 changes: 5 additions & 0 deletions bbs/alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ int __attribute__ ((format (gnu_printf, 5, 6))) __bbs_asprintf(const char *file,

size_t bbs_malloc_trim(void)
{
#ifdef __linux__
int res;
size_t diff;
void *before, *after;
Expand All @@ -193,4 +194,8 @@ size_t bbs_malloc_trim(void)
diff = (size_t) (before - after); /* Number of bytes released (which should be based on the page size) */
bbs_debug(2, "malloc_trim: %d, before: %p, after: %p, bytes released: %lu\n", res, before, after, diff);
return diff;
#else
bbs_debug(2, "malloc_trim not supported by this platform\n");
return 0;
#endif
}
31 changes: 24 additions & 7 deletions bbs/backtrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,20 @@
#include <pthread.h>
#include <execinfo.h>
#include <dlfcn.h>

/* Hack for compiling on FreeBSD */
#if !defined(PACKAGE) && defined(__FreeBSD__)
#define PACKAGE
#ifndef PACKAGE_VERSION
#define PACKAGE_VERSION
#include <bfd.h>
#else
#include <bfd.h>
#endif /* PACKAGE_VERSION */
#undef PACKAGE
#else
#include <bfd.h>
#endif /* PACKAGE */

#define BT_MAX_STACK_FRAMES 20
#define BT_MSG_BUFF_LEN 1024
Expand Down Expand Up @@ -238,20 +251,24 @@ void bbs_log_backtrace(void)
{
char **bt_syms;
void *array[BT_MAX_STACK_FRAMES]; /* Maximum number of stack frames to dump. */
int size;

#ifdef __FreeBSD__
size_t i, size;
#else
int i, size;
#endif

size = backtrace(array, BT_MAX_STACK_FRAMES);
bt_syms = backtrace_symbols(array, size);

bbs_error("Got %d backtrace records\n", size);
bbs_error("Got %d backtrace records\n", (int) size);

{
/* Scope for retstrings, since size is not known at beginning of function */
char *retstrings[size];
int i;
#pragma GCC diagnostic pop
memset(retstrings, 0, sizeof(*retstrings));
bt_get_symbols(array, size, retstrings); /* Get backtraces with friendly symbols */
bt_get_symbols(array, (int) size, retstrings); /* Get backtraces with friendly symbols */
for (i = 0; i < size; i++) {
if (retstrings[i]) {
if (strchr(retstrings[i], '\n')) {
Expand All @@ -264,16 +281,16 @@ void bbs_log_backtrace(void)
if (frame) {
*frame++ = '\0';
}
bbs_error("%2d: %s\n", i, s);
bbs_error("%2d: %s\n", (int) i, s);
s = frame;
} while (frame);
} else {
bbs_error("%2d: %s\n", i, retstrings[i]);
bbs_error("%2d: %s\n", (int) i, retstrings[i]);
}
free(retstrings[i]); /* Free symbols as we're done using them */
} else {
/* Fallback to backtrace_symbols output */
bbs_error("%2d: %s\n", i, bt_syms[i]);
bbs_error("%2d: %s\n", (int) i, bt_syms[i]);
}
}
free(bt_syms);
Expand Down
19 changes: 14 additions & 5 deletions bbs/bbs.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,18 @@
#include <signal.h>
#include <poll.h>
#include <fcntl.h> /* use O_NONBLOCK */

#ifdef __linux__
#include <linux/limits.h> /* use PATH_MAX */
#include <sys/resource.h> /* use rlimit */
#include <sys/prctl.h> /* use prctl */
#include <sys/capability.h>
#include <linux/capability.h>
#endif

#include <sys/resource.h> /* use rlimit */
#include <grp.h> /* use getgrnam */
#include <pwd.h> /* use getpwnam */
#include <sys/ioctl.h>
#include <sys/capability.h>
#include <linux/capability.h>

#include "include/module.h" /* use load_modules */
#include "include/alertpipe.h"
Expand Down Expand Up @@ -147,6 +151,7 @@ static int set_cwd(void)

static void check_cap(int isroot)
{
#ifdef __linux__
cap_t caps;
cap_value_t cap;
cap_flag_value_t flag;
Expand Down Expand Up @@ -228,9 +233,11 @@ static void check_cap(int isroot)
cleanup:
if (cap_free(caps) == -1) {
cap_err("Failed to free process capabilities: %s\n", strerror(errno));
return;
}
return;
#else
UNUSED(isroot);
bbs_debug(3, "Capabilities not supported\n");
#endif /* __linux__ */
}

#pragma GCC diagnostic ignored "-Wsign-conversion"
Expand Down Expand Up @@ -327,10 +334,12 @@ static int run_init(int argc, char *argv[])
}

if (!is_root() && option_dumpcore) {
#ifdef __linux__
if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) < 0) {
fprintf(stderr, "Unable to set the process for core dumps after changing to a non-root user. %s\n", strerror(errno));
return -1;
}
#endif /* __linux__ */
}

if (set_cwd()) {
Expand Down
3 changes: 3 additions & 0 deletions bbs/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@
#include <string.h>
#include <ctype.h>
#include <unistd.h>

#ifdef __linux__
#include <linux/limits.h> /* use PATH_MAX */
#endif

#include "include/linkedlists.h"
#include "include/config.h"
Expand Down
20 changes: 13 additions & 7 deletions bbs/crypt.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,29 @@
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <crypt.h>
#include <string.h> /* use strdup */
#include <ctype.h> /* use isprint, isalnum */
#include <sys/random.h>

#ifdef __linux__
#include <crypt.h>
#endif

#ifdef __GLIBC__
#include <gnu/libc-version.h>
#endif

#if !(defined __GLIBC__ && __GLIBC_MINOR__ >= 31)
#if defined(__linux__) && !(defined __GLIBC__ && __GLIBC_MINOR__ >= 31)
/* crypt with blowfish, from Openwall, since
* Debian 10's glibc's crypt doesn't have blowfish support, unlike Debian 11's.
* blowfish isn't available in Debian 10: https://github.com/NigelCunningham/pam-MySQL/issues/55
*
* XXX crypt_blowfish.c is only needed if NEED_CRYPTO_IMPL is defined.
*/
#define NEED_CRYPTO_IMPL
#define NEED_GENSALT_IMPL
#elif defined(__FreeBSD__)
#define NEED_GENSALT_IMPL
#endif

#ifdef NEED_CRYPTO_IMPL
Expand Down Expand Up @@ -81,7 +87,7 @@ int bbs_rand_alnum(char *buf, size_t len)
return 0;
}

#ifdef NEED_CRYPTO_IMPL
#ifdef NEED_GENSALT_IMPL
/*! \note Thank you, PHP */
static int php_bin2hex(const unsigned char *old, size_t oldlen, char *result, size_t newlen)
{
Expand Down Expand Up @@ -109,7 +115,7 @@ static int php_bin2hex(const unsigned char *old, size_t oldlen, char *result, si

char *bbs_password_salt(void)
{
#ifndef NEED_CRYPTO_IMPL
#ifndef NEED_GENSALT_IMPL
/* cost can be 4-31: https://manpages.debian.org/unstable/libcrypt-dev/crypt.5.en.html */
return crypt_gensalt_ra("$2b$", 11, NULL, 0); /* 2b = bcrypt */
#else
Expand Down Expand Up @@ -186,16 +192,16 @@ char *bbs_password_hash(const char *password, const char *salt)
#ifndef NEED_CRYPTO_IMPL
#ifdef CRYPT_DEBUG
bbs_debug(9, "Using real crypt_r\n");
#endif
#endif /* CRYPT_DEBUG */
hash = crypt_r(password, salt, &data); /* Use the real crypt_r */
#else
#ifdef CRYPT_DEBUG
bbs_debug(9, "Using alternate crypt_r\n");
#endif
#endif /* CRYPT_DEBUG */
data.current_salt[0] = '$';
data.current_salt[1] = '2';
hash = __crypt_r(password, salt, &data); /* Use our custom implementation of crypt_r */
#endif
#endif /* NEED_CRYPTO_IMPL */

if (strlen_zero(hash)) {
bbs_error("Failed to compute hash: %s\n", strerror(errno));
Expand Down
5 changes: 4 additions & 1 deletion bbs/logger.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,15 @@
#include <unistd.h>
#include <sys/time.h> /* use gettimeofday */
#include <unistd.h> /* use write */
#include <linux/limits.h> /* use PATH_MAX */
#include <sys/stat.h> /* use mkdir */
#include <sys/types.h>
#include <pthread.h>
#include <poll.h>

#ifdef __linux__
#include <linux/limits.h> /* use PATH_MAX */
#endif

#include "include/utils.h" /* use bbs_gettid, bbs_tvnow */
#include "include/linkedlists.h"
#include "include/cli.h"
Expand Down
4 changes: 4 additions & 0 deletions bbs/mail.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@
#include <unistd.h> /* use close */
#include <sys/time.h> /* use gettimeofday */

#ifdef __FreeBSD__
#include <libgen.h> /* use basename */
#endif

#include "include/base64.h"
#include "include/mail.h"
#include "include/config.h"
Expand Down
5 changes: 4 additions & 1 deletion bbs/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,13 @@
#include <stdio.h>
#include <string.h>
#include <dlfcn.h>
#include <linux/limits.h> /* use PATH_MAX */
#include <unistd.h> /* use usleep */
#include <poll.h>

#ifdef __linux__
#include <linux/limits.h> /* use PATH_MAX */
#endif

#include "include/linkedlists.h"
#include "include/stringlist.h"
#include "include/module.h"
Expand Down
6 changes: 3 additions & 3 deletions bbs/node.c
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,7 @@ static void node_shutdown(struct bbs_node *node, int unique)
if (!unique) {
/* node is now no longer a valid reference, since bbs_node_handler calls node_free (in another thread) before it quits. */
if (skipjoin) {
bbs_debug(3, "Skipping join of node %d thread %lu\n", nodeid, node_thread);
bbs_debug(3, "Skipping join of node %d thread %lu\n", nodeid, (unsigned long) node_thread);
} else { /* Either bbs_node_handler thread is detached, or somebody else is joining it */
bbs_debug(3, "Waiting for node %d to exit\n", nodeid);
bbs_pthread_join(node_thread, NULL); /* Wait for the bbs_node_handler thread to exit, and then clean it up. */
Expand Down Expand Up @@ -721,7 +721,7 @@ int bbs_interrupt_node(unsigned int nodenum)
* since we can easily enough check the interrupt status in the necessary places on EINTR. */
err = pthread_kill(node->thread, SIGUSR1); /* Uncaught signal, so the blocking I/O call will get interrupted */
if (err) {
bbs_warning("pthread_kill(%lu) failed: %s\n", node->thread, strerror(err));
bbs_warning("pthread_kill(%lu) failed: %s\n", (unsigned long) node->thread, strerror(err));
bbs_node_unlock(node);
return 1;
}
Expand Down Expand Up @@ -1395,7 +1395,7 @@ static int node_handler_term(struct bbs_node *node)
void bbs_node_begin(struct bbs_node *node)
{
bbs_assert_exists(node);
bbs_assert((int) node->thread);
bbs_assert((unsigned long) node->thread > 0);
bbs_assert(node->fd != -1);
bbs_assert_exists(node->protname); /* Will fail if a network comm driver forgets to set before calling bbs_node_handler */

Expand Down
Loading

0 comments on commit 3b479c6

Please sign in to comment.