diff options
| author | Matt Wilson <msw@redhat.com> | 1999-05-06 18:50:50 +0000 |
|---|---|---|
| committer | Matt Wilson <msw@redhat.com> | 1999-05-06 18:50:50 +0000 |
| commit | 3a8069a96bd89cf4fdedf03eccc7781d17fec6a7 (patch) | |
| tree | bc8a9fd486a54535a719c838663728d32b5b0448 /loader | |
| parent | a47ebb82d8e73b4a940baeec26584b53908865b1 (diff) | |
beginnings of new stage1
Diffstat (limited to 'loader')
| -rw-r--r-- | loader/Makefile | 54 | ||||
| -rw-r--r-- | loader/init.c | 759 | ||||
| -rw-r--r-- | loader/loader.c | 61 | ||||
| -rw-r--r-- | loader/minilibc.c | 201 | ||||
| -rw-r--r-- | loader/minilibc.h | 82 |
5 files changed, 1157 insertions, 0 deletions
diff --git a/loader/Makefile b/loader/Makefile new file mode 100644 index 000000000..d28848798 --- /dev/null +++ b/loader/Makefile @@ -0,0 +1,54 @@ +DESTDIR = ../../trees/initrd + +OBJS = loader.o +SOURCES = $(subst .o,.c,$(OBJS)) +BINS = loader init + +ifeq (.depend,$(wildcard .depend)) +TARGET=$(PROGS) +else +TARGET=depend $(PROGS) +endif + +OPTS = -O2 + +CFLAGS = $(DEBUG) $(OPTS) -Wall -D_GNU_SOURCE=1 -I/usr/include/rpm -I.. -DUSE_ALT_DNS=1 + +STATIC = -static + +ARCH := $(patsubst i%86,i386,$(shell uname -m)) +ifeq (i386,$(ARCH)) +MINILIBC=minilibc.o +CFLAGS+=-DUSE_MINILIBC=1 -DUSE_LOGDEV -DVERSION='"$(VERSION)"' +LDFLAGS = -nostdlib /usr/lib/crt1.o +STATIC=-static +else +CFLAGS+=-DUSE_MINILIBC=0 +STATIC= +endif + +VERSION = 6.0 + +all: $(BINS) + +install: all + rm -f $(DESTDIR)/sbin/loader + mkdir -p $(DESTDIR)/sbin + install -s loader $(DESTDIR)/sbin/loader + install -s init $(DESTDIR)/sbin/loader + +loader: $(OBJS) + $(CC) $(STATIC) -o $@ $(OBJS) -lpopt -lnewt -lslang + +init: init.o $(MINILIBC) + $(CC) $(STATIC) -g $(LDFLAGS) -o $@ init.o $(MINILIBC) + +clean: + rm -f *.o .depend *~ + +depend: + $(CPP) $(CFLAGS) -DHAVE_CONFIG_H -M $(SOURCES) > .depend + +ifeq (.depend,$(wildcard .depend)) +include .depend +endif diff --git a/loader/init.c b/loader/init.c new file mode 100644 index 000000000..1b653f319 --- /dev/null +++ b/loader/init.c @@ -0,0 +1,759 @@ +/* + * init.c + * + * This is the install type init + * + * Erik Troan (ewt@redhat.com) + * + * Copyright 1996 Red Hat Software + * + * This software may be freely redistributed under the terms of the GNU + * public license. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#if USE_MINILIBC +#include "minilibc.h" +#else +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <net/if.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/ioctl.h> +#include <sys/klog.h> +#include <sys/mount.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/un.h> +#include <sys/wait.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <sys/reboot.h> +#include <termios.h> + + +#define syslog klogctl +#endif + +#define KICK_FLOPPY 1 +#define KICK_BOOTP 2 + +#define MS_REMOUNT 32 + +#define ENV_PATH 0 +#define ENV_LD_LIBRARY_PATH 1 +#define ENV_HOME 2 +#define ENV_TERM 3 +#define ENV_DEBUG 4 + +char * environ[] = { + "PATH=/usr/bin:/bin:/sbin:/usr/sbin:/mnt/sbin:/mnt/usr/sbin:" + "/mnt/bin:/mnt/usr/bin", + "LD_LIBRARY_PATH=/lib:/usr/lib:/mnt/lib:/mnt/usr/lib", + "HOME=/", + "TERM=linux", + "DEBUG=", + NULL +}; + + +/* + * this needs to handle the following cases: + * + * 1) run from a CD root filesystem + * 2) run from a read only nfs rooted filesystem + * 3) run from a floppy + * 4) run from a floppy that's been loaded into a ramdisk + * + */ + +int testing; + +void printstr(char * string) { + write(1, string, strlen(string)); +} + +void fatal_error(int usePerror) { +/* FIXME */ +#if 0 + if (usePerror) + perror("failed:"); + else +#endif + printf("failed.\n"); + + printf("\nI can't recover from this.\n"); + while (1) ; +} + +int doMke2fs(char * device, char * size) { + char * args[] = { "/usr/bin/mke2fs", NULL, NULL, NULL }; + int pid, status; + + args[1] = device; + args[2] = size; + + if (!(pid = fork())) { + /* child */ + execve("/usr/bin/mke2fs", args, environ); + fatal_error(1); + } + + wait4(-1, &status, 0, NULL); + + return 0; +} + +int hasNetConfiged(void) { + int rc; + int s; + struct ifconf configs; + struct ifreq devs[10]; + + #ifdef __i386__ + return 0; + #endif + + s = socket(AF_INET, SOCK_STREAM, 0); + if (s < 0) { + /* FIXME was perror*/ + printf("error creating socket: %d\n", errno); + return 0; + } else { + /* this is just good enough to tell us if we have anything + configured */ + configs.ifc_len = sizeof(devs); + configs.ifc_buf = (void *) devs; + + rc = ioctl(s, SIOCGIFCONF, &configs); + if (rc < 0) { + /* FIXME was perror*/ + printstr("SIOCGIFCONF"); + return 0; + } + if (configs.ifc_len == 0) { + return 0; + } + + return 1; + } + + return 0; +} + +void doklog(char * fn) { + fd_set readset, unixs; + int in, out, i; + int log; + int s; + int sock = -1; + struct sockaddr_un sockaddr; + char buf[1024]; + int readfd; + + in = open("/proc/kmsg", O_RDONLY,0); + if (in < 0) { + /* FIXME: was perror */ + printstr("open /proc/kmsg"); + return; + } + + out = open(fn, O_WRONLY, 0); + if (out < 0) + printf("couldn't open %s for syslog -- still using /tmp/syslog\n", fn); + + log = open("/tmp/syslog", O_WRONLY | O_CREAT, 0644); + if (log < 0) { + /* FIXME: was perror */ + printstr("error opening /tmp/syslog"); + sleep(5); + + close(in); + return; + } + + /* if we get this far, we should be in good shape */ + + if (fork()) { + /* parent */ + close(in); + close(out); + close(log); + return; + } + close(0); + close(1); + close(2); + + dup2(1, log); + +#if defined(USE_LOGDEV) + /* now open the syslog socket */ + sockaddr.sun_family = AF_UNIX; + strcpy(sockaddr.sun_path, "/dev/log"); + sock = socket(AF_UNIX, SOCK_STREAM, 0); + if (sock < 0) { + printf("error creating socket: %d\n", errno); + sleep(5); + } + printstr("got socket\n"); + if (bind(sock, (struct sockaddr *) &sockaddr, sizeof(sockaddr.sun_family) + + strlen(sockaddr.sun_path))) { + printf("bind error: %d\n", errno); + sleep(5); + } + printstr("bound socket\n"); + chmod("/dev/log", 0666); + if (listen(sock, 5)) { + printf("listen error: %d\n", errno); + sleep(5); + } +#endif + + syslog(8, NULL, 1); + + FD_ZERO(&unixs); + while (1) { + memcpy(&readset, &unixs, sizeof(unixs)); + + if (sock >= 0) FD_SET(sock, &readset); + FD_SET(in, &readset); + + i = select(20, &readset, NULL, NULL, NULL); + if (i <= 0) continue; + + if (FD_ISSET(in, &readset)) { + i = read(in, buf, sizeof(buf)); + if (i > 0) { + if (out >= 0) write(out, buf, i); + write(log, buf, i); + } + } + + for (readfd = 0; readfd < 20; ++readfd) { + if (FD_ISSET(readfd, &readset) && FD_ISSET(readfd, &unixs)) { + i = read(readfd, buf, sizeof(buf)); + if (i > 0) { + if (out >= 0) { + write(out, buf, i); + write(out, "\n", 1); + } + + write(log, buf, i); + write(log, "\n", 1); + } else if (i == 0) { + /* socket closed */ + close(readfd); + FD_CLR(readfd, &unixs); + } + } + } + + if (sock >= 0 && FD_ISSET(sock, &readset)) { + s = sizeof(sockaddr); + readfd = accept(sock, (struct sockaddr *) &sockaddr, &s); + if (readfd < 0) { + if (out >= 0) write(out, "error in accept\n", 16); + write(log, "error in accept\n", 16); + close(sock); + sock = -1; + } else { + FD_SET(readfd, &unixs); + } + } + } +} + +#if defined(__alpha__) +char * findKernel(void) { + char * dev, * file; + struct stat sb; + + dev = getenv("bootdevice"); + file = getenv("bootfile"); + + if (!dev || !file) { + printf("I can't find your kernel. When you are booting" + " from a CDROM, you must pass\n"); + printf("the bootfile argument to the kernel if your" + " boot loader doesn't do so automatically.\n"); + printf("\n"); + printf("You should now reboot your system and try " + "again\n"); + + while (1) ; + } + + if (!strcmp(dev, "fd0")) { + if (!strcmp(file, "vmlinux.gz")) { + printf("The kernel on a boot floppy must be named vmlinux.gz. " + "You\n"); + printf("are using a kernel named %s instead. You'll have " + "to\n", file); + printf("fix this and try again.\n"); + + while (1) ; + } + + return NULL; + } else { + if (stat(file, &sb)) { + printf("I can't find your kernel. When you are booting" + " from a CDROM, you must pass\n"); + printf("the bootfile argument to the kernel if your" + " boot loader doesn't do so automatically.\n"); + printf("\n"); + printf("You should now reboot your system and try " + "again\n"); + + while (1) ; + } + + return file; + } +} +#endif + +int setupTerminal(int fd) { + struct winsize winsize; + + if (ioctl(fd, TIOCGWINSZ, &winsize)) { + printf("failed to get winsize"); + fatal_error(1); + } + + winsize.ws_row = 24; + winsize.ws_col = 80; + + if (ioctl(fd, TIOCSWINSZ, &winsize)) { + printf("failed to set winsize"); + fatal_error(1); + } + + environ[ENV_TERM] = "TERM=vt100"; + + return 0; +} + +void unmountFilesystems(void) { + int fd, size; + char buf[65535]; /* this should be big enough */ + char * chptr, * start; + struct { + char * name; + int len; + } filesystems[500], tmp; + int numFilesystems = 0; + int i, j; + + fd = open("/proc/mounts", O_RDONLY, 0); + if (fd < 1) { + /* FIXME: was perror */ + printstr("failed to open /proc/mounts"); + sleep(2); + return; + } + + size = read(fd, buf, sizeof(buf) - 1); + buf[size] = '\0'; + + close(fd); + + chptr = buf; + while (*chptr) { + while (*chptr != ' ') chptr++; + chptr++; + start = chptr; + while (*chptr != ' ') chptr++; + *chptr++ = '\0'; + filesystems[numFilesystems].name = start; + filesystems[numFilesystems].len = strlen(start); + numFilesystems++; + while (*chptr != '\n') chptr++; + chptr++; + } + + /* look ma, a *bubble* sort */ + for (i = 0; i < (numFilesystems - 1); i++) { + for (j = i; j < numFilesystems; j++) { + if (filesystems[i].len < filesystems[j].len) { + tmp = filesystems[i]; + filesystems[i] = filesystems[j]; + filesystems[j] = tmp; + } + } + } + + /* -1 because the last one will always be '/' */ + for (i = 0; i < numFilesystems - 1; i++) { + printf("\t%s", filesystems[i].name); + /* don't need to unmount /tmp. it is busy anyway. */ + if (!testing && strncmp(filesystems[i].name, "/tmp", 4)) { + if (umount(filesystems[i].name) < 0) { + /* FIXME printf(" failed: %s", strerror(errno));*/ + printstr(" umount failed"); + } + } + printf("\n"); + } +} + +void readargs(int * isRescue, int * isSerial, int * isExpert, int * isKick, + int * forceSupp, int * isNetwork) { + char buf[512]; + char * arg; + int fd; + int size; + int done = 0; + char * start, * end; + + printf("opening /proc/cmdline... "); + + if ((fd = open("/proc/cmdline", O_RDONLY, 0)) < 0) fatal_error(1); + + size = read(fd, buf, sizeof(buf) - 1); + buf[size] = '\0'; + close(fd); + + printf("done\n"); + + printf("checking command line arguments... "); + start = buf; + + while (!done) { + while (*start && isspace(*start)) start++; + if (!(*start)) break; + + end = start; + while (*end && !isspace(*end) && *end != '\n') end++; + + if (!*end) done = 1; + *end = '\0'; + + if (!*start || + !strcmp(start, "auto") || + !strncmp(start, "BOOT_IMAGE", 10) || + !strncmp(start, "initrd=", 7) || + !strncmp(start, "bootdevice=", 11) || + !strncmp(start, "bootfile=", 9) || + !strcmp(start, "ro") || + !strncmp(start, "root=", 5) || + !strncmp(start, "mem=", 4) || + !strncmp(start, "hda=", 4) || + !strncmp(start, "hdb=", 4) || + !strncmp(start, "hdc=", 4) || + !strncmp(start, "hdd=", 4) || + !strncmp(start, "load_ramdisk", 12) || + !strncmp(start, "prompt_ramdisk", 14)) { + /* lilo does this for us -- we don't care */ + } else if (!strcmp(start, "debug")) { + printf("\n\tdebug disk mode enabled"); + environ[ENV_DEBUG] = "DEBUG=1"; + } else if (!strcmp(start, "rescue")) { + printf("\n\trescue disk mode enabled"); + *isRescue = 1; + } else if (!strcmp(start, "serial")) { + printf("\n\tserial mode enabled"); + *isSerial = 1; + } else if (!strcmp(start, "expert")) { + printf("\n\texpert mode enabled"); + *isExpert = 1; + } else if (!strcmp(start, "supp")) { + *forceSupp = 1; + } else if (!strcmp(start, "local")) { + *isNetwork = 0; + } else if (!strcmp(start, "network")) { + *isNetwork = 1; + } else if (!strncmp(start, "kickstart", 9) || + !strncmp(start, "ks", 2)) { + arg = strchr(start, '='); + + if (arg) { + *isKick = KICK_FLOPPY; + printf("\n\ta floppy kickstart install will be performed"); + } else { + *isKick = KICK_BOOTP; + printf("\n\ta bootp kickstart install will be performed"); + } + } else { + printf("\n\tunknown option '%s'!", start); + sleep(5); + } + + start = end + 1; + } + printf("done\n"); +} + +int main(void) { + pid_t installpid, childpid; + int waitStatus; + int fd; + int nfsRoot = 0; + int roRoot = 0; + int cdRoot = 0; + int isRescue = 0; + int isSerial = 0; + int isExpert = 0; + int isKick = 0; + int isNetwork = 0; + int doReboot = 0; + int doShutdown =0; + int forceSupp = 0; +#ifdef __alpha__ + char * kernel; +#endif + char * argv[15]; + char ** argvp = argv; + + /* getpid() != 1 should work, by linuxrc tends to get a larger pid */ + testing = (getpid() > 50); + + if (!testing) { + /* turn off screen blanking */ + printstr("\033[9;0]"); + printstr("\033[8]"); + } + + printstr("hello\n"); + + printf("Red Hat install init version %s starting\n", VERSION); + + printf("mounting /proc filesystem... "); + + if (!testing) { + if (mount("/proc", "/proc", "proc", 0, NULL)) + fatal_error(1); + } + + printf("done\n"); + + readargs(&isRescue, &isSerial, &isExpert, &isKick, &forceSupp, &isNetwork); + + if (isSerial) { + fd = open("/dev/ttyS0", O_RDWR, 0); + if (fd < 0) { + printf("failed to open /dev/ttyS0"); + fatal_error(1); + } + write(fd, "Switching to serial console...", 29); + + /* gulp */ + dup2(fd, 0); + dup2(fd, 1); + dup2(fd, 2); + + printf("done\n\n"); + + printf("Red Hat install init version %s using a serial console\n", + VERSION); + + printf("remember, cereal is an important part of a nutritionally " + "balanced breakfast.\n\n"); + + setupTerminal(0); + + close(fd); + } + + if (!testing) { + sethostname("localhost.localdomain", 21); + /* the default domainname (as of 2.0.35) is "(none)", which confuses + glibc */ + setdomainname("", 0); + } + + printf("checking for NFS root filesystem..."); + if (hasNetConfiged()) { + printf("yes\n"); + roRoot = nfsRoot = 1; + } else { + printf("no\n"); + } + + if (!nfsRoot) { + printf("trying to remount root filesystem read write... "); + if (mount("/", "/", NULL, MS_REMOUNT | MS_MGC_VAL, NULL)) { + printf("failed (but that's okay)\n"); + + roRoot = 1; + } else { + printf("done\n"); + + /* 2.0.18 (at least) lets us remount a CD r/w!! */ + printf("checking for writeable /tmp... "); + fd = open("/tmp/tmp", O_WRONLY | O_CREAT, 0644); + if (fd < 0) { + printf("no (probably a CD rooted install)\n"); + roRoot = 1; + } else { + close(fd); + unlink("/tmp/tmp"); + printf("yes\n"); + } + } + } + + if (!testing && roRoot) { + printf("creating 300k of ramdisk space... "); + if (doMke2fs("/dev/ram", "300")) + fatal_error(0); + + printf("done\n"); + + printf("mounting /tmp from ramdisk... "); + if (mount("/dev/ram", "/tmp", "ext2", 0, NULL)) + fatal_error(1); + + printf("done\n"); + + if (!nfsRoot) cdRoot = 1; + } + + /* Now we have some /tmp space set up, and /etc and /dev point to + it. We should be in pretty good shape. */ + + if (!testing) + doklog("/dev/tty4"); + + /* Go into normal init mode - keep going, and then do a orderly shutdown + when: + + 1) /bin/install exits + 2) we receive a SIGHUP + */ + + printf("running install...\n"); + + if (!(installpid = fork())) { + /* child */ + if (!isSerial) { + fd = open("/dev/tty1", O_RDWR, 0); + if (fd < 0) { + printf("failed to open /dev/tty1"); + fatal_error(1); + } + + dup2(fd, 0); + dup2(fd, 1); + dup2(fd, 2); + + setsid(); + if (ioctl(0, TIOCSCTTY, NULL)) { + printf("could not set new controlling tty"); + } + + setsid(); + close(fd); + } + + if (0 && (nfsRoot || cdRoot)) { + symlink("/", "/tmp/rhimage"); + symlink("/", "/tmp/image"); + + *argvp++ = "/usr/bin/runinstall2"; + *argvp++ = argv[0]; + *argvp++ = "--method"; + *argvp++ = nfsRoot ? "nfs" : "cdrom"; + +#if 0 /* we don't need this anymore */ +# if defined(__alpha__) + if (cdRoot && (kernel = findKernel())) { + *argvp++ = "--kernel"; + *argvp++ = kernel; + } +# endif +#endif /* not needed */ + } else { + *argvp++ = "/bin/loader"; + } + + if (isRescue) + *argvp++ = "--rescue"; + + if (isExpert) *argvp++ = "--expert"; + if (forceSupp) *argvp++ = "--forcesupp"; + if (isKick == KICK_FLOPPY) + *argvp++ = "--ks=floppy"; + else if (isKick) + *argvp++ = "--ks=bootp"; + +#ifdef __i386__ + if (isNetwork) + *argvp++ = "--network"; + else + *argvp++ = "--local"; +#endif + + *argvp++ = NULL; + + execve(argv[0], argv, environ); + + exit(0); + } + + while (!doShutdown) { + childpid = wait4(-1, &waitStatus, 0, NULL); + + if (childpid == installpid) + doShutdown = 1; + } + + if (!WIFEXITED(waitStatus) || WEXITSTATUS(waitStatus)) { + printf("install exited abnormally "); + if (WIFSIGNALED(waitStatus)) { + printf("-- recieved signal %d", WTERMSIG(waitStatus)); + } + printf("\n"); + } else { + doReboot = 1; + } + + if (testing) + exit(0); + + sync(); sync(); + + if (!testing) { + printf("sending termination signals..."); + kill(-1, 15); + sleep(2); + printf("done\n"); + + printf("sending kill signals..."); + kill(-1, 9); + sleep(2); + printf("done\n"); + } + + printf("unmounting filesystems...\n"); + unmountFilesystems(); + + if (doReboot) { + printf("rebooting system\n"); + sleep(2); + + #if USE_MINILIBC + reboot(0xfee1dead, 672274793, 0x1234567); + #else + reboot(RB_AUTOBOOT); + #endif + } else { + printf("you may safely reboot your system\n"); + while (1); + } + + exit(0); + + return 0; +} diff --git a/loader/loader.c b/loader/loader.c new file mode 100644 index 000000000..328c6d332 --- /dev/null +++ b/loader/loader.c @@ -0,0 +1,61 @@ +/* + * loader.c + * + * This is the installer loader. Its job is to somehow load the rest + * of the installer into memory and run it. This may require setting + * up some devices and networking, etc. + * + * Erik Troan <ewt@redhat.com> + * Matt Wilson <msw@redhat.com> + * + * Copyright 1999 Red Hat Software + * + * This software may be freely redistributed under the terms of the GNU + * public license. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include <unistd.h> +#include <popt.h> +#include <newt.h> +#include "isys/imount.h" + +#define _(x) x + +int main(int argc, char ** argv) { + char * arg; + poptContext optCon; + int testing, rc; + struct poptOption optionTable[] = { + { "test", '\0', POPT_ARG_NONE, &testing, 0 }, + { 0, 0, 0, 0, 0 } + }; + + optCon = poptGetContext(NULL, argc, argv, optionTable, 0); + + if ((rc = poptGetNextOpt(optCon)) < -1) { + fprintf(stderr, "bad option %s: %s\n", + poptBadOption(optCon, POPT_BADOPTION_NOALIAS), + poptStrerror(rc)); + exit(1); + } + + if ((arg = poptGetArg(optCon))) { + fprintf(stderr, "unexpected argument: %s\n", arg); + exit(1); + } + + newtDrawRootText(0, 0, _("Welcome to Red Hat Linux")); + + newtPushHelpLine(_(" <Tab>/<Alt-Tab> between elements | <Space> selects | <F12> next screen ")); + + newtFinished(); + + execv(testing ? "../anaconda" : "/sbin/anaconda", argv); + + return 0; +} diff --git a/loader/minilibc.c b/loader/minilibc.c new file mode 100644 index 000000000..31628c4d8 --- /dev/null +++ b/loader/minilibc.c @@ -0,0 +1,201 @@ +#define MINILIBC_INTERNAL + +#include "minilibc.h" + +int atexit (void (*__func) (void)) { + return 0; +} + +void exit() { +} + +char ** _environ = NULL; +int errno = 0; + +void _init (int __status) { +} + +void __libc_init_first (int __status) { +} + +int +__libc_start_main (int (*main) (int, char **, char **), int argc, + char **argv, void (*init) (void), void (*fini) (void), + void (*rtld_fini) (void), void *stack_end) +{ + exit ((*main) (argc, argv, NULL)); + /* never get here */ + return 0; +} + +void _fini (int __status) { +} + +inline int socket(int a, int b, int c) { + unsigned long args[] = { a, b, c }; + + return socketcall(SYS_SOCKET, args); +} + +inline int bind(int a, void * b, int c) { + unsigned long args[] = { a, (long) b, c }; + + return socketcall(SYS_BIND, args); +} + +inline int listen(int a, int b) { + unsigned long args[] = { a, b, 0 }; + + return socketcall(SYS_LISTEN, args); +} + +inline int accept(int a, void * addr, void * addr2) { + unsigned long args[] = { a, (long) addr, (long) addr2 }; + + return socketcall(SYS_ACCEPT, args); +} + +int strlen(const char * string) { + int i = 0; + + while (*string++) i++; + + return i; +} + +char * strncpy(char * dst, const char * src, int len) { + char * chptr = dst; + int i = 0; + + while (*src && i < len) *dst++ = *src++, i++; + if (i < len) *dst = '\0'; + + return chptr; +} + +char * strcpy(char * dst, const char * src) { + char * chptr = dst; + + while (*src) *dst++ = *src++; + *dst = '\0'; + + return chptr; +} + +void * memcpy(void * dst, const void * src, int count) { + char * a = dst; + const char * b = src; + + while (count--) + *a++ = *b++; + + return dst; +} + +void sleep(int secs) { + struct timeval tv; + + tv.tv_sec = secs; + tv.tv_usec = 0; + + select(0, NULL, NULL, NULL, &tv); +} + +int strcmp(const char * a, const char * b) { + int i, j; + + i = strlen(a); j = strlen(b); + if (i < j) + return -1; + else if (j < i) + return 1; + + while (*a && (*a == *b)) a++, b++; + + if (!*a) return 0; + + if (*a < *b) + return -1; + else + return 1; +} + +int strncmp(const char * a, const char * b, int len) { + char buf1[1000], buf2[1000]; + + strncpy(buf1, a, len); + strncpy(buf2, b, len); + buf1[len] = '\0'; + buf2[len] = '\0'; + + return strcmp(buf1, buf2); +} + +void printint(int i) { + char buf[10]; + char * chptr = buf + 9; + int j = 0; + + if (i < 0) { + write(1, "-", 1); + i = -1 * i; + } + + while (i) { + *chptr-- = '0' + (i % 10); + j++; + i = i / 10; + } + + write(1, chptr + 1, j); +} + +char * strchr(char * str, int ch) { + char * chptr; + + chptr = str; + while (*chptr) { + if (*chptr == ch) return chptr; + chptr++; + } + + return NULL; +} + +void printf(char * fmt, ...) { + char buf[2048]; + char * start = buf; + char * chptr = buf; + va_list args; + char * strarg; + int numarg; + + strcpy(buf, fmt); + va_start(args, fmt); + + while (start) { + while (*chptr != '%' && *chptr) chptr++; + + if (*chptr == '%') { + *chptr++ = '\0'; + printstr(start); + + switch (*chptr++) { + case 's': + strarg = va_arg(args, char *); + printstr(strarg); + break; + + case 'd': + numarg = va_arg(args, int); + printint(numarg); + break; + } + + start = chptr; + } else { + printstr(start); + start = NULL; + } + } +} diff --git a/loader/minilibc.h b/loader/minilibc.h new file mode 100644 index 000000000..fac68f2a4 --- /dev/null +++ b/loader/minilibc.h @@ -0,0 +1,82 @@ +#include <stdarg.h> + +#define NULL ((void *) 0) + +#define WIFSTOPPED(status) (((status) & 0xff) == 0x7f) +#define WIFSIGNALED(status) (!WIFSTOPPED(status) && !WIFEXITED(status)) +#define WEXITSTATUS(status) (((status) & 0xff00) >> 8) +#define WTERMSIG(status) ((status) & 0x7f) +#define WSTOPSIG(status) WEXITSTATUS(status) +#define WIFEXITED(status) (WTERMSIG(status) == 0) + +#define MS_MGC_VAL 0xc0ed0000 + +#define isspace(a) (a == ' ' || a == '\t') + +extern char ** _environ; + +extern int errno; + +#include <linux/if.h> +#include <linux/un.h> +#include <linux/socket.h> +#include <linux/types.h> +#include <linux/net.h> +#include <linux/time.h> +#include <asm/posix_types.h> +#include <asm/termios.h> +#include <asm/ioctls.h> +#include <asm/unistd.h> +#include <asm/fcntl.h> + +#ifndef MINILIBC_INTERNAL +static inline _syscall5(int,mount,const char *,spec,const char *,dir,const char *,type,unsigned long,rwflag,const void *,data); +static inline _syscall5(int,_newselect,int,n,fd_set *,rd,fd_set *,wr,fd_set *,ex,struct timeval *,timeval); +static inline _syscall4(int,wait4,pid_t,pid,int *,status,int,opts,void *,rusage) +static inline _syscall3(int,write,int,fd,const char *,buf,unsigned long,count) +static inline _syscall3(int,reboot,int,magic,int,magic_too,int,flag) +static inline _syscall3(int,execve,const char *,fn,void *,argv,void *,envp) +static inline _syscall3(int,read,int,fd,const char *,buf,unsigned long,count) +static inline _syscall3(int,open,const char *,fn,int,flags,mode_t,mode) +static inline _syscall3(int,ioctl,int,fd,int,request,void *,argp) +static inline _syscall2(int,dup2,int,one,int,two) +static inline _syscall2(int,kill,pid_t,pid,int,sig) +static inline _syscall2(int,symlink,const char *,a,const char *,b) +static inline _syscall2(int,chmod,const char * ,path,mode_t,mode) +static inline _syscall2(int,sethostname,const char *,name,int,len) +static inline _syscall2(int,setdomainname,const char *,name,int,len) +static inline _syscall1(int,umount,const char *,dir) +static inline _syscall1(int,unlink,const char *,fn) +static inline _syscall1(int,close,int,fd) +static inline _syscall0(int,getpid) +static inline _syscall0(int,sync) +static inline _syscall0(int,fork) +static inline _syscall0(pid_t,setsid) +static inline _syscall1(int,exit,int,exitcode) +static inline _syscall3(int,syslog,int, type, char *, buf, int, len); +#else +static inline _syscall5(int,_newselect,int,n,fd_set *,rd,fd_set *,wr,fd_set *,ex,struct timeval *,timeval); +static inline _syscall3(int,write,int,fd,const char *,buf,unsigned long,count) +static inline _syscall2(int,socketcall,int,code,unsigned long *, args) +#endif + +#define select _newselect + +extern int errno; + +inline int socket(int a, int b, int c); +inline int bind(int a, void * b, int c); +inline int listen(int a, int b); +inline int accept(int a, void * addr, void * addr2); +int strlen(const char * string); +char * strcpy(char * dst, const char * src); +void * memcpy(void * dst, const void * src, int count); +void sleep(int secs); +int strcmp(const char * a, const char * b); +int strncmp(const char * a, const char * b, int len); +void printint(int i); +void printf(char * fmt, ...); +char * strchr(char * str, int ch); +char * strncpy(char * dst, const char * src, int len); + +void printstr(char * string); |
