/* vi: set sw=4 ts=4: */
/*
 *
 * mdev - Mini udev for busybox
 *
 * Copyright 2005 Rob Landley <rob@landley.net>
 * Copyright 2005 Frank Sorenson <frank@tuxrocks.com>
 *
 * Licensed under GPL version 2, see file LICENSE in this tarball for details.
 */

#include "busybox.h"
#include "xregex.h"

#define DEV_PATH	"/dev"

struct mdev_globals
{
	int root_major, root_minor;
} mdev_globals;

#define bbg mdev_globals

/* mknod in /dev based on a path like "/sys/block/hda/hda1" */
static void make_device(char *path, int delete)
{
	char *device_name;
	int major, minor, type, len;
	int mode = 0660;
	uid_t uid = 0;
	gid_t gid = 0;
	char *temp = path + strlen(path);
	char *command = NULL;

	/* Try to read major/minor string.  Note that the kernel puts \n after
	 * the data, so we don't need to worry about null terminating the string
	 * because sscanf() will stop at the first nondigit, which \n is.  We
	 * also depend on path having writeable space after it. */

	if (!delete) {
		strcat(path, "/dev");
		len = open_read_close(path, temp + 1, 64);
		*temp++ = 0;
		if (len < 1) return;
	}

	/* Determine device name, type, major and minor */

	device_name = strrchr(path, '/') + 1;
	type = path[5]=='c' ? S_IFCHR : S_IFBLK;

	/* If we have a config file, look up permissions for this device */

	if (ENABLE_FEATURE_MDEV_CONF) {
		char *conf, *pos, *end;
		int line, fd;

		/* mmap the config file */
		fd = open("/etc/mdev.conf", O_RDONLY);
		if (fd < 0)
			goto end_parse;
		len = xlseek(fd, 0, SEEK_END);
		conf = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
		close(fd);
		if (!conf)
			goto end_parse;

		line = 0;
		/* Loop through lines in mmaped file*/
		for (pos=conf; pos-conf<len;) {
			int field;
			char *end2;

			line++;
			/* find end of this line */
			for (end=pos; end-conf<len && *end!='\n'; end++)
				;

			/* Three fields: regex, uid:gid, mode */
			for (field=0; field < (3 + ENABLE_FEATURE_MDEV_EXEC);
					field++)
			{
				/* Skip whitespace */
				while (pos<end && isspace(*pos)) pos++;
				if (pos==end || *pos=='#') break;
				for (end2=pos;
					end2<end && !isspace(*end2) && *end2!='#'; end2++)
					;

				if (field == 0) {
					/* Regex to match this device */

					char *regex = strndupa(pos, end2-pos);
					regex_t match;
					regmatch_t off;
					int result;

					/* Is this it? */
					xregcomp(&match,regex, REG_EXTENDED);
					result = regexec(&match, device_name, 1, &off, 0);
					regfree(&match);

					/* If not this device, skip rest of line */
					if (result || off.rm_so
							|| off.rm_eo != strlen(device_name))
						break;
				}
				if (field == 1) {
					/* uid:gid */

					char *s, *s2;

					/* Find : */
					for (s=pos; s<end2 && *s!=':'; s++)
						;
					if (s == end2) break;

					/* Parse UID */
					uid = strtoul(pos, &s2, 10);
					if (s != s2) {
						struct passwd *pass;
						pass = getpwnam(strndupa(pos, s-pos));
						if (!pass) break;
						uid = pass->pw_uid;
					}
					s++;
					/* parse GID */
					gid = strtoul(s, &s2, 10);
					if (end2 != s2) {
						struct group *grp;
						grp = getgrnam(strndupa(s, end2-s));
						if (!grp) break;
						gid = grp->gr_gid;
					}
				}
				if (field == 2) {
					/* mode */

					mode = strtoul(pos, &pos, 8);
					if (pos != end2) break;
				}
				if (ENABLE_FEATURE_MDEV_EXEC && field == 3) {
					// Command to run
					const char *s = "@$*";
					const char *s2;
					s2 = strchr(s, *pos++);
					if (!s2) {
						// Force error
						field = 1;
						break;
					}
					if ((s2-s+1) & (1<<delete))
						command = xstrndup(pos, end-pos);
				}

				pos = end2;
			}

			/* Did everything parse happily? */

			if (field > 2) break;
			if (field) bb_error_msg_and_die("bad line %d",line);

			/* Next line */
			pos = ++end;
		}
		munmap(conf, len);
 end_parse:	/* nothing */ ;
	}

	umask(0);
	if (!delete) {
		if (sscanf(temp, "%d:%d", &major, &minor) != 2) return;
		if (mknod(device_name, mode | type, makedev(major, minor)) && errno != EEXIST)
			bb_perror_msg_and_die("mknod %s", device_name);

		if (major == bbg.root_major && minor == bbg.root_minor)
			symlink(device_name, "root");

		if (ENABLE_FEATURE_MDEV_CONF) chown(device_name, uid, gid);
	}
	if (command) {
		int rc;
		char *s;

		s = xasprintf("MDEV=%s", device_name);
		putenv(s);
		rc = system(command);
		s[4] = 0;
		putenv(s);
		free(s);
		free(command);
		if (rc == -1) bb_perror_msg_and_die("cannot run %s", command);
	}
	if (delete) unlink(device_name);
}

/* Recursive search of /sys/block or /sys/class.  path must be a writeable
 * buffer of size PATH_MAX containing the directory string to start at. */

static void find_dev(char *path)
{
	DIR *dir;
	size_t len = strlen(path);
	struct dirent *entry;

	dir = opendir(path);
	if (dir == NULL)
		return;

	while ((entry = readdir(dir)) != NULL) {
		struct stat st;

		/* Skip "." and ".." (also skips hidden files, which is ok) */

		if (entry->d_name[0] == '.')
			continue;

		// uClibc doesn't fill out entry->d_type reliably. so we use lstat().

		snprintf(path+len, PATH_MAX-len, "/%s", entry->d_name);
		if (!lstat(path, &st) && S_ISDIR(st.st_mode)) find_dev(path);
		path[len] = 0;

		/* If there's a dev entry, mknod it */

		if (!strcmp(entry->d_name, "dev")) make_device(path, 0);
	}

	closedir(dir);
}

int mdev_main(int argc, char **argv);
int mdev_main(int argc, char **argv)
{
	char *action;
	char *env_path;
	RESERVE_CONFIG_BUFFER(temp,PATH_MAX);

	xchdir(DEV_PATH);

	/* Scan */

	if (argc == 2 && !strcmp(argv[1],"-s")) {
		struct stat st;

		xstat("/", &st);
		bbg.root_major = major(st.st_dev);
		bbg.root_minor = minor(st.st_dev);
		strcpy(temp,"/sys/block");
		find_dev(temp);
		strcpy(temp,"/sys/class");
		find_dev(temp);

	/* Hotplug */

	} else {
		action = getenv("ACTION");
		env_path = getenv("DEVPATH");
		if (!action || !env_path)
			bb_show_usage();

		sprintf(temp, "/sys%s", env_path);
		if (!strcmp(action, "add")) make_device(temp,0);
		else if (!strcmp(action, "remove")) make_device(temp,1);
	}

	if (ENABLE_FEATURE_CLEAN_UP) RELEASE_CONFIG_BUFFER(temp);
	return 0;
}
