/*
 * This programs intends to replace some basic linuxrc scripts found in initrd
 * This one is made for my old configuration with lvm
 */

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mount.h>
#include <linux/unistd.h> 
#include <errno.h>
#include <sys/types.h> 
#include <unistd.h> 
#include <sys/wait.h> 
#include <sys/stat.h>
#include <linux/kdev_t.h>

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

//Like system(), but more controllable (especially regarding signals)
void launch(char *commande) {
        int pid=fork();
        if(pid ==0 ) {
                int nb;
                char *cmd=strdup(commande);
                char *cmd2=strdup(cmd);
                nb= (strtok(cmd" ") != NULL) ? 1 : 0;
                if(nb==0)
                        exit(-1);
                for(nb=1;strtok(NULL" ")!=NULL;nb++);
                char **args=malloc(sizeof(char*)*nb+1);
                free(cmd);
                cmd=cmd2;
                if(!args)
                        exit(-1);
                args[1]=NULL;
                args[0]=strtok(cmd" ");
                for(nb=1;(args[nb]=strtok(NULL" "))!=NULL;nb++) {
                        args=realloc(argssizeof(char*)*nb+1);
                }
                args[nb]=NULL;
                execvp(args[0], args);
                exit(-1);
        }
        int ret;
        waitpid(pid, &ret0);
}

//Q&D error check
void check_errno(char *what) {
        if(errno==EINTR)
                errno=0;
        if(errno>0) {
                perror(what);
                exit(1);
        }
}

//Look at dm-dev.c for more information about this function
void create_mapper_control() {
        FILE *file=fopen("/proc/misc""r");
        char *buf=NULL;
        size_t len=-1;
        while(getline(&buf, &lenfile)>0) {
                char dev_name[256];
                int dev_nb=-1;
                sscanf(buf"\t%d %255s\n", &dev_nbdev_name);
                if(strcmp(dev_name"device-mapper")==0) {
                        printf("%d:%s\n"dev_nbdev_name);
                        unlink("/dev/mapper/control");
                        mknod("/dev/mapper/control"S_IFCHR|0700,MKDEV(/*misc devices */10,dev_nb));
                }
                buf=NULL;
        }
        fclose(file);
}

//Prepare resume (or at least suspend for later) with suspend2 (syntax may have changed)
void launch_resume() {
        FILE *file=fopen("/proc/software_suspend/resume2""w");
        char *str;
        str="swap:0x0301\n"
        fwrite(strstrlen(str),1,file);
        fclose(file);
        file=fopen("/proc/software_suspend/do_resume""w");
        fwrite("\n"2,1,file);
        fclose(file);
}

//All this should be explicit, if not just email me
int main(int argcchar **argvchar **envp) {
        mount("procfs""/proc""proc"0,NULL);
        check_errno("mount /proc");
        create_mapper_control();
        launch("/bin/lvm vgscan");
        check_errno("vgscan");
        launch("/bin/lvm vgchange -a y");
        check_errno("vgchange");
        launch("/bin/lvm vgmknodes");
        check_errno("vgmknodes");
        launch_resume();
        mount("/dev/pierre/fnux""/sysroot""reiserfs"0"user_xattr,acl");
        check_errno("mount /sysroot");
        struct stat stat_buf;
        if(stat("/dev/mapper/pierre-fnux", &stat_buf)==0)
                printf("pierre/fnux = %x\n", (unsigned int)stat_buf.st_rdev);
        umount("/proc");
        check_errno("umount /proc");
        chdir("/sysroot");
        check_errno("cd /sysroot");
        if(pivot_root(".""initrd")!=0) {
                check_errno("pivot_root");
                exit(-1);
        }
        argv[0]="init";
        chroot(".");
        execve("/sbin/init"argvenvp);
        return 0;
}