Annotation of OSKit-Mach/kern/boot_script.c, revision 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.