Introduction
Introduction Statistics Contact Development Disclaimer Help
Initial commit - smdev - suckless mdev
git clone git://git.suckless.org/smdev
Log
Files
Refs
README
LICENSE
---
commit 733f60dba2b8c878945b856c23a6bc44de52fc11
Author: sin <[email protected]>
Date: Tue, 20 Aug 2013 13:26:10 +0100
Initial commit
Diffstat:
A LICENSE | 21 +++++++++++++++++++++
A Makefile | 59 +++++++++++++++++++++++++++++…
A arg.h | 55 +++++++++++++++++++++++++++++…
A config.h | 26 ++++++++++++++++++++++++++
A config.mk | 12 ++++++++++++
A smdev.c | 209 +++++++++++++++++++++++++++++…
A util.h | 13 +++++++++++++
A util/agetcwd.c | 18 ++++++++++++++++++
A util/apathmax.c | 25 +++++++++++++++++++++++++
A util/eprintf.c | 46 +++++++++++++++++++++++++++++…
A util/estrtol.c | 27 +++++++++++++++++++++++++++
A util/recurse.c | 40 +++++++++++++++++++++++++++++…
12 files changed, 551 insertions(+), 0 deletions(-)
---
diff --git a/LICENSE b/LICENSE
@@ -0,0 +1,21 @@
+MIT/X Consortium License
+
+© 2013 sin <[email protected]>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/Makefile b/Makefile
@@ -0,0 +1,59 @@
+include config.mk
+
+.POSIX:
+.SUFFIXES: .c .o
+
+LIB = \
+ util/agetcwd.o \
+ util/apathmax.o \
+ util/eprintf.o \
+ util/estrtol.o \
+ util/recurse.o
+
+SRC = smdev.c
+
+OBJ = $(SRC:.c=.o) $(LIB)
+BIN = $(SRC:.c=)
+MAN = $(SRC:.c=.1)
+
+all: options binlib
+
+options:
+ @echo mdev build options:
+ @echo "CFLAGS = $(CFLAGS)"
+ @echo "LDFLAGS = $(LDFLAGS)"
+ @echo "CC = $(CC)"
+
+binlib: util.a
+ $(MAKE) bin
+
+bin: $(BIN)
+
+$(OBJ): util.h config.mk
+
+.o:
+ @echo LD $@
+ @$(LD) -o $@ $< util.a $(LDFLAGS)
+
+.c.o:
+ @echo CC $<
+ @$(CC) -c -o $@ $< $(CFLAGS)
+
+util.a: $(LIB)
+ @echo AR $@
+ @$(AR) -r -c $@ $(LIB)
+ @ranlib $@
+
+install: all
+ @echo installing executable to $(DESTDIR)$(PREFIX)/sbin
+ @mkdir -p $(DESTDIR)$(PREFIX)/sbin
+ @cp -f $(BIN) $(DESTDIR)$(PREFIX)/sbin
+ @cd $(DESTDIR)$(PREFIX)/sbin && chmod 755 $(BIN)
+
+uninstall:
+ @echo removing executable from $(DESTDIR)$(PREFIX)/sbin
+ @cd $(DESTDIR)$(PREFIX)/sbin && rm -f $(BIN)
+
+clean:
+ @echo cleaning
+ @rm -f $(BIN) $(OBJ) $(LIB) util.a
diff --git a/arg.h b/arg.h
@@ -0,0 +1,55 @@
+/*
+ * Copy me if you can.
+ * by 20h
+ */
+
+#ifndef __ARG_H__
+#define __ARG_H__
+
+extern char *argv0;
+
+#define USED(x) ((void)(x))
+
+/* use main(int argc, char *argv[]) */
+#define ARGBEGIN for (argv0 = *argv, argv++, argc--;\
+ argv[0] && argv[0][1]\
+ && argv[0][0] == '-';\
+ argc--, argv++) {\
+ char _argc;\
+ char **_argv;\
+ int brk;\
+ if (argv[0][1] == '-' && argv[0][2] == '\0') {\
+ argv++;\
+ argc--;\
+ break;\
+ }\
+ for (brk = 0, argv[0]++, _argv = argv;\
+ argv[0][0] && !brk;\
+ argv[0]++) {\
+ if (_argv != argv)\
+ break;\
+ _argc = argv[0][0];\
+ switch (_argc)
+
+#define ARGEND }\
+ USED(_argc);\
+ }\
+ USED(argv);\
+ USED(argc);
+
+#define ARGC() _argc
+
+#define EARGF(x) ((argv[0][1] == '\0' && argv[1] == NULL)?\
+ ((x), abort(), (char *)0) :\
+ (brk = 1, (argv[0][1] != '\0')?\
+ (&argv[0][1]) :\
+ (argc--, argv++, argv[0])))
+
+#define ARGF() ((argv[0][1] == '\0' && argv[1] == NULL)?\
+ (char *)0 :\
+ (brk = 1, (argv[0][1] != '\0')?\
+ (&argv[0][1]) :\
+ (argc--, argv++, argv[0])))
+
+#endif
+
diff --git a/config.h b/config.h
@@ -0,0 +1,26 @@
+/* See LICENSE file for copyright and license details. */
+struct {
+ const char *devregex;
+ const char *user;
+ const char *group;
+ int mode;
+ const char *path;
+ const char *cmd;
+} Rules[] = {
+ { "null", "root", "root", 0666, NULL, "@chmod 666 $SMDEV" },
+ { "zero", "root", "root", 0666, NULL, NULL },
+ { "full", "root", "root", 0666, NULL, NULL },
+ { "random", "root", "root", 0666, NULL, NULL },
+ { "urandom", "root", "root", 0666, NULL, NULL },
+ { "mem", "root", "root", 0640, NULL, NULL },
+ { "kmem", "root", "root", 0640, NULL, NULL },
+ { "console", "root", "tty", 0600, NULL, "@chmod 600 $SMDEV" },
+ { "ptmx", "root", "tty", 0666, NULL, NULL },
+ { "pty.*", "root", "tty", 0660, NULL, NULL },
+ { "tty", "root", "tty", 0666, NULL, NULL },
+ { "tty[0-9]*", "root", "tty", 0660, NULL, NULL },
+ { "vcsa*[0-9]*","root", "tty", 0660, NULL, NULL },
+ { "sd[a-z].*", "root", "disk", 0660, NULL, NULL },
+ { "sr[0-9]*", "root", "cdrom", 0660, NULL, "@ln -sf $SMDEV cdrom" },
+ { ".*", "root", "root", 0777, NULL, NULL },
+};
diff --git a/config.mk b/config.mk
@@ -0,0 +1,12 @@
+# smdev version
+VERSION = 0.0
+
+# paths
+PREFIX = /usr/local
+
+#CC = gcc
+#CC = musl-gcc
+LD = $(CC)
+CPPFLAGS = -D_BSD_SOURCE -D_GNU_SOURCE
+CFLAGS = -g -ansi -Wall $(CPPFLAGS)
+LDFLAGS = -g
diff --git a/smdev.c b/smdev.c
@@ -0,0 +1,209 @@
+/* See LICENSE file for copyright and license details. */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <pwd.h>
+#include <grp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <regex.h>
+#include "config.h"
+#include "util.h"
+
+static int devtomajmin(const char *path, int *maj, int *min);
+static int devtype(const char *majmin);
+static int create_dev(const char *path);
+static void sysrecurse(const char *path);
+
+static void
+usage(void)
+{
+ eprintf("usage: %s [-s]\n", argv0);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int sflag = 0;
+
+ ARGBEGIN {
+ case 's':
+ sflag = 1;
+ break;
+ default:
+ usage();
+ } ARGEND;
+
+ if (!sflag)
+ usage();
+
+ recurse("/sys/devices", sysrecurse);
+
+ return 0;
+}
+
+/* Example `path' is /sys/devices/virtual/tty/tty0/dev */
+static int
+devtomajmin(const char *path, int *maj, int *min)
+{
+ char buf[BUFSIZ];
+ int fd;
+ ssize_t n;
+
+ fd = open(path, O_RDONLY);
+ if (fd < 0)
+ eprintf("open %s:", path);
+ n = read(fd, buf, sizeof(buf) - 1);
+ close(fd);
+ if (n < 0)
+ eprintf("%s: read error:", path);
+ if (!n)
+ return -1;
+ if (buf[n - 1] == '\n')
+ buf[n - 1] = '\0';
+ buf[n] = '\0';
+ sscanf(buf, "%d:%d", maj, min);
+ return 0;
+}
+
+static int
+devtype(const char *majmin)
+{
+ char path[PATH_MAX];
+
+ snprintf(path, sizeof(path), "/sys/dev/block/%s", majmin);
+ if (!access(path, F_OK))
+ return S_IFBLK;
+ snprintf(path, sizeof(path), "/sys/dev/char/%s", majmin);
+ if (!access(path, F_OK))
+ return S_IFCHR;
+ return -1;
+}
+
+static int
+create_dev(const char *path)
+{
+ struct passwd *pw;
+ struct group *gr;
+ regex_t match;
+ regmatch_t off;
+ char *regex;
+ char buf[64], *p;
+ char tmppath[PATH_MAX], devpath[PATH_MAX], *dev;
+ char *devname;
+ int maj, min, type;
+ int i, ret;
+
+ p = strrchr(path, '/');
+ if (!p)
+ return -1;
+ p++;
+ devname = strdup(p);
+ if (!devname)
+ eprintf("strdup:");
+ snprintf(devpath, sizeof(devpath), "/dev/%s", devname);
+
+ snprintf(tmppath, sizeof(tmppath), "%s/dev", path);
+ ret = devtomajmin(tmppath, &maj, &min);
+ if (ret < 0) {
+ free(devname);
+ return -1;
+ }
+
+ snprintf(buf, sizeof(buf), "%d:%d", maj, min);
+ type = devtype(buf);
+ if (type < 0) {
+ free(devname);
+ return -1;
+ }
+
+ for (i = 0; i < LEN(Rules); i++) {
+ regex = strdup(Rules[i].devregex);
+ if (!regex)
+ eprintf("strdup:");
+
+ ret = regcomp(&match, regex, REG_EXTENDED);
+ if (ret < 0)
+ eprintf("regcomp:");
+
+ ret = regexec(&match, devname, 1, &off, 0);
+ regfree(&match);
+ free(regex);
+
+ if (ret || off.rm_so || off.rm_eo != strlen(devname))
+ continue;
+
+ if (Rules[i].cmd) {
+ switch (Rules[i].cmd[0]) {
+ case '@':
+ case '$':
+ case '*':
+ fprintf(stderr, "Unsupported command '%s' for …
+ Rules[i].cmd, Rules[i].devregex);
+ break;
+ default:
+ eprintf("Invalid command '%s'\n", Rules[i].cmd…
+ }
+ }
+
+ dev = devpath;
+ if (Rules[i].path) {
+ switch (Rules[i].path[0]) {
+ case '=':
+ if (Rules[i].path[strlen(Rules[i].path) - 1] =…
+ snprintf(devpath, sizeof(devpath), "/d…
+ if (mkdir(devpath, 0755) < 0)
+ eprintf("mkdir %s:", devpath);
+ strcat(devpath, devname);
+ } else {
+ snprintf(devpath, sizeof(devpath),
+ "/dev/%s", &Rules[i].path[1]);
+ }
+ break;
+ case '>':
+ fprintf(stderr, "Unsupported path '%s' for tar…
+ Rules[i].path, Rules[i].devregex);
+ break;
+ default:
+ eprintf("Invalid path '%s'\n", Rules[i].path);
+ }
+ }
+
+ ret = mknod(dev, Rules[i].mode | type, makedev(maj, min));
+ if (ret < 0 && errno != EEXIST)
+ eprintf("mknod %s:", dev);
+
+ pw = getpwnam(Rules[i].user);
+ if (!pw)
+ eprintf("getpwnam %s:", Rules[i].user);
+
+ gr = getgrnam(Rules[i].group);
+ if (!gr)
+ eprintf("getgrnam %s:", Rules[i].group);
+
+ ret = chown(dev, pw->pw_uid, gr->gr_gid);
+ if (ret < 0)
+ eprintf("chown %s:", dev);
+ break;
+ }
+
+ free(devname);
+ return 0;
+}
+
+static void
+sysrecurse(const char *path)
+{
+ char *cwd;
+
+ recurse(path, sysrecurse);
+ if (!strcmp(path, "dev")) {
+ cwd = agetcwd();
+ create_dev(cwd);
+ free(cwd);
+ }
+}
diff --git a/util.h b/util.h
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#include "arg.h"
+
+#define LEN(x) (sizeof (x) / sizeof *(x))
+
+extern char *argv0;
+
+char *agetcwd(void);
+void apathmax(char **, long *);
+void enprintf(int, const char *, ...);
+void eprintf(const char *, ...);
+long estrtol(const char *, int);
+void recurse(const char *, void (*)(const char *));
diff --git a/util/agetcwd.c b/util/agetcwd.c
@@ -0,0 +1,18 @@
+/* See LICENSE file for copyright and license details. */
+#include <unistd.h>
+
+#include "../util.h"
+
+char *
+agetcwd(void)
+{
+ char *buf;
+ long size;
+
+ apathmax(&buf, &size);
+ if(!getcwd(buf, size))
+ eprintf("getcwd:");
+
+ return buf;
+}
+
diff --git a/util/apathmax.c b/util/apathmax.c
@@ -0,0 +1,25 @@
+/* See LICENSE file for copyright and license details. */
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "../util.h"
+
+void
+apathmax(char **p, long *size)
+{
+ errno = 0;
+
+ if((*size = pathconf("/", _PC_PATH_MAX)) == -1) {
+ if(errno == 0) {
+ *size = BUFSIZ;
+ } else {
+ eprintf("pathconf:");
+ }
+ }
+
+ if(!(*p = malloc(*size)))
+ eprintf("malloc:");
+}
+
diff --git a/util/eprintf.c b/util/eprintf.c
@@ -0,0 +1,46 @@
+/* See LICENSE file for copyright and license details. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../util.h"
+
+char *argv0;
+
+static void venprintf(int, const char *, va_list);
+
+void
+eprintf(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ venprintf(EXIT_FAILURE, fmt, ap);
+ va_end(ap);
+}
+
+void
+enprintf(int status, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ venprintf(status, fmt, ap);
+ va_end(ap);
+}
+
+void
+venprintf(int status, const char *fmt, va_list ap)
+{
+ /*fprintf(stderr, "%s: ", argv0);*/
+
+ vfprintf(stderr, fmt, ap);
+
+ if(fmt[0] && fmt[strlen(fmt)-1] == ':') {
+ fputc(' ', stderr);
+ perror(NULL);
+ }
+
+ exit(status);
+}
diff --git a/util/estrtol.c b/util/estrtol.c
@@ -0,0 +1,27 @@
+/* See LICENSE file for copyright and license details. */
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "../util.h"
+
+long
+estrtol(const char *s, int base)
+{
+ char *end;
+ long n;
+
+ errno = 0;
+ n = strtol(s, &end, base);
+ if(*end != '\0') {
+ if(base == 0)
+ eprintf("%s: not an integer\n", s);
+ else
+ eprintf("%s: not a base %d integer\n", s, base);
+ }
+ if(errno != 0)
+ eprintf("%s:", s);
+
+ return n;
+}
+
diff --git a/util/recurse.c b/util/recurse.c
@@ -0,0 +1,40 @@
+/* See LICENSE file for copyright and license details. */
+#include <dirent.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+#include "../util.h"
+
+void
+recurse(const char *path, void (*fn)(const char *))
+{
+ char *cwd;
+ struct dirent *d;
+ struct stat st;
+ DIR *dp;
+
+ if(lstat(path, &st) == -1 || !S_ISDIR(st.st_mode)) {
+ return;
+ } else if(!(dp = opendir(path))) {
+ eprintf("opendir %s:", path);
+ }
+
+ cwd = agetcwd();
+ if(chdir(path) == -1)
+ eprintf("chdir %s:", path);
+
+ while((d = readdir(dp))) {
+ if(strcmp(d->d_name, ".") && strcmp(d->d_name, ".."))
+ fn(d->d_name);
+ }
+
+ closedir(dp);
+ if(chdir(cwd) == -1)
+ eprintf("chdir %s:", cwd);
+
+ free(cwd);
+}
+
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.