Remove magic numbers in print_message_file
[yaboot.git] / second / cfg.c
index 62085e0db4402d846510c63182f01c31d0cb32fe..21db256305724d36371ed536d935768fa545c595 100644 (file)
@@ -1,21 +1,23 @@
-/* Handling and parsing of silo.conf
-   
-   Copyright (C) 1995 Werner Almesberger
-                1996 Jakub Jelinek
-   
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-   
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+/*
+ *  cfg.c - Handling and parsing of yaboot.conf
+ *
+ *  Copyright (C) 1995 Werner Almesberger
+ *                1996 Jakub Jelinek
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
 
 #include "setjmp.h"
 #include "stdarg.h"
@@ -26,6 +28,8 @@
 
 /* Imported functions */
 extern int strcasecmp(const char *s1, const char *s2);
+extern int strncasecmp(const char *cs, const char *ct, size_t n);
+extern char bootoncelabel[1024];
 
 typedef enum {
      cft_strg, cft_flag, cft_end
@@ -37,7 +41,7 @@ typedef struct {
      void *data;
 } CONFIG;
 
-#define MAX_TOKEN 200
+#define MAX_TOKEN 511
 #define MAX_VAR_NAME MAX_TOKEN
 #define EOF -1
 
@@ -88,7 +92,6 @@ CONFIG cf_image[] =
      {cft_flag, "pause-after", NULL},
      {cft_strg, "pause-message", NULL},
      {cft_flag, "novideo", NULL},
-     {cft_strg, "sysmap", NULL},
      {cft_end, NULL, NULL}};
 
 static char flag_set;
@@ -99,10 +102,12 @@ static char *currp = NULL;
 static char *endp = NULL;
 static char *file_name = NULL;
 static CONFIG *curr_table = cf_options;
+static int ignore_entry;
 static jmp_buf env;
 
 static struct IMAGES {
      CONFIG table[sizeof (cf_image) / sizeof (cf_image[0])];
+     int obsolete;
      struct IMAGES *next;
 } *images = NULL;
 
@@ -275,6 +280,16 @@ static int cfg_next (char **item, char **value)
      return 1;
 }
 
+static char *cfg_get_strg_i (CONFIG * table, char *item)
+{
+     CONFIG *walk;
+
+     for (walk = table; walk->type != cft_end; walk++)
+          if (walk->name && !strcasecmp (walk->name, item))
+               return walk->data;
+     return 0;
+}
+
 #if 0
 // The one and only call to this procedure is commented out
 // below, so we don't need this unless we decide to use it again.
@@ -285,13 +300,85 @@ static void cfg_return (char *item, char *value)
 }
 #endif
 
