|
|
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 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.