Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(cron): support Debian and Ubuntu #211

Merged
merged 1 commit into from
Jun 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions features/src/cron/bbsuid.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* Copyright (C) 2008 Natanael Copa <[email protected]>
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation. See http://www.gnu.org/ for details.
*
*/

#include <sys/stat.h>
#include <sys/types.h>

#include <libgen.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <err.h>

#define BBSUID_PATH "/bin/bbsuid"

const static char * applets[] = {
"/bin/mount",
"/bin/umount",
"/bin/su",
"/usr/bin/crontab",
"/usr/bin/passwd",
"/usr/bin/traceroute",
"/usr/bin/traceroute6",
"/usr/bin/vlock",
NULL
};


static const char *applet_from_path(const char *str)
{
const char *p = strrchr(str, '/');
if (p == NULL)
p = str;
else
p++;
return p;
}

static int is_valid_applet(const char *str)
{
int i;
for (i = 0; applets[i] != NULL; i++) {
const char *a = applet_from_path(applets[i]);
if (strcmp(applet_from_path(str), a) == 0)
return 1;
}
return 0;
}

int exec_busybox(const char *app, int argc, char **argv)
{
char **newargv = malloc((argc + 2) * sizeof(char *));
int i;
newargv[0] = "/bin/busybox";
newargv[1] = (char *)app;
for (i = 1; i < argc; i++)
newargv[i+1] = argv[i];
newargv[argc+1] = NULL;
execv(newargv[0], newargv);
perror(newargv[0]);
free(newargv);
return 1;
}

static int install_links(void)
{
int i, r = 0;
/* we don't want others than root to install the symlinks */
if (getuid() != 0)
errx(1, "Only root can install symlinks");

for (i = 0; applets[i] != NULL; i++) {
const char *a = applets[i];
struct stat st;
if (lstat(a, &st) == 0 && S_ISLNK(st.st_mode))
unlink(a);
if (symlink(BBSUID_PATH, a) < 0)
r++;
}

return r;
}

int main(int argc, char **argv)
{
const char *app = applet_from_path(argv[0]);

if (strcmp(app, "bbsuid") == 0) {
if (argc == 2 && strcmp(argv[1], "--install") == 0)
return install_links();
errx(1, "Use --install to install symlinks");
}

if (is_valid_applet(app))
return exec_busybox(app, argc, argv);

errx(1, "%s is not a valid applet", app);
return 1;
}

4 changes: 2 additions & 2 deletions features/src/cron/devcontainer-feature.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
"id": "cron",
"name": "Cron",
"description": "Enables cron in the Dev Environment",
"version": "1.0.3",
"version": "1.1.0",
"options": {
"enabled": {
"type": "boolean",
"default": false,
"default": true,
"description": "Enable cron"
},
"run_wp_cron": {
Expand Down
68 changes: 59 additions & 9 deletions features/src/cron/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,73 @@ if [ "$(id -u || true)" -ne 0 ]; then
exit 1
fi

: "${_REMOTE_USER:?"_REMOTE_USER is required"}"

if [ "${ENABLED:-}" = 'true' ]; then
echo '(*) Installing cron...'
apk add --no-cache busybox-suid

# shellcheck source=/dev/null
. /etc/os-release
: "${ID:=}"
: "${ID_LIKE:=${ID}}"

case "${ID_LIKE}" in
"debian")
# In Ubuntu Noble, cron now depends on systemd. We need to install busybox-static and use it as crond/crontab to avoid garbage in the system.
PACKAGES_NOREMOVE=""
PACKAGES=""
if [ ! -f /usr/bin/busybox ]; then
PACKAGES_NOREMOVE="${PACKAGES_NOREMOVE} busybox-static"
fi

if ! dpkg -s libc6-dev >/dev/null 2>&1; then
PACKAGES="${PACKAGES} libc6-dev"
fi

if ! hash cc >/dev/null 2>&1; then
PACKAGES="${PACKAGES} tcc"
fi

if [ -n "${PACKAGES}" ] || [ -n "${PACKAGES_NOREMOVE}" ]; then
apt-get update
# shellcheck disable=SC2086
apt-get install -y --no-install-recommends ${PACKAGES} ${PACKAGES_NOREMOVE}
fi

cc -O2 bbsuid.c -o /usr/local/bin/bbsuid

if [ -n "${PACKAGES}" ]; then
# shellcheck disable=SC2086
apt-get purge -y --auto-remove ${PACKAGES}
fi

apt-get clean
rm -rf /var/lib/apt/lists/*

chown root:root /usr/local/bin/bbsuid
chmod 04111 /usr/local/bin/bbsuid
ln -s /usr/local/bin/bbsuid /usr/bin/crontab
ln -s /usr/bin/busybox /usr/sbin/crond
install -D -d -m 0755 -o root -g root /var/spool/cron/crontabs
;;

"alpine")
apk add --no-cache busybox-suid
;;

*)
echo "(!) Unsupported distribution: ${ID}"
exit 1
;;
esac

install -D -m 0755 -o root -g root service-run /etc/sv/cron/run
install -d -m 0755 -o root -g root /etc/service
install -m 0755 -o root -g root wp-cron.sh /usr/local/bin/wp-cron.sh
ln -sf /etc/sv/cron /etc/service/cron

if [ "${RUN_WP_CRON:-}" = 'true' ] && [ -n "${WP_CRON_SCHEDULE:-}" ]; then
if [ -z "${_REMOTE_USER}" ] || [ "${_REMOTE_USER}" = "root" ]; then
WEB_USER=www-data
else
WEB_USER="${_REMOTE_USER}"
fi

echo "${WP_CRON_SCHEDULE} /usr/bin/flock -n /tmp/wp-cron.lock /usr/local/bin/wp-cron.sh" | crontab -u "${WEB_USER}" -
install -m 0755 -o root -g root wp-cron.sh /usr/local/bin/wp-cron.sh
echo "${WP_CRON_SCHEDULE} /usr/bin/flock -n /tmp/wp-cron.lock /usr/local/bin/wp-cron.sh" | crontab -u "${_REMOTE_USER}" -
fi

echo 'Done!'
Expand Down
2 changes: 1 addition & 1 deletion features/src/cron/service-run
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

exec 2>&1

/usr/sbin/crond -f -d 8 -L /var/log/cron.log
exec /usr/sbin/crond -f -l 8