Annotation of OSKit-Mach/kern/boot_script.c, revision 1.1.1.1

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