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--