aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilly Tarreau <w@1wt.eu>2006-07-16 14:53:20 +0200
committerWilly Tarreau <willy@wtap.(none)>2006-07-26 11:00:38 +0200
commit3462eae1e5f60349b089529769a159c4df4375ed (patch)
treec968456ec80963acfd6e4f13c71c9905dac39d81
parent[RELEASE] flxutils-0.1.11 (diff)
downloadflxutils-3462eae1e5f60349b089529769a159c4df4375ed.tar.xz
[RELEASE] flxutils-0.1.11.1v0.1.11.1
-rw-r--r--init/Makefile2
-rw-r--r--init/README.255
-rwxr-xr-xinit/examples/.linuxrc82
-rwxr-xr-xinit/examples/.preinit83
-rw-r--r--init/init.c635
-rwxr-xr-xscripts/pkg1833
6 files changed, 2073 insertions, 617 deletions
diff --git a/init/Makefile b/init/Makefile
index bc1ed4f..8b95b06 100644
--- a/init/Makefile
+++ b/init/Makefile
@@ -1,3 +1,3 @@
OBJS=init mkdev
include ../include/rules.make
-CFLAGS+=-fomit-frame-pointer
+CFLAGS+=-fomit-frame-pointer -Wl,--gc-sections
diff --git a/init/README.2 b/init/README.2
new file mode 100644
index 0000000..f306601
--- /dev/null
+++ b/init/README.2
@@ -0,0 +1,55 @@
+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())
+ - 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/examples/.linuxrc b/init/examples/.linuxrc
new file mode 100755
index 0000000..24c7300
--- /dev/null
+++ b/init/examples/.linuxrc
@@ -0,0 +1,82 @@
+#!/linuxrc <
+# mem, kmem, null, zero, random, urandom, tty0, tty, console, ptmx, initctl
+# full, fd
+
+md /var 755
+md /proc 755
+md /cdrom 755
+ln var/tmp /tmp
+
+mt /proc /proc proc rw
+mt /var /var tmpfs rw mode=755
+md /var/tmp 1777
+md /var/run 755
+md /dev/pts 755
+
+bl 0600 0 0 3 0 hd[c,ab,64][I,0-16,1]
+bl 0600 0 0 22 0 hd[c,cd,64][I,0-16,1]
+bl 0600 0 0 33 0 hd[c,ef,64][I,0-16,1]
+bl 0600 0 0 8 0 sd[c,a-h,16][I,0-15,1]
+md /dev/rd 755 # DAC960 raid disks (majors 48-55)
+bl 0600 0 0 48 0 rd/c0d[i,0-31,8]
+bl 0600 0 0 48 1 rd/c0d[i,0-31,8]p[i,1-7,1]
+md /dev/ida 755 # Compaq raid disks (majors 72-79)
+bl 0600 0 0 72 0 ida/c0d[i,0-15,16]
+bl 0600 0 0 72 1 ida/c0d[i,0-15,16]p[i,1-15,1]
+md /dev/cciss 755 # Compaq CCISS raid disks (major 104)
+bl 0600 0 0 104 0 cciss/c0d[i,0-15,16]
+bl 0600 0 0 104 1 cciss/c0d[i,0-15,16]p[i,1-15,1]
+bl 0600 0 0 11 0 sr[i,0-16,1]
+ch 0600 0 0 9 0 st[i,0-15,1]
+bl 0600 0 0 9 0 md[i,0-15,1]
+bl 0600 0 0 2 0 fd0
+bl 0600 0 0 2 28 fd0u1440
+ch 0600 0 5 2 0 pty[c,p-za-f,16][h,0-f,1]
+ch 0600 0 5 3 0 tty[c,p-za-f,16][h,0-f,1]
+ch 0600 0 5 4 1 tty[i,1-12,1]
+bl 0600 0 0 7 0 loop[i,0-9,1]
+bl 0600 0 0 1 0 ram[i,0-9,1]
+ch 0600 0 5 4 64 ttyS[i,0-9,1]
+ch 0600 0 3 10 1 psaux
+bl 0400 0 0 1 250 initrd
+md /dev/input 755
+ch 0600 0 0 13 63 input/mice
+
+ln psaux /dev/mouse
+
+ec "Looking for a valid CDROM."
+ex /sbin/findcdrom
+&{
+ ec "Found! Mounting the CDROM..."
+ mt /dev/cdrom /cdrom iso9660 ro
+ &ec "Done."
+ |ec "Failed."
+}
+|{
+ ec "No CDROM found. You can try by yourself : 'ex /sbin/findcdrom'."
+ ec "Then mount it into /cdrom : 'mt /dev/cdrom /cdrom iso9660 ro'."
+ rd
+}
+
+# we don't need all this anymore.
+um /var
+um /proc
+
+# pivot_root only works on mount points, so we'll fake
+# /cdrom by remounting /cdrom/root into it
+bi /cdrom/root /cdrom
+bi /dev /cdrom/dev
+pr /cdrom mnt/initrd
+|rd "<pr /cdrom mnt/initrd> failed !!! Try by hand..."
+
+um /mnt/initrd/dev
+um /mnt/initrd/cdrom /mnt/cdrom
+um /mnt/initrd
+
+te RDSHELL=1
+&rd "You have requested this prompt by appending RDSHELL=1 to the kernel cmd line."
+
+in /sbin/init
+
+# now we're on the root, and /dev will be unmounted on exit
+
diff --git a/init/examples/.preinit b/init/examples/.preinit
new file mode 100755
index 0000000..fead5ba
--- /dev/null
+++ b/init/examples/.preinit
@@ -0,0 +1,83 @@
+#!/sbin/init <
+# mem, kmem, null, zero, random, urandom, tty0, tty, console, ptmx, initctl
+# full, fd
+mt /proc /proc proc rw
+mt /var /var tmpfs rw mode=755
+md /var/tmp 1777
+md /var/run 755
+md /dev/pts 755
+
+bl 0600 0 0 3 0 hd[c,ab,64][I,0-16,1]
+bl 0600 0 0 22 0 hd[c,cd,64][I,0-16,1]
+bl 0600 0 0 33 0 hd[c,ef,64][I,0-16,1]
+bl 0600 0 0 8 0 sd[c,a-h,16][I,0-15,1]
+md /dev/rd 755 # DAC960 raid disks (majors 48-55)
+bl 0600 0 0 48 0 rd/c0d[i,0-31,8]
+bl 0600 0 0 48 1 rd/c0d[i,0-31,8]p[i,1-7,1]
+md /dev/ida 755 # Compaq raid disks (majors 72-79)
+bl 0600 0 0 72 0 ida/c0d[i,0-15,16]
+bl 0600 0 0 72 1 ida/c0d[i,0-15,16]p[i,1-15,1]
+md /dev/cciss 755 # Compaq CCISS raid disks (major 104)
+bl 0600 0 0 104 0 cciss/c0d[i,0-15,16]
+bl 0600 0 0 104 1 cciss/c0d[i,0-15,16]p[i,1-15,1]
+bl 0600 0 0 11 0 sr[i,0-16,1]
+ch 0600 0 0 9 0 st[i,0-15,1]
+bl 0600 0 0 9 0 md[i,0-15,1]
+bl 0600 0 0 2 0 fd0
+bl 0600 0 0 2 28 fd0u1440
+ch 0600 0 5 2 0 pty[c,p-za-f,16][h,0-f,1]
+ch 0600 0 5 3 0 tty[c,p-za-f,16][h,0-f,1]
+ch 0600 0 5 4 1 tty[i,1-12,1]
+bl 0600 0 0 7 0 loop[i,0-9,1]
+bl 0600 0 0 1 0 ram[i,0-9,1]
+ch 0600 0 5 4 64 ttyS[i,0-9,1]
+ch 0600 0 3 10 1 psaux
+ch 0600 0 0 10 144 nvram
+ch 0600 0 0 10 130 watchdog
+bl 0400 0 0 1 250 initrd
+ch 0600 0 0 14 0 mixer
+ch 0600 0 0 14 3 dsp
+md /dev/input 755
+ch 0600 0 0 13 63 input/mice
+md /dev/fs 755
+
+ln psaux /dev/mouse
+
+te RAMCOPY=1
+&{
+ ec "Copying whole RootFS to RAM (can take a while)..."
+ mt / /mnt/initrd tmpfs rw size=33554432
+ &ex /bin/cp -dRfpx / /mnt/initrd
+ &{
+ bi /proc /mnt/initrd/proc
+ bi /var /mnt/initrd/var
+ bi /dev /mnt/initrd/dev
+ pr /mnt/initrd mnt/initrd # move mnt/initrd to /, and / to the new /mnt/initrd
+ um /mnt/initrd/dev
+ um /mnt/initrd/proc
+ um /mnt/initrd/var
+ um /mnt/initrd
+ ec "RootFS now running from RAM."
+ }
+ |{
+ um /mnt/initrd
+ ec "Failed to copy the RootFS into RAM."
+ }
+}
+
+te AUTORUN=1
+&{
+ mt /dev/fd0 /mnt/floppy ext2 ro
+ |mt /dev/fd0 /mnt/floppy vfat ro
+ &{
+ ex /mnt/floppy/autorun
+ um /mnt/floppy
+ }
+ |ec "Could not find an autorun file on the floppy disk."
+}
+
+te INITSHELL=1
+&rd "You have requested this prompt by appending INITSHELL=1 to the kernel cmd line."
+
+in /sbin/init-sysv
+
diff --git a/init/init.c b/init/init.c
index 4593a40..9204f62 100644
--- a/init/init.c
+++ b/init/init.c
@@ -158,6 +158,16 @@ wrong for now:
#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;
@@ -174,32 +184,41 @@ static void print(char *c) {
typedef unsigned char uchar;
-extern char **environ;
-
-static const char cfg_fname[] = "/.preinit"; /* configuration file */
-static const char tmpfs_fs[] = "tmpfs";
-static const char dev_console[] = "dev/console";
-static const char dev_root[] = "dev/root";
-static const char dev_name[] = "/dev";
-static const char root_dir[] = "/";
-static const char var_dir[] = "/var";
-static const char var_run[] = "/var/run";
-static const char var_tmp[] = "/var/tmp";
-static const char proc_dir[] = "/proc";
-static const char proc_self_fd[] = "/proc/self/fd";
-static const char proc_cmdline[] = "/proc/cmdline";
-static const char sbin_init_sysv[] = "sbin/init-sysv";
-static const char str_rebuild[] = "rebuild";
-static const char dev_options[] = "size=0,nr_inodes=4096,mode=755";
-
-#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 UID_ROOT 0
-#define GID_ROOT 0
-#define GID_TTY 5
-#define GID_KMEM 9
+/* 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))) str__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))) 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
@@ -207,6 +226,7 @@ static const char dev_options[] = "size=0,nr_inodes=4096,mode=755";
#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;
@@ -226,30 +246,6 @@ struct dev_varstr {
uchar scale;
};
-static const 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 },
-};
-
-#define NB_TOKENS 15
-
enum {
TOK_LN = 0, /* ln : make a symlink */
TOK_MD, /* md : mkdir */
@@ -262,21 +258,31 @@ enum {
TOK_FI, /* fi : make a fifo */
TOK_MA, /* ma : set umask */
TOK_PR, /* pr : pivot root */
- TOK_MV, /* mv : move */
- TOK_UM, /* um : umount */
+ 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 = 0xc0, /* any condition */
+ 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 struct {
+static const __attribute__ ((__section__(STR_SECT),__aligned__(1))) struct {
char lcmd[2]; /* long form */
char scmd; /* short form */
char minargs; /* min #args */
@@ -293,11 +299,44 @@ static const struct {
"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;
@@ -306,6 +345,11 @@ 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;
@@ -450,23 +494,39 @@ static inline int read_cfg(char *cfg_file) {
* TOK_EOF if nothing left. All args are copied into <cfg_args> as an array
* of pointers. Maximum line length is 256 chars and maximum args number is 15.
*/
-static int parse_cfg() {
+static int parse_cfg(char **cfg_data) {
int nbargs;
int token;
int cond;
+ char *cfg_line = *cfg_data;
memset(cfg_args, 0, sizeof(cfg_args));
while (*cfg_line) {
char c, *p = cfg_line;
+ cond = 0;
/* search beginning of line */
- while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r')
+ do {
+ if (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\r') {
+ if (*p == '|') {
+ cond |= TOK_COND_OR;
+ } else if (*p == '&') {
+ cond |= TOK_COND_AND;
+ } else if (*p == '!') {
+ cond ^= TOK_COND_NEG;
+ } else {
+ /* catches any printable char and the final zero */
+ break;
+ }
+ }
p++;
+ } while (1);
/* now search end of line */
cfg_line = p;
- while (*cfg_line && *cfg_line != '#' && *cfg_line != '\n' && *cfg_line != '\r')
+ while (*cfg_line && *cfg_line != '#' && *cfg_line != '\n' && *cfg_line != '\r') {
cfg_line++;
+ }
/* terminate the line cleanly to avoid further tests */
while (c = *cfg_line) {
@@ -475,37 +535,39 @@ static int parse_cfg() {
break;
}
+ /* update the caller's pointer once for all. */
+ *cfg_data = cfg_line;
+
/* skip empty lines */
if (!*p)
continue;
-
- if (*p == '|') {
- cond = TOK_COND_OR;
- p++;
- }
- else if (*p == '&') {
- cond = TOK_COND_AND;
- p++;
- }
- else
- cond = 0;
/* fills the cfg_args[] array with the command itself, followed by all
- * args.
+ * args. cfg_args[last+1]=NULL.
*/
for (nbargs = 0; *p && (nbargs < MAX_CFG_ARGS - 1); nbargs++) {
- int backslash = 0;
+ int backslash = 0, quote = 0;
cfg_args[nbargs] = p;
do {
if (backslash) {
backslash = 0;
+ if (*p == 'n')
+ *p = '\n';
+ else if (*p == 'r')
+ *p = '\r';
+ else if (*p == 't')
+ *p = '\t';
memmove(p - 1, p, cfg_line - p);
- }
- else {
+ } else {
backslash = (*p == '\\');
- p++;
+ if (*p == '"') {
+ memmove(p, p + 1, cfg_line - p - 1);
+ quote = !quote;
+ }
+ else
+ p++;
}
- } while (*p && (backslash || (*p != ' ' && *p != '\t')));
+ } while (*p && (backslash || quote || (*p != ' ' && *p != '\t')));
if (*p) {
*p = 0;
do p++; while (*p == ' ' || *p == '\t');
@@ -527,8 +589,10 @@ static int parse_cfg() {
return TOK_EOF;
}
-/* makes a dev entry */
+/* makes a dev entry. continues on error, but reports them. */
static inline int mknod_chown(mode_t mode, uid_t uid, gid_t gid, uchar major, uchar minor, char *name) {
+ int error;
+
if (mknod(name, mode, makedev(major, minor)) == -1) {
error = 1;
print("init/error : mknod("); print(name); print(") failed\n");
@@ -538,6 +602,8 @@ static inline int mknod_chown(mode_t mode, uid_t uid, gid_t gid, uchar major, uc
error = 1;
print("init/error : chown("); print(name); print(") failed\n");
}
+
+ return error;
}
/* breaks a 3-fields, comma-separated string into 3 fields */
@@ -861,16 +927,49 @@ static mode_t a2mode(char *ascii) {
return m;
}
-int main(int argc, char **argv) {
+int main(int argc, char **argv, char **envp) {
int old_umask;
int pid1, err;
int cfg_ok;
int rebuild;
int token;
+ int cmd_input = INPUT_FILE;
+ static char cmd_line[256]; /* one line of config from the prompt */
struct stat statf;
char *cmdline_arg;
char *cfg_file;
+ int brace_level, kbd_level, run_level;
+ struct {
+ int error;
+ int cond;
+ } context[MAX_BRACE_LEVEL];
+
+ /* first, we'll check if we have been called as 'linuxrc', used only in
+ initrd. In this particular case, we ignore all arguments and use
+ /.linuxrc as a configuration file.
+ */
+
+#ifdef DEBUG
+ print("argv[0]: "); print(argv[0]); print("\n");
+ sleep(1);
+#endif
+ /* if we are called as "linuxrc" or "/linuxrc", then we work a bit
+ * differently : /dev is unmounted at the end, and we proceed even if the
+ * pid is not 1.
+ *
+ * Warning: for an unknown reason (isolinux, kernel?) specifying
+ * 'init=/linuxrc' or 'init=linuxrc' on the command line doesn't work
+ * because 'init' is set in argv[0] ! But setting it by hand works,
+ * so does 'init=/.linuxrc'. Rather strange. So the best solution is
+ * to link /sbin/init to /.linuxrc so that the interpreter's name is
+ * used even if nothing is specified.
+ */
+ if (!strcmp(argv[0], str_linuxrc) || !strcmp(argv[0], str__linuxrc)) {
+ linuxrc = 1;
+ rebuild = 0;
+ pid1 = 0;
+ }
/* check if a config file name has been given to preinit : init [ \< <cfg_file> ] [ init args ] */
if (argc > 2 && *argv[1] == '<') {
cfg_file = argv[2];
@@ -879,28 +978,40 @@ int main(int argc, char **argv) {
argc -= 2;
}
else
- cfg_file = (char *)cfg_fname;
+ cfg_file = linuxrc ? (char *)cfg_linuxrc : (char *)cfg_fname;
- /* restore the correct name. Warning: in the case where init is launched
- * from userspace, the config file is not read again so only the hardcoded
- * name will be used for the executable name.
- */
- *argv = &sbin_init_sysv;/*"sbin/init-sysv"*/;
- old_umask = umask(0);
+ if (!linuxrc) {
+ /*FIXME*/
+ /* restore the correct name. Warning: in the case where init is launched
+ * from userspace, the config file is not read again so only the hardcoded
+ * name will be used for the executable name.
+ */
+ *argv = (char *)&sbin_init_sysv; /*"sbin/init-sysv"*/;
+ /* if "rebuild" is passed as the only argument, then we'll try to rebuild a
+ * full /dev even if not pid==1, but only if it was not already populated
+ */
+ rebuild = (argc == 2 && streq(argv[1], str_rebuild/*"rebuild"*/));
+ pid1 = (getpid() == 1);
+ }
+ else {
+ *argv = (char *)&sbin_init; /* "sbin/init" */
+ }
- /* if "rebuild" is passed as the only argument, then we'll try to rebuild a
- * full /dev even if not pid==1, but only if it was not already populated
- */
- rebuild = (argc == 2 && streq(argv[1], str_rebuild/*"rebuild"*/));
+ if (pid1 || linuxrc) {
+ setsid();
+ }
- pid1 = (getpid() == 1) /*|| 1*/;
+ old_umask = umask(0);
cfg_ok = (read_cfg(cfg_file) == 0);
chdir(root_dir); /* be sure not to stay under /dev ! */
/* do nothing if we're not called as the first process */
- if (pid1 || rebuild) {
- /* check if /dev is already populated : /dev/console should exist */
- if (stat(dev_console, &statf) == -1) {
+ if (pid1 || linuxrc || rebuild) {
+ /* check if /dev is already populated : /dev/console should exist. We
+ * can safely ignore and overwrite /dev in case of linuxrc, reason why
+ * we don't test the presence of /dev/console.
+ */
+ if (linuxrc || stat(dev_console, &statf) == -1) {
print("init/info: /dev/console not found, rebuilding /dev.\n");
if (mount(dev_name, dev_name, tmpfs_fs, MS_MGC_VAL, dev_options) == -1)
print("init/err: cannot mount /dev.\n");
@@ -923,13 +1034,13 @@ int main(int argc, char **argv) {
*/
reopen_console();
}
- }
- else {
- if (!pid1) {
- /* we don't want to rebuild anything else if pid is not 1 */
- print("init/info: /dev is OK.\n");
- return 0;
- }
+ } else if (!pid1) {
+ /* we don't want to rebuild anything else if pid is not 1 */
+#ifdef DEBUG
+ print("init/info: /dev is OK.\n");
+ sleep(10);
+#endif
+ return 0;
}
/* if /dev/root is non-existent, we'll try to make it now */
@@ -950,13 +1061,70 @@ int main(int argc, char **argv) {
/* here, the cwd is still "/" */
if (cfg_ok) {
- while ((token = parse_cfg()) != TOK_EOF) {
+ print("ready to parse file : "); print(cfg_file); print("\n");
+
+ run_level = brace_level = 0;
+ context[brace_level].error = 0;
+ context[brace_level].cond = 0;
+
+ /* main parsing loop */
+ while (1) {
int cond = 0;
- int lasterr = error;
+ if (cmd_input == INPUT_KBD) {
+ int len;
+ char *cmd_ptr = cmd_line;
+ static char prompt[MAX_BRACE_LEVEL + 4];
+ char *p = prompt;
+ int lev1, lev2;
+
+ p += my_strlcpy(p, error ? CONST_STR("ER\n>") : CONST_STR("OK\n>"), 5);
+
+ lev1 = run_level;
+ lev2 = brace_level;
+ while (lev1) {
+ *p++ = '>';
+ lev1--;
+ lev2--;
+ }
+ if (lev2) {
+ *p++ = '{';
+ while (lev2--)
+ *p++ = '>';
+ *p++ = '}';
+ }
+ *p++ = ' ';
+ write(1, prompt, p-prompt);
+
+ len = read(0, cmd_line, sizeof(cmd_line)-1);
+ if (len > 0) {
+ cmd_line[len] = 0;
+ token = parse_cfg(&cmd_ptr);
+ if (token == TOK_EOF) /* empty line */
+ continue;
+ } else {
+ token = TOK_DOT;
+ }
+
+ if (token == TOK_DOT) {
+ cmd_input = INPUT_FILE;
+ brace_level = kbd_level;
+ /* if it was not right, 'rd' would not have been called : */
+ run_level = brace_level;
+ /* don't report prompt errors to the rest of the config ! */
+ error = 0;
+ }
+ }
+
+ if (cmd_input == INPUT_FILE) {
+ token = parse_cfg(&cfg_line);
+ if (token == TOK_EOF || token == TOK_DOT)
+ break;
+ }
+
if (token == TOK_UNK) {
print("unknown command.\n");
- break;
+ continue;
}
cond = token & TOK_COND;
@@ -964,27 +1132,152 @@ int main(int argc, char **argv) {
if (cfg_args[tokens[token].minargs] == NULL) {
print("Missing args\n");
- break;
+ continue;
}
- /* skip conditionnal executions if unneeded */
- if ((cond & TOK_COND_OR) && (!lasterr) ||
- (cond & TOK_COND_AND) && (lasterr))
- continue;
-
/* now we can reset the error */
+ context[brace_level].error = error;
error = 0;
- /* the first command set is always available */
+ if (token == TOK_CB) { /* closing brace */
+ if (cond & TOK_COND) {
+ print("Conditions not permitted with a closing brace.\n");
+ /* we close the brace anyway, ignoring the condition. */
+ } else if (brace_level == 0) {
+ print("Too many closing braces.\n");
+ error = context[brace_level].error;
+ continue;
+ }
+ /* transmit the current error to the upper level, and restore the upper
+ * condition to know if we had to negate the result or not.
+ */
+ error = context[brace_level--].error;
+ cond = context[brace_level].cond;
+ if (run_level > brace_level)
+ run_level = brace_level;
+ goto finish_cmd;
+ }
+ else if (token == TOK_OB) { /* opening brace */
+ if (brace_level == MAX_BRACE_LEVEL - 1) {
+ print("Too many brace levels.\n");
+ error = context[brace_level].error;
+ break;
+ }
+
+ /* if this block should not be executed because of a particular
+ * condition, we'll mark the new level to be skipped, so that
+ * other braces are correctly counted but not evaluated.
+ */
+ if ((run_level == brace_level) &&
+ (!(cond & TOK_COND_OR) || context[brace_level].error) &&
+ (!(cond & TOK_COND_AND) || !context[brace_level].error)) {
+ /* save the current condition to properly handle a negation.
+ * The error code has already been set to 0.
+ */
+ context[brace_level++].cond = cond;
+ run_level = brace_level;
+ }
+ else {
+ /* the braces will not be evaluated because a & or | prevents
+ * it to do so. Since we want to be able to chain these
+ * expressions to do if/then/else with &{}|{}, we'll propagate
+ * the current error code and void the condition.
+ */
+ error = context[brace_level].error;
+ context[brace_level++].cond = 0;
+ }
+ continue;
+ }
+
+ //printf("parsing intruction <%s %s...> at level %d (%d)\n", cfg_args[0], cfg_args[1], brace_level, run_level);
+ /* skip conditionnal executions if they cannot change the error status,
+ * as well as blocks of code excluded from the evaluation
+ */
+ if ((cond & TOK_COND_OR) && !context[brace_level].error ||
+ (cond & TOK_COND_AND) && context[brace_level].error ||
+ (run_level < brace_level)) {
+ error = context[brace_level].error;
+ continue;
+ }
+
+
+ /*
+ * Now we begin to parse the 'real' commands. The first set is always available
+ */
+
if (token == TOK_IN) {
- /* I <path> : specify the path to init */
+ /* I | in <path> : specify the path to init.
+ * Problem: what to do with init args ?
+ * We could pass ours, but if init is replaced with a
+ * shell, this one might be called with 'auto'...
+ * So we flush them all.
+ */
print("<I>nit : used config name for init\n");
- *argv = cfg_args[1];
+ argv[0] = cfg_args[1];
+ argv[1] = NULL;
+
+ /* in keyboard mode, specifying init stops any further parsing,
+ * so that the rest of the config file can be skipped.
+ */
+ if (cmd_input == INPUT_KBD)
+ break;
+ else {
+ /* non sense to switch error status when assigning init */
+ error = context[brace_level].error;
+ continue;
+ }
+ //} else if (token == TOK_EC) {
+ /* ec <string> : echo a string */
+ //int l = strlen(cfg_args[1]);
+ //cfg_args[1][l] = '\n';
+ //write(1, cfg_args[1], l + 1);
+ //goto finish_cmd;
+ } else if (token == TOK_RD || token == TOK_EC) {
+ /* ec <string> : echo a string */
+ /* rd <string> : display message then read commands from the console instead of the file */
+ char *msg;
+ int len;
+
+ if (cfg_args[1] != NULL) {
+ len = strlen(cfg_args[1]);
+ cfg_args[1][len] = '\n';
+ write(1, cfg_args[1], len + 1);
+ }
+ if (token != TOK_RD)
+ goto finish_cmd;
+
+ if (cmd_input == INPUT_KBD) {
+ msg = (char *)msg_err_console;
+ len = sizeof(msg_err_console) - 1;
+ } else {
+ msg = (char *)msg_ent_console;
+ len = sizeof(msg_ent_console) - 1;
+ kbd_level = brace_level;
+ }
+ error = context[brace_level].error;
+ write(1, msg, len);
+ cmd_input = INPUT_KBD;
continue;
- }
+ } else if (token == TOK_TE) {
+ /* te <var=val> : compare an environment variable to a value.
+ * In fact, look for the exact assignment in the environment.
+ * The result is OK if found, NOK if not.
+ */
+ char **env = envp;
+ while (*env) {
+ //printf("testing <%s> against <%s>\n", cfg_args[1], *env);
+ if (!strcmp(*env, cfg_args[1]))
+ break;
+ env++;
+ }
+ error = (*env == NULL);
+ goto finish_cmd;
+ }
- if (!pid1 && !rebuild) { /* other options are reserved for pid 1 only or rebuild mode */
+ /* other options are reserved for pid 1/linuxrc/rebuild and prompt mode */
+ if (!pid1 && !linuxrc && !rebuild && cmd_input != INPUT_KBD) {
print("Command ignored since pid not 1\n");
+ error = context[brace_level].error;
continue;
}
@@ -996,14 +1289,14 @@ int main(int argc, char **argv) {
error = 1;
print("<D>irectory : mkdir() failed\n");
}
- continue;
+ goto finish_cmd;
case TOK_LN:
/* L from to : make a symlink */
if (symlink(cfg_args[1], cfg_args[2]) == -1) {
error = 1;
print("<S>ymlink : symlink() failed\n");
}
- continue;
+ goto finish_cmd;
case TOK_BL:
/* B <mode> <uid> <gid> <major> <minor> <naming rule> : build a block device */
case TOK_CH:
@@ -1011,38 +1304,33 @@ int main(int argc, char **argv) {
if (chdir(dev_name) == -1) {
print("<B>lock_dev/<C>har_dev : cannot chdir(/dev)\n");
error = 1;
- continue;
+ goto finish_cmd;
}
multidev(a2mode(cfg_args[1]) | ((token == TOK_BL) ? S_IFBLK : S_IFCHR),
(uid_t)ATOL(cfg_args[2]), (gid_t)ATOL(cfg_args[3]),
ATOL(cfg_args[4]), ATOL(cfg_args[5]), cfg_args[6]);
chdir(root_dir);
- continue;
+ goto finish_cmd;
case TOK_FI:
/* F <mode> <uid> <gid> <name> : build a fifo */
if (chdir(dev_name) == -1) {
- error = 1;
print("<F>ifo : cannot chdir(/dev)\n");
+ error = 1;
+ goto finish_cmd;
}
- mknod_chown(a2mode(cfg_args[1]) | S_IFIFO,
- (uid_t)ATOL(cfg_args[2]), (gid_t)ATOL(cfg_args[3]),
- 0, 0, cfg_args[4]);
-
+ error = mknod_chown(a2mode(cfg_args[1]) | S_IFIFO,
+ (uid_t)ATOL(cfg_args[2]), (gid_t)ATOL(cfg_args[3]),
+ 0, 0, cfg_args[4]);
chdir(root_dir);
- continue;
- case TOK_EC: {
- /* ec <string> : echo a string */
- int l = strlen(cfg_args[1]);
- cfg_args[1][l] = '\n';
- write(1, cfg_args[1], l + 1);
- continue;
- }
+ goto finish_cmd;
} /* end of switch() */
- if (!pid1) { /* other options are reserved for pid 1 only */
+ /* other options are reserved for pid 1/linuxrc/prompt mode only */
+ if (!pid1 && !linuxrc && cmd_input != INPUT_KBD) {
print("Command ignored since pid not 1\n");
+ error = context[brace_level].error;
continue;
}
@@ -1096,7 +1384,7 @@ int main(int argc, char **argv) {
}
mntarg = MS_RDONLY;
- if (cfg_args[4] != NULL && streq(cfg_args[4], "rw")) {
+ if (cfg_args[4] != NULL && streq(cfg_args[4], CONST_STR("rw"))) {
print("<M>ount : 'rw' flag found, mounting read/write\n");
mntarg &= ~MS_RDONLY;
}
@@ -1131,7 +1419,7 @@ int main(int argc, char **argv) {
res = fork();
if (res == 0) {
chroot(exec_dir);
- execve(exec_args[0], exec_args, environ);
+ execve(exec_args[0], exec_args, envp);
print("<E>xec(child) : execve() failed\n");
return 1;
}
@@ -1140,7 +1428,7 @@ int main(int argc, char **argv) {
while (wait(&error) != res)
print("<E>xec(parent) : signal received\n");
- error = !WIFEXITED(error);
+ error = (WIFEXITED(error) > 0) ? WEXITSTATUS(error) : 1;
print("<E>xec(parent) : child exited\n");
}
else {
@@ -1160,12 +1448,12 @@ int main(int argc, char **argv) {
print("<P>ivot : error during chdir(new root)\n");
}
- if (pivot_root(".", cfg_args[2]) == -1) {
+ if (pivot_root(/*CONST_STR(".")*/cur_dir, cfg_args[2]) == -1) {
error = 1;
print("<P>ivot : error during pivot_root()\n");
}
- chroot(".");
+ chroot(cur_dir/*CONST_STR(".")*/);
if (chdir(root_dir) == -1) {
error = 1;
print("<P>ivot : error during chdir(/)\n");
@@ -1175,15 +1463,27 @@ int main(int argc, char **argv) {
reopen_console();
break;
case TOK_MV:
- /* K <old_dir> <new_dir> : keep directory <old_dir> after a pivot. */
+ /* K | mv <fs_dir> <new_dir> :
+ * initially used to keep directory <old_dir> after a pivot, now used to
+ * move a filesystem to another directory.
+ */
+ if (mount(cfg_args[1], cfg_args[2], cfg_args[1], MS_MGC_VAL | MS_MOVE, NULL) == 0)
+ break;
+ /* if it doesn't work, we'll try to cheat with BIND/UMOUNT */
+ case TOK_BI:
+ /* bi <old_dir> <new_dir> : bind old_dir to new_dir, which means that directory
+ * <new_dir> will show the same contents as <old_dir>.
+ */
if (mount(cfg_args[1], cfg_args[2], cfg_args[1], MS_MGC_VAL | MS_BIND, NULL) == -1) {
error = 1;
- print("<mv> : error during mount\n");
+ print("<bi> : error during mount|bind\n");
}
- /* fall through umount */
+ if (token == TOK_BI)
+ break;
+ /* fall through umount if we were trying a move */
case TOK_UM:
/* O <old_dir> : umount <old_dir> after a pivot. */
- if (umount(cfg_args[1]) == -1) {
+ if (umount2(cfg_args[1], MNT_DETACH) == -1) {
error = 1;
print("<um> : error during umount\n");
}
@@ -1224,9 +1524,13 @@ int main(int argc, char **argv) {
print("unknown cmd in /.preinit\n");
break;
}
- } /* while (token != TOK_EOF) */
- } else if (pid1) {
- print("init/info : error while opening configuration file\n");
+ finish_cmd:
+ if (cond & TOK_COND_NEG)
+ error = !error;
+ } /* while (1) */
+ } else if (pid1 && !linuxrc) {
+ print("init/info : error while opening configuration file : ");
+ print(cfg_file); print("\n");
/* /.preinit was not found. In this case, we take default actions :
* - mount /proc
@@ -1253,22 +1557,57 @@ int main(int argc, char **argv) {
}
}
}
+ else {
+ print("init/info : error while opening configuration file : ");
+ print(cfg_file); print("\n");
+ }
if (rebuild) {
+ print("end of rebuild\n");
+#ifdef SLOW_DEBUG
+ sleep(10);
+#endif
/* nothing more to do */
return 0;
}
- /* handle the lilo command line "INIT=prog" */
- if ((cmdline_arg = find_arg("INIT")) != NULL) {
- argv[0] = cmdline_arg;
- argv[1] = NULL;
- }
+ /* We undo all that we can to restore a clean context.
+ * In case the init has been specified by the user at the console prompt,
+ * we don't close 0/1/2 nor dismount /dev, else we wouldn't be able to do
+ * anything.
+ */
+ if (cmd_input != INPUT_KBD) {
+ if (linuxrc) {
+ close(2); close(1); close(0);
+ umount2(dev_name, MNT_DETACH);
+ print("exit from linuxrc\n");
+#ifdef SLOW_DEBUG
+ sleep(10);
+#endif
+ /* handle the lilo command line "init2=prog" */
+ cmdline_arg = find_arg(CONST_STR("init2"));
+ } else {
+ /* handle the lilo command line "INIT=prog" */
+ cmdline_arg = find_arg(CONST_STR("INIT"));
+ }
+
+ if (cmdline_arg != NULL) {
+ argv[0] = cmdline_arg;
+ argv[1] = NULL;
+ }
+ }
print("init/debug: *argv = "); print (*argv); print("\n");
umask(old_umask);
- err = execve(*argv, argv, environ);
+#ifdef SLOW_DEBUG
+ sleep(10);
+#endif
+ err = execve(*argv, argv, envp);
print("init/error : last execve() failed\n");
- sleep(200);
+
+ /* we'll get a panic there, so let some time for the user to read messages */
+ if (pid1)
+ sleep(60);
+
return err;
}
diff --git a/scripts/pkg b/scripts/pkg
index c9f111c..ab88db7 100755
--- a/scripts/pkg
+++ b/scripts/pkg
@@ -1,563 +1,1460 @@
#!/bin/bash
-#
-# /usr/sbin/pkg - Formilux source package manager - version 0.2.3 - 2003-03-20
+
+# pkg - Formilux package builder - version 0.3.2 - 2003-06-09
#
# Copyright (C) 2001-2003 Benoit Dolez & Willy Tarreau
# mailto: benoit@ant-computing.com,willy@ant-computing.com
#
# This program is licenced under GPLv2 ( http://www.gnu.org/licenses/gpl.txt )
-########## WARNING ##########
-# this version is not compatible anymore with versions earlier than 0.2.0
-#############################
+## WARNING ##
+# This version is not compatible with pkg scripts written for pre-0.2.0 versions
+
+
+# Usage:
+# pkg <action> [ pkg [ pkg2 ] ]
+#
+# pkg newpkg [ new_pkg [ old_pkg ] ]
+# ex: pkg newpkg openssl-0.9.6g-flx0.1 openssl-0.9.6d-flx0.1
+# pkg newpkg apache apache-1.3
+# pkg newpkg bash
+# pkg newpkg gcc gcc-3*flx*.1
+#
+# pkg setpkg [ new_pkg ]
+# ex: pkg setpkg openssl-0.9.6g-flx0.1
+#
+# pkg { info | cat | edit } [ pkg ]
+# ex: pkg info
+# pkg info bash
+# pkg edit modutils-2.4
+# pkg cat gzip-1.3
+#
+# pkg { compile,build,prepack,strip,pack,unpack,delpack,release,clean }*
+#
+# pkg { patch | unpatch } [ patch_name ]
+#
+# pkg { any_command } [ any_args ]
+#
+
+# don't return stupid names, and we also want dotfiles and use extended globbing
+shopt -s nullglob
+shopt -s dotglob
+shopt -s extglob
+
+# disable pathnames expansion
+set -o noglob
+
+# change the default mask to avoid common security problems
+umask og-w
+
+# set some constants
+KERNDIR=${KERNDIR:-/usr/src/linux}
+FLXARCH=${FLXARCH:-$(uname -m)}
+DEVROOT=${DEVROOT:-/var/flx-dev}
+PKGROOT=${PKGROOT:-/var/flx-pkg}
+# use -p1 by default to apply a patch
+PATCH_LEVEL=${PATCH_LEVEL:-1}
+# the suffix that we use to name different builds. It also matches build
+# versions with this name followed by a number (BUILDVER)
+BUILDSFX=${BUILDSFX:-flx}
+BUILDVER=${BUILDVER:-0}
+
+PKGSUFF="tgz"
+CFGSUFF="cfg"
+INSTNAME=".flxdisk"
+LINKNAME=".flxpkg"
-# patch -p1 by default
-PATCH_LEVEL=1
+FILE_LIST=
-function logit {
- echo "$*"
- $*
- return $?
+######
+###### here are some functions for manipulating package names
+######
+
+# returns the radix from a package name. Eg: 'pkg-1.2.3a-flx0.12' returns 'pkg'
+function get_pkg_radix {
+ echo ${1%%[-_][0-9]*}
}
-function do_compile_only {
- $FLXMAKE
- return $?
+# returns the version from a package name. Eg: 'pkg-1.2.3a-flx0.12' returns '1.2.3a'
+function get_pkg_ver {
+ local ver=${1#${1%%[_-][0-9]*}[._-]}
+ ver=${ver%-${BUILDSFX}*}
+ [ "$ver" = "$1" ] || echo $ver
}
-function pre_prepack {
- if [ "$UID" != "0" -a "$force" != "1" ]; then
- echo "You must specify '--force' to install as non-root"
- exit 1
- fi
- if [ -d `pwd`/.flxdisk ] ; then rm -rf `pwd`/.flxdisk ; fi
+# returns the build number from a package name when appropriate, or empty when
+# there's nothing. Eg: 'pkg-1.2.3a-flx0.12-pkg' returns 'flx0.12'
+function get_build_num {
+ local build=${1##${1%%-${BUILDSFX}*([0-9]).+([0-9])*}} # -flx0.12-pkg
+ build=${build%%${build##-${BUILDSFX}*([0-9]).+([0-9])}} # -flx0.12
+ build=${build#-} # flx0.12
+ [ "$build" != "$1" ] && echo $build
}
-function post_prepack {
- if [ -d $ROOTDIR/opt ] ; then
- (cd $ROOTDIR/opt ; mkdir bin sbin lib )
- (cd $ROOTDIR/opt ; find */bin -type f -perm +111 -exec ln -s ../{} bin \; -printf "ln -s ../%p $ROOTDIR/opt/bin\n" )
- (cd $ROOTDIR/opt ; find */sbin -type f -perm +111 -exec ln -s ../{} sbin \; -printf "ln -s ../%p $ROOTDIR/opt/sbin\n" )
- (cd $ROOTDIR/opt ; find */lib -type f -perm +111 -exec ln -s ../{} lib \; -printf "ln -s ../%p $ROOTDIR/opt/lib\n" )
- fi
+# returns the build number following a known build. Eg: 'flx0.12' returns 'flx0.13'
+function get_next_build {
+ local prefix=${1%%.*}
+ local suffix=${1##*.}
+ echo $prefix.$[$suffix + 1]
}
-function do_compile {
- do_config_only && do_compile_only
+# This function accepts a list of versionned names, and returns them sorted by
+# version number. The names must NOT contain any '|' or '~' character, or they
+# will be discarded. Names that don't have any version are also discarded.
+function sortnames {
+ local IFS FIELD NUMERIC_VERSION ALPHA_VERSION VERSION
+ local base version rest filename i t file flist
+ local -a list
+
+ # a numeric versions consists in a series of numbers delimited by dots, and
+ # optionnally ending with one or several dots, so that strange namings are
+ # correctly processed. An alphanumeric version consists in everything that
+ # cannot match a numeric version, optionnaly ending with one or more dots.
+ IFS=$'\n'
+ FIELD='\([^|]*\)'
+ NUMERIC_VERSION='\([0-9]\+\(\.[0-9]\+[.]*\)*\)'
+ ALPHA_VERSION='\([^0-9~|.]\+[.]*\)'
+ VERSION="\($NUMERIC_VERSION\|$ALPHA_VERSION\)"
+
+ # make the list appear in the form 'package|version|rest|full_name'
+ list=($(echo "$*" | grep -v "|~" | sed -e "s/$VERSION/\1|/" \
+ -e "s/^$FIELD|$VERSION/\1|\2|/" \
+ -e "s/^$FIELD|$FIELD|$FIELD$/\1|\2|\3~\1\2\3/" \
+ -e "s/^[^|]*|[^|]*$//"))
+
+ # there's a risk that it doesn't complete for all the list, and that some
+ # elements keep a "rest". But what can we do about it ?
+
+ # we loop on the list if there's at least one element
+ # this will build alternating series of numeric-only and non-numeric
+ # substrings, packed by six.
+ while [ "${list[0]}" ] ; do
+ # now we add sub-version delimiters ','
+ list=( $(for file in ${list[*]} ; do
+ IFS="|~" ; set -- $file
+ base=$1 ; version=$2 ; rest=$3 ; filename=$4
+ if [ -z "$rest" ] ; then
+ IFS="." ; set -- $version
+ # we append a dot to the version for sed below.
+ echo "$base,$1,$2,$3,$4,$5,$6|.~$filename"
+ continue
+ fi
+ IFS="." ; set -- $version
+ echo "$base,$1,$2,$3,$4,$5,$6|$rest~$filename"
+ done | sed -e "s/^$FIELD|\($VERSION\|\.\)/\1|\2|/"))
+ IFS=$'\n'
+ # and we stop once everyone has "|\.|~" (no rest)
+ if echo "${list[*]}" | grep -vq "|\.|~" ; then : ; else break ; fi
+ done
+
+ # now construct a field separator list for 'sort'. Since it's full of bugs,
+ # the only way for it to work is -k1,1 -k2,2n -k3,3n ...
+ # To match most cases, we'll assume that most of our packages will be
+ # numbered NNNNNNAAAAAANNN... (6 numbers, 6 alpha, repeating).
+ IFS=',' ; i=1 ; flist=
+ for t in ${list[0]%%|*} ; do
+ if [ $i -eq 1 -o $[(($i-2)/6)&1] -eq 1 ]; then
+ flist="$flist${flist:+ }-k$i,$i"
+ else
+ flist="$flist${flist:+ }-k$i,$i"n
+ fi
+ i=$[$i+1];
+ done
+
+ IFS=$'\n'$'\t'' '
+ # Do not use '-u' since sort is stupid enough to remove nearly identical
+ # lines !
+ #echo "${list[*]}" | sort -t , -u $flist | cut -f2 -d~
+ echo "${list[*]}" | sort -t , $flist | cut -f2 -d~
}
+######
+###### here are "exported" functions, which can be used and redefined by build.cfg
+######
+
+# builds everything from a clean start
function do_build {
- for i in clean compile prepack strip pack ; do
- if declare -f pre_$i > /dev/null ; then ( pre_$i ) ; fi
- if [ $? != 0 ] ; then break ; fi
- if declare -f do_$i > /dev/null ; then ( do_$i ) ; fi
- if [ $? != 0 ] ; then break ; fi
- if declare -f post_$i > /dev/null ; then ( post_$i ) ; fi
- if [ $? != 0 ] ; then break ; fi
- done
+ local ACTION
+ # ACTION will be inherited by other functions
+ for ACTION in clean compile prepack strip pack ; do
+ declare -f pre_$ACTION > /dev/null && { ( pre_$ACTION $* ) || return $?; }
+ declare -f do_$ACTION > /dev/null && { ( do_$ACTION $* ) || return $?; }
+ declare -f post_$ACTION > /dev/null && { ( post_$ACTION $* ) || return $?; }
+ done
}
-function do_delpack {
- if [ -d `pwd`/.flxdisk ] ; then rm -rf `pwd`/.flxdisk ; fi
+# this function returns one exact package name from a list of potentially
+# interesting ones, classed from higher preference to lower. They are all
+# passed as strings, constituting packages names, or some of the following
+# special names :
+# %P => use current directory as the source for the name
+# %L => use the package pointed to by the ${LINKNAME} link
+# %D => use the default package
+# If several packages match a given pattern, the user is asked to select the
+# desired one.
+# The result is returned in REPLY.
+function get_name {
+ local pattern pkg_name
+ local radix ver build
+ local -a rel_list dev_list sort_list
+ local i
+
+ REPLY=
+ for pattern in $*; do
+ if [ "$pattern" = "%P" ]; then
+ pattern=$(basename $(pwd))
+ elif [ "$pattern" = "%L" ]; then
+ if [ -L ${LINKNAME} -a -d ${LINKNAME}/. ]; then
+ # the link is always an EXACT name, so we return it as-is.
+ pattern=$(readlink ${LINKNAME})
+ REPLY=$(basename $pattern)
+ return
+ else
+ continue
+ fi
+ elif [ "$pattern" = "%D" ]; then
+ pattern=default
+ fi
+ radix=$(get_pkg_radix $pattern)
+ ver=$(get_pkg_ver $pattern)
+ build=$(get_build_num $pattern)
+ pkg_name=${radix:-*}-${ver:-*}-${build:-*}
+
+ REPLY=
+ # we loop until pkg_name is empty, which allows recursive choices.
+ while [ "$pkg_name" ]; do
+ # now we'll try to build a list of potentially matching packages for
+ # each pattern. We'll reduce the original name until either we have
+ # a non-empty list or the package name is void.
+ rel_list=( ); dev_list=( )
+ while [ "$pkg_name" -a -z "$rel_list" -a -z "$dev_list" ]; do
+ rel_list=( $(find $PKGROOT/ -maxdepth 1 -type d -name ${pkg_name} -printf "%f\n" 2>/dev/null) )
+ if [ "$release_only" != "1" ]; then
+ dev_list=( $(find $DEVROOT/ -maxdepth 1 -type d -name ${pkg_name} -printf "%f\n" 2>/dev/null) )
+ fi
+
+ if [ -z "${rel_list[*]}" -a -z "${dev_list[*]}" ]; then
+ radix=$(get_pkg_radix $pkg_name)
+ ver=$(get_pkg_ver $pkg_name)
+ build=$(get_build_num $pkg_name)
+
+ if [ "$ver" -a "$ver" != "*" -a "$radix" != "$pkg_name" ]; then
+ if [ "$build" -a "$build" != "*" ]; then
+ pkg_name=${radix}-${ver}-*
+ elif [ "${ver%.*}" != "$ver" ]; then
+ # let's reduce the version precision
+ pkg_name=${radix}-${ver%.*}-*
+ else
+ pkg_name=${radix}-*
+ fi
+ else
+ break
+ fi
+ else
+ break
+ fi
+ done
+
+ # we're prepared to break the big loop, unless someone sets pkg_name again.
+ pkg_name=
+ sort_list=( $(sortnames ${dev_list[*]} ${rel_list[*]}) )
+
+ # if we matched nothing, we jump to the next pattern, and if we matched
+ # exactly one result, we return it immediately.
+ if [ ${#sort_list[*]} -eq 0 ]; then
+ continue
+ elif [ ${#sort_list[*]} -eq 1 ]; then
+ REPLY=${sort_list[0]}
+ return
+ fi
+
+ # now, we'll present the possible names to the user.
+ i=0
+ printf " %5d : - None of the following packages -\n" 0
+ while [ $i -lt ${#sort_list[*]} ]; do
+ # we'll display an 'R' in front of released names, or a 'D' for dev.
+ if [ "${rel_list[*]/${sort_list[$i]}/}" != "${rel_list[*]}" ]; then
+ printf " %5d : [R] %s\n" $[$i+1] ${sort_list[$i]}
+ else
+ printf " %5d : [D] %s\n" $[$i+1] ${sort_list[$i]}
+ fi
+ i=$[$i+1]
+ done
+ echo
+
+ while : ; do
+ echo -n "Choice [${sort_list[${#sort_list[*]}-1]}]: "; read i
+ if [ -z "$i" ]; then
+ # empty string, we use the last choice which is the preferred one.
+ i=${#sort_list[*]}
+ REPLY=${sort_list[$[$i-1]]}
+ return
+ elif [ "${i//[0-9]/}" ]; then
+ # not a plain integer, we'll allow to recursively re-select
+ #pattern=${pattern}*${i}
+ pattern=${i}
+ radix=$(get_pkg_radix $pattern)
+ ver=$(get_pkg_ver $pattern)
+ build=$(get_build_num $pattern)
+ pkg_name=${radix:-*}-${ver:-*}-${build:-*}
+ break;
+ elif [ $i -le 0 ]; then
+ # if the user explicitly replied "0", then he wants other choices.
+ break;
+ elif [ $i -le ${#sort_list[*]} ]; then
+ REPLY=${sort_list[$[$i-1]]}
+ return
+ fi
+ done
+ # we get here only either if someone tries to refine the package name or
+ # if he refuses these ones.
+ done
+ done
}
-function do_clean {
- make distclean || make mrproper || make clean
- ( do_delpack )
+# choose a package and make ${LINKNAME} point to it
+function do_setpkg {
+ rm -f ${LINKNAME}
+ ln -s $PKGDIR ${LINKNAME}
}
+
+# look for existing packages, and propose a new version for the current one
+function do_newpkg {
+ local -a rel_list dev_list sort_list
+ local pkg_name new_name
+ local radix ver build
+
+ set -o noglob
+ if [ -e ${LINKNAME} ]; then
+ if [ -L ${LINKNAME} ]; then
+ if [ -d ${LINKNAME}/. ]; then
+ echo "Error! the link '${LINKNAME}' already exists. Please remove it by manually."
+ exit 1
+ else
+ rm -f ${LINKNAME}
+ fi
+ else
+ echo "Error! '${LINKNAME}' already exists and is not a link. Please remove it by manually."
+ exit 1
+ fi
+ fi
+
+ if [ $# -gt 0 ]; then
+ # the user has specified an explicit version string
+ new_name=$1
+ if [ $# -gt 1 ]; then
+ pkg_name=$2
+ fi
+ else
+ # the user has not specified any version string, we'll use the directory
+ # name.
+ new_name=$(basename $(pwd))
+ fi
+
+ rel_list=( ); dev_list=( )
+
+ # now we'll have to guess the new package name.
+ # The build rev part (flx*.*) will be ignored.
+ # We'll look for existing packages with the exact
+ # name+version, and if found, use this + the first unused build number.
+ # If not found, a new package is created with the exact name and flx0.1
+
+ radix=$(get_pkg_radix $new_name)
+ ver=$(get_pkg_ver $new_name)
+ build=$(get_build_num $new_name)
+ new_name=${radix:-*}-${ver:-*}
+
+ rel_list=( $(find $PKGROOT/ -maxdepth 1 -type d -name ${new_name}\* -printf "%f\n" 2>/dev/null) )
+ dev_list=( $(find $DEVROOT/ -maxdepth 1 -type d -name ${new_name}\* -printf "%f\n" 2>/dev/null) )
+ sort_list=(${rel_list[*]} ${dev_list[*]})
+
+ if [ "${sort_list[*]}" ]; then
+ sort_list=($(IFS=$'\n'; echo "${sort_list[*]%-${BUILDSFX}*([0-9]).+([0-9])*}" | sort -u) )
+ sort_list=( $(sortnames ${sort_list[*]}) )
+ if [ "${radix/*\\**/}" -a "${ver/*\\**/}" ] && \
+ ! (IFS=$'\n';echo "${sort_list[*]}"|grep -q "^$new_name\$"); then
+ # if the package was properly named, and not already listed, let's
+ # propose it on last position.
+ sort_list=( ${sort_list[*]} $new_name )
+ fi
+ # echo "package_list : ${sort_list[*]}"
+
+ # now, we'll present the possible names to the user
+ if [ ${#sort_list[*]} -gt 1 ]; then
+ local i=0
+ echo; echo ">>> Please select the name of the package to create :";echo
+ while [ $i -lt ${#sort_list[*]} ]; do
+ # we'll display an 'R' in front of released names, or a 'D' for dev.
+ if [ "${rel_list[*]/${sort_list[$i]}/}" != "${rel_list[*]}" ]; then
+ printf " %5d : [R] %s\n" $[$i+1] ${sort_list[$i]}
+ else
+ printf " %5d : [D] %s\n" $[$i+1] ${sort_list[$i]}
+ fi
+ i=$[$i+1]
+ done
+
+ echo
+ while : ; do
+ echo -n "Choice [${sort_list[${#sort_list[*]}-1]}]: "; read i
+ if [ -z "$i" ]; then
+ new_name=${sort_list[${#sort_list[*]}-1]}
+ break
+ elif [ "${i//[0-9]/}" ]; then
+ # not a plain integer, we'll take it for the new name
+ new_name=$i
+ break;
+ elif [ $i -ge 1 -a $i -le ${#sort_list[*]} ]; then
+ new_name=${sort_list[$[$i-1]]}
+ break;
+ fi
+ done
+ else
+ new_name=${sort_list[0]}
+ fi
+ # we'll search for all packages starting with the same name and version
+ # in both release and dev dirs. Then we'll be able to deduce the latest
+ # build number used.
+# sort_list=( $(find $PKGROOT/ $DEVROOT/ -maxdepth 1 -type d -name ${new_name}-${BUILDSFX}*.\* -printf "%f\n" 2>/dev/null|sort -u) )
+ sort_list=( $(find $PKGROOT/ $DEVROOT/ -maxdepth 1 -type d -name ${new_name}-${BUILDSFX}${BUILDVER}.\* -printf "%f\n" 2>/dev/null|sort -u) )
+ if [ ${#sort_list[*]} -eq 0 ]; then
+ # this can happen with new BUILDSFX/BUILDVER
+ new_name=${new_name}-${BUILDSFX}${BUILDVER}.1
+ else
+ sort_list=( $(sortnames ${sort_list[*]} ))
+ new_name=${new_name}-$(get_next_build $(get_build_num ${sort_list[${#sort_list[*]}-1]}))
+ fi
+ else
+ if [ -z "${radix/*\\**/}" -o -z "${ver/*\\**/}" ]; then
+ echo "Error: no existing package matches $new_name, and wildcards"
+ echo "or incomplete names cannot be part of a real name."
+ exit 1
+ fi
+ # we keep new_name since it's syntactically correct
+ new_name=${new_name}-${BUILDSFX}${BUILDVER}.1
+ fi
+
+ #echo "new_name: $new_name"
+
+ # if pkg_name is unspecified, we'll use the current directory name to guess
+ # the source package, else we'll use the explicit name
+ echo; echo ">>> Please select the package to use as a reference :"; echo
+
+ get_name $pkg_name $new_name %P %D
+
+ if [ -z "$REPLY" ]; then
+ echo "No reference package found (even default). Please specify one."
+ exit 1
+ fi
+
+ echo "Using '$REPLY'."
+
+ if [ -e "$PKGROOT/$REPLY/build.cfg" ]; then
+ pkg_name=$PKGROOT/$REPLY
+ else
+ pkg_name=$DEVROOT/$REPLY
+ fi
+
+ # new_name is always relative to DEVROOT
+ #echo "new_name: $new_name ; old_name: $(basename $pkg_name)"
+
+ # we should verify that new_name/released doesn't exist before extracting
+ # anything into it, or even that new_name doesn't exist at all.
+ new_name=$DEVROOT/$new_name
+ if [ -e $new_name ]; then
+ echo "Error! new directory $new_name already exists. Refusing to overwrite."
+ exit 1
+ fi
+
+ rm -f ${LINKNAME} && mkdir -p $new_name && ln -s $new_name ${LINKNAME} && \
+ tar -C $pkg_name --exclude='compiled/*' --exclude='released.*' -cplf - . | tar -C $new_name -xf - || \
+ (rmdir $new_name ; rm -f ${LINKNAME})
+ echo "A new package '$(basename $new_name)' has been created as '$new_name', based on '$(basename $pkg_name)'."
+ echo "The link '${LINKNAME}' now points to it."
+ echo
+ if [ $(find $new_name/patches -type f |wc -l) -gt 0 ]; then
+ echo "*** Warning: there are patches to be applied, use >>>pkg info<<< ***"
+ echo
+ fi
+ set +o noglob
+ return 0
+}
+
+
function do_edit {
- echo "Editing $CFGFILE..."
- vi $CFGFILE
+ echo "Editing $CFGFILE..."
+ vi $CFGFILE
}
function do_cat {
- cat $CFGFILE
+ cat $CFGFILE
}
-function do_patch {
- find . -name '*.rej' -o -name '*~' | xargs rm -f
+function pre_info {
+ echo "Information for package '$EXACTPKG' :"
+
+ echo " Package version : $PKGVER (\$PKGVER)"
+ echo " Distrib version : $DISTVER (\$DISTVER)"
+ echo -n " Config. file : "
+ if [ -e $CFGFILE ]; then
+ echo "$CFGFILE"
+ else
+ echo "none found."
+ fi
+ echo " Package file : $PKGDIR/compiled/$EXACTPKG-$FLXARCH.$PKGSUFF"
+ echo -n " Package size : "
+ if [ -e $PKGDIR/compiled/$EXACTPKG-$FLXARCH.$PKGSUFF ]; then
+ echo "$(du -b $PKGDIR/compiled/$EXACTPKG-$FLXARCH.$PKGSUFF |cut -f1) bytes."
+ else
+ echo "does not exist yet."
+ fi
+ [ "$PATCH_LIST" ] && echo " Patches list : $PATCH_LIST"
+ return 0
+}
+
+# does only compile, not changing the current config
+function do_compile_only {
+ $FLXMAKE
+ return $?
+}
+
+# new simplified name for 'config_only', which is deprecated, not changing current scripts.
+function do_config {
+ if declare -f do_config_only >/dev/null 2>&1; then
+ do_config_only
+ return $?
+ else
+ return 0
+ fi
+}
+
+# configures and compiles
+function do_compile {
+ do_config && do_compile_only
+}
+
+# preparatory work for prepack()
+function pre_prepack {
+ if [ "$UID" != "0" -a "$force" != "1" ]; then
+ echo "You must specify '--force' to install as non-root"
+ exit 1
+ fi
+ # WARNING! here, we don't use $ROOTDIR because we don't want to risk
+ # erasing a wrong directory as root !
+ [ -d $(pwd)/${INSTNAME} ] && rm -rf $(pwd)/${INSTNAME}
+ return 0
+}
- for i in $PATCH_LIST; do
- patch -Np$PATCH_LEVEL < $CFGROOT/$CFGDIR/patches/$i
+# some cleanup of an eventual opt directory after prepack()
+function post_prepack {
+ local dir
+ if [ -d $ROOTDIR/opt ] ; then (
+ cd $ROOTDIR/opt
+ for dir in bin sbin lib ; do
+ mkdir $dir
+ find */$dir -type f -perm +111 -exec ln -s ../{} $dir \; -printf "ln -s ../%p $ROOTDIR/opt/$dir\n"
done
+ ) fi
+ return 0
+}
- if [ -z "`find . -name '*.rej'`" ]; then
- find . -name '*~' | xargs rm -f
- fi
+# deletes the current prepack directory.
+function do_delpack {
+ # WARNING! here, we don't use $ROOTDIR because we don't want to risk
+ # erasing a wrong directory as root !
+ [ -d $(pwd)/${INSTNAME} ] && rm -rf $(pwd)/${INSTNAME}
+ return 0
+}
+
+# does a full clean
+function do_clean {
+ make distclean || make mrproper || make clean
+ ( do_delpack )
+ return 0
+}
+
+# applies all the patches to the current sources
+# files which match *.rej and *~ will be deleted
+function do_patch {
+ local i
+ find . -name '*.rej' -o -name '*~' | xargs rm -f
+
+ for i in $PATCH_LIST; do
+ patch -Np$PATCH_LEVEL < $PKGDIR/patches/$i
+ done
+
+ if [ -z "$(find . -name '*.rej')" ]; then
+ find . -name '*~' | xargs rm -f
+ fi
+ return 0
}
+# reverts all the patches from the current sources
+# files which match *.rej and *~ will be deleted
function do_unpatch {
- UNPATCH_LIST=""
+ local i
+ local UNPATCH_LIST=""
- find . -name '*.rej' -o -name '*~' | xargs rm -f
+ find . -name '*.rej' -o -name '*~' | xargs rm -f
- for i in $PATCH_LIST; do
- UNPATCH_LIST="$i $UNPATCH_LIST"
- done
+ for i in $PATCH_LIST; do
+ UNPATCH_LIST="$i $UNPATCH_LIST"
+ done
- for i in $UNPATCH_LIST; do
- patch -RNp$PATCH_LEVEL < $CFGROOT/$CFGDIR/patches/$i
- done
+ for i in $UNPATCH_LIST; do
+ patch -RNp$PATCH_LEVEL < $PKGDIR/patches/$i
+ done
- if [ -z "`find . -name '*.rej'`" ]; then
- find . -name '*~' | xargs rm -f
- fi
+ if [ -z "$(find . -name '*.rej')" ]; then
+ find . -name '*~' | xargs rm -f
+ fi
+ return 0
+}
+
+# extracts a binary package into $ROOTDIR, to reflect the state prior to pack().
+function do_unpack {
+ local FILE=$PKGDIR/compiled/$EXACTPKG-$FLXARCH.$PKGSUFF
+ mkdir -p $ROOTDIR
+ cd $ROOTDIR
+
+ echo -n "Extracting $FILE into $ROOTDIR ... "
+ tar zUxpf $FILE >/dev/null 2>&1
+ echo "done."
+ return 0
+}
+
+# strips symbols from executables before building the package.
+# Abort if ROOTDIR doesn't exist (thus needing prepack() first).
+function do_strip {
+ if [ ! -d $ROOTDIR ] ; then
+ echo "Error: directory $ROOTDIR doesn't exist. Make sure you dir 'prepack'."
+ exit 1
+ fi
+ #find $ROOTDIR/. -type f | xargs file | grep ":.*executable.*not stripped" | cut -f1 -d: | xargs strip -x --strip-unneeded -R .note -R .comment > /dev/null 2>&1
+ # allow executable and shared (.so), but not relocatable (.o), both stripped or not stripped
+ find $ROOTDIR/. -type f | xargs file | grep ":.*ELF.*\(executable\|\shared\).*stripped" | cut -f1 -d: | xargs strip -x --strip-unneeded -R .note -R .comment > /dev/null 2>&1
+ return 0
+}
+
+# forces pack() to strip before starting, even if do_pack() is redefined by the user.
+function pre_pack {
+ ( do_strip )
+ return 0
}
+# this function finds perl dependencies for a given file.
+# It's only called from do_pack_files() and do_pack()
function get_perl_depend {
- filename=$1
- DEP=`grep "^\(.*['{\"]\)*[ ]*\(require\|use\) \+['\"]*[a-zA-Z][a-z:/A-Z0-9-_]*[; '\"]" $filename | \
+ local filename=$1
+ local dep DEP
+ local DEP_FILE=$PKGDIR/compiled/$EXACTPKG-$FLXARCH.dep
+
+ DEP=$(grep "^\(.*['{\"]\)*[ ]*\(require\|use\) \+['\"]*[a-zA-Z][a-z:/A-Z0-9-_]*[; '\"]" $filename | \
sed -e 's/.*\(require\|use\) \+["'\'']\?\([^'\''" };]\+\)["'\'']\?/§§\2§§/g' \
-e 's/§§\([^§]\+\)§§[^§]*/ \1/g' | \
- sed 's@::@/@g'`
- if [ "x$DEP" != "x" ] ; then
- echo -n "$filename" >> $F
- for dep in $DEP ; do
- if [ "x${dep/*.*}" != "x" ] ; then
- echo -n " $dep.pm" >> $F
- else
- echo -n " $dep" >> $F
+ sed 's@::@/@g')
+ if [ "x$DEP" != "x" ] ; then
+ echo -n "$filename" >> $DEP_FILE
+ for dep in $DEP ; do
+ if [ "x${dep/*.*}" != "x" ] ; then
+ echo -n " $dep.pm" >> $DEP_FILE
+ else
+ echo -n " $dep" >> $DEP_FILE
fi
- done
- echo >> $F
- fi
+ done
+ echo >> $DEP_FILE
+ fi
}
-function do_pack {
+# same as pack, except that it uses files in the current directory as the root
+# entries, and that no strip, link nor compression is performed.
+# Only entries listed in the file pointed to by variable FILE_LIST find their
+# way to the archive.
+# This function relies on get_perl_depend().
+function do_pack_files {
+ local DEP_FILE FPNAME
+
+ find . -not -type l | xargs touch -m
+
+ # full path name of different files
+ FPNAME=$PKGDIR/compiled/$EXACTPKG-$FLXARCH
+ DEP_FILE=$FPNAME.dep
+
+ # FIXME: absurde ? : rm puis cat !
+ rm -rf $DEP_FILE
+ if [ -e $DEP_FILE.diff ] ; then cat $DEP_FILE.diff $DEP_FILE ; fi
+
+ echo -n "Creating $DEP_FILE ... "
+ touch $DEP_FILE
+ find . -type f -o -type l | while read ; do
+ case $REPLY in
+ *.pm|*.pl|*.ph)
+ get_perl_depend $REPLY
+ ;;
+ */man/man*/*.[0-9n])
+ echo "$REPLY \$MAN" >> $DEP_FILE
+ ;;
+ */info/*.info|*/info/*.info-[0-9]*)
+ echo "$REPLY \$INFO" >> $DEP_FILE
+ ;;
+ */sbin/*|*/bin/*|*/lib/*|*/libexec/*)
+ flr="$(file $REPLY)"
+ case "$flr" in
+ *\ shell\ *)
+ echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') \$SHELL">>$DEP_FILE
+ ;;
+ *perl\ commands*)
+ echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') ">>$DEP_FILE
+ get_perl_depend $REPLY
+ ;;
+ *:\ symbolic\ link*)
+ echo "$REPLY $(echo $flr | cut -f5 -d' ')" >> $DEP_FILE
+ ;;
+ *\ ELF\ 32-bit\ LSB*dynamically\ linked*)
+ echo "$REPLY $(ldd $REPLY 2>/dev/null | grep -v 'statically linked' | awk '{print $1}' | tr '\012' ' ')" >> $DEP_FILE
+ ;;
+ *\ ELF\ 32-bit\ LSB*shared\ object*)
+ echo "$REPLY $(ldd $REPLY 2>/dev/null | grep -v 'statically linked' | awk '{print $1}' | tr '\012' ' ')" >> $DEP_FILE
+ ;;
+ esac
+ ;;
+ esac
+ done
+ echo "done."
+
+ echo -n "Creating $FPNAME.lst ... "
+ # we try the special case of the '.' entry which is needed to set the root permissions.
+ # this entry must be set as "." in FILE_LIST.
+ if grep -q '^.[ ]' $FILE_LIST; then
+ set -- $(grep '^.[ ]' $FILE_LIST)
+ owner=${2%%:*}
+ group=${2##*:}
+ echo "d $3 $owner $group 0 -------------------------------- 0 ."
+ fi > $FPNAME.lst
+ (flx sign --no-depth --ignore-dot $(cut -f1 -d' ' $FILE_LIST|sed -e 's,/$,,') >> $FPNAME.lst) > /dev/null 2>&1
+ echo "done."
+
+ echo -n "Creating $FPNAME.$PKGSUFF ... "
+
+ # we want everything, including directories.
+ cut -f1 -d' ' $FILE_LIST|sed -e 's,/$,,' | tar -T - --no-recursion -cf - | gzip -9 >$FPNAME.$PKGSUFF 2>/dev/null
+ echo "done."
+ return 0
+}
+
+
+# packs the prepacked files into a new file located in $DEVROOT.
+# any eventual old package is removed.
+# this function relies on do_pack_files(), get_perl_depend(),
+function do_pack {
+ local DEP_FILE FPNAME
+
# use the file list when available
if [ "$FILE_LIST" ]; then
- do_pack_files
- return $?
+ do_pack_files
+ return $?
fi
- if [ ! -d $ROOTDIR ] ; then export ROOTDIR=`pwd` ; fi
- cd $ROOTDIR
+ # FIXME: is this normal ???
+ if [ ! -d $ROOTDIR ] ; then export ROOTDIR=$(pwd) ; fi
+ cd $ROOTDIR
## ( find lib -type l -name "lib*.so*" | xargs rm -f ; \
## find usr/lib -type l -name "lib*.so*" | xargs rm -f ; \
## ldconfig -nr . ) > /dev/null 2>&1
- ldconfig -nr . lib usr/lib > /dev/null 2>&1
- find . ! -type l | xargs touch -m
-
- F=$PKGROOT/$packver.dep
-
- rm -rf $F
- if [ -e $F.diff ] ; then cat $F.diff $F ; fi
-
- echo -n "Creating $F ... "
- touch $F
- find . -type f -o -type l | while read ; do
- case $REPLY in
- *.pm|*.pl|*.ph)
- get_perl_depend $REPLY
- ;;
- */man/man*/*.[0-9n])
- if [ "${REPLY/*gz}" ] ; then
- if [ -L $REPLY ] ; then
- LINK=`readlink $REPLY`
- rm $REPLY
- ln -s $LINK.gz $REPLY.gz
- else
- gzip -f -9 $REPLY
- chmod 644 $REPLY.gz
- fi
- fi
- echo "$REPLY \$MAN" >> $F
- ;;
- */info/*.info|*/info/*.info-[0-9]*)
- if [ "${REPLY/*gz}" ] ; then
- gzip -f -9 $REPLY
- chmod 644 $REPLY.gz
- fi
- echo "$REPLY \$INFO" >> $F
- ;;
- */sbin/*|*/bin/*|*/lib/*|*/libexec/*)
- flr="`file $REPLY`"
- case "$flr" in
- *\ shell\ *)
- echo "$REPLY `head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/'` \$SHELL">>$F
- ;;
- *perl\ commands*)
- echo "$REPLY `head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/'` ">>$F
- get_perl_depend $REPLY
- ;;
- *:\ symbolic\ link*)
- echo "$REPLY `echo $flr | cut -f5 -d' '`" >> $F
- ;;
- *\ ELF\ 32-bit\ LSB*dynamically\ linked*)
- echo "$REPLY `ldd $REPLY 2>/dev/null | grep -v 'statically linked' | awk '{print $1}' | tr '\012' ' '`" >> $F
- ;;
- *\ ELF\ 32-bit\ LSB*shared\ object*)
- echo "$REPLY `ldd $REPLY 2>/dev/null | grep -v 'statically linked' | awk '{print $1}' | tr '\012' ' '`" >> $F
- ;;
- esac
- ;;
- esac
- done
- echo "done."
-
- echo -n "Creating $PKGROOT/$packver.lst ... "
- (find . ! -type d -o -empty | cut -c3-| xargs flx sign --ignore-dot --no-depth > $PKGROOT/$packver.lst) > /dev/null 2>&1
- echo "done."
-
- F=$PKGROOT/$packver.$PKGSUFF
- echo -n "Creating $F ... "
- # we want everything, and directories only if they're empty. All this without './'
- # we shouldn't get an empty line since . should contain at least what we want to tar !
- find . ! -type d -o -empty | cut -c3- | tar -T - -cf - | gzip -9 >$F 2>/dev/null
- echo "done."
-
- if [ -n "$CFGFILE" ]; then
- F=$CFGROOT/$CFGDIR/$pack.$CFGSUFF
- echo -n "Creating $F ... "
- if [ "$F" != "$CFGFILE" ]; then cp -f "$CFGFILE" "$F"; echo "done." ; else echo "up to date."; fi
- fi
-
+ ldconfig -nr . lib usr/lib > /dev/null 2>&1
+ find . ! -type l | xargs touch -m
+
+ # full path name of different files
+ FPNAME=$PKGDIR/compiled/$EXACTPKG-$FLXARCH
+ DEP_FILE=$FPNAME.dep
+
+ # FIXME: absurde ? : rm puis cat !
+ rm -rf $DEP_FILE
+ if [ -e $DEP_FILE.diff ] ; then cat $DEP_FILE.diff $DEP_FILE ; fi
+
+ echo -n "Creating $DEP_FILE ... "
+ touch $DEP_FILE
+ find . -type f -o -type l | while read ; do
+ case $REPLY in
+ *.pm|*.pl|*.ph)
+ get_perl_depend $REPLY
+ ;;
+ */man/man*/*.[0-9n])
+ if [ "${REPLY/*gz}" ] ; then
+ if [ -L $REPLY ] ; then
+ LINK=$(readlink $REPLY)
+ rm $REPLY
+ ln -s $LINK.gz $REPLY.gz
+ else
+ gzip -f -9 $REPLY
+ chmod 644 $REPLY.gz
+ fi
+ fi
+ echo "$REPLY \$MAN" >> $DEP_FILE
+ ;;
+ */info/*.info|*/info/*.info-[0-9]*)
+ if [ "${REPLY/*gz}" ] ; then
+ gzip -f -9 $REPLY
+ chmod 644 $REPLY.gz
+ fi
+ echo "$REPLY \$INFO" >> $DEP_FILE
+ ;;
+ */sbin/*|*/bin/*|*/lib/*|*/libexec/*)
+ flr="$(file $REPLY)"
+ case "$flr" in
+ *\ shell\ *)
+ echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') \$SHELL">>$DEP_FILE
+ ;;
+ *perl\ commands*)
+ echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') ">>$DEP_FILE
+ get_perl_depend $REPLY
+ ;;
+ *:\ symbolic\ link*)
+ echo "$REPLY $(echo $flr | cut -f5 -d' ')" >> $DEP_FILE
+ ;;
+ *\ ELF\ 32-bit\ LSB*dynamically\ linked*)
+ echo "$REPLY $(ldd $REPLY 2>/dev/null | grep -v 'statically linked' | awk '{print $1}' | tr '\012' ' ')" >> $DEP_FILE
+ ;;
+ *\ ELF\ 32-bit\ LSB*shared\ object*)
+ echo "$REPLY $(ldd $REPLY 2>/dev/null | grep -v 'statically linked' | awk '{print $1}' | tr '\012' ' ')" >> $DEP_FILE
+ ;;
+ esac
+ ;;
+ esac
+ done
+ echo "done."
+
+ echo -n "Creating $FPNAME.lst ... "
+ (find . ! -type d -o -empty | cut -c3-| xargs flx sign --ignore-dot --no-depth > $FPNAME.lst) > /dev/null 2>&1
+ echo "done."
+
+ echo -n "Creating $FPNAME.$PKGSUFF ... "
+ # we want everything, and directories only if they're empty. All this without './'
+ # we shouldn't get an empty line since . should contain at least what we want to tar !
+ find . ! -type d -o -empty | cut -c3- | tar -T - -cf - | gzip -9 >$FPNAME.$PKGSUFF 2>/dev/null
+ echo "done."
+ return 0
}
-function do_unpack {
- mkdir -p $ROOTDIR
- cd $ROOTDIR
+function usage {
+ echo "Usage:"
+ echo " pkg [-options]* <action> [ pkg [ pkg2 ] ]"
+ echo
+ echo " pkg newpkg [ new_pkg [ old_pkg ] ]"
+ echo " ex: pkg newpkg openssl-0.9.6g-${BUILDSFX}${BUILDVER}.1 openssl-0.9.6d-${BUILDSFX}${BUILDVER}.1"
+ echo " pkg newpkg apache apache-1.3"
+ echo " pkg newpkg bash"
+ echo " pkg newpkg gcc gcc-3*${BUILDSFX}*.1"
+ echo
+ echo " pkg setpkg [ new_pkg ]"
+ echo " ex: pkg setpkg openssl-0.9.6g-${BUILDSFX}${BUILDVER}.1"
+ echo
+ echo " pkg { info | cat | edit } [ pkg ]"
+ echo " ex: pkg info"
+ echo " pkg info bash"
+ echo " pkg edit modutils-2.4"
+ echo " pkg cat gzip-1.3"
+ echo
+ echo " pkg { compile | config | compile_only | build | prepack }*"
+ echo " pkg { strip | pack | unpack | delpack | release | clean }*"
+ echo
+ echo " pkg { patch | unpatch } [ patch_name ]"
+ echo
+ echo " pkg { any_command } [ any_args ]"
+ echo
+ echo "User variables are :"
+ echo "PKGROOT : directory containing released packages <$PKGROOT>"
+ echo "DEVROOT : directory containing unreleased packages <$DEVROOT>"
+ echo "ROOTDIR : base directory for package installation (not source), <$ROOTDIR>"
+ echo "FLXARCH : architecture to use for the package, <$FLXARCH>"
+ echo "KERNDIR : kernel sources location, if needed, <$KERNDIR>"
+# Those two are not user-settable anymore
+# echo "CFGFILE : force to use of a .pkg, <$CFGFILE>"
+# echo "DISTVER : build version (${BUILDSFX}${BUILDVER}.1)"
+ exit 1
+}
- F=$PKGROOT/$packver.$PKGSUFF
- echo -n "Extracting $F into $ROOTDIR ... "
- tar zUxpf $F >/dev/null 2>&1
- echo "done."
+# displays usage
+function do_help {
+ usage
+ return 0
}
-# same as pack, except that it uses files in the current directory as the root
-# entries, and that no strip, link nor compression is performed.
-# Only entries listed in the file pointed to by variable FILE_LIST find their
-# way to the archive.
-function do_pack_files {
-## ( find lib -type l -name "lib*.so*" | xargs rm -f ; \
-## find usr/lib -type l -name "lib*.so*" | xargs rm -f ; \
-## ldconfig -nr . ) > /dev/null 2>&1
- find . ! -type l | xargs touch -m
-
- F=$PKGROOT/$packver.dep
-
- # absurde ? : rm puis cat !
- rm -rf $F
- if [ -e $F.diff ] ; then cat $F.diff $F ; fi
-
- echo -n "Creating $F ... "
- touch $F
- find . -type f -o -type l | while read ; do
- case $REPLY in
- *.pm|*.pl|*.ph)
- get_perl_depend $REPLY
- ;;
- */man/man*/*.[0-9n])
- echo "$REPLY \$MAN" >> $F
- ;;
- */info/*.info|*/info/*.info-[0-9]*)
- echo "$REPLY \$INFO" >> $F
- ;;
- */sbin/*|*/bin/*|*/lib/*|*/libexec/*)
- flr="`file $REPLY`"
- case "$flr" in
- *\ shell\ *)
- echo "$REPLY `head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/'` \$SHELL">>$F
- ;;
- *perl\ commands*)
- echo "$REPLY `head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/'` ">>$F
- get_perl_depend $REPLY
- ;;
- *:\ symbolic\ link*)
- echo "$REPLY `echo $flr | cut -f5 -d' '`" >> $F
- ;;
- *\ ELF\ 32-bit\ LSB*dynamically\ linked*)
- echo "$REPLY `ldd $REPLY 2>/dev/null | grep -v 'statically linked' | awk '{print $1}' | tr '\012' ' '`" >> $F
- ;;
- *\ ELF\ 32-bit\ LSB*shared\ object*)
- echo "$REPLY `ldd $REPLY 2>/dev/null | grep -v 'statically linked' | awk '{print $1}' | tr '\012' ' '`" >> $F
- ;;
- esac
- ;;
- esac
- done
- echo "done."
-
- echo -n "Creating $PKGROOT/$packver.lst ... "
- # we try the special case of the '.' entry which is needed to set the root permissions.
- # this entry must be set as "." in FILE_LIST.
- if grep -q '^.[ ]' $FILE_LIST; then
- set -- $(grep '^.[ ]' $FILE_LIST)
- owner=${2%%:*}
- group=${2##*:}
- echo "d $3 $owner $group 0 -------------------------------- 0 ."
- fi > $PKGROOT/$packver.lst
- (flx sign --no-depth --ignore-dot `cut -f1 -d' ' $FILE_LIST|sed -e 's,/$,,'` >> $PKGROOT/$packver.lst) > /dev/null 2>&1
- echo "done."
-
- F=$PKGROOT/$packver.$PKGSUFF
- echo -n "Creating $F ... "
-
- # we want everything, and directories only if they're empty. All this without './'
- # we shouldn't get an empty line since . should contain at least what we want to tar !
- cut -f1 -d' ' $FILE_LIST|sed -e 's,/$,,' | tar -T - --no-recursion -cf - | gzip -9 >$F 2>/dev/null
- echo "done."
-
- if [ -n "$CFGFILE" ]; then
- F=$CFGROOT/$CFGDIR/$pack.$CFGSUFF
- echo -n "Creating $F ... "
- if [ "$F" != "$CFGFILE" ]; then cp -f "$CFGFILE" "$F"; echo "done." ; else echo "up to date."; fi
- fi
-
+function do_release {
+ echo "#####################################################"
+ echo "# Release command not implemented yet ! Aborting... #"
+ echo "#####################################################"
+ exit 1
+ return 0
}
-function do_strip {
- if [ ! -d $ROOTDIR ] ; then export ROOTDIR=`pwd` ; fi
- #find $ROOTDIR/. -type f | xargs file | grep ":.*executable.*not stripped" | cut -f1 -d: | xargs strip -x --strip-unneeded -R .note -R .comment > /dev/null 2>&1
- # allow executable and shared (.so), but not relocatable (.o), both stripped or not stripped
- find $ROOTDIR/. -type f | xargs file | grep ":.*ELF.*\(executable\|\shared\).*stripped" | cut -f1 -d: | xargs strip -x --strip-unneeded -R .note -R .comment > /dev/null 2>&1
- return 0
-}
+######
+###### here are some functions used only from main
+######
-function pre_pack {
- ( do_strip )
+function known_cmd {
+ declare -f pre_$ACTION > /dev/null && { ( pre_$ACTION $* ) || return $?; }
+ declare -f do_$ACTION > /dev/null && { ( do_$ACTION $* ) || return $?; }
+ declare -f post_$ACTION > /dev/null && { ( post_$ACTION $* ) || return $?; }
}
+
+######
+###### here is the main entry point
+######
+
+# scan the command line
+
+release_only=0
+force=0
+PRINTUSAGE=0
+ARGLIST=( )
+ACTION=
+CHAINCMD=1
+
+[ $# -eq 0 ] && PRINTUSAGE=1
+
+while [ $# -gt 0 ] ; do
+ case "$1" in
+ --force )
+ force=1
+ ;;
+ --help|-h)
+ PRINTUSAGE=1
+ ;;
+ --rel|-r*)
+ release_only=1
+ ;;
+ --)
+ shift
+ ARGLIST=(${ARGLIST[*]} $*)
+ break
+ ;;
+ -* )
+ PRINTUSAGE=1
+ ;;
+ *)
+ ARGLIST=(${ARGLIST[*]} "$1")
+ ;;
+ esac
+ shift
+done
+
+
+#echo "arglist=${ARGLIST[*]}"
+
+[ $PRINTUSAGE -gt 0 ] && usage
+[ ${#ARGLIST[*]} -lt 1 ] && usage
+
+# Some actions can be chained, others not. we'll get the longest
+# possible chain, and stop once we encounter a non-chainable action
+
+while [ $CHAINCMD -gt 0 ]; do
+ set -o noglob
+ ACTION=${ARGLIST[0]}
+
+ # unset ARGLIST[0] ### doesn't work in scripts with this shitty bash !!!
+ ARGLIST[0]= ; ARGLIST=( ${ARGLIST[*]} ) # gets expanded with shitty bash !
+
+ case "$ACTION" in
+ newpkg)
+ CHAINCMD=0
+ KNOWNCMD=1
+ # newpkg is the only command which doesn't start by a package lookup.
+ ;;
+ setpkg)
+ CHAINCMD=0
+ KNOWNCMD=1
+ get_name $1 %P default
+ ;;
+ info|edit|cat)
+ CHAINCMD=0
+ KNOWNCMD=1
+ get_name ${ARGLIST[0]} %L %P %D
+ ;;
+ patch|unpatch)
+ CHAINCMD=0
+ KNOWNCMD=1
+ REPLY=$(basename $(readlink ${LINKNAME}) 2>/dev/null)
+ # get_name %L
+ ;;
+ compile_only|config|config_only|compile|build|prepack|strip|pack|unpack|delpack|release|clean)
+ KNOWNCMD=1
+ REPLY=$(basename $(readlink ${LINKNAME}) 2>/dev/null)
+ # get_name %L
+ ;;
+ *)
+ CHAINCMD=0
+ KNOWNCMD=0
+ REPLY=$(basename $(readlink ${LINKNAME}) 2>/dev/null)
+ # get_name %L
+ ;;
+ esac
+
+ set +o noglob
+ if [ "$ACTION" != "newpkg" ]; then
+ if [ -z "$REPLY" ]; then
+ echo "Error: package name not found."
+ exit 1
+ fi
+ EXACTPKG=$REPLY
+
+ if [ -e "$PKGROOT/$EXACTPKG/build.cfg" ]; then
+ PKGDIR=$PKGROOT/$EXACTPKG
+ else
+ PKGDIR=$DEVROOT/$EXACTPKG
+ fi
+ CFGFILE=$PKGDIR/build.cfg
+ PKGRADIX=$(get_pkg_radix $EXACTPKG)
+ PKGVER=$(get_pkg_ver $EXACTPKG)
+ DISTVER=$(get_build_num $EXACTPKG)
+ ROOTDIR=${ROOTDIR:-$(pwd)/${INSTNAME}}
+
+ # for compatibility with old functions. Not used anywhere outside this script.
+ packver=$EXACTPKG
+ pack=$PKGRADIX
+
+ . $CFGFILE
+ fi
+
+ case "$FLXARCH" in
+ i686) arch=i686 cpu=i686 basearch=i386 ;;
+ i486) arch=i486 cpu=i486 basearch=i386 ;;
+ i386) arch=i386 cpu=i386 basearch=i386 ;;
+ *) arch=i586 cpu=i686 basearch=i386 ;;
+ esac
+
+ if [ -z "$FLXMAKE" ]; then
+ FLXMAKE=make
+ fi
+
+ export DISTVER PKGRADIX PKGVER FLXMAKE PATCH_LIST FILE_LIST
+
+# echo "ACTION=$ACTION, KNOWNCMD=$KNOWNCMD, CHAINCMD=$CHAINCMD"
+# echo "ARGLIST=${ARGLIST[*]}"
+
+ if [ $KNOWNCMD -gt 0 ]; then
+ known_cmd ${ARGLIST[*]} || exit 1
+ else
+ if declare -f do_$ACTION >/dev/null; then
+ ( do_$ACTION ${ARGLIST[*]} ) || exit 1
+ fi
+ fi
+
+ # now, we'll loop only if we were in a chainable action
+done
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+exit 99
+
+###############################################################################################################
+###############################################################################################################
+###############################################################################################################
+###############################################################################################################
+
+
+DEAD CODE BELOW !!!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
function usage {
- echo "Usage: pkg <action>"
- echo " action is one of :"
- echo " help : display this help."
- echo " info : get information on current package."
- echo " newpkg : build a more recent .pkg script from an old one."
- echo " cat : display last .pkg file."
- echo " edit : edit last .pkg file."
- echo " patch : apply a list of patches to the directory prior to compile."
- echo " unpatch : revert a list of patches to the directory."
- echo " compile : do_compile=do_config_only+do_compile_only in .pkg script ($CFGROOT/$CFGDIR)"
- echo " prepack : execute do_prepack in .pkg script ($CFGROOT/$CFGDIR)"
- echo " strip : strip binaries in temporary directory"
- echo " pack : strip binaries, then package into $PKGROOT"
- echo " delpack : remove temporary directory"
- echo " clean : execute 'make clean' and remove temporary directory."
- echo " build : execute clean compile prepack pack."
- echo " unpack : extract package into temporary directory"
- echo "Variables are :"
- echo "CFGROOT : directory for .pkg and patches, <$CFGROOT>"
- echo "CFGFILE : force to use of a .pkg, <$CFGFILE>"
- echo "PKGROOT : directory for .lst, .tgz and .dep, <$PKGROOT>"
- echo "ROOTDIR : base directory for package (not source), <$ROOTDIR>"
- echo "FLXARCH : architecture for package name, <$FLXARCH>"
- echo "KERNDIR : base directory for package (not source), <$KERNDIR>"
- echo "DISTVER : build version (flx.1)"
- exit 1
+ echo "Usage: pkg <action> [new_pkg [old_pkg]]"
+ echo " action is one of :"
+ echo " help : display this help."
+ echo " info : get information on current package."
+ echo " newpkg : build a more recent .pkg script from an old one."
+ echo " cat : display last .pkg file."
+ echo " edit : edit last .pkg file."
+ echo " patch : apply a list of patches to the directory prior to compile."
+ echo " unpatch : revert a list of patches to the directory."
+ echo " compile : do_compile=do_config_only+do_compile_only in .pkg script ($CFGROOT/$CFGDIR)"
+ echo " prepack : execute do_prepack in .pkg script ($CFGROOT/$CFGDIR)"
+ echo " strip : strip binaries in temporary directory"
+ echo " pack : strip binaries, then package into $PKGROOT"
+ echo " delpack : remove temporary directory"
+ echo " clean : execute 'make clean' and remove temporary directory."
+ echo " build : execute clean compile prepack pack."
+ echo " unpack : extract package into temporary directory"
+ echo "Variables are :"
+ echo "CFGROOT : directory for .pkg and patches, <$CFGROOT>"
+ echo "CFGFILE : force to use of a .pkg, <$CFGFILE>"
+ echo "PKGROOT : directory for .lst, .tgz and .dep, <$PKGROOT>"
+ echo "ROOTDIR : base directory for package (not source), <$ROOTDIR>"
+ echo "FLXARCH : architecture for package name, <$FLXARCH>"
+ echo "KERNDIR : base directory for package (not source), <$KERNDIR>"
+ echo "DISTVER : build version (flx.1)"
+ exit 1
}
-function do_help {
- usage
-}
-function pre_info {
- echo "Information for package $pack: "
-
- echo " Package version : $PKGVER (\$PKGVER)"
- echo " Distrib version : $DISTVER (\$DISTVER)"
- echo -n " Config. file : "
- if [ -e $CFGFILE ]; then
- echo "$CFGFILE"
- else
- echo "none found."
- fi
- echo " Package file : $PKGROOT/$packver.$PKGSUFF"
- echo -n " Package size : "
- if [ -e $PKGROOT/$packver.$PKGSUFF ]; then
- echo "`du -b $PKGROOT/$packver.$PKGSUFF|cut -f1` bytes."
- else
- echo "does not exist yet."
- fi
- if [ "$PATCH_LIST" ]; then
- echo " Patches list : $PATCH_LIST"
- fi
-}
-function do_newpkg {
- echo "WARNING!!! the 'newpkg' feature is in beta stage !!!"
- if [ -n "$CFGFILE" ]; then
- F=$CFGROOT/$PKGRADIX-$PKGVER-$DISTVER-pkg/$pack.$CFGSUFF
- echo -n "Creating $F ... "
- if [ "$F" != "$CFGFILE" ]; then
- mkdir -p $CFGROOT/$PKGRADIX-$PKGVER-$DISTVER-pkg && cp -f "$CFGFILE" "$F" &&
- cp -af $CFGROOT/$CFGDIR/patches $CFGROOT/$PKGRADIX-$PKGVER-$DISTVER-pkg/ >/dev/null 2>&1
- echo "done."
- else
- echo "up to date."
- fi
- fi
-}
-# setting fixed vars
-if [ -z "$KERNDIR" ] ; then KERNDIR="/usr/src/linux" ; fi
-if [ -z "$CFGROOT" ] ; then CFGROOT="/var/flx-src" ; fi
-if [ -z "$PKGROOT" ] ; then PKGROOT="/var/flx-pkg" ; fi
-#if [ -z "$DISTVER" ] ; then DISTVER="flx.1" ; fi
-if [ "$FLXARCH" = "" ]; then FLXARCH=`uname -m` ; fi
-PKGSUFF="tgz"
-CFGSUFF="pkg"
-exe=`basename $0`
-# check for action type
-echo $exe | grep -q "^pkg"
-if [ $? = 0 -a "$exe" != "pkg" ] ; then
- type=`echo $exe | cut -c4-`
-else
- type=$1
+
+
+
+for ACTION in ${ARGLIST[*]}; do
+
+# now we will try to identify two packages names :
+# - the EXACT one, deduced from command line, then version symlink, then the
+# directory name ; this one doesn't have to exist to be correct.
+# - the NEAREST one, deduced from the same criterions, with and without
+# versions, and based on EXISTING files only.
+# The NEAREST one will be used as a source, while the EXACT one will be used as
+# a target. When the EXACT one exists, the NEAREST one must obviously be the
+# same.
+
+# EXACTPKG can be specified as an environment variable if needed
+[ $NEAREST_IS_SRC -eq 0 ] && [ -z "$EXACTPKG" -a ${#ARGLIST[*]} -gt 0 ] && EXACTPKG=$(basename ${ARGLIST[0]})
+[ -z "$EXACTPKG" -a -L .flxver ] && EXACTPKG=$(readlink .flxver)
+[ -z "$EXACTPKG" ] && EXACTPKG=$(basename $(pwd))
+
+if [ -z "$(get_pkg_ver $EXACTPKG)" ]; then
+ TEMP=$(sortnames $CFGROOT/$EXACTPKG-[0-9]* | tail -1)
+ TEMP=${TEMP:-$(sortnames $CFGROOT/$EXACTPKG.* | tail -1)}
+ TEMP=${TEMP:-$(sortnames $CFGROOT/$EXACTPKG-* | tail -1)}
+ TEMP=${TEMP:-$(sortnames $CFGROOT/$EXACTPKG* | tail -1)}
+# if [ -z "$TEMP" ]; then
+# echo "Cannot find a suitable package for the current directory. Please specify"
+# echo "a correct name on the command line."
+# usage
+# exit 1
+# fi
+ [ "$TEMP" ] && EXACTPKG=$(basename $TEMP)
+ [ -z "$(get_pkg_ver $EXACTPKG)" ] && EXACTPKG=$EXACTPKG-0
fi
-# look for parameters
-if [ "$type" = "$1" -a "${type##-*}" ] ; then shift ; fi
-case $1 in
- --force ) force=1; shift ;;
- --help ) usage ;;
- --source) type=source_only ;;
- -* ) shift ;;
-esac
-
-if [ "$type" = "" ] ; then
- usage ;
+if [ -z "$(get_build_num $EXACTPKG)" ]; then
+ RADIX=$(get_pkg_radix $EXACTPKG)
+ TEMP=$(sortnames $CFGROOT/$EXACTPKG-* $CFGROOT/$EXACTPKG $CFGROOT/$RADIX | tail -1)
+
+ VER=$(get_pkg_ver $TEMP)
+ BUILD=$(get_build_num $TEMP)
+ EXACTPKG=${RADIX}-${VER:-0}-${BUILD:-flx.1}
fi
-# execute action
-if [ "$type" = "find" ] ; then
- for i in * ; do
- pkgf=`grep "/$i\$" $CFGROOT/$CFGDIR/*.$CFGSUFF | cut -f1 -d: | tr '\012' ' '`
- echo "$i: $pkgf"
- done
-elif [ "$type" != "source_only" ] ; then
- ARGV=$*
-
- # look for package name from directory name
- pack=`pwd`
- pack=`basename $pack | sed -e 's/[-_][0-9].*$//'`
-
- # for package
- if [ -n "$pack" ] ; then
-
- packver=`pwd`
- packver=`basename $packver`
-
- if [ -z "$DISTVER" ]; then
- if echo $packver | grep -q -- "-flx\." ; then
- DISTVER=`echo $packver|sed 's/\(.*-\)\(flx.[0-9]\+\)\(.*\)/\2/'`
- fi
+NEWPKGRADIX=$(get_pkg_radix $EXACTPKG)
+NEWPKGVER=$(get_pkg_ver $EXACTPKG)
+NEWDISTVER=$(get_build_num $EXACTPKG)
+NEWDISTVER=${NEWDISTVER:-flx.1}
+EXACTPKG=$NEWPKGRADIX-$NEWPKGVER-$NEWDISTVER
+
+trylist=( )
+[ -d "$CFGROOT/$EXACTPKG" -o -f "$CFGROOT/$EXACTPKG.$PKGSUFF" ] && trylist=( ${trylist[*]} $EXACTPKG)
+[ ${#ARGLIST[*]} -gt 0 ] && trylist=( ${trylist[*]} $(basename ${ARGLIST[0]}))
+[ -L .flxver ] && trylist=( ${trylist[*]} $(readlink .flxver))
+trylist=( ${trylist[*]} $NEWPKGRADIX-$NEWPKGVER )
+trylist=( ${trylist[*]} $NEWPKGRADIX )
+trylist=( ${trylist[*]} $(basename $(pwd)))
+trylist=( ${trylist[*]} "default")
+
+echo trylist=${trylist[*]}
+
+for NEARESTPKG in ${trylist[*]}; do
+ if [ -z "$(get_pkg_ver $NEARESTPKG)" ]; then
+ TEMP=$(sortnames $CFGROOT/$NEARESTPKG-[0-9]* | tail -1)
+ TEMP=${TEMP:-$(sortnames $CFGROOT/$NEARESTPKG.* | tail -1)}
+ TEMP=${TEMP:-$(sortnames $CFGROOT/$NEARESTPKG-* | tail -1)}
+ #TEMP=${TEMP:-$(sortnames $CFGROOT/$NEARESTPKG | tail -1)}
+ [ "$TEMP" ] && NEARESTPKG=$(basename $TEMP) || continue
fi
- # source configuration
- if [ -z "$ROOTDIR" ] ; then ROOTDIR=`pwd`/.flxdisk ; fi
- if [ -n "$CFGFILE" ]; then
- CFGDIR=`dirname $CFGFILE`
- CFGROOT=`dirname $CFGDIR`
- CFGDIR=`basename $CFGDIR`
- . $CFGFILE
- else
- #CFGFILE=`find $CFGROOT/ -name "$pack[-_]*-${DISTVER:-*}-$FLXARCH.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1`
- #CFGFILE=${CFGFILE:-`find $CFGROOT/ -name "$pack[-_]*-${DISTVER:-*}-*.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1`}
- #CFGFILE=${CFGFILE:-`find $CFGROOT/ -name "$pack[-_]*.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1`}
- #CFGFILE=${CFGFILE:-`find $CFGROOT/ -name "$pack.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1`}
- CFGFILE=`find $CFGROOT/ -maxdepth 1 -type d -name "$pack[-_]*-${DISTVER:-*}-pkg"|sed -e "s/-pkg\$//"|sort|tail -1`
- CFGFILE=${CFGFILE:-`find $CFGROOT/ -maxdepth 1 -type d -name "$pack[-_]*-pkg"|sed -e "s/-pkg\$//"|sort|tail -1`}
- CFGFILE=${CFGFILE:-`find $CFGROOT/ -maxdepth 1 -type f -name "$pack[-_]*-${DISTVER:-*}-pkg.$PKGSUFF"|sed -e "s/-pkg\.$PKGSUFF\$//"|sort|tail -1`}
- CFGFILE=${CFGFILE:-`find $CFGROOT/ -maxdepth 1 -type f -name "$pack[-_]*-pkg.$PKGSUFF"|sed -e "s/-pkg\.$PKGSUFF\$//"|sort|tail -1`}
-
- # to be completed
-
- if [ -z "$CFGFILE" ]; then
- echo "CFGFILE not found. Cannot continue." >&2
- exit 1
- fi
-
- if [ -d $CFGFILE ]; then
- CFGROOT=`dirname $CFGFILE`
- CFGDIR=`basename $CFGFILE`-pkg
- CFGFILE=$CFGROOT/$CFGDIR/$pack.$CFGSUFF
- else
- CFGROOT=`dirname $CFGFILE`
- CFGDIR=`basename $CFGFILE`-pkg
- CFGFILE=$CFGROOT/$CFGDIR/$pack.$CFGSUFF
- if [ ! -e $CFGROOT/$CFGDIR ]; then
- echo "Opening package $CFGROOT/$CFGDIR.$PKGSUFF into $CFGROOT/$CFGDIR..."
- mkdir -p $CFGROOT/$CFGDIR && tar -C $CFGROOT/$CFGDIR -Uxpf $CFGROOT/$CFGDIR.$PKGSUFF
- if [ $? != 0 ]; then
- echo "There was an error during this operation. You may have to manually clean $CFGROOT/$CFGDIR. Cannot continue !"
- exit 1
- else
- echo "Done !"
- fi
- fi
- fi
-
- if [ -e "$CFGFILE" ]; then
- . $CFGFILE
- else
- echo "CFGFILE ($CFGFILE) not found. Cannot continue." >&2
- exit 1
- fi
- fi
+ RADIX=$(get_pkg_radix $NEARESTPKG)
+ VER=$(get_pkg_ver $NEARESTPKG)
+ BUILD=$(get_build_num $NEARESTPKG)
+ NEARESTPKG=${RADIX}${VER:+-$VER}${BUILD:+-$BUILD}
+
+ #### [ "$(get_build_num $NEARESTPKG)" ] &&
+
+ [ -d "$CFGROOT/$NEARESTPKG" -o -f "$CFGROOT/$NEARESTPKG.$PKGSUFF" ] && break
+echo NEARESTPKG=$NEARESTPKG
+
+ ###TEMP=$(sortnames $CFGROOT/$NEARESTPKG-* | tail -1)
+ ###[ "$(get_build_num $TEMP)" ] && NEARESTPKG=$(basename $TEMP) && break
+done
+
+RADIX=$(get_pkg_radix $NEARESTPKG)
+VER=$(get_pkg_ver $NEARESTPKG)
+BUILD=$(get_build_num $NEARESTPKG)
+NEARESTPKG=${RADIX}${VER:+-$VER}${BUILD:+-$BUILD}
+
+echo "EXACTPKG=$EXACTPKG"
+echo "NEARESTPKG=$NEARESTPKG"
+
+# to be removed ## look if there was an argument, in which case we would treat it as a package
+# to be removed ## name (either source or destination, depending on the action). These variables
+# to be removed ## are set :
+# to be removed ## - ARGPKGFULL : full package name with version
+# to be removed ## - ARGPKGRADIX : package radix name (without version)
+# to be removed ## - ARGPKGVER : package version without -flx*
+# to be removed ## - ARGDISTVER : package build version (flx*)
+# to be removed #
+# to be removed #if [ ${#ARGLIST[*]} -gt 0 ]; then
+# to be removed # ARGPKGFULL=$(basename ${ARGLIST[0]})
+# to be removed # ARGPKGRADIX=$(get_pkg_radix $ARGPKGFULL)
+# to be removed # ARGPKGVER=$(get_pkg_ver $ARGPKGFULL)
+# to be removed # if echo $ARGPKGFULL | grep -q -- "-flx\." ; then
+# to be removed # ARGDISTVER=$(get_build_num $ARGPKGFULL)
+# to be removed # fi
+# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGFULL* |tail -1)}
+# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGRADIX-$ARGPKGVER-* |tail -1)}
+# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGRADIX-$ARGPKGVER* |tail -1)}
+# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGRADIX-* |tail -1)}
+# to be removed #fi
+# to be removed #
+# to be removed ## look for package name from the '.flxver' link in current dir, then dir name
+# to be removed #
+# to be removed #if [ -L .flxver ]; then
+# to be removed # PKGFULL=$(readlink .flxver)
+# to be removed #else
+# to be removed # PKGFULL=$(basename $(pwd))
+# to be removed #fi
+# to be removed #
+# to be removed #PKGRADIX=$(get_pkg_radix $PKGFULL)
+# to be removed #PKGVER=$(get_pkg_ver $PKGFULL)
+# to be removed #
+# to be removed #if [ -z "$DISTVER" ] && echo $PKGFULL | grep -q -- "-flx\." ; then
+# to be removed # DISTVER=$(get_build_num $PKGFULL)
+# to be removed #fi
+# to be removed #
+# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGFULL* |tail -1)}
+# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGRADIX-$PKGVER-* |tail -1)}
+# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGRADIX-$PKGVER* |tail -1)}
+# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGRADIX-* |tail -1)}
+# to be removed #
+# to be removed #
+# to be removed #
+# to be removed ## now process the destination parameters
+# to be removed #
+# to be removed #if [ -L .flxver ]; then
+# to be removed # NEWPKGFULL=$(readlink .flxver)
+# to be removed #else
+# to be removed # NEWPKGFULL=$(basename $(pwd))
+# to be removed #fi
+# to be removed #
+# to be removed #NEWPKGRADIX=$(get_pkg_radix $NEWPKGFULL)
+# to be removed #NEWPKGVER=$(get_pkg_ver $NEWPKGFULL)
+# to be removed #NEWPKGVER=${NEWPKGVER:-$PKGVER}
+# to be removed #
+# to be removed #if [ -z "$NEWDISTVER" ] && echo $NEWPKGFULL | grep -q -- "-flx\." ; then
+# to be removed # NEWDISTVER=$(get_build_num $NEWPKGFULL)
+# to be removed #fi
+# to be removed #NEWDISTVER=${NEWDISTVER:-$DISTVER}
+# to be removed #
+# to be removed ## recompute the new package version
+# to be removed #NEWBASECFG=${NEWBASECFG:-$NEWPKGRADIX-$NEWPKGVER-$NEWDISTVER}
+# to be removed #
+
+
+# now this is rather simple : for nearly all actions, NEWPKGFULL is used as the
+# directory name for the new package. If it cannot be found, all actions except
+# info and newpkg will fail. So we have to do a newpkg before using a new dir.
+
+if [ ! -d "$CFGROOT/$NEARESTPKG" -a ! -f "$CFGROOT/$NEARESTPKG.$PKGSUFF" ]; then
+ echo "Config directory <$NEARESTPKG> (NEARESTPKG) does not exist, use 'newpkg' first."
+ exit 1
+fi
+
+# source configuration
+ROOTDIR=${ROOTDIR:-$(pwd)/${INSTNAME}}
+
+
+CURPKG=$NEARESTPKG
+PKGRADIX=$(get_pkg_radix $NEARESTPKG)
+PKGVER=$(get_pkg_ver $NEARESTPKG)
+if echo $NEARESTPKG | grep -q -- "-flx\." ; then
+ DISTVER=$(get_build_num $NEARESTPKG)
+ NEARESTPKG=$PKGRADIX-$PKGVER-$DISTVER
+else
+ DISTVER=
+ NEARESTPKG=$PKGRADIX-$PKGVER
+fi
+
+CFGDIR=$CFGROOT/$CURPKG
+CFGFILE=$CFGDIR/$PKGRADIX.$CFGSUFF
+
+echo "CFGFILE=$CFGFILE, PKGVER=$PKGVER, CFGDIR=$CFGDIR"
+
+exit 0
+
- if [ -z "$DISTVER" ]; then
- if echo $CFGFILE | grep -q -- "-flx\." ; then
- DISTVER=`echo $CFGFILE|sed 's/\(.*-\)\(flx.[0-9]\+\)\(.*\)/\2/'`
- else
- DISTVER='flx.1'
+
+if [ -n "$CFGFILE" ]; then
+ CFGDIR=$NEWCFGROOT/$NEWBASECFG
+ . $CFGFILE
+else
+ #CFGFILE=`find $CFGROOT/ -name "$pack[-_]*-${DISTVER:-*}-$FLXARCH.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1`
+ #CFGFILE=${CFGFILE:-`find $CFGROOT/ -name "$pack[-_]*-${DISTVER:-*}-*.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1`}
+ #CFGFILE=${CFGFILE:-`find $CFGROOT/ -name "$pack[-_]*.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1`}
+ #CFGFILE=${CFGFILE:-`find $CFGROOT/ -name "$pack.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1`}
+ CFGFILE=`find $CFGROOT/ -maxdepth 1 -type d -name "$pack[-_]*-${DISTVER:-*}-pkg"|sed -e "s/-pkg\$//"|sort|tail -1`
+ CFGFILE=${CFGFILE:-`find $CFGROOT/ -maxdepth 1 -type d -name "$pack[-_]*-pkg"|sed -e "s/-pkg\$//"|sort|tail -1`}
+ CFGFILE=${CFGFILE:-`find $CFGROOT/ -maxdepth 1 -type f -name "$pack[-_]*-${DISTVER:-*}-pkg.$PKGSUFF"|sed -e "s/-pkg\.$PKGSUFF\$//"|sort|tail -1`}
+ CFGFILE=${CFGFILE:-`find $CFGROOT/ -maxdepth 1 -type f -name "$pack[-_]*-pkg.$PKGSUFF"|sed -e "s/-pkg\.$PKGSUFF\$//"|sort|tail -1`}
+
+ # to be completed
+
+ if [ -z "$CFGFILE" ]; then
+ echo "CFGFILE not found. Cannot continue." >&2
+ exit 1
+ fi
+
+ if [ -d $CFGFILE ]; then
+ CFGROOT=`dirname $CFGFILE`
+ CFGDIR=`basename $CFGFILE`-pkg
+ CFGFILE=$CFGROOT/$CFGDIR/$pack.$CFGSUFF
+ else
+ CFGROOT=`dirname $CFGFILE`
+ CFGDIR=`basename $CFGFILE`-pkg
+ CFGFILE=$CFGROOT/$CFGDIR/$pack.$CFGSUFF
+ if [ ! -e $CFGROOT/$CFGDIR ]; then
+ echo "Opening package $CFGROOT/$CFGDIR.$PKGSUFF into $CFGROOT/$CFGDIR..."
+ mkdir -p $CFGROOT/$CFGDIR && tar -C $CFGROOT/$CFGDIR -Uxpf $CFGROOT/$CFGDIR.$PKGSUFF
+ if [ $? != 0 ]; then
+ echo "There was an error during this operation. You may have to manually clean $CFGROOT/$CFGDIR. Cannot continue !"
+ exit 1
+ else
+ echo "Done !"
+ fi
+ fi
+ fi
+
+ if [ -e "$CFGFILE" ]; then
+ . $CFGFILE
+ else
+ echo "CFGFILE ($CFGFILE) not found. Cannot continue." >&2
+ exit 1
+ fi
fi
- fi
- echo $packver | grep -q -- "-flx\."
- if [ $? != 0 ] ; then
- packver=$packver-$DISTVER
- fi
+ if [ -z "$DISTVER" ]; then
+ if echo $CFGFILE | grep -q -- "-flx\." ; then
+ DISTVER=`echo $CFGFILE|sed 's/\(.*-\)\(flx.[0-9]\+\)\(.*\)/\2/'`
+ else
+ DISTVER='flx.1'
+ fi
+ fi
- echo $packver | grep -q -- "-$FLXARCH\$"
- if [ $? != 0 ] ; then packver=$packver-$FLXARCH ; fi
-
- prefix=${packver%%[._-][0-9]*}
- suffix=${packver#$prefix[._-]}
- PKGVER=${suffix%-flx*}
- PKGRADIX=$prefix
- #echo "packver=$packver suffix=$suffix PKGVER=$PKGVER"
- if [ -z "$DISTVER" ]; then
- DISTVER=${suffix#$PKGVER-}
- if [ "$DISTVER" = "$PKGVER" ]; then
- DISTVER="flx.1"
- else
- DISTVER=${DISTVER%-*}
- fi
- fi
+ echo $packver | grep -q -- "-flx\."
+ if [ $? != 0 ] ; then
+ packver=$packver-$DISTVER
+ fi
- case "$FLXARCH" in
- i686) arch=i686 cpu=i686 basearch=i386 ;;
- i486) arch=i486 cpu=i486 basearch=i386 ;;
- i386) arch=i386 cpu=i386 basearch=i386 ;;
- *) arch=i586 cpu=i686 basearch=i386 ;;
- esac
+ echo $packver | grep -q -- "-$FLXARCH\$"
+ if [ $? != 0 ] ; then packver=$packver-$FLXARCH ; fi
+
+ prefix=${packver%%[._-][0-9]*}
+ suffix=${packver#$prefix[._-]}
+ PKGVER=${suffix%-flx*}
+ PKGRADIX=$prefix
+ #echo "packver=$packver suffix=$suffix PKGVER=$PKGVER"
+ if [ -z "$DISTVER" ]; then
+ DISTVER=${suffix#$PKGVER-}
+ if [ "$DISTVER" = "$PKGVER" ]; then
+ DISTVER="flx.1"
+ else
+ DISTVER=${DISTVER%-*}
+ fi
+ fi
- if [ -z "$FLXMAKE" ]; then
- FLXMAKE=make
- fi
+ case "$FLXARCH" in
+ i686) arch=i686 cpu=i686 basearch=i386 ;;
+ i486) arch=i486 cpu=i486 basearch=i386 ;;
+ i386) arch=i386 cpu=i386 basearch=i386 ;;
+ *) arch=i586 cpu=i686 basearch=i386 ;;
+ esac
+
+ if [ -z "$FLXMAKE" ]; then
+ FLXMAKE=make
+ fi
- if [ -z "$PATCH_LIST" ]; then
- PATCH_LIST=${CFGFILE%%.$CFGSUFF}.diff
- if [ ! -e "$PATCH_LIST" ]; then
- unset PATCH_LIST
+ if [ -z "$PATCH_LIST" ]; then
+ PATCH_LIST=${CFGFILE%%.$CFGSUFF}.diff
+ if [ ! -e "$PATCH_LIST" ]; then
+ unset PATCH_LIST
+ fi
fi
- fi
- export DISTVER PKGRADIX PKGVER FLXMAKE PATCH_LIST FILE_LIST
+ export DISTVER PKGRADIX PKGVER FLXMAKE PATCH_LIST FILE_LIST
- if declare -f pre_$type > /dev/null ; then ( pre_$type ) ; fi
- if [ $? != 0 ] ; then exit ; fi
- if declare -f do_$type > /dev/null ; then ( do_$type ) ; fi
- if [ $? != 0 ] ; then exit ; fi
- if declare -f post_$type > /dev/null ; then ( post_$type ) ; fi
-
- fi
- # done
+ declare -f pre_$ACTION > /dev/null && ( pre_$ACTION )
+ [ $? != 0 ] && exit $?
+ declare -f do_$ACTION > /dev/null && ( do_$ACTION )
+ [ $? != 0 ] && exit $?
+ declare -f post_$ACTION > /dev/null && ( post_$ACTION )
+ [ $? != 0 ] && exit $?
+ fi
fi