Annotation of Gnu-Mach/kern/boot_script.c, revision 1.1.1.3

1.1       root        1: /* Boot script parser for Mach.  */
                      2: 
                      3: /* Written by Shantanu Goel ([email protected]).  */
                      4: 
                      5: #include <mach/mach_types.h>
                      6: #include <string.h>
                      7: #include "boot_script.h"
                      8: 
                      9: 
                     10: /* This structure describes a symbol.  */
                     11: struct sym
                     12: {
                     13:   /* Symbol name.  */
                     14:   const char *name;
                     15: 
                     16:   /* Type of value returned by function.  */
                     17:   int type;
                     18: 
                     19:   /* Symbol value.  */
1.1.1.2   root       20:   long val;
1.1       root       21: 
                     22:   /* For function symbols; type of value returned by function.  */
                     23:   int ret_type;
                     24: 
                     25:   /* For function symbols; if set, execute function at the time
                     26:      of command execution, not during parsing.  A function with
                     27:      this field set must also have `no_arg' set.  Also, the function's
                     28:      `val' argument will always be NULL.  */
                     29:   int run_on_exec;
                     30: };
                     31: 
                     32: /* Additional values symbols can take.
                     33:    These are only used internally.  */
                     34: #define VAL_SYM                10      /* symbol table entry */
                     35: #define VAL_FUNC       11      /* function pointer */
                     36: 
                     37: /* This structure describes an argument.  */
                     38: struct arg
                     39: {
                     40:   /* Argument text copied verbatim.  0 if none.  */
                     41:   char *text;
                     42: 
                     43:   /* Type of value assigned.  0 if none.  */
                     44:   int type;
                     45: 
                     46:   /* Argument value.  */
1.1.1.2   root       47:   long val;
1.1       root       48: };
                     49: 
                     50: /* List of commands.  */
                     51: static struct cmd **cmds = 0;
                     52: 
                     53: /* Amount allocated for `cmds'.  */
                     54: static int cmds_alloc = 0;
                     55: 
                     56: /* Next available slot in `cmds'.  */
                     57: static int cmds_index = 0;
                     58: 
                     59: /* Symbol table.  */
                     60: static struct sym **symtab = 0;
                     61: 
                     62: /* Amount allocated for `symtab'.  */
                     63: static int symtab_alloc = 0;
                     64: 
                     65: /* Next available slot in `symtab'.  */
                     66: static int symtab_index = 0;
                     67: 
                     68: /* Create a task and suspend it.  */
                     69: static int
1.1.1.2   root       70: create_task (struct cmd *cmd, long *val)
1.1       root       71: {
                     72:   int err = boot_script_task_create (cmd);
1.1.1.2   root       73:   *val = (long) cmd->task;
1.1       root       74:   return err;
                     75: }
                     76: 
                     77: /* Resume a task.  */
                     78: static int
1.1.1.3 ! root       79: resume_task (struct cmd *cmd, const long *val)
1.1       root       80: {
                     81:   return boot_script_task_resume (cmd);
                     82: }
                     83: 
                     84: /* Resume a task when the user hits return.  */
                     85: static int
