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