tech-embed archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Where to start...?



The attached mini_init.c works for me. (Note that this is a stripped down version of an init that did a bit more stuff that is specific to our system).

Compile with "cc -Wall -Werror -static -o init mini_init.c".

/Erik

Rose, Brian wrote:

From: Erik Anggard <erik.anggard%packetfront.com@localhost>
List: tech-embed

Well, if you want to get really minimalistic all you'll need is:
- A kernel (comment out all options and devices you don't need, in the config file before compiling it to reduce the size of the kernel). - A root device: if you don't have a hardrive you can use a memory disk beded in the kernel (like in the installation-kernel) or NFS. - Your own statically linked /sbin/init on the root device. This is the only userland process started by the kernel so if your system only need to run one program call it init and place it in /sbin. (Your program might have to do some of the things that the original init does, e.g. if your program wants do console io you will need a /dev/console and your init will have to open that device and dup2 fd's 0, 1 and 2 to that fd). You can of course use the standard init and instead creat your own
/etc/rc.

Has anyone created a minimal init that just sets up the console? I've tried
looking through the init code, but I'm not seeing where it sets this up.

I'm currently looking through all the glibc functions to find outhow to do
this. Is there a simple code snippet somewhere that shows how to set up the
console and operate a simple C program (aka Hello World!)?

Thanks for the help.


Brian Rose Brian dot Rose at icn dot siemens dot com 407-942-6934 If you hold a Unix shell to your ear, do you hear the C?

/* $Id: asrbl.c,v 1.48 2002/03/05 10:34:09 eriang Exp $ */

/*
 * File:    mini_init.c
 * By:      Erik Anggard, PacketFront Sweden AB
 * Created: 2001-10-02
 *
 * Minimal init process.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <sys/param.h>
#include <sys/reboot.h>
#include <sys/mount.h>
#include <ufs/ufs/ufsmount.h>
#include <sys/cdefs.h>
#include <sys/socket.h>
#include <stddef.h>
#include <syslog.h>



/*
 * Defines
 */
#define DEFAULT_ROOTUID -2
#define PATH_CONSOLE "/dev/console"
#define MAXCMD 128


/*
 * Prototypes
 */
static void reboot_system(void);
static void critical(char *msg);
static int setup_tty(char *name, int redirect);
void badsig_handler(int sig);
static int setup_signals(void);


/*
 * Globals 
*/
int single = 0;


/*
 * main
 */
int 
main(int argc, char *argv[])
{
        struct ufs_args args;
        char cmdstr[MAXCMD+1], *s, *s2;
        int done;

        if (argc == 2 && !strcmp(argv[1], "-s"))
                single = 1;
                
        if (single) {
                openlog("init", LOG_CONS|LOG_ODELAY, LOG_AUTH);

                /* remount root fs in read-write */
                bzero(&args, sizeof(struct ufs_args));
                args.export.ex_root = DEFAULT_ROOTUID;
                if (mount(MOUNT_FFS, "/", MNT_UPDATE, &args) == -1)
                        syslog(LOG_ALERT, "init: failed to remount root files "
                               "system read-write\n");

                setup_signals();

                setup_tty(PATH_CONSOLE, 1);

        }


        done = 0;
        while (!done) {
                /* Display simple prompt. */
                printf("# ");
                if ((s = fgets(cmdstr, MAXCMD, stdin)) != NULL) {
                        /* strip white space */
                        while (isspace(*s)) s++;
                        s2 = s;
                        while (*s2 != '\0') s2++;
                        s2--;
                        while (isspace(*s2) && s2 > s) s2--;
                        s2[1] = '\0';
                        if (*s == '\0')
                                continue;
                        /* Handle commands. */
                        if (!strcmp(s, "reboot")) {
                                done = 1;
                        } else if (!strcmp(s, "test")) {
                                printf("test!\n");
                        } else {
                                printf("unkown command: %s\n", s);
                        }
                        
                }
        }
        

        if (single)
                reboot_system();

        return (0);
}


/*
 * reboot
 */
static void 
reboot_system(void)
{

        if (reboot(RB_AUTOBOOT, NULL) == -1)
                perror("reboot");

        for (;;);
}


/*
 * critical
 */
static void 
critical(char *msg)
{
        syslog(LOG_EMERG, "%s", msg);
        reboot_system();
}


/* Setup the console for output/input/whatever. Much of this is
 * taken from the NetBSD init and libs. 
 */
static int 
setup_tty(char *name, int redirect)
{
        int fd;

        revoke(name);
        sleep(2); /* NetBSD does this. */

        if((fd = open(name, O_RDWR)) == -1)
                critical("Unable to open tty");

        /* Taken from login_tty */
        setsid();
        if(ioctl(fd, TIOCSCTTY, NULL) == -1)
                critical("Unable to set controlling tty");
        if (redirect) {
                dup2(fd, 0);
                dup2(fd, 1);
                dup2(fd, 2);
        }
        if (fd > 2)
                close(fd);

        return 0;
}


/*
 * badsig_handler
 */
void 
badsig_handler(int sig)
{
        char text[64];

        snprintf(text, 64, "Received signal %d", sig);
        critical(text);
}


/* Signal choices taken from NetBSD init. */
static int 
setup_signals(void)
{
        struct sigaction sa;
        sigset_t mask;
  
        sigemptyset(&sa.sa_mask);
        sa.sa_flags = 0;
        sa.sa_handler = badsig_handler;
        sigaction(SIGSYS, &sa, NULL);
        sigaction(SIGABRT, &sa, NULL);
        sigaction(SIGFPE, &sa, NULL);
        sigaction(SIGILL, &sa, NULL);
        sigaction(SIGSEGV, &sa, NULL);
        sigaction(SIGBUS, &sa, NULL);
        sigaction(SIGXCPU, &sa, NULL);
        sigaction(SIGXFSZ, &sa, NULL);
        sigaction(SIGTERM, &sa, NULL);
        
        sigemptyset(&sa.sa_mask);
        sa.sa_flags = 0;
        sa.sa_handler = (void *)reboot_system;
        sigaction(SIGUSR1, &sa, NULL);
        
        sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
        sa.sa_handler = badsig_handler;
        sigaction(SIGCHLD, &sa, NULL);

        sigfillset(&mask);
        sigdelset(&mask, SIGABRT);
        sigdelset(&mask, SIGFPE);
        sigdelset(&mask, SIGILL);
        sigdelset(&mask, SIGSEGV);
        sigdelset(&mask, SIGBUS);
        sigdelset(&mask, SIGSYS);
        sigdelset(&mask, SIGXCPU);
        sigdelset(&mask, SIGXFSZ);
        sigdelset(&mask, SIGHUP);
        sigdelset(&mask, SIGTERM);
        sigdelset(&mask, SIGUSR1);
        
        sigprocmask(SIG_SETMASK, &mask, NULL);
        sigemptyset(&sa.sa_mask);

        return 0;
}






Home | Main Index | Thread Index | Old Index