/* 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, fd;
	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");
		fd = open(path, O_RDONLY);
		len = read(fd, temp + 1, 64);
		*temp++ = 0;
		close(fd);
		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;

		/* mmap the config file */
		if (-1 != (fd=open("/etc/mdev.conf",O_RDONLY))) {
			len = lseek(fd, 0, SEEK_END);
			conf = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
			if (conf) {
				int 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) {
							/* 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;

						} else 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;
							}
						} else if (field == 2) {
							/* mode */

							mode = strtoul(pos, &pos, 8);
							if (pos != end2) break;
						} else if (ENABLE_FEATURE_MDEV_EXEC && field == 3) {
							// Command to run
							char *s = "@$*", *s2;
							if (!(s2 = strchr(s, *pos++))) {
								// 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);
			}
			close(fd);
		}
	}

	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 failed", 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;

	if ((dir = opendir(path)) == 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[])
{
	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;

		stat("/", &st);  // If this fails, we have bigger problems.
		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;
}