1.1.1.3 ! root       86: prompt_resume_task (struct cmd *cmd, const long *val)
1.1       root       87: {
                     88:   return boot_script_prompt_task_resume (cmd);
                     89: }
                     90: 
                     91: /* List of builtin symbols.  */
                     92: static struct sym builtin_symbols[] =
                     93: {
1.1.1.2   root       94:   { "task-create", VAL_FUNC, (long) create_task, VAL_TASK, 0 },
                     95:   { "task-resume", VAL_FUNC, (long) resume_task, VAL_NONE, 1 },
                     96:   { "prompt-task-resume", VAL_FUNC, (long) prompt_resume_task, VAL_NONE, 1 },
1.1       root       97: };
                     98: #define NUM_BUILTIN (sizeof (builtin_symbols) / sizeof (builtin_symbols[0]))
                     99: 
                    100: /* Free CMD and all storage associated with it.
                    101:    If ABORTING is set, terminate the task associated with CMD,
                    102:    otherwise just deallocate the send right.  */
                    103: static void
                    104: free_cmd (struct cmd *cmd, int aborting)
                    105: {
                    106:   if (cmd->task)
                    107:     boot_script_free_task (cmd->task, aborting);
                    108:   if (cmd->args)
                    109:     {
                    110:       int i;
                    111:       for (i = 0; i < cmd->args_index; i++)
                    112:        boot_script_free (cmd->args[i], sizeof *cmd->args[i]);
                    113:       boot_script_free (cmd->args, sizeof cmd->args[0] * cmd->args_alloc);
                    114:     }
                    115:   if (cmd->exec_funcs)
                    116:     boot_script_free (cmd->exec_funcs,
                    117:                      sizeof cmd->exec_funcs[0] * cmd->exec_funcs_alloc);
                    118:   boot_script_free (cmd, sizeof *cmd);
                    119: }
                    120: 
                    121: /* Free all storage allocated by the parser.
                    122:    If ABORTING is set, terminate all tasks.  */
                    123: static void
                    124: cleanup (int aborting)
                    125: {
                    126:   int i;
                    127: 
                    128:   for (i = 0; i < cmds_index; i++)
                    129:     free_cmd (cmds[i], aborting);
                    130:   boot_script_free (cmds, sizeof cmds[0] * cmds_alloc);
                    131:   cmds = 0;
                    132:   cmds_index = cmds_alloc = 0;
                    133: 
                    134:   for (i = 0; i < symtab_index; i++)
                    135:     boot_script_free (symtab[i], sizeof *symtab[i]);
                    136:   boot_script_free (symtab, sizeof symtab[0] * symtab_alloc);
                    137:   symtab = 0;
                    138:   symtab_index = symtab_alloc = 0;
                    139: }
                    140: 
                    141: /* Add PTR to the list of pointers PTR_LIST, which
                    142:    currently has ALLOC amount of space allocated to it, and
                    143:    whose next available slot is INDEX.  If more space
                    144:    needs to to allocated, INCR is the amount by which
                    145:    to increase it.  Return 0 on success, non-zero otherwise.  */
                    146: static int
                    147: add_list (void *ptr, void ***ptr_list, int *alloc, int *index, int incr)
                    148: {
                    149:   if (*index == *alloc)
                    150:     {
                    151:       void **p;
                    152: 
                    153:       *alloc += incr;
                    154:       p = boot_script_malloc (*alloc * sizeof (void *));
                    155:       if (! p)
                    156:        {
                    157:          *alloc -= incr;
                    158:          return 1;
                    159:        }
                    160:       if (*ptr_list)
                    161:        {
                    162:          memcpy (p, *ptr_list, *index * sizeof (void *));
                    163:          boot_script_free (*ptr_list, (*alloc - incr) * sizeof (void *));
                    164:        }
                    165:       *ptr_list = p;
                    166:     }
                    167:   *(*ptr_list + *index) = ptr;
                    168:   *index += 1;
                    169:   return 0;
                    170: }
                    171: 
                    172: /* Create an argument with TEXT, value type TYPE, and value VAL.
                    173:    Add the argument to the argument list of CMD.  */
                    174: static struct arg *
                    175: add_arg (struct cmd *cmd, char *text, int type, int val)
                    176: {
                    177:   struct arg *arg;
                    178: 
                    179:   arg = boot_script_malloc (sizeof (struct arg));
                    180:   if (arg)
                    181:     {
                    182:       arg->text = text;
                    183:       arg->type = type;
                    184:       arg->val = val;
                    185:       if (add_list (arg, (void ***) &cmd->args,
                    186:                    &cmd->args_alloc, &cmd->args_index, 5))
                    187:        {
                    188:          boot_script_free (arg, sizeof *arg);
                    189:          return 0;
                    190:        }
                    191:     }
                    192:   return arg;
                    193: }
                    194: 
                    195: /* Search for the symbol NAME in the symbol table.  */
                    196: static struct sym *
                    197: sym_lookup (const char *name)
                    198: {
                    199:   int i;
                    200: 
                    201:   for (i = 0; i < symtab_index; i++)
                    202:     if (! strcmp (name, symtab[i]->name))
                    203:       return symtab[i];
                    204:   return 0;
                    205: }
                    206: 
                    207: /* Create an entry for symbol NAME in the symbol table.  */
                    208: static struct sym *
                    209: sym_enter (const char *name)
                    210: {
                    211:   struct sym *sym;
                    212: 
                    213:   sym = boot_script_malloc (sizeof (struct sym));
                    214:   if (sym)
                    215:     {
                    216:       memset (sym, 0, sizeof (struct sym));
                    217:       sym->name = name;
                    218:       if (add_list (sym, (void ***) &symtab, &symtab_alloc, &symtab_index, 20))
                    219:        {
                    220:          boot_script_free (sym, sizeof *sym);
                    221:          return 0;
                    222:        }
                    223:     }
                    224:   return sym;
                    225: }
                    226: 
                    227: /* Parse the command line CMDLINE.  */
                    228: int
                    229: boot_script_parse_line (void *hook, char *cmdline)
                    230: {
                    231:   char *p, *q;
                    232:   int error;
                    233:   struct cmd *cmd;
                    234:   struct arg *arg;
                    235: 
                    236:   /* Extract command name.  Ignore line if it lacks a command.  */
                    237:   for (p = cmdline; *p == ' ' || *p == '\t'; p++)
                    238:     ;
                    239:   if (*p == '#')
                    240:     /* Ignore comment line.  */
                    241:     return 0;
                    242: 
                    243: #if 0
                    244:   if (*p && *p != ' ' && *p != '\t' && *p != '\n')
                    245:     {
                    246:       printf ("(bootstrap): %s\n", cmdline);
                    247:     }
                    248: #endif
                    249: 
                    250:   for (q = p; *q && *q != ' ' && *q != '\t' && *q != '\n'; q++)
                    251:     ;
                    252:   if (p == q)
                    253:       return 0;
                    254: 
                    255:   *q = '\0';
                    256: 
                    257:   /* Allocate a command structure.  */
                    258:   cmd = boot_script_malloc (sizeof (struct cmd));
                    259:   if (! cmd)
                    260:     return BOOT_SCRIPT_NOMEM;
                    261:   memset (cmd, 0, sizeof (struct cmd));
                    262:   cmd->hook = hook;
                    263:   cmd->path = p;
                    264:   p = q + 1;
                    265: 
                    266:   for (arg = 0;;)
                    267:     {
                    268:       if (! arg)
                    269:        {
                    270:          /* Skip whitespace.  */
                    271:          while (*p == ' ' || *p == '\t')
                    272:            p++;
                    273: 
                    274:          /* End of command line.  */
                    275:          if (! *p || *p == '\n')
                    276:            {
                    277:              /* Add command to list.  */
                    278:              if (add_list (cmd, (void ***) &cmds,
                    279:                            &cmds_alloc, &cmds_index, 10))
                    280:                {
                    281:                  error = BOOT_SCRIPT_NOMEM;
                    282:                  goto bad;
                    283:                }
                    284:              return 0;
                    285:            }
                    286:        }
                    287: 
                    288:       /* Look for a symbol.  */
                    289:       if (arg || (*p == '$' && (*(p + 1) == '{' || *(p + 1) == '(')))
                    290:        {
                    291:          char end_char = (*(p + 1) == '{') ? '}' : ')';
                    292:          struct sym *sym = 0;
                    293: 
                    294:          for (p += 2;;)
                    295:            {
                    296:              char c;
1.1.1.2   root      297:              int i, type;
                    298:              long val;
1.1       root      299:              struct sym *s;
                    300: 
                    301:              /* Parse symbol name.  */
                    302:              for (q = p; *q && *q != '\n' && *q != end_char && *q != '='; q++)
                    303:                ;
                    304:              if (p == q || ! *q || *q == '\n'
                    305:                  || (end_char == '}' && *q != '}'))
                    306:                {
                    307:                  error = BOOT_SCRIPT_SYNTAX_ERROR;
                    308:                  goto bad;
                    309:                }
                    310:              c = *q;
                    311:              *q = '\0';
                    312: 
                    313:              /* See if this is a builtin symbol.  */
                    314:              for (i = 0; i < NUM_BUILTIN; i++)
                    315:                if (! strcmp (p, builtin_symbols[i].name))
                    316:                  break;
                    317: 
                    318:              if (i < NUM_BUILTIN)
                    319:                s = &builtin_symbols[i];
                    320:              else
                    321:                {
                    322:                  /* Look up symbol in symbol table.
                    323:                     If no entry exists, create one.  */
                    324:                  s = sym_lookup (p);
                    325:                  if (! s)
                    326:                    {
                    327:                      s = sym_enter (p);
                    328:                      if (! s)
                    329:                        {
                    330:                          error = BOOT_SCRIPT_NOMEM;
                    331:                          goto bad;
                    332:                        }
                    333:                    }
                    334:                }
                    335: 
                    336:              /* Only values are allowed in ${...} constructs.  */
                    337:              if (end_char == '}' && s->type == VAL_FUNC)
                    338:                return BOOT_SCRIPT_INVALID_SYM;
                    339: 
                    340:              /* Check that assignment is valid.  */
                    341:              if (c == '=' && s->type == VAL_FUNC)
                    342:                {
                    343:                  error = BOOT_SCRIPT_INVALID_ASG;
                    344:                  goto bad;
                    345:                }
                    346: 
                    347:              /* For function symbols, execute the function.  */
                    348:              if (s->type == VAL_FUNC)
                    349:                {
                    350:                  if (! s->run_on_exec)
                    351:                    {
                    352:                      (error
1.1.1.2   root      353:                       = ((*((int (*) (struct cmd *, long *)) s->val))
1.1       root      354:                          (cmd, &val)));
                    355:                      if (error)
                    356:                        goto bad;
                    357:                      type = s->ret_type;
                    358:                    }
                    359:                  else
                    360:                    {
                    361:                      if (add_list (s, (void ***) &cmd->exec_funcs,
                    362:                                    &cmd->exec_funcs_alloc,
                    363:                                    &cmd->exec_funcs_index, 5))
                    364:                        {
                    365:                          error = BOOT_SCRIPT_NOMEM;
                    366:                          goto bad;
                    367:                        }
                    368:                      type = VAL_NONE;
                    369:                      goto out;
                    370:                    }
                    371:                }
                    372:              else if (s->type == VAL_NONE)
                    373:                {
                    374:                  type = VAL_SYM;
1.1.1.2   root      375:                  val = (long) s;
1.1       root      376:                }
                    377:              else
                    378:                {
                    379:                  type = s->type;
                    380:                  val = s->val;
                    381:                }
                    382: 
                    383:              if (sym)
                    384:                {
                    385:                  sym->type = type;
                    386:                  sym->val = val;
                    387:                }
                    388:              else if (arg)
                    389:                {
                    390:                  arg->type = type;
                    391:                  arg->val = val;
                    392:                }
                    393: 
                    394:            out:
                    395:              p = q + 1;
                    396:              if (c == end_char)
                    397:                {
                    398:                  /* Create an argument if necessary.
                    399:                     We create an argument if the symbol appears
                    400:                     in the expression by itself.
                    401: 
                    402:                     NOTE: This is temporary till the boot filesystem
                    403:                     servers support arguments.  When that happens,
                    404:                     symbol values will only be printed if they're
                    405:                     associated with an argument.  */
                    406:                  if (! arg && end_char == '}')
                    407:                    {
                    408:                      if (! add_arg (cmd, 0, type, val))
                    409:                        {
                    410:                          error = BOOT_SCRIPT_NOMEM;
                    411:                          goto bad;
                    412:                        }
                    413:                    }
                    414:                  arg = 0;
                    415:                  break;
                    416:                }
                    417:              if (s->type != VAL_FUNC)
                    418:                sym = s;
                    419:            }
                    420:        }
                    421:       else
                    422:        {
                    423:          char c;
                    424: 
                    425:          /* Command argument; just copy the text.  */
                    426:          for (q = p;; q++)
                    427:            {
                    428:              if (! *q || *q == ' ' || *q == '\t' || *q == '\n')
                    429:                break;
                    430:              if (*q == '$' && *(q + 1) == '{')
                    431:                break;
                    432:            }
                    433:          c = *q;
                    434:          *q = '\0';
                    435: 
                    436:          /* Add argument to list.  */
                    437:          arg = add_arg (cmd, p, VAL_NONE, 0);
                    438:          if (! arg)
                    439:            {
                    440:              error = BOOT_SCRIPT_NOMEM;
                    441:              goto bad;
                    442:            }
                    443:          if (c == '$')
                    444:            p = q;
                    445:          else
                    446:            {
                    447:              if (c)
                    448:                p = q + 1;
                    449:              else
                    450:                p = q;
                    451:              arg = 0;
                    452:            }
                    453:        }
                    454:     }
                    455: 
                    456: 
                    457:  bad:
                    458:   free_cmd (cmd, 1);
                    459:   cleanup (1);
                    460:   return error;
                    461: }
                    462: 
                    463: /* Ensure that the command line buffer can accommodate LEN bytes of space.  */
                    464: #define CHECK_CMDLINE_LEN(len) \
                    465: { \
                    466:   if (cmdline_alloc - cmdline_index < len) \
                    467:     { \
                    468:       char *ptr; \
                    469:       int alloc, i; \
                    470:       alloc = cmdline_alloc + len - (cmdline_alloc - cmdline_index) + 100; \
                    471:       ptr = boot_script_malloc (alloc); \
                    472:       if (! ptr) \
                    473:        { \
                    474:          error = BOOT_SCRIPT_NOMEM; \
                    475:          goto done; \
                    476:        } \
                    477:       memcpy (ptr, cmdline, cmdline_index); \
                    478:       for (i = 0; i < argc; ++i) \
                    479:        argv[i] = ptr + (argv[i] - cmdline); \
                    480:       boot_script_free (cmdline, cmdline_alloc); \
                    481:       cmdline = ptr; \
                    482:       cmdline_alloc = alloc; \
                    483:     } \
                    484: }
                    485: 
                    486: /* Execute commands previously parsed.  */
                    487: int