+static int match_arch(const char *name)
+{
+       static prom_handle root;
+       static char model[256], *p;
+
+       if (!root) {
+               if (!(root = prom_finddevice("/")))
+                       return 0;
+       }
+
+       if (!model[0]) {
+               if (!prom_getprop(root, "compatible", model, sizeof(model)))
+                       return 0;
+       }
+
+       for (p = model; *p; p += strlen(p) + 1) {
+               if (!strcasecmp(p, name))
+                       return 1;
+       }
+
+       return 0;
+}
+
+static void check_for_obsolete(const char *label)
+{
+       struct IMAGES *p;
+       char *cur_label;
+
+       /* Make sure our current entry isn't obsolete (ignored) */
+       for (p = images; p; p = p->next) {
+               if (curr_table == p->table && p->obsolete)
+                       return;
+       }
+
+       for (p = images; p; p = p->next) {
+               if (curr_table == p->table)
+                       continue;
+
+               cur_label = cfg_get_strg_i (p->table, "label");
+               if (!cur_label)
+                       cur_label = cfg_get_strg_i (p->table, "image");
+
+               if (!cur_label)
+                       continue;
+
+               if (!strcasecmp(cur_label, label))
+                       p->obsolete = 1;
+       }
+}
+
 static int cfg_set (char *item, char *value)
 {
      CONFIG *walk;
 
-     if (!strcasecmp (item, "image")) {
+     if (!strncasecmp (item, "image", 5)) {
          struct IMAGES **p = &images;
+         int ignore = 0;
+
+         if (item[5] == '[' && item[strlen(item) - 1] == ']') {
+               char *s, *q = item;
 
+               /* Get rid of braces */
+               item[strlen(item) - 1] = 0;
+               item[5] = 0;
+
+               for (s = item + 6; q; s = q) {
+                       q = strchr(s, '|');
+                       if (q)
+                               *q++ = 0;
+
+                       if (match_arch(s))
+                               goto cfg_set_cont;
+                }
+               /* This just creates an unused table. It will get ignored */
+               ignore = 1;
+         } else if (item[5])
+                goto cfg_set_redo;
+
+cfg_set_cont:
          while (*p)
               p = &((*p)->next);
          *p = (struct IMAGES *)malloc (sizeof (struct IMAGES));
@@ -300,9 +387,12 @@ static int cfg_set (char *item, char *value)
               return -1;
          }
          (*p)->next = 0;
+         (*p)->obsolete = ignore;
          curr_table = ((*p)->table);
          memcpy (curr_table, cf_image, sizeof (cf_image));
      }
+
+cfg_set_redo:
      for (walk = curr_table; walk->type != cft_end; walk++) {
          if (walk->name && !strcasecmp (walk->name, item)) {
               if (value && walk->type != cft_strg)
@@ -310,6 +400,8 @@ static int cfg_set (char *item, char *value)
               else if (!value && walk->type == cft_strg)
                    cfg_warn ("Value expected for '%s'", walk->name);
               else {
+                   if (!strcasecmp (item, "label"))
+                        check_for_obsolete(value);
                    if (walk->data)
                         cfg_warn ("Duplicate entry '%s'", walk->name);
                    if (walk->type == cft_flag)
@@ -320,12 +412,39 @@ static int cfg_set (char *item, char *value)
               break;
          }
      }
+
      if (walk->type != cft_end)
          return 1;
-//    cfg_return (item, value);
+
+     //cfg_return (item, value);
+
      return 0;
 }
 
+static int cfg_reset ()
+{
+    CONFIG *walk;
+#if DEBUG
+    prom_printf("Resetting image table\n");
+#endif
+    line_num = 0;
+    images = NULL;
+    curr_table = NULL;
+    curr_table = cf_options;
+    for (walk = curr_table; walk->type != cft_end; walk++) {
+#if DEBUG
+        prom_printf("ItemA %s = %s\n", walk->name, walk->data);
+#endif
+        if (walk->data != NULL)
+            walk->data = NULL;
+#if DEBUG
+        prom_printf("ItemB %s = %s\n\n", walk->name, walk->data);
+#endif
+    }
+
+    return 0;
+}
+
 int cfg_parse (char *cfg_file, char *buff, int len)
 {
      char *item, *value;
@@ -334,6 +453,8 @@ int cfg_parse (char *cfg_file, char *buff, int len)
      currp = buff;
      endp = currp + len;
 
+     cfg_reset();
+
      if (setjmp (env))
          return -1;
      while (1) {
@@ -342,22 +463,12 @@ int cfg_parse (char *cfg_file, char *buff, int len)
          if (!cfg_set (item, value)) {
 #if DEBUG
               prom_printf("Can't set item %s to value %s\n", item, value);
-#endif     
+#endif
          }
          free (item);
      }
 }
 
-static char *cfg_get_strg_i (CONFIG * table, char *item)
-{
-     CONFIG *walk;
-
-     for (walk = table; walk->type != cft_end; walk++)
-         if (walk->name && !strcasecmp (walk->name, item))
-              return walk->data;
-     return 0;
-}
-
 char *cfg_get_strg (char *image, char *item)
 {
      struct IMAGES *p;
@@ -367,6 +478,9 @@ char *cfg_get_strg (char *image, char *item)
      if (!image)
          return cfg_get_strg_i (cf_options, item);
      for (p = images; p; p = p->next) {
+         if (p->obsolete)
+                 continue;
+
          label = cfg_get_strg_i (p->table, "label");
          if (!label) {
               label = cfg_get_strg_i (p->table, "image");
@@ -394,10 +508,16 @@ static int printl_count = 0;
 static void printlabel (char *label, int defflag)
 {
      int len = strlen (label);
+     char a = ' ';
 
      if (!printl_count)
          prom_printf ("\n");
-     prom_printf ("%s %s",defflag?"*":" ", label);
+     switch (defflag) {
+         case 1:  a='*'; break;
+         case 2:  a='&'; break;
+         default: a=' '; break;
+     }
+     prom_printf ("%c %s", a, label);
      while (len++ < 25)
          prom_putchar (' ');
      printl_count++;
@@ -415,6 +535,9 @@ void cfg_print_images (void)
 
      printl_count = 0;
      for (p = images; p; p = p->next) {
+         if (p->obsolete)
+                 continue;
+
          label = cfg_get_strg_i (p->table, "label");
          if (!label) {
               label = cfg_get_strg_i (p->table, "image");
@@ -422,7 +545,9 @@ void cfg_print_images (void)
               if (alias)
                    label = alias + 1;
          }
-         if(!strcmp(ret,label))
+         if(!strcmp(bootoncelabel,label))
+              defflag=2;
+         else if(!strcmp(ret,label))
               defflag=1;
          else
               defflag=0;
@@ -437,15 +562,21 @@ void cfg_print_images (void)
 char *cfg_get_default (void)
 {
      char *label;
+     struct IMAGES *p;
      char *ret = cfg_get_strg_i (cf_options, "default");
 
      if (ret)
          return ret;
      if (!images)
          return 0;
-     ret = cfg_get_strg_i (images->table, "label");
+
+     for (p = images; p && p->obsolete; p = p->next);
+     if (!p)
+            return 0;
+
+     ret = cfg_get_strg_i (p->table, "label");
      if (!ret) {
-         ret = cfg_get_strg_i (images->table, "image");
+         ret = cfg_get_strg_i (p->table, "image");
          label = strrchr (ret, '/');
          if (label)
               ret = label + 1;
@@ -453,9 +584,46 @@ char *cfg_get_default (void)
      return ret;
 }
 
-/* 
+/*
+ * cfg_set_default_by_mac ()
+ * return 1 if the default cf_option was changed to label with the MAC addr
+ * return 0 if not changed
+ */
+int cfg_set_default_by_mac (char *mac_addr)
+{
+     CONFIG *walk;
+     struct IMAGES *tmp;
+     char * label = NULL;
+     int haslabel = 0;
+
+     /* check if there is an image label equal to mac_addr */
+     for (tmp = images; tmp; tmp = tmp->next) {
+        label = cfg_get_strg_i (tmp->table, "label");
+        if (!strcmp(label,mac_addr)){
+            haslabel = 1;
+        }
+     }
+
+     if (!haslabel)
+         return 0;
+     else {
+         /*
+          * if there is an image label equal to mac_addr, change the default
+          * cf_options to this image label
+          */
+         for (walk = cf_options; walk->type != cft_end; walk++) {
+             if (!strcasecmp(walk->name,"default")) {
+                 walk->data = mac_addr;
+                 return 1;
+             }
+         }
+         return 0;
+     }
+}
+
+/*
  * Local variables:
- * c-file-style: "K&R"
+ * c-file-style: "k&r"
  * c-basic-offset: 5
  * End:
  */