substroot: add a handy tool we'll use for boot scripts
authorAlan Cox <alan@linux.intel.com>
Sat, 14 Jul 2018 00:31:58 +0000 (01:31 +0100)
committerAlan Cox <alan@linux.intel.com>
Sat, 14 Jul 2018 00:31:58 +0000 (01:31 +0100)
Applications/util/Makefile.6502
Applications/util/Makefile.68000
Applications/util/Makefile.6809
Applications/util/substroot.1 [new file with mode: 0644]
Applications/util/substroot.c [new file with mode: 0644]

index 24bb8d6..f1144fd 100644 (file)
@@ -40,6 +40,7 @@ SRCSNS = \
        reboot.c \
        rm.c \
        rmdir.c \
+       substroot.c \
        sum.c \
        sync.c \
        tee.c \
index 954807d..7ff03f7 100644 (file)
@@ -43,6 +43,7 @@ SRCSNS = \
        reboot.c \
        rm.c \
        rmdir.c \
+       substroot.c \
        sum.c \
        sync.c \
        tee.c \
index 39fb538..28f51ef 100644 (file)
@@ -43,6 +43,7 @@ SRCSNS = \
        reboot.c \
        rm.c \
        rmdir.c \
+       substroot.c \
        sum.c \
        sync.c \
        tee.c \
diff --git a/Applications/util/substroot.1 b/Applications/util/substroot.1
new file mode 100644 (file)
index 0000000..a913396
--- /dev/null
@@ -0,0 +1,21 @@
+SUBSTROOT(8)
+## NAME
+*substroot* - substitute root filesystem device path into arguments
+## SYNOPSIS
+*substroot* command \[arg...\]
+## DESCRIPTION
+The *substroot* command replaces each argument that consists only of a '%'
+sign with the path to the root device and then executes the resulting
+command.
+
+It is intended for use in startup and shutdown scripts where there may be no
+pipes available and thus shell substitution cannot be used.
+## EXIT STATUS
+*substroot* exits with a status of 255 if an error occurs, otherwise the
+error code of the resulting command will be returned.
+## SEE ALSO
+prtroot(8)
+## STANDARDS
+substroot is a Fuzix specific command
+## AUTHOR
+Written by Alan Cox.
diff --git a/Applications/util/substroot.c b/Applications/util/substroot.c
new file mode 100644 (file)
index 0000000..44469b2
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ *     Substitute the root device path for % in a command line and then
+ *     execute the result.
+ *
+ *     Used in things liek boot scripts where we may not have pipes and thus
+ *     command line substitutions. We can't put this functionality in each
+ *     command, and in a few cases it won't fit (fsck for example).
+ *
+ *  (C) Copyright 2018 Alan Cox
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/mount.h>
+#include <dirent.h>
+#include <unistd.h>
+
+#define DEV_PATH "/dev/"
+
+static char *root_device(void)
+{
+       static DIR dp;
+       struct dirent *entry;
+       struct stat filestat, rootstat;
+       static char namebuf[sizeof(DEV_PATH) + MAXNAMLEN + 1];
+
+       if (stat("/", &rootstat) == 0 && opendir_r(&dp, DEV_PATH) != (DIR *) NULL) {
+               while ((entry = readdir(&dp)) != (struct dirent *) NULL) {
+                       strcpy(namebuf, DEV_PATH);
+                       strlcat(namebuf, entry->d_name, sizeof(namebuf));
+                       if (stat(namebuf, &filestat) != 0)
+                               continue;
+                       if (!S_ISBLK(filestat.st_mode))
+                               continue;
+                       if (filestat.st_rdev != rootstat.st_dev)
+                               continue;
+                       return namebuf;
+               }
+       }
+       return NULL;
+}
+
+int main(int argc, char *argv[])
+{
+       char *root = root_device();
+       int n = 2;
+       if (root == NULL) {
+               write(2, "substroot: unable to find root device.\n", 39);
+               exit(255);
+       }
+       if (argc < 2) {
+               write(2, "substroot app ...\n", 18);
+               exit(255);
+       }
+       while (n < argc) {
+               if (strcmp(argv[n], "%") == 0)
+                       argv[n] = root;
+               n++;
+       }
+       execvp(argv[1], argv + 1);
+       perror(argv[1]);
+       exit(1);
+}