TIP: Click on subject to list as thread! ANSI
echo: c_echo
to: CHARLES ANGELICH
from: Pascal Schmidt
date: 2003-12-13 12:53:04
subject: Re: [C] Gating

Hi CHARLES! :-)

 CA> Note: No listing of new C programs are posted here _ever_. ;-) 
linuxrc program to boot a Linux system off a CD-ROM / filesystem (written
by me, but let's say I'm putting this into the public domain). This needs a
few more ingredients besides the C program to work, though. Something
similar to this is used by Knoppix and others, but I wrote mine from
scratch.

This can be compiled with

    gcc -static -Os -march=i386 linuxrc.c -o linuxrc
    strip linuxrc

and then it needs to be put onto a filesystem image as /linuxrc together
with an empty /mnt directory and a /dev directory containing /dev/console,
/dev/hda through /dev/hdt, and /dev/scd0 through /dev/scd9. This filesystem
image can then be compressed with gzip and passed to a linux kernel as an
initial ramdisk image. On boot, the kernel will unpack the image and run
the /linuxrc program. The program then locates the CD-ROM devices in the
system and tries each of them in turn to find a disc with the file
/etc/rc.d/rc.sysinit (system initialization script) on it. If it is found,
it is made the new / filesystem and /sbin/init is executed from it.

   ----- linuxrc.c begins -----
#include 
#include 
#include 
#include 

#include 
#include 
#include 
#include 
#include 

int pivot_root(const char *new_root, const char *put_old);

#define KLOG_GET_MESSAGES       3
#define KLOG_SET_LOGLEVEL       8

#define BUFSIZE         65536
#define DEVNAMEMAX      16
#define UNIQUEFILE      "/mnt/etc/rc.d/rc.sysinit"

void halt_system(void)
{
        while (1)
                ;
}

void check_okay(int res, const char *errmsg)
{
        if (res < 0) {
                printf("Error: %s\n", errmsg);
                halt_system();
        }
}

int correct_medium(const char *devname)
{
        int res;
        struct stat buf;
        
        res = mount(devname, "/mnt", "iso9660", (0xC0ED
<< 16) | MS_RDONLY, 0);
        if (res == -1) {
                printf("No suitable medium on %s\n", devname);
                return 0;
        }
                
        res = stat(UNIQUEFILE, &buf);
        if (res == -1) {
                umount("/mnt");
                printf("Unrelated filesystem on %s\n", devname);
                return 0;
        }
        
        printf("Root filesystem found on %s\n", devname);
        return 1;
}

void change_root(void)
{
        int res;

        res = chdir("/mnt");
        check_okay(res, "could not cd into CD-ROM root filesystem");
        
        res = pivot_root("/mnt", "/mnt/initrd");
        check_okay(res, "could not change / to CD-ROM root filesystem");
        
        execl("/sbin/init", "/sbin/init");
        
        check_okay(-1, "could not execute /sbin/init");
}

int main(int argc, char **argv)
{
        char buf[BUFSIZE];
        char devname[DEVNAMEMAX];
        char *work, *line, *sub;
        int res, found = 0;
        
        puts("Attempting to locate CD-ROM device");

        klogctl(KLOG_SET_LOGLEVEL, NULL, 1);

        memset(buf, 0, BUFSIZE);

        res = klogctl(KLOG_GET_MESSAGES, buf, BUFSIZE);
        check_okay(res, "could not read kernel messages");

        work = buf;
        while (work) {
                line = strsep(&work, "\n");
                
                sub = strstr(line, "ATAPI CD/DVD-ROM drive");
                if (sub) {
                        memset(devname, 0, DEVNAMEMAX);
                        strcpy(devname, "/dev/");
                        memcpy(devname+5, line+3, 3);
                        
                        printf("ATAPI CD-ROM at: %s\n", devname);
                        
                        if (correct_medium(devname))
                                change_root();
                        
                        found = 1;
                }
                
                sub = strstr(line, "Attached scsi CD-ROM sr");
                if (sub) {
                        memset(devname, 0, DEVNAMEMAX);
                        strcpy(devname, "/dev/scd");
                        memcpy(devname+8, line+26, 1);
                        
                        printf("SCSI CD-ROM at: %s\n", devname);
                        
                        if (correct_medium(devname))
                                change_root();
                        
                        found = 1;
                }
        }

        if (!found)
                puts("No CD-ROM device found");
        else
                puts("Root filesystem not found on CD-ROM device(s)");
        
        halt_system();
        
        /* NOT REACHED */
        return 0;
}
   ----- linuxrc.c ends -----

Ciao
Pascal

--- Msged/LNX 6.1.1
* Origin: The Nine have left Minas Morgul. (1:153/401.2)
SEEN-BY: 633/267 270
@PATH: 153/401 307 140/1 106/2000 633/267

SOURCE: echomail via fidonet.ozzmosis.com

Email questions or comments to sysop@ipingthereforeiam.com
All parts of this website painstakingly hand-crafted in the U.S.A.!
IPTIA BBS/MUD/Terminal/Game Server List, © 2025 IPTIA Consulting™.