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