/*
 * Copyright (C) 2008 Natanael Copa <natanael.copa@gmail.com>
 * 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;
}