/*
* 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>
#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;
}