/* 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("Couldn't 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;
}
