Subject: Re: Where to start...?
To: Rose, Brian <Brian.Rose@icn.siemens.com>
From: Erik Anggard <erik.anggard@packetfront.com>
List: tech-embed
Date: 08/26/2002 11:15:19
This is a multi-part message in MIME format.
--------------060704090605000904010201
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit
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>
>>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?
>
>
--------------060704090605000904010201
Content-Type: text/plain;
name="mini_init.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="mini_init.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;
}
--------------060704090605000904010201--