]>
git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/nash/nash.c
4 * Simple code to load modules, mount root, and get things going. Uses
5 * dietlibc to keep things small.
7 * Erik Troan (ewt@redhat.com)
8 * Jeremy Katz (katzj@redhat.com)
9 * Peter Jones (pjones@redhat.com)
11 * Copyright 2002-2005 Red Hat Software
13 * This software may be freely redistributed under the terms of the GNU
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 /* We internalize losetup, mount, raidautorun, and echo commands. Other
23 commands are run from the filesystem. Comments and blank lines work as
24 well, argument parsing is screwy. */
35 #include <sys/ioctl.h>
36 #include <sys/mount.h>
37 #include <sys/socket.h>
40 #include <sys/types.h>
44 #include <sys/ioctl.h>
45 #include <sys/reboot.h>
48 #include <asm/unistd.h>
50 #include "mount_by_label.h"
52 /* Need to tell loop.h what the actual dev_t type is. */
54 #if defined(__alpha) || (defined(__sparc__) && defined(__arch64__))
55 #define dev_t unsigned int
57 #define dev_t unsigned short
59 #include <linux/loop.h>
63 #define syslog klogctl
65 #include <linux/cdrom.h>
67 #include <linux/raid/md_u.h>
70 #define RAID_AUTORUN _IO (MD_MAJOR, 0x14)
90 #define MNT_DETACH 0x2
93 extern dev_t
name_to_dev_t(char *name
);
94 extern int display_uuid_cache(void);
96 #define MAX(a, b) ((a) > (b) ? a : b)
98 int testing
= 0, quiet
= 0, reallyquiet
= 0;
100 #define PATH "/usr/bin:/bin:/sbin:/usr/sbin"
104 "LVM_SUPPRESS_FD_WARNINGS=1",
108 int smartmknod(char * device
, mode_t mode
, dev_t dev
) {
112 strncpy(buf
, device
, 256);
118 if (access(buf
, F_OK
) && errno
== ENOENT
)
126 return mknod(device
, mode
, dev
);
129 char * getArg(char * cmd
, char * end
, char ** arg
) {
132 if (!cmd
|| cmd
>= end
) return NULL
;
134 while (isspace(*cmd
) && cmd
< end
) cmd
++;
135 if (cmd
>= end
) return NULL
;
139 else if (*cmd
== '\'')
145 /* This doesn't support \ escapes */
146 while (cmd
< end
&& *cmd
!= quote
) cmd
++;
149 printf("error: quote mismatch for %s\n", *arg
);
157 while (!isspace(*cmd
) && cmd
< end
) cmd
++;
160 *arg
= getenv(*arg
+1);
167 while (isspace(*cmd
)) cmd
++;
172 /* taken from anaconda/isys/probe.c */
173 static int readFD (int fd
, char **buf
)
179 *buf
= malloc (size
);
185 p
= &(*buf
) [filesize
];
186 s
= read (fd
, p
, 4096);
193 *buf
= realloc (*buf
, size
);
196 if (filesize
== 0 && s
< 0) {
206 #define CMDLINESIZE 256
208 #define CMDLINESIZE 1024
211 /* get the contents of the kernel command line from /proc/cmdline */
212 static char * getKernelCmdLine(void) {
216 fd
= open("/proc/cmdline", O_RDONLY
, 0);
218 printf("getKernelCmdLine: failed to open /proc/cmdline: %d\n", errno
);
222 buf
= malloc(CMDLINESIZE
);
226 i
= read(fd
, buf
, CMDLINESIZE
);
228 printf("getKernelCmdLine: failed to read /proc/cmdline: %d\n", errno
);
241 /* get the start of a kernel arg "arg". returns everything after it
242 * (useful for things like getting the args to init=). so if you only
243 * want one arg, you need to terminate it at the n */
244 static char * getKernelArg(char * arg
) {
245 char * start
, * cmdline
;
247 cmdline
= start
= getKernelCmdLine();
248 if (start
== NULL
) return NULL
;
250 if (isspace(*start
)) {
254 if (strncmp(start
, arg
, strlen(arg
)) == 0) {
255 return start
+ strlen(arg
);
257 while (*++start
&& !isspace(*start
))
264 int mountCommand(char * cmd
, char * end
) {
265 char * fsType
= NULL
;
268 char * deviceDir
= NULL
;
269 char * options
= NULL
;
271 int mustRemoveDir
= 0;
273 int flags
= MS_MGC_VAL
;
276 cmd
= getArg(cmd
, end
, &device
);
278 printf("usage: mount [--ro] [-o <opts>] -t <type> <device> <mntpoint>\n");
282 while (cmd
&& *device
== '-') {
283 if (!strcmp(device
, "--ro")) {
285 } else if (!strcmp(device
, "--bind")) {
288 } else if (!strcmp(device
, "-o")) {
289 cmd
= getArg(cmd
, end
, &options
);
291 printf("mount: -o requires arguments\n");
294 } else if (!strcmp(device
, "-t")) {
295 if (!(cmd
= getArg(cmd
, end
, &fsType
))) {
296 printf("mount: missing filesystem type\n");
301 cmd
= getArg(cmd
, end
, &device
);
305 printf("mount: missing device\n");
309 if (!(cmd
= getArg(cmd
, end
, &mntPoint
))) {
310 printf("mount: missing mount point\n");
315 printf("mount: filesystem type expected\n");
320 printf("mount: unexpected arguments\n");
324 /* need to deal with options */
327 char * start
= options
;
329 newOpts
= alloca(strlen(options
) + 1);
333 end
= strchr(start
, ',');
335 end
= start
+ strlen(start
);
341 if (!strcmp(start
, "ro"))
343 else if (!strcmp(start
, "rw"))
345 else if (!strcmp(start
, "nosuid"))
347 else if (!strcmp(start
, "suid"))
349 else if (!strcmp(start
, "nodev"))
351 else if (!strcmp(start
, "dev"))
353 else if (!strcmp(start
, "noexec"))
355 else if (!strcmp(start
, "exec"))
357 else if (!strcmp(start
, "sync"))
358 flags
|= MS_SYNCHRONOUS
;
359 else if (!strcmp(start
, "async"))
360 flags
&= ~MS_SYNCHRONOUS
;
361 else if (!strcmp(start
, "nodiratime"))
362 flags
|= MS_NODIRATIME
;
363 else if (!strcmp(start
, "diratime"))
364 flags
&= ~MS_NODIRATIME
;
365 else if (!strcmp(start
, "noatime"))
367 else if (!strcmp(start
, "atime"))
368 flags
&= ~MS_NOATIME
;
369 else if (!strcmp(start
, "remount"))
371 else if (!strcmp(start
, "defaults"))
375 strcat(newOpts
, ",");
376 strcat(newOpts
, start
);
385 if (!strncmp("LABEL=", device
, 6)) {
391 devName
= get_spec_by_volume_label(device
+ 6, &major
, &minor
);
395 if (access(device
, F_OK
)) {
402 deviceDir
= alloca(strlen(device
) + 1);
403 strcpy(deviceDir
, device
);
404 ptr
= deviceDir
+ (strlen(device
) - 1);
407 if (mkdir(deviceDir
, 0644)) {
408 printf("mkdir: cannot create directory %s\n", deviceDir
);
413 if (smartmknod(device
, S_IFBLK
| 0600, makedev(major
, minor
))) {
414 printf("mount: cannot create device %s (%d,%d)\n",
415 device
, major
, minor
);
424 printf("mount %s%s%s-t '%s' '%s' '%s' (%s%s%s%s%s%s%s)\n",
425 options
? "-o '" : "",
426 options
? options
: "",
427 options
? "\' " : "",
428 fsType
, device
, mntPoint
,
429 (flags
& MS_RDONLY
) ? "ro " : "",
430 (flags
& MS_NOSUID
) ? "nosuid " : "",
431 (flags
& MS_NODEV
) ? "nodev " : "",
432 (flags
& MS_NOEXEC
) ? "noexec " : "",
433 (flags
& MS_SYNCHRONOUS
) ? "sync " : "",
434 (flags
& MS_REMOUNT
) ? "remount " : "",
435 (flags
& MS_NOATIME
) ? "noatime " : ""
438 if (mount(device
, mntPoint
, fsType
, flags
, options
)) {
439 printf("mount: error %d mounting %s\n", errno
, fsType
);
444 if (mustRemove
) unlink(device
);
445 if (mustRemoveDir
) rmdir(deviceDir
);
450 int otherCommand(char * bin
, char * cmd
, char * end
, int doFork
) {
456 static const char * sysPath
= PATH
;
457 const char * pathStart
;
458 const char * pathEnd
;
459 char * stdoutFile
= NULL
;
462 args
= (char **)malloc(sizeof(char *) * 128);
467 if (!strchr(bin
, '/')) {
470 pathEnd
= strchr(pathStart
, ':');
472 if (!pathEnd
) pathEnd
= pathStart
+ strlen(pathStart
);
474 strncpy(fullPath
, pathStart
, pathEnd
- pathStart
);
475 fullPath
[pathEnd
- pathStart
] = '/';
476 strcpy(fullPath
+ (pathEnd
- pathStart
+ 1), bin
);
479 if (*pathStart
) pathStart
++;
481 if (!access(fullPath
, X_OK
)) {
488 *nextArg
= strdup(bin
);
490 while (cmd
&& cmd
< end
) {
492 cmd
= getArg(cmd
, end
, nextArg
);
498 /* if the next-to-last arg is a >, redirect the output properly */
499 if (((nextArg
- args
) >= 2) && !strcmp(*(nextArg
- 2), ">")) {
500 stdoutFile
= *(nextArg
- 1);
501 *(nextArg
- 2) = NULL
;
503 stdoutFd
= open(stdoutFile
, O_CREAT
| O_RDWR
| O_TRUNC
, 0600);
505 printf("nash: failed to open %s: %d\n", stdoutFile
, errno
);
514 printf(" '%s'", *nextArg
++);
516 printf(" (> %s)", stdoutFile
);
519 if (!doFork
|| !(pid
= fork())) {
522 execve(args
[0], args
, env
);
523 printf("ERROR: failed in exec of %s\n", args
[0]);
530 wpid
= wait4(-1, &status
, 0, NULL
);
532 printf("ERROR: Failed to wait for process %d\n", wpid
);
538 if (!WIFEXITED(status
) || WEXITSTATUS(status
)) {
539 printf("ERROR: %s exited abnormally with value %d ! (pid %d)\n", args
[0], WEXITSTATUS(status
), pid
);
550 static int lsdir(char *thedir
, char * prefix
) {
552 struct dirent
* entry
;
556 if (!(dir
= opendir(thedir
))) {
557 printf("error opening %s: %d\n", thedir
, errno
);
562 while ((entry
= readdir(dir
))) {
563 if (entry
->d_name
[0] == '.')
565 snprintf(fn
, 1024, "%s/%s", thedir
, entry
->d_name
);
567 printf("%s%s", prefix
, fn
);
569 if (S_ISDIR(sb
.st_mode
)) {
571 pfx
= malloc(strlen(prefix
) + 3);
572 sprintf(pfx
, "%s ", prefix
);
574 } else if (S_ISCHR(sb
.st_mode
)) {
575 printf(" c %d %d\n", major(sb
.st_rdev
), minor(sb
.st_rdev
));
576 } else if (S_ISBLK(sb
.st_mode
)) {
577 printf(" b %d %d\n", major(sb
.st_rdev
), minor(sb
.st_rdev
));
578 } else if (S_ISLNK(sb
.st_mode
)) {
580 target
= malloc(1024);
581 readlink(fn
, target
, 1024);
582 printf("->%s\n", target
);
591 int catCommand(char * cmd
, char * end
) {
596 if (!(cmd
= getArg(cmd
, end
, &file
))) {
597 printf("cat: argument expected\n");
601 if ((fd
= open(file
, O_RDONLY
)) < 0) {
602 printf("cat: error opening %s: %d\n", file
, errno
);
607 while (read(fd
, buf
, 1024) > 0) {
613 int lsCommand(char * cmd
, char * end
) {
616 if (!(cmd
= getArg(cmd
, end
, &dir
))) {
617 printf("ls: argument expected\n");
626 int execCommand(char * cmd
, char * end
) {
629 if (!(cmd
= getArg(cmd
, end
, &bin
))) {
630 printf("exec: argument expected\n");
634 return otherCommand(bin
, cmd
, end
, 0);
637 int losetupCommand(char * cmd
, char * end
) {
641 struct loop_info loopInfo
;
644 if (!(cmd
= getArg(cmd
, end
, &device
))) {
645 printf("losetup: missing device\n");
649 if (!(cmd
= getArg(cmd
, end
, &file
))) {
650 printf("losetup: missing file\n");
655 printf("losetup: unexpected arguments\n");
660 printf("losetup '%s' '%s'\n", device
, file
);
662 dev
= open(device
, O_RDWR
, 0);
664 printf("losetup: failed to open %s: %d\n", device
, errno
);
668 fd
= open(file
, O_RDWR
, 0);
670 printf("losetup: failed to open %s: %d\n", file
, errno
);
675 if (ioctl(dev
, LOOP_SET_FD
, (long) fd
)) {
676 printf("losetup: LOOP_SET_FD failed: %d\n", errno
);
684 memset(&loopInfo
, 0, sizeof(loopInfo
));
685 strcpy(loopInfo
.lo_name
, file
);
687 if (ioctl(dev
, LOOP_SET_STATUS
, &loopInfo
))
688 printf("losetup: LOOP_SET_STATUS failed: %d\n", errno
);
697 int raidautorunCommand(char * cmd
, char * end
) {
701 if (!(cmd
= getArg(cmd
, end
, &device
))) {
702 printf("raidautorun: raid device expected as first argument\n");
707 printf("raidautorun: unexpected arguments\n");
711 /* with udev, the raid devices don't exist until they get started.
712 * this won't work so well with raidautorun. so, let's be smart
713 * and create them ourselves if we need to */
714 if (access(device
, R_OK
& W_OK
)) {
716 if (sscanf(device
, "/dev/md%d", &minor
) != 1) {
717 printf("raidautorun: unable to autocreate %s\n", device
);
721 if (smartmknod(device
, S_IFBLK
| 0600, makedev(RAID_MAJOR
, minor
))) {
722 printf("raidautorun: unable to autocreate %s\n", device
);
727 fd
= open(device
, O_RDWR
, 0);
729 printf("raidautorun: failed to open %s: %d\n", device
, errno
);
733 if (ioctl(fd
, RAID_AUTORUN
, 0)) {
734 printf("raidautorun: RAID_AUTORUN failed: %d\n", errno
);
744 extern int pivot_root(char *, char *);
747 static int my_pivot_root(char * one
, char * two
) {
749 return pivot_root(one
, two
);
751 return syscall(__NR_pivot_root
, one
, two
);
755 int pivotrootCommand(char * cmd
, char * end
) {
759 if (!(cmd
= getArg(cmd
, end
, &new))) {
760 printf("pivotroot: new root mount point expected\n");
764 if (!(cmd
= getArg(cmd
, end
, &old
))) {
765 printf("pivotroot: old root mount point expected\n");
770 printf("pivotroot: unexpected arguments\n");
774 if (my_pivot_root(new, old
)) {
775 printf("pivotroot: pivot_root(%s,%s) failed: %d\n", new, old
, errno
);
782 #define MAX_INIT_ARGS 32
783 /* 2.6 magic not-pivot-root but kind of similar stuff.
784 * This is based on code from klibc/utils/run_init.c
786 int switchrootCommand(char * cmd
, char * end
) {
788 const char * initprogs
[] = { "/sbin/init", "/etc/init",
789 "/bin/init", "/bin/sh", NULL
};
790 char * init
, * cmdline
= NULL
;
792 /* Don't try to unmount the old "/", there's no way to do it. */
793 const char * umounts
[] = { "/dev", "/proc", "/sys", NULL
};
797 cmd
= getArg(cmd
, end
, &new);
799 if (!strcmp(new, "--movedev"))
801 cmd
= getArg(cmd
, end
, &new);
805 printf("switchroot: new root mount point expected\n");
810 printf("switchroot: chdir(%s) failed: %d\n", new, errno
);
814 init
= getKernelArg("init=");
816 cmdline
= getKernelCmdLine();
820 mount("/dev", "./dev", NULL
, MS_MOVE
, NULL
);
823 if ((fd
= open("./dev/console", O_RDWR
)) < 0) {
824 printf("ERROR opening /dev/console!!!!: %d\n", errno
);
828 if (dup2(fd
, 0) != 0) printf("error dup2'ing fd of %d to 0\n", fd
);
829 if (dup2(fd
, 1) != 1) printf("error dup2'ing fd of %d to 1\n", fd
);
830 if (dup2(fd
, 2) != 2) printf("error dup2'ing fd of %d to 2\n", fd
);
834 fd
= open("/", O_RDONLY
);
835 for (; umounts
[i
] != NULL
; i
++) {
836 if (!quiet
) printf("unmounting old %s\n", umounts
[i
]);
837 if (umount2(umounts
[i
], MNT_DETACH
)) {
838 printf("ERROR unmounting old %s: %d\n", umounts
[i
], errno
);
839 printf("forcing unmount of %s\n", umounts
[i
]);
840 umount2(umounts
[i
], MNT_FORCE
);
845 if (mount(".", "/", NULL
, MS_MOVE
, NULL
)) {
846 printf("switchroot: mount failed: %d\n", errno
);
851 if (chroot(".") || chdir("/")) {
852 printf("switchroot: chroot() failed: %d\n", errno
);
857 /* release the old "/" */
862 for (j
= 0; initprogs
[j
] != NULL
; j
++) {
863 if (!access(initprogs
[j
], X_OK
)) {
864 init
= strdup(initprogs
[j
]);
870 initargs
= (char **)malloc(sizeof(char *)*(MAX_INIT_ARGS
+1));
871 if (cmdline
&& init
) {
872 initargs
[i
++] = strdup(init
);
878 if (cmdline
!= NULL
) {
879 char * chptr
, * start
;
881 start
= chptr
= cmdline
;
882 for (; (i
< MAX_INIT_ARGS
) && (*start
!= '\0'); i
++) {
883 while (*chptr
&& !isspace(*chptr
)) chptr
++;
884 if (*chptr
!= '\0') *(chptr
++) = '\0';
885 initargs
[i
] = strdup(start
);
892 if (access(initargs
[0], X_OK
)) {
893 printf("WARNING: can't access %s\n", initargs
[0]);
895 execv(initargs
[0], initargs
);
896 printf("exec of init (%s) failed!!!: %d\n", initargs
[0], errno
);
900 int isEchoQuiet(int fd
) {
901 if (!reallyquiet
) return 0;
902 if (fd
!= 1) return 0;
906 int echoCommand(char * cmd
, char * end
) {
908 char ** nextArg
= args
;
916 if (testing
&& !quiet
) {
921 while ((cmd
= getArg(cmd
, end
, nextArg
))) {
922 if (!strncmp("-n", *nextArg
, MAX(2, strlen(*nextArg
)))) {
925 length
+= strlen(*nextArg
);
931 if ((nextArg
- args
>= 2) && !strcmp(*(nextArg
- 2), ">")) {
932 outFd
= open(*(nextArg
- 1), O_WRONLY
| O_CREAT
| O_TRUNC
, 0644);
934 printf("echo: cannot open %s for write: %d\n",
935 *(nextArg
- 1), errno
);
942 string
= (char *)malloc(length
* sizeof(char));
944 for (i
= 0; i
< num
;i
++) {
945 if (i
) strcat(string
, " ");
946 strncat(string
, args
[i
], strlen(args
[i
]));
949 if (newline
) strcat(string
, "\n");
950 if (!isEchoQuiet(outFd
)) write(outFd
, string
, strlen(string
));
952 if (outFd
!= 1) close(outFd
);
958 int umountCommand(char * cmd
, char * end
) {
961 if (!(cmd
= getArg(cmd
, end
, &path
))) {
962 printf("umount: path expected\n");
967 printf("umount: unexpected arguments\n");
972 printf("umount %s failed: %d\n", path
, errno
);
979 int mkrootdevCommand(char * cmd
, char * end
) {
988 if (!(cmd
= getArg(cmd
, end
, &path
))) {
989 printf("mkrootdev: path expected\n");
994 printf("mkrootdev: unexpected arguments\n");
998 root
= getKernelArg("root=");
1002 while (*chptr
&& !isspace(*chptr
)) chptr
++;
1006 if (root
&& !access(root
, R_OK
)) {
1007 if (!symlink(root
, "/dev/root"))
1011 if (root
&& !strncmp(root
, "LABEL=", 6)) {
1012 if (get_spec_by_volume_label(root
+ 6, &major
, &minor
)) {
1013 if (smartmknod(path
, S_IFBLK
| 0600, makedev(major
, minor
))) {
1014 printf("mount: cannot create device %s (%d,%d)\n",
1015 path
, major
, minor
);
1022 printf("mkrootdev: label %s not found\n", root
+ 6);
1027 if (root
&& !strncmp(root
, "UUID=", 5)) {
1028 if (get_spec_by_uuid(root
+5, &major
, &minor
)) {
1029 if (smartmknod(path
, S_IFBLK
| 0600, makedev(major
, minor
))) {
1030 printf("mount: cannot create device %s (%d,%d)\n",
1031 path
, major
, minor
);
1038 printf("mkrootdev: UUID %s not found\n", root
+5);
1043 fd
= open("/proc/sys/kernel/real-root-dev", O_RDONLY
, 0);
1045 printf("mkrootdev: failed to open /proc/sys/kernel/real-root-dev: %d\n", errno
);
1049 i
= read(fd
, buf
, sizeof(buf
));
1051 printf("mkrootdev: failed to read real-root-dev: %d\n", errno
);
1064 printf("mkrootdev: bad device %s\n", buf
);
1068 if (!devNum
&& root
)
1069 devNum
= name_to_dev_t(root
);
1071 if (smartmknod(path
, S_IFBLK
| 0700, devNum
)) {
1072 printf("mkrootdev: mknod failed: %d\n", errno
);
1079 int mkdirCommand(char * cmd
, char * end
) {
1081 int ignoreExists
= 0;
1083 cmd
= getArg(cmd
, end
, &dir
);
1085 if (cmd
&& !strcmp(dir
, "-p")) {
1087 cmd
= getArg(cmd
, end
, &dir
);
1091 printf("mkdir: directory expected\n");
1095 if (mkdir(dir
, 0755)) {
1096 if (!ignoreExists
&& errno
== EEXIST
) {
1097 printf("mkdir: failed to create %s: %d\n", dir
, errno
);
1105 int accessCommand(char * cmd
, char * end
) {
1110 cmd
= getArg(cmd
, end
, &permStr
);
1111 if (cmd
) cmd
= getArg(cmd
, end
, &file
);
1113 if (!cmd
|| *permStr
!= '-') {
1114 printf("usage: access -[perm] file\n");
1121 case 'r': perms
|= R_OK
; break;
1122 case 'w': perms
|= W_OK
; break;
1123 case 'x': perms
|= X_OK
; break;
1124 case 'f': perms
|= F_OK
; break;
1126 printf("perms must be -[r][w][x][f]\n");
1133 if ((file
== NULL
) || (access(file
, perms
)))
1139 int sleepCommand(char * cmd
, char * end
) {
1143 if (!(cmd
= getArg(cmd
, end
, &delaystr
))) {
1144 printf("sleep: delay expected\n");
1148 delay
= atoi(delaystr
);
1154 int readlinkCommand(char * cmd
, char * end
) {
1156 char * buf
, * respath
, * fullpath
;
1160 if (!(cmd
= getArg(cmd
, end
, &path
))) {
1161 printf("readlink: file expected\n");
1165 if (lstat(path
, &sb
) == -1) {
1166 fprintf(stderr
, "unable to stat %s: %d\n", path
, errno
);
1170 if (!S_ISLNK(sb
.st_mode
)) {
1171 printf("%s\n", path
);
1176 if (readlink(path
, buf
, 512) == -1) {
1177 fprintf(stderr
, "error readlink %s: %d\n", path
, errno
);
1182 /* symlink is absolute */
1183 if (buf
[0] == '/') {
1184 printf("%s\n", buf
);
1189 /* nope, need to handle the relative symlink case too */
1190 respath
= strrchr(path
, '/');
1195 fullpath
= malloc(512);
1196 /* and normalize it */
1197 snprintf(fullpath
, 512, "%s/%s", path
, buf
);
1198 respath
= malloc(PATH_MAX
);
1199 if (!(respath
= realpath(fullpath
, respath
))) {
1200 fprintf(stderr
, "error realpath %s: %d\n", fullpath
, errno
);
1205 printf("%s\n", respath
);
1213 int doFind(char * dirName
, char * name
) {
1217 char * strBuf
= alloca(strlen(dirName
) + 1024);
1219 if (!(dir
= opendir(dirName
))) {
1220 fprintf(stderr
, "error opening %s: %d\n", dirName
, errno
);
1225 while ((d
= readdir(dir
))) {
1228 strcpy(strBuf
, dirName
);
1229 strcat(strBuf
, "/");
1230 strcat(strBuf
, d
->d_name
);
1232 if (!strcmp(d
->d_name
, name
))
1233 printf("%s\n", strBuf
);
1235 if (!strcmp(d
->d_name
, ".") || !strcmp(d
->d_name
, "..")) {
1240 if (lstat(strBuf
, &sb
)) {
1241 fprintf(stderr
, "failed to stat %s: %d\n", strBuf
, errno
);
1246 if (S_ISDIR(sb
.st_mode
))
1247 doFind(strBuf
, name
);
1252 printf("error reading from %s: %d\n", dirName
, errno
);
1261 int findCommand(char * cmd
, char * end
) {
1265 cmd
= getArg(cmd
, end
, &dir
);
1266 if (cmd
) cmd
= getArg(cmd
, end
, &name
);
1267 if (cmd
&& strcmp(name
, "-name")) {
1268 printf("usage: find [path] -name [file]\n");
1272 if (cmd
) cmd
= getArg(cmd
, end
, &name
);
1274 printf("usage: find [path] -name [file]\n");
1278 return doFind(dir
, name
);
1281 int findlodevCommand(char * cmd
, char * end
) {
1285 struct loop_info loopInfo
;
1286 char separator
[2] = "";
1289 printf("usage: findlodev\n");
1293 if (!access("/dev/.devfsd", X_OK
))
1294 strcpy(separator
, "/");
1296 for (devNum
= 0; devNum
< 256; devNum
++) {
1297 sprintf(devName
, "/dev/loop%s%d", separator
, devNum
);
1298 if ((fd
= open(devName
, O_RDONLY
)) < 0) return 0;
1300 if (ioctl(fd
, LOOP_GET_STATUS
, &loopInfo
)) {
1302 printf("%s\n", devName
);
1312 int mknodCommand(char * cmd
, char * end
) {
1313 char * path
, * type
;
1314 char * majorStr
, * minorStr
;
1320 cmd
= getArg(cmd
, end
, &path
);
1321 cmd
= getArg(cmd
, end
, &type
);
1322 cmd
= getArg(cmd
, end
, &majorStr
);
1323 cmd
= getArg(cmd
, end
, &minorStr
);
1325 printf("mknod: usage mknod <path> [c|b] <major> <minor>\n");
1329 if (!strcmp(type
, "b")) {
1331 } else if (!strcmp(type
, "c")) {
1334 printf("mknod: invalid type\n");
1338 major
= strtol(majorStr
, &chptr
, 10);
1340 printf("invalid major number\n");
1344 minor
= strtol(minorStr
, &chptr
, 10);
1346 printf("invalid minor number\n");
1350 if (smartmknod(path
, mode
| 0600, makedev(major
, minor
))) {
1351 printf("mknod: failed to create %s: %d\n", path
, errno
);
1358 int mkdevicesCommand(char * cmd
, char * end
) {
1362 char * start
, * chptr
;
1368 if (!(cmd
= getArg(cmd
, end
, &prefix
))) {
1369 printf("mkdevices: path expected\n");
1374 printf("mkdevices: unexpected arguments\n");
1378 if ((fd
= open("/proc/partitions", O_RDONLY
)) < 0) {
1379 printf("mkrootdev: failed to open /proc/partitions: %d\n", errno
);
1383 i
= readFD(fd
, &buf
);
1386 printf("failed to read /proc/partitions: %d\n", errno
);
1392 start
= strchr(buf
, '\n');
1395 start
= strchr(buf
, '\n');
1397 if (!start
) return 1;
1401 while (*start
&& isspace(*start
)) start
++;
1402 major
= strtol(start
, &chptr
, 10);
1404 if (start
!= chptr
) {
1406 while (*start
&& isspace(*start
)) start
++;
1407 minor
= strtol(start
, &chptr
, 10);
1409 if (start
!= chptr
) {
1411 while (*start
&& isspace(*start
)) start
++;
1412 while (*start
&& !isspace(*start
)) start
++;
1413 while (*start
&& isspace(*start
)) start
++;
1418 while (!isspace(*chptr
)) chptr
++;
1423 printf("% 3d % 3d %s\n", major
, minor
, start
);
1425 char * ptr
, * deviceDir
;
1428 sprintf(devName
, "%s/%s", prefix
, start
);
1437 deviceDir
= alloca(strlen(devName
) + 1);
1438 strcpy(deviceDir
, devName
);
1439 ptr
= deviceDir
+ (strlen(devName
) - 1);
1442 if (access(deviceDir
, X_OK
) && mkdir(deviceDir
, 0644)) {
1443 printf("mkdir: cannot create directory %s: %d\n", deviceDir
, errno
);
1446 if (smartmknod(devName
, S_IFBLK
| 0600,
1447 makedev(major
, minor
))) {
1448 printf("failed to create %s\n", devName
);
1459 start
= strchr(start
, '\n');
1460 if (!*start
) return 1;
1467 static int getDevNumFromProc(char * file
, char * device
) {
1468 char buf
[32768], line
[4096];
1473 if ((fd
= open(file
, O_RDONLY
)) == -1) {
1474 printf("can't open file %s: %d\n", file
, errno
);
1478 num
= read(fd
, buf
, sizeof(buf
));
1481 printf("failed to read %s: %d\n", file
, errno
);
1488 end
= strchr(start
, '\n');
1489 while (start
&& end
) {
1491 if ((sscanf(start
, "%d %s", &num
, line
)) == 2) {
1492 if (!strncmp(device
, line
, strlen(device
)))
1496 end
= strchr(start
, '\n');
1501 int mkDMNodCommand(char * cmd
, char * end
) {
1502 int major
= getDevNumFromProc("/proc/devices", "misc");
1503 int minor
= getDevNumFromProc("/proc/misc", "device-mapper");
1505 if ((major
== -1) || (minor
== -1)) {
1506 printf("Unable to find device-mapper major/minor\n");
1510 if (!access("/dev/mapper/control", R_OK
)) {
1512 if (stat("/dev/mapper/control", &sb
) == 0) {
1513 if (S_ISCHR(sb
.st_mode
) && (sb
.st_rdev
== makedev(major
, minor
)))
1517 unlink("/dev/mapper/control");
1520 if (smartmknod("/dev/mapper/control", S_IFCHR
| 0600,
1521 makedev(major
, minor
))) {
1522 printf("failed to create /dev/mapper/control\n");
1529 int setQuietCommand(char * cmd
, char * end
) {
1532 if ((fd
= open("/proc/cmdline", O_RDONLY
)) >= 0) {
1533 char * buf
= malloc(512);
1534 rc
= read(fd
, buf
, 511);
1535 if (strstr(buf
, "quiet") != NULL
)
1547 int runStartup(int fd
) {
1548 char contents
[32768];
1550 char * start
, * end
;
1554 i
= read(fd
, contents
, sizeof(contents
) - 1);
1555 if (i
== (sizeof(contents
) - 1)) {
1556 printf("Failed to read /startup.rc -- file too large.\n");
1565 while (isspace(*start
) && *start
&& (*start
!= '\n')) start
++;
1568 while (*start
&& (*start
!= '\n')) start
++;
1570 if (*start
== '\n') {
1576 printf("(last line in /startup.rc is empty)\n");
1580 /* start points to the beginning of the command */
1582 while (*end
&& (*end
!= '\n')) end
++;
1584 printf("(last line in /startup.rc missing \\n -- skipping)\n");
1589 /* end points to the \n at the end of the command */
1592 while (chptr
< end
&& !isspace(*chptr
)) chptr
++;
1594 if (!strncmp(start
, "mount", MAX(5, chptr
- start
)))
1595 rc
= mountCommand(chptr
, end
);
1596 else if (!strncmp(start
, "losetup", MAX(7, chptr
- start
)))
1597 rc
= losetupCommand(chptr
, end
);
1598 else if (!strncmp(start
, "echo", MAX(4, chptr
- start
)))
1599 rc
= echoCommand(chptr
, end
);
1600 else if (!strncmp(start
, "raidautorun", MAX(11, chptr
- start
)))
1601 rc
= raidautorunCommand(chptr
, end
);
1602 else if (!strncmp(start
, "pivot_root", MAX(10, chptr
- start
)))
1603 rc
= pivotrootCommand(chptr
, end
);
1604 else if (!strncmp(start
, "switchroot", MAX(10, chptr
- start
)))
1605 rc
= switchrootCommand(chptr
, end
);
1606 else if (!strncmp(start
, "mkrootdev", MAX(9, chptr
- start
)))
1607 rc
= mkrootdevCommand(chptr
, end
);
1608 else if (!strncmp(start
, "umount", MAX(6, chptr
- start
)))
1609 rc
= umountCommand(chptr
, end
);
1610 else if (!strncmp(start
, "exec", MAX(4, chptr
- start
)))
1611 rc
= execCommand(chptr
, end
);
1612 else if (!strncmp(start
, "mkdir", MAX(5, chptr
- start
)))
1613 rc
= mkdirCommand(chptr
, end
);
1614 else if (!strncmp(start
, "access", MAX(6, chptr
- start
)))
1615 rc
= accessCommand(chptr
, end
);
1616 else if (!strncmp(start
, "find", MAX(4, chptr
- start
)))
1617 rc
= findCommand(chptr
, end
);
1618 else if (!strncmp(start
, "findlodev", MAX(7, chptr
- start
)))
1619 rc
= findlodevCommand(chptr
, end
);
1620 else if (!strncmp(start
, "showlabels", MAX(10, chptr
-start
)))
1621 rc
= display_uuid_cache();
1622 else if (!strncmp(start
, "mkdevices", MAX(9, chptr
-start
)))
1623 rc
= mkdevicesCommand(chptr
, end
);
1624 else if (!strncmp(start
, "sleep", MAX(5, chptr
-start
)))
1625 rc
= sleepCommand(chptr
, end
);
1626 else if (!strncmp(start
, "mknod", MAX(5, chptr
-start
)))
1627 rc
= mknodCommand(chptr
, end
);
1628 else if (!strncmp(start
, "mkdmnod", MAX(7, chptr
-start
)))
1629 rc
= mkDMNodCommand(chptr
, end
);
1630 else if (!strncmp(start
, "readlink", MAX(8, chptr
-start
)))
1631 rc
= readlinkCommand(chptr
, end
);
1632 else if (!strncmp(start
, "setquiet", MAX(8, chptr
-start
)))
1633 rc
= setQuietCommand(chptr
, end
);
1635 else if (!strncmp(start
, "cat", MAX(3, chptr
-start
)))
1636 rc
= catCommand(chptr
, end
);
1637 else if (!strncmp(start
, "ls", MAX(2, chptr
-start
)))
1638 rc
= lsCommand(chptr
, end
);
1642 rc
= otherCommand(start
, chptr
+ 1, end
, 1);
1651 int main(int argc
, char **argv
) {
1657 name
= strrchr(argv
[0], '/');
1663 if (!strcmp(name
, "modprobe"))
1665 if (!strcmp(name
, "hotplug")) {
1666 argv
[0] = strdup("/sbin/udev");
1667 execv(argv
[0], argv
);
1668 printf("ERROR: exec of udev failed!\n");
1672 testing
= (getppid() != 0) && (getppid() != 1);
1675 while (argc
&& **argv
== '-') {
1676 if (!strcmp(*argv
, "--force")) {
1680 } else if (!strcmp(*argv
, "--quiet")) {
1683 } else if (!strcmp(*argv
, "--reallyquiet")) {
1687 printf("unknown argument %s\n", *argv
);
1692 if (force
&& !quiet
)
1693 printf("(forcing normal run)\n");
1695 if (testing
&& !quiet
)
1696 printf("(running in test mode).\n");
1698 if (!quiet
) printf("Red Hat nash version %s starting\n", VERSION
);
1701 fd
= open(*argv
, O_RDONLY
, 0);
1703 printf("nash: cannot open %s: %d\n", *argv
, errno
);
1708 /* runStartup closes fd */
1709 rc
= runStartup(fd
);