1.1.1.3 ! root      488: boot_script_exec (void)
1.1       root      489: {
                    490:   int cmd_index;
                    491: 
                    492:   for (cmd_index = 0; cmd_index < cmds_index; cmd_index++)
                    493:     {
                    494:       char **argv, *cmdline;
                    495:       int i, argc, cmdline_alloc;
                    496:       int cmdline_index, error, arg_index;
                    497:       struct cmd *cmd = cmds[cmd_index];
                    498: 
                    499:       /* Skip command if it doesn't have an associated task.  */
                    500:       if (cmd->task == 0)
                    501:        continue;
                    502: 
                    503:       /* Allocate a command line and copy command name.  */
                    504:       cmdline_index = strlen (cmd->path) + 1;
                    505:       cmdline_alloc = cmdline_index + 100;
                    506:       cmdline = boot_script_malloc (cmdline_alloc);
                    507:       if (! cmdline)
                    508:        {
                    509:          cleanup (1);
                    510:          return BOOT_SCRIPT_NOMEM;
                    511:        }
                    512:       memcpy (cmdline, cmd->path, cmdline_index);
                    513: 
                    514:       /* Allocate argument vector.  */
                    515:       argv = boot_script_malloc (sizeof (char *) * (cmd->args_index + 2));
                    516:       if (! argv)
                    517:        {
                    518:          boot_script_free (cmdline, cmdline_alloc);
                    519:          cleanup (1);
                    520:          return BOOT_SCRIPT_NOMEM;
                    521:        }
                    522:       argv[0] = cmdline;
                    523:       argc = 1;
                    524: 
                    525:       /* Build arguments.  */
                    526:       for (arg_index = 0; arg_index < cmd->args_index; arg_index++)
                    527:        {
                    528:          struct arg *arg = cmd->args[arg_index];
                    529: 
                    530:          /* Copy argument text.  */
                    531:          if (arg->text)
                    532:            {
                    533:              int len = strlen (arg->text);
                    534: 
                    535:              if (arg->type == VAL_NONE)
                    536:                len++;
                    537:              CHECK_CMDLINE_LEN (len);
                    538:              memcpy (cmdline + cmdline_index, arg->text, len);
                    539:              argv[argc++] = &cmdline[cmdline_index];
                    540:              cmdline_index += len;
                    541:            }
                    542: 
                    543:          /* Add value of any symbol associated with this argument.  */
                    544:          if (arg->type != VAL_NONE)
                    545:            {
                    546:              char *p, buf[50];
                    547:              int len;
                    548:              mach_port_t name;
                    549: 
                    550:              if (arg->type == VAL_SYM)
                    551:                {
                    552:                  struct sym *sym = (struct sym *) arg->val;
                    553: 
                    554:                  /* Resolve symbol value.  */
                    555:                  while (sym->type == VAL_SYM)
                    556:                    sym = (struct sym *) sym->val;
                    557:                  if (sym->type == VAL_NONE)
                    558:                    {
                    559:                      error = BOOT_SCRIPT_UNDEF_SYM;
                    560:                      goto done;
                    561:                    }
                    562:                  arg->type = sym->type;
                    563:                  arg->val = sym->val;
                    564:                }
                    565: 
                    566:              /* Print argument value.  */
                    567:              switch (arg->type)
                    568:                {
                    569:                case VAL_STR:
                    570:                  p = (char *) arg->val;
                    571:                  len = strlen (p);
                    572:                  break;
                    573: 
                    574:                case VAL_TASK:
                    575:                case VAL_PORT:
                    576:                  if (arg->type == VAL_TASK)
                    577:                    /* Insert send right to task port.  */
                    578:                    error = boot_script_insert_task_port
                    579:                      (cmd, (task_t) arg->val, &name);
                    580:                  else
                    581:                    /* Insert send right.  */
                    582:                    error = boot_script_insert_right (cmd,
                    583:                                                      (mach_port_t) arg->val,
                    584:                                                      &name);
                    585:                  if (error)
                    586:                    goto done;
                    587: 
                    588:                  i = name;
                    589:                  p = buf + sizeof (buf);
                    590:                  len = 0;
                    591:                  do
                    592:                    {
                    593:                      *--p = i % 10 + '0';
                    594:                      len++;
                    595:                    }
                    596:                  while (i /= 10);
                    597:                  break;
                    598: 
                    599:                default:
                    600:                  error = BOOT_SCRIPT_BAD_TYPE;
                    601:                  goto done;
                    602:                }
                    603:              len++;
                    604:              CHECK_CMDLINE_LEN (len);
                    605:              memcpy (cmdline + cmdline_index, p, len - 1);
                    606:              *(cmdline + cmdline_index + len - 1) = '\0';
                    607:              if (! arg->text)
                    608:                  argv[argc++] = &cmdline[cmdline_index];
                    609:              cmdline_index += len;
                    610:            }
                    611:        }
                    612: 
                    613:       /* Terminate argument vector.  */
                    614:       argv[argc] = 0;
                    615: 
                    616:       /* Execute the command.  */
                    617:       if (boot_script_exec_cmd (cmd->hook, cmd->task, cmd->path,
                    618:                                argc, argv, cmdline, cmdline_index))
                    619:        {
                    620:          error = BOOT_SCRIPT_EXEC_ERROR;
                    621:          goto done;
                    622:        }
                    623: 
                    624:       error = 0;
                    625: 
                    626:     done:
                    627:       boot_script_free (cmdline, cmdline_alloc);
                    628:       boot_script_free (argv, sizeof (char *) * (cmd->args_index + 2));
                    629:       if (error)
                    630:        {
                    631:          cleanup (1);
                    632:          return error;
                    633:        }
                    634:     }
                    635: 
                    636:   for (cmd_index = 0; cmd_index < cmds_index; cmd_index++)
                    637:     {
                    638:       int i;
                    639:       struct cmd *cmd = cmds[cmd_index];
                    640: 
                    641:       /* Execute functions that want to be run on exec.  */
                    642:       for (i = 0; i < cmd->exec_funcs_index; i++)
                    643:        {
                    644:          struct sym *sym = cmd->exec_funcs[i];
                    645:          int error = ((*((int (*) (struct cmd *, int *)) sym->val))
                    646:                       (cmd, 0));
                    647:          if (error)
                    648:            {
                    649:              cleanup (1);
                    650:              return error;
                    651:            }
                    652:        }
                    653:     }
                    654: 
                    655:   cleanup (0);
                    656:   return 0;
                    657: }
                    658: 
                    659: /* Create an entry for the variable NAME with TYPE and value VAL,
                    660:    in the symbol table.  */
                    661: int
1.1.1.2   root      662: boot_script_set_variable (const char *name, int type, long val)
1.1       root      663: {
                    664:   struct sym *sym = sym_enter (name);
                    665: 
                    666:   if (sym)
                    667:     {
                    668:       sym->type = type;
                    669:       sym->val = val;
                    670:     }
                    671:   return sym ? 0 : 1;
                    672: }
                    673: 
                    674: 
                    675: /* Define the function NAME, which will return type RET_TYPE.  */
                    676: int
                    677: boot_script_define_function (const char *name, int ret_type,
                    678:                             int (*func) (const struct cmd *cmd, int *val))
                    679: {
                    680:   struct sym *sym = sym_enter (name);
                    681: 
                    682:   if (sym)
                    683:     {
                    684:       sym->type = VAL_FUNC;
1.1.1.2   root      685:       sym->val = (long) func;
1.1       root      686:       sym->ret_type = ret_type;
                    687:       sym->run_on_exec = ret_type == VAL_NONE;
                    688:     }
                    689:   return sym ? 0 : 1;
                    690: }
                    691: 
                    692: 
                    693: /* Return a string describing ERR.  */
                    694: char *
                    695: boot_script_error_string (int err)
                    696: {
                    697:   switch (err)
                    698:     {
                    699:     case BOOT_SCRIPT_NOMEM:
                    700:       return "no memory";
                    701: 
                    702:     case BOOT_SCRIPT_SYNTAX_ERROR:
                    703:       return "syntax error";
                    704: 
                    705:     case BOOT_SCRIPT_INVALID_ASG:
                    706:       return "invalid variable in assignment";
                    707: 
                    708:     case BOOT_SCRIPT_MACH_ERROR:
                    709:       return "mach error";
                    710: 
                    711:     case BOOT_SCRIPT_UNDEF_SYM:
                    712:       return "undefined symbol";
                    713: 
                    714:     case BOOT_SCRIPT_EXEC_ERROR:
                    715:       return "exec error";
                    716: 
                    717:     case BOOT_SCRIPT_INVALID_SYM:
                    718:       return "invalid variable in expression";
                    719: 
                    720:     case BOOT_SCRIPT_BAD_TYPE:
                    721:       return "invalid value type";
                    722:     }
                    723:   return 0;
                    724: }
                    725: 
                    726: #ifdef BOOT_SCRIPT_TEST
                    727: #include <stdio.h>
                    728: 
                    729: int
                    730: boot_script_exec_cmd (void *hook,
                    731:                      mach_port_t task, char *path, int argc,
                    732:                      char **argv, char *strings, int stringlen)
                    733: {
                    734:   int i;
                    735: 
                    736:   printf ("port = %d: ", (int) task);
                    737:   for (i = 0; i < argc; i++)
                    738:     printf ("%s ", argv[i]);
                    739:   printf ("\n");
                    740:   return 0;
                    741: }
                    742: 
                    743: void
                    744: main (int argc, char **argv)
                    745: {
                    746:   char buf[500], *p;
                    747:   int len;
                    748:   FILE *fp;
                    749:   mach_port_t host_port, device_port;
                    750: 
                    751:   if (argc < 2)
                    752:     {
                    753:       fprintf (stderr, "Usage: %s <script>\n", argv[0]);
                    754:       exit (1);
                    755:     }
                    756:   fp = fopen (argv[1], "r");
                    757:   if (! fp)
                    758:     {
                    759:       fprintf (stderr, "Can't open %s\n", argv[1]);
                    760:       exit (1);
                    761:     }
                    762:   host_port = 1;
                    763:   device_port = 2;
                    764:   boot_script_set_variable ("host-port", VAL_PORT, (int) host_port);
                    765:   boot_script_set_variable ("device-port", VAL_PORT, (int) device_port);
                    766:   boot_script_set_variable ("root-device", VAL_STR, (int) "hd0a");
                    767:   boot_script_set_variable ("boot-args", VAL_STR, (int) "-ad");
                    768:   p = buf;
                    769:   len = sizeof (buf);
                    770:   while (fgets (p, len, fp))
                    771:     {
                    772:       int i, err;
                    773: 
                    774:       i = strlen (p) + 1;
                    775:       err = boot_script_parse_line (0, p);
                    776:       if (err)
                    777:        {
                    778:          fprintf (stderr, "error %s\n", boot_script_error_string (err));
                    779:          exit (1);
                    780:        }
                    781:       p += i;
                    782:       len -= i;
                    783:     }
                    784:   boot_script_exec ();
                    785:   exit (0);
                    786: }
                    787: #endif /* BOOT_SCRIPT_TEST */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.