diff options
author | Willy Tarreau <w@1wt.eu> | 2006-07-16 14:53:35 +0200 |
---|---|---|
committer | Willy Tarreau <willy@wtap.(none)> | 2006-07-26 11:51:24 +0200 |
commit | 0781bb99431d00e7001e84245499190eb4ed05ed (patch) | |
tree | 2bbdab3eb3a78b3b8b4cb1c401614b19549d9e56 | |
parent | [RELEASE] flxutils-0.1.19 (diff) | |
download | flxutils-0781bb99431d00e7001e84245499190eb4ed05ed.tar.gz |
[RELEASE] flxutils-0.1.20v0.1.20
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | init/README.2~ | 56 | ||||
-rw-r--r-- | init/init.c~ | 1746 | ||||
-rwxr-xr-x | scripts/pkg | 6 |
4 files changed, 7 insertions, 1805 deletions
@@ -33,3 +33,7 @@ .tgz, .lst, and .dep ; do_config & do_compile_only done in sub-shells ; automatic permissions on /etc/profile.d/*. Better handling of symlinks. - release 0.1.19 + +2003/10/26 + - fixes to pkg (0.3.17) + - release 0.1.20 diff --git a/init/README.2~ b/init/README.2~ deleted file mode 100644 index 03ce196..0000000 --- a/init/README.2~ +++ /dev/null @@ -1,56 +0,0 @@ -Résumé rapide des commandes les plus courantes : - - - { ... } : bloc d'instructions - - &<cmd> : n'exécute CMD que si le retour précédent est OK - - |<cmd> : n'exécute CMD que si le retour précédent est ERR - - !<cmd> : inverse le code de retour de CMD, et peut être - combiné à &,| - - - te VAR=VAL => retourne TRUE si VAR=VAL dans l'env. - - in : spécifie l'init auquel on donne la main - - ec : echo - - rd : passe en mode prompt clavier, en affichant le - message. Ne retourne jamais d'erreur. Le prompt - compte les niveaux pour s'y retrouver avec les {} :-) - - mt : mount ; um : umount - - mv : mount --move ; bi : mount --bind - - ex : exécute dans un sous-process (system()) - - /path/prog args : idem. - - rx xxx yyy : execute yyy dans chroot xxx; - - md : mkdir ; ln : lien - - bl,ch,fi : devices block, char, fifo - - pr xxx yyy : pivot_root : root -> xxx/yyy ; xxx->root - - -C'est une conf opérationnelle de boot avec un linuxrc dans un initrd -et un .preinit sur un CD. -Par défaut, le kernel charge /sbin/init à partir de l'initrd. Ce dernier -est un lien qui pointe vers le script /.linuxrc, référençant lui-même -/linuxrc comme interpréteur. Le résultat est que l'on exécute : - /linuxrc < /sbin/init ce qui revient à /linuxrc < /.linuxrc - -Il est possible de forcer le chemin de linuxrc par 'init=/xxxxx' au boot. - -Ensuite, le script linuxrc monte le CD puis exécute soit /sbin/init, soit -le nom en regard de la ligne 'in xxxx' dans la conf, soit xxxx si -'init2=xxxx' est précisé sur la ligne de commande, soit enfin le paramètre -de 'in' fourni au clavier en mode prompt si "RDSHELL=1" est passé au noyau. - -Le /sbin/init du CD utilise par défaut /.preinit (qu'on aurait pu appeler -en direct par 'init=' venant d'un kernel sans initrd, ou 'init2=' venant -d'un initrd équipé du linuxrc décrit ci-dessus). - -Si le paramètre "RAMCOPY=1" est passé au kernel, alors le script recopie -tout le CD en RAM, puis le démonte. - -Si le paramètre "AUTORUN=1" est passé au kernel, alors il tentera de monter -une disquette en ext2 puis en fat, pour y exécuter /autorun dans un -sous-processus. - -Si le paramètre "INITSHELL=1" est passé au kernel, alors l'utilisateur -récupère un prompt. - -Enfin, le script transfère l'exécution à /sbin/init-sysv, ou au binaire -désigné par 'in' dans le script, ou par celui désigné par le paramètre -"INIT=xxx" passé au kernel. - diff --git a/init/init.c~ b/init/init.c~ deleted file mode 100644 index 3f6b45f..0000000 --- a/init/init.c~ +++ /dev/null @@ -1,1746 +0,0 @@ -/* - WARNING ! THIS CODE IS OPTIMIZED FOR SIZE WITH COMPILED-IN ARGUMENTS. IT IS - SUBJECT TO BUFFER OVERFLOWS SO DON'T USE IT WITH RUNTIME ARGUMENTS !!! -*/ - -/* TODO : - - make the config buffer bigger - - a few security checks (buffer overflows...) - - cleanup the code a bit -*/ - -/* - preinit - new try on 2002/04/20 - Willy Tarreau <willy AT meta-x.org> - - usage : /sbin/preinit [ \< config_file ] [ { init args | "rebuild" } ] - - Note : the "\< config_file" is to be used within configuration files : - #!/sbin/preinit < - .... - Thus, when you pass "init=/.preinit", the kernel executes : - /sbin/preinit < /.preinit - - The '<' character has been chosen for its rareness. - - the "rebuild" argument make the tool only rebuild a complete /dev - tree from the informations contained in the .preinit file, and then - exit. It does this even if the pid is not 1, but doesn't execute nor - mount anything. Only mkdir, links, blocks, chars and fifo devices are - created. Very useful before a lilo : - - # chroot /mnt/disk /.preinit rebuild - # lilo -r /mnt/disk - # umount /mnt/disk/dev - - If /dev/console is found under /dev, it will not be rebuilt. - - **** needs to rework the doc a bit since it's not up-to-date. **** - - This code tries to build a few filesystem squeleton so that init has enough - to work correctly : - - mount -t proc /proc /proc - - mount -t tmpfs /dev /dev - - get information from a file : /.preinit which describes what to mount, - what ramdisks, links and dirs to make : - -ln L source dest - make a symlink from <source> to <dest> -md D path [ mode ] - create a directory named <path> with the mode <mode>. If mode is left - undefined, 0755 is assumed. -mt M blkdev[(major:minor)] path fstype [ { ro | rw } [ flags ] ] - if <major:minor> is specified, create a block device <blkdev> - with <major> and <minor> and mode 0600. - mount <blkdev> under <path> with type <fstype>, read-only, except if - rw is specified, and args <flags>. -in I path - set the next init program to <path> -ex E cmd [ args ]* - execute <cmd> with args <args> and wait for its completion. -rx R dir cmd [ args ]* - chroot to <dir>, execute <cmd> with args <args> and wait for its completion. -bl B mode uid gid major minor naming_rule - create a set of block devices -ch C mode uid gid major minor naming_rule - create a set of char devices -fi F mode uid gid name - create a fifo -ma U mode - change umask -pr P <new_root> <put_old_relative> - pivot root : old root is displaced into new_root/put_old_relative, and - new_root is displaced under /. -mv K <old_dir> <new_dir> - keep directory <old_dir> after a pivot, then unmount it from old_dir. - usefull for /dev, /proc, /var ... -um O <old_dir> - umount <old_dir> after a pivot for example. -lo l </dev/loopX> <file> - losetup /dev/loopX file. - # anything - comment. - - The devices naming rules consist in strings mixed with numbering rules delimited with - brackets. Each numbering rule has 4 comma-separated fields : - - type of this string portion : 'c' for a single char, 'i' for an int, 'I' for an int - for which 0 is not printed, 'h' for an hex digit - - the range : - - chars: any concatenation of character ranges separated with a dash '-': 'a-fk-npq' - - ints : either an int or a range composed of 2 ints separated with a dash : '1-16' - - hex : same as int, but with hex digits (case insensitive) - - the scale : how much to add to the minor device for each step in the range. - - The commands may be prefixed with a '|' or '&', in which case, they will be - executed only if the previous command failed (|) or succeeded (&). - - Example : - ln hda3 /dev/disk => symlinks /dev/disk to hda3 - md /var/tmp 1777 => creates a directory /var/tmp with mode 1777 - mt /dev/hda1 /boot ext2 => attempts to mount /dev/hda1 read-only under /boot. - |mt /dev/hda1(3:1) /boot ext2 => only if the previous command failed, creates /dev/hda1 with major 3, minor 1 and mounts it under /boot - in /sbin/init-std => the following init will be this /sbin/init-std (31 chars max) - ex /sbin/initramdisk /dev/ram6 1200 => executes /sbin/initramdisk with these args and waits for its completion - bl 0600 0 0 3 1 hd[c,ab,64][i,1-16,1] => makes all hdaX and hdbX with X ranging from 1 to 16 - ch 0600 0 5 2 0 pty[c,p-za-f,16][h,0-f,1] => makes all 256 pty* - #comment => ignore this line - - For executable reduction reasons, the .preinit file is limited to 4 kB. - - The choice of the init program is quite complex, because we want to avoid - stupid loops and buggy behaviours while conservating quite a parametrable - init. Basically, we'll use environment variables that we will destroy once - read, to avoid getting them again if we loop on ourselves (imagine an - 'exec /sbin/init" from a shell cmd line, which will blindly re-exec a shell). - So there are two distinct cases (init and linuxrc) : - - 1) linuxrc - We want to be able to either return or transfer execution to the real init. - - - if we find "init2=xxxx" in the env, we memorize it and move it away from the env. - - if "in xxxx" has been specified on a keyboard input from an "rd" - statement, we unconditionnaly do an execve("xxx", "xxx", ##no args##, ##envp##). - - if the env contained "init2=xxxx", we do an execve("xxxx", "xxxx", ##no args##, ##envp##). - we don't pass the args because it is a rescue init, such as a shell, and - we don't want it to fail on "bash: auto: command not found" or similar. - - if the conf contained "in xxxx", we do an execve("xxxx", "xxxx", argv[], ##envp##) - because we want it to know about the original args. Eg: init=/linuxrc single - - if the conf didn't contain "in xxxx", we unmount all what we can and - return. The kernel will be able to switch over to the next init stage. - - 2) init, or anything else (telinit, ...) - We want to transfer execution to the real init. - - - if we find "INIT=xxxx" in the env, we memorize it and move it away from the env. - - if "in xxxx" has been specified on a keyboard input from an "rd" - statement, we unconditionnaly do an execve("xxx", "xxx", ##no args##, ##envp##). - - if the env contained "INIT=xxxx", we do an execve("xxxx", "xxxx", ##no args##, ##envp##). - we don't pass the args because it is a rescue init, such as a shell, and - we don't want it to fail on "bash: auto: command not found" or similar. - - if the conf contained "in xxxx", we do an execve("xxxx", "xxxx", argv[], ##envp##) - because we want it to know about the original args. Eg: init=/.preinit single - - if the conf didn't contain "in xxxx", we transfer execution to "/sbin/init-sysv". - - Note: basically, each time an environment variable is read, it must be killed afterwards. - Eg: init2=, INIT=, ... - - - The root directory should contain the following dirs : - - /var (directory) -> can be a ramfs or a real dir on another device - - /var/tmp (directory) -> idem - - /tmp (directory) -> idem - - /etc (directory or symlink) -> several possibilities : - - directory on the root fs (preferably) - - directory on another fs - - ramfs (or ramdisk) and directory extracted from other source - - symlink to /boot/etc (in this case, /boot/etc must be a populated directory) - /etc will already have several symlinks - - /boot (mandatory directory) contains the following : - - [kernel version] (directory) with vmlinuz, System.map, config and - the tree behind /lib/modules/[version] - - current (symlink to kernel version) - - vmlinuz (symlink to current/vmlinuz) - - System.map (symlink to current/System.map) - - config (symlink to current/config) - - eventually initrd (symlink to current/initrd) - - modules.dep (symlink to current/modules.dep) - - modules.pcimap (symlink to current/modules.pcimap) - - /boot *may* contain the following : - - etc (populated directory) - - bootfstab (if /etc and /boot/etc empty or non-existant) - - This helps in making /lib/modules : it will simply be a symlink to - /boot/current which will contain all modules. - - -wrong for now: - /tmp will always be linked to fs/var/tmp. - /var will always be linked to fs/var. - /fs must contain a description file for it (what to mount where, what to - initialize) so that init has a working filesystem hierarchy and fstab works. - /fs should be FAT-compatible, at least for its root structure. -*/ - -#include <stdio.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <fcntl.h> -#include <unistd.h> -#include <string.h> -#include <ctype.h> -#include <sys/mount.h> -#include <stdlib.h> -#include <sys/ioctl.h> -#include <sys/stat.h> -#include <linux/loop.h> - -#ifndef MNT_DETACH -#define MNT_DETACH 2 -#endif - -#ifndef MS_MOVE -#define MS_MOVE 8192 -#endif - -#define STR_SECT ".rodata" - -#ifdef DEBUG -static void print(char *c) { - char *p = c; - while (*p) - p++; - write(0, c, p-c); -} -#else -#define print(a,...) do{}while(0) -#endif - -//#define ATOL(x) atol(x) -#define ATOL(x) my_atoul(x) - -typedef unsigned char uchar; - - -/* this ordering is awful but it's the most efficient regarding space wasted in - * long strings alignment with gcc-2.95.3 (gcc 3.2.3 doesn't try to align long - * strings). - */ -static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) msg_ent_console[] = "Entering command line mode : enter one command per line, end with '.'\n"; -static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) root_dir[] = "/"; -static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) cur_dir[] = "."; -static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) dev_name[] = "/dev"; -static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) var_dir[] = "/var"; -static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) cfg_fname[] = "/.preinit"; /* configuration file */ -static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) msg_err_console[] = "Command ignored, input alread bound to console !\n"; -static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) dev_console[] = "dev/console"; -static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) str_rebuild[] = "rebuild"; -static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) var_tmp[] = "/var/tmp"; -static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) var_run[] = "/var/run"; -static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) proc_self_fd[] = "/proc/self/fd"; -//static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) proc_cmdline[] = "/proc/cmdline"; -//static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) sbin_init[] = "sbin/init"; -static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) sbin_init_sysv[] = "sbin/init-sysv"; -static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) cfg_linuxrc[] = "/.linuxrc"; -static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) dev_options[] = "size=0,nr_inodes=4096,mode=755"; -static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) str__linuxrc[] = "/linuxrc"; -static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) proc_dir[] = "/proc"; -static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) tmpfs_fs[] = "tmpfs"; -static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) dev_root[] = "dev/root"; - - -#define tmp_name (var_tmp + 4) // static const char tmp_name[] = "/tmp"; -#define proc_fs (proc_dir+1) // static const char proc_fs[] = "proc"; -#define fd_dir (proc_self_fd + 11) // static const char fd_dir[] = "fd"; -#define str_linuxrc (str__linuxrc+1) // "linuxrc" - - -#define CONST_STR(x) ({ static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) ___str___[]=x; (char *)___str___; }) - -/* used by naming rules */ -#define MAX_FIELDS 8 -#define MAX_DEVNAME_LEN 64 -#define MAX_CFG_SIZE 4096 -#define MAX_CFG_ARGS 16 -//#define MAX_CMDLINE_LEN 512 -#define MAX_BRACE_LEVEL 10 - -struct dev_varstr { - char type; - union { - struct { - char *set; - char *ptr; - char value; /* value to be printed */ - uchar index; /* index in the set */ - } chr; - struct { - uchar low; - uchar high; - uchar value; - } num; - } u; - uchar scale; -}; - -enum { - TOK_LN = 0, /* ln : make a symlink */ - TOK_MD, /* md : mkdir */ - TOK_MT, /* mt : mount */ - TOK_IN, /* in : set init program */ - TOK_EX, /* ex : execute */ - TOK_RX, /* rx : execute under chroot */ - TOK_BL, /* bl : make block devices */ - TOK_CH, /* ch : make char devices */ - TOK_FI, /* fi : make a fifo */ - TOK_MA, /* ma : set umask */ - TOK_PR, /* pr : pivot root */ - TOK_MV, /* mv : move a filesystem */ - TOK_BI, /* bi : bind a directory */ - TOK_UM, /* um : umount a filesystem */ - TOK_LO, /* lo : losetup */ - TOK_EC, /* ec : echo */ - TOK_TE, /* te : test an environment variable */ - TOK_RD, /* rd : read a command from the console */ - TOK_OB, /* { : begin a command block */ - TOK_CB, /* } : end a command block */ - TOK_DOT, /* . : end of config */ - TOK_UNK, /* unknown command */ - TOK_EOF, /* end of file */ - TOK_COND_NEG = 0x20, /* negate the result before evaluation */ - TOK_COND_OR = 0x40, /* conditionnal OR */ - TOK_COND_AND = 0x80, /* conditionnal AND */ - TOK_COND = 0xE0, /* any condition */ -}; - -/* counts from TOK_LN to TOK_DOT */ -#define NB_TOKENS 21 - -/* this contains all two-chars command, 1-char commands, followed by a token - * number. - */ -static const __attribute__ ((__section__(STR_SECT),__aligned__(1))) struct { - char lcmd[2]; /* long form */ - char scmd; /* short form */ - char minargs; /* min #args */ -} tokens[NB_TOKENS] = { - "ln", 'L', 2, /* TOK_LN */ - "md", 'D', 1, /* TOK_MD */ - "mt", 'M', 3, /* TOK_MT */ - "in", 'I', 1, /* TOK_IN */ - "ex", 'E', 1, /* TOK_EX */ - "rx", 'R', 2, /* TOK_RX */ - "bl", 'B', 6, /* TOK_BL */ - "ch", 'C', 6, /* TOK_CH */ - "fi", 'F', 4, /* TOK_FI */ - "ma", 'U', 1, /* TOK_MA */ - "pr", 'P', 2, /* TOK_PR */ - "mv", 'K', 2, /* TOK_MV */ - "bi", 'K', 2, /* TOK_BI */ - "um", 'O', 1, /* TOK_UM */ - "lo", 'l', 2, /* TOK_LO */ - "ec", 0, 0, /* TOK_EC */ - "te", 0, 1, /* TOK_TE */ - "rd", 0, 0, /* TOK_RD */ - "{", '{', 0, /* TOK_OB */ - "}", '}', 0, /* TOK_CB */ - ".", '.', 0, /* TOK_DOT : put every command before this one */ -}; - -#define UID_ROOT 0 -#define GID_ROOT 0 -#define GID_TTY 5 -#define GID_KMEM 9 - -static const __attribute__ ((__section__(STR_SECT),__aligned__(1))) struct { - char name[8]; - short gid; - char major, minor; - mode_t mode; /* mode + S_IFCHR, S_IFBLK, S_IFIFO */ -} dev_nodes[] = { - /* console must always be at the first location */ - { "console", GID_TTY, 5, 1, 0600 | S_IFCHR }, - { "mem", GID_KMEM, 1, 1, 0640 | S_IFCHR }, - { "kmem", GID_KMEM, 1, 2, 0640 | S_IFCHR }, - { "null", GID_ROOT, 1, 3, 0666 | S_IFCHR }, - { "port", GID_KMEM, 1, 4, 0640 | S_IFCHR }, - { "zero", GID_ROOT, 1, 5, 0666 | S_IFCHR }, - { "full", GID_ROOT, 1, 7, 0666 | S_IFCHR }, - { "random", GID_ROOT, 1, 8, 0644 | S_IFCHR }, - { "urandom", GID_ROOT, 1, 9, 0644 | S_IFCHR }, - { "tty0", GID_TTY, 4, 0, 0600 | S_IFCHR }, - { "tty", GID_TTY, 5, 0, 0666 | S_IFCHR }, - { "ptmx", GID_TTY, 5, 2, 0666 | S_IFCHR }, - { "initctl", GID_ROOT, 0, 0, 0600 | S_IFIFO }, -} ; - -static char cfg_data[MAX_CFG_SIZE]; -static char *cfg_args[MAX_CFG_ARGS]; -static char *cfg_line; -//static char cmdline[MAX_CMDLINE_LEN]; -static char *cst_str[MAX_FIELDS]; -static char *var_str[MAX_FIELDS]; -static struct dev_varstr var[MAX_FIELDS]; -static int error; /* an error has emerged from last operation */ -static int linuxrc; /* non-zero if we were called as 'linuxrc' */ - -/* the two input modes */ -#define INPUT_FILE 0 -#define INPUT_KBD 1 - -static unsigned long my_atoul(const char *s) { - unsigned long res = 0; - unsigned long digit; - - while (*s) { - digit = *s - '0'; - if (digit > 9) - return 0; - res = res * 10 + digit; - s++; - } - return res; -} - -static int streq(const char *str1, const char *str2) { - char c1; - while ((c1 = *str1) && c1 == *str2) { /* the second test ensures that *str2 != 0 */ - str1++; - str2++; - } - return ((c1 | *str2) == 0); -} - -/* - * copies at most <size-1> chars from <src> to <dst>. Last char is always - * set to 0, unless <size> is 0. The number of chars copied is returned - * (excluding the terminating zero). - * This code has been optimized for size and speed : on x86, it's 45 bytes - * long, uses only registers, and consumes only 4 cycles per char. - */ -static inline int my_strlcpy(char *dst, const char *src, int size) { - char *orig = dst; - if (size) { - while (--size && (*dst = *src)) { - src++; dst++; - } - *dst = 0; - } - return dst - orig; -} - -static void reopen_console() { - int i, fd, oldfd; - - oldfd = dup2(0, 3); // keep a valid console on fd 3 - - for (i = 0; i < 3; i++) - close(i); - - fd = open(dev_console, O_RDWR); // fd = 0 (stdin) or -1 (error) - if (fd < 0) - dup(oldfd); // restore 0 from old console - - close(oldfd); - dup(0); // stdout - dup(0); // stderr - - print("init/info : reopened /dev/console\n"); -} - -#if 0 -/* reads the kernel command line </proc/cmdline> into memory and searches - * for the first assignment of the required variable. Return its value - * (which may be empty) or NULL if not found. - */ -char *find_arg(char *arg) { - char *a, *c; - - /* read cmdline the first time */ - if (!*cmdline) { - int fd, len; - - if ((fd = open(proc_cmdline, O_RDONLY)) == -1) - return NULL; - if ((len = read(fd, cmdline, sizeof(cmdline)-1)) == -1) { - close(fd); - return NULL; - } - cmdline[len] = 0; - close(fd); - } - - /* search for the required arg in cmdline */ - c = cmdline; - a = arg; - - while (*c) { - if (*a == 0) { - /* complete match. is it a full word ? */ - if (*c == '=') { - a = ++c; - while ((*a != ' ') && (*a != '\0') && (*a != '\n')) - a++; - *a = 0; - return c; /* return value */ - } - else if (*c == ' ' || *c == '\n' || *c == '\0') { - *c = 0; - return c; /* return pointer to empty string */ - } - else { /* not full word. bad match. */ - c -= (a - arg) - 1; - a = arg; - } - } - if (*c == *a) { - a++; - c++; - } - else |