From db1771cfbe08ee6b9eb39c398cd6b67e545b6770 Mon Sep 17 00:00:00 2001 From: marco_g Date: Sat, 13 Mar 2004 13:59:25 +0000 Subject: [PATCH] 2004-03-14 Marco Gerards * commands/boot.c: New file. * commands/cat.c: Likewise. * commands/cmp.c: Likewise. * commands/ls.c: Likewise. * commands/terminal.c: Likewise. * normal/command.c: Include and . (pupa_register_command): Changed interface to match the new argument parser. (pupa_command_execute): Changed (almost rewritten) so it uses pupa_split_command. Added support for setting variables using the syntax `foo=bar'. (rescue_command): Changed to work with the new argument parser. (terminal_command): Moved from here to commands/terminal.c. (set_command): New function. (unset_command): New function. (insmod_command): New function. (rmmod_command): New function. (lsmod_command): New function. (pupa_command_init): Don't initialize the command terminal anymore. Initialize the commands set, unset, insmod, rmmod and lsmod. * conf/i386-pc.rmk (kernel_img_SOURCES): Add kern/env.c. (kernel_img_HEADERS): Add arg.h and env.h. (pupa_mkimage_LDFLAGS): Add kern/env.c. (pupa_emu_SOURCES): Add kern/env.c, commands/ls.c, commands/terminal.c commands/boot.c commands/cmp.c commands/cat.c, normal/arg.c. (pkgdata_MODULES): Add ls.mod, boot.mod, cmp.mod, cat.mod and terminal.mod. (normal_mod_SOURCES): Add normal/arg.c and normal/arg.c. (boot_mod_SOURCES): New variable. (terminal_mod_SOURCES): Likewise. (ls_mod_SOURCES): Likewise. (cmp_mod_SOURCES): Likewise. (cat_mod_SOURCES): Likewise. * normal/arg.c: New file. * kern/env.c: Likewise. * include/pupa/arg.h: Likewise. * include/pupa/env.h: Likewise. * font/manager.c (font_command): Changed to match argument parsing interface changes. (PUPA_MOD_INIT): Likewise. * hello/hello.c (pupa_cmd_hello): Likewise. (PUPA_MOD_INIT): Likewise. * include/pupa/disk.h: Include . (pupa_print_partinfo): New prototype. * include/pupa/dl.h (pupa_dl_set_prefix): Prototype removed. (pupa_dl_get_prefix): Likewise. * include/pupa/misc.h: Include . (pupa_isgraph): New prototype. (pupa_isdigit): Likewise. (pupa_split_cmdline): Likewise. * include/pupa/normal.h: Include . (pupa_command): Changed the prototype of the member `func' to match the argument parsing interface. Added member `options'. (pupa_register_command): Updated to match function. (pupa_arg_parse): New prototype. (pupa_hello_init) [PUPA_UTIL]: New prototype. (pupa_hello_fini) [PUPA_UTIL]: Likewise. (pupa_ls_init) [PUPA_UTIL]: Likewise. (pupa_ls_fini) [PUPA_UTIL]: Likewise. (pupa_cat_init) [PUPA_UTIL]: Likewise. (pupa_cat_fini) [PUPA_UTIL]: Likewise. (pupa_boot_init) [PUPA_UTIL]: Likewise. (pupa_boot_fini) [PUPA_UTIL]: Likewise. (pupa_cmp_init) [PUPA_UTIL]: Likewise. (pupa_cmp_fini) [PUPA_UTIL]: Likewise. (pupa_terminal_init) [PUPA_UTIL]: Likewise. (pupa_terminal_fini) [PUPA_UTIL]: Likewise. * kern/disk.c: Include . (pupa_print_partinfo): New function. * kern/dl.c: Include . (pupa_dl_dir): Variable removed. (pupa_dl_load): Use the environment variable `prefix' instead of the variable pupa_dl_dir. (pupa_dl_set_prefix): Function removed. (pupa_dl_get_prefix): Likewise. * kern/i386/pc/init.c: Include . (pupa_machine_init): Use the environment variable `prefix' instead of using pupa_dl_set_prefix to set the prefix. * kern/main.c: Include . (pupa_set_root_dev): Use the environment variable `prefix' instead of using pupa_dl_get_prefix to get the prefix. * kern/misc.c: Include . (pupa_isdigit): New function. (pupa_isgraph): Likewise. (pupa_ftoa): Likewise. (pupa_vsprintf): Added support for printing values of the type `double'. Make it possible to format variable output when using formatting like `%1.2%f'. (pupa_split_cmdline): New function. * kern/rescue.c: Include . (next_word): Removed function. (pupa_rescue_cmd_prefix): Likewise. (pupa_rescue_cmd_set): New function. (pupa_rescue_cmd_unset): New function. (pupa_enter_rescue_mode): Use the `pupa_split_cmdline' function to split the command line instead of splitting it here. Added support for setting variables using the syntax `foo=bar'. Don't initialize the prefix command anymore. Initialized the set and unset commands. * normal/cmdline.c: Include . (pupa_tab_complete): Added prototypes for print_simple_completion, print_partition_completion, add_completion, iterate_commands, iterate_dev, iterate_part and iterate_dir. Moved code to print partition information from here to kern/disk.c. (pupa_cmdline_run): Don't check if the funtion exists anymore. * normal/main.c: Include . (pupa_rescue_cmd_normal): Use the environment variable `prefix' instead of using pupa_dl_get_prefix to get the prefix. * term/i386/pc/vga.c: Include . (check_vga_mem): Cast pointers to `void *' to silence a gcc warning. (pupa_vga_putchar) [! DEBUG_VGA]: Removed for this case. (pupa_vga_setcolor): Declare unused variables with `__attribute__ ((unused))' to silence a gcc warning. (pupa_vga_setcolor): Likewise. (debug_command): Changed to match argument parsing interface changes. * util/pupa-emu.c: Include . (options): Added 0's for unused fields to silence a gcc warning. (argp): Likewise. (main): Use the environment variable `prefix' instead of using pupa_dl_set_prefix to set the prefix. Initialize the commands ls, boot, cmp, cat and terminal. Finish the commands boot, cmp, cat and terminal. * util/i386/pc/getroot.c: Include . * util/misc.c: Include . (pupa_malloc): Rewritten so errors are correctly reported. (pupa_realloc): Likewise. (pupa_memalign): Likewise. (pupa_mm_init_region): Declare unused variables with `__attribute__ ((unused))' to silence a gcc warning. * normal/i386/setjmp.S: Remove tab at the end of the file to silence a gcc warning. * loader/i386/pc/linux.c (pupa_rescue_cmd_initrd): Declare unused variables with `__attribute__ ((unused))' to silence a gcc warning. * loader/i386/pc/multiboot.c (pupa_multiboot_unload): Make the local variable i unsigned to silence a gcc warning. * kern/term.c: Include . (pupa_more_lines): New variable. (pupa_more): Likewise. (pupa_putcode): When the pager is active pause at the end of every screen. (pupa_set_more): New function. * include/pupa/term.h (pupa_set_more): New prototype. --- ChangeLog | 154 ++++++++++++++++ commands/boot.c | 65 +++++++ commands/cat.c | 97 ++++++++++ commands/cmp.c | 124 +++++++++++++ commands/ls.c | 262 +++++++++++++++++++++++++++ commands/terminal.c | 99 +++++++++++ conf/i386-pc.mk | 314 ++++++++++++++++++++++++++++++-- conf/i386-pc.rmk | 35 +++- font/manager.c | 12 +- hello/hello.c | 10 +- include/grub/arg.h | 66 +++++++ include/grub/disk.h | 6 +- include/grub/dl.h | 2 - include/grub/env.h | 49 +++++ include/grub/misc.h | 6 + include/grub/normal.h | 27 ++- include/grub/term.h | 1 + kern/disk.c | 42 +++++ kern/dl.c | 18 +- kern/env.c | 209 ++++++++++++++++++++++ kern/i386/pc/init.c | 6 +- kern/main.c | 5 +- kern/misc.c | 332 +++++++++++++++++++++++++++++++++- kern/rescue.c | 148 +++++++++------- kern/term.c | 49 ++++- loader/i386/pc/linux.c | 3 +- loader/i386/pc/multiboot.c | 2 +- normal/arg.c | 354 +++++++++++++++++++++++++++++++++++++ normal/cmdline.c | 66 ++----- normal/command.c | 268 +++++++++++++++++++--------- normal/main.c | 3 +- term/i386/pc/vga.c | 16 +- util/grub-emu.c | 25 ++- util/i386/pc/getroot.c | 1 + util/misc.c | 16 +- 35 files changed, 2607 insertions(+), 285 deletions(-) create mode 100644 commands/boot.c create mode 100644 commands/cat.c create mode 100644 commands/cmp.c create mode 100644 commands/ls.c create mode 100644 commands/terminal.c create mode 100644 include/grub/arg.h create mode 100644 include/grub/env.h create mode 100644 kern/env.c create mode 100644 normal/arg.c diff --git a/ChangeLog b/ChangeLog index bc9dc2712..a76878006 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,157 @@ +2004-03-14 Marco Gerards + + * commands/boot.c: New file. + * commands/cat.c: Likewise. + * commands/cmp.c: Likewise. + * commands/ls.c: Likewise. + * commands/terminal.c: Likewise. + * normal/command.c: Include and . + (pupa_register_command): Changed interface to match the new + argument parser. + (pupa_command_execute): Changed (almost rewritten) so it uses + pupa_split_command. Added support for setting variables using the + syntax `foo=bar'. + (rescue_command): Changed to work with the new argument parser. + (terminal_command): Moved from here to commands/terminal.c. + (set_command): New function. + (unset_command): New function. + (insmod_command): New function. + (rmmod_command): New function. + (lsmod_command): New function. + (pupa_command_init): Don't initialize the command terminal + anymore. Initialize the commands set, unset, insmod, rmmod and + lsmod. + * conf/i386-pc.rmk (kernel_img_SOURCES): Add kern/env.c. + (kernel_img_HEADERS): Add arg.h and env.h. + (pupa_mkimage_LDFLAGS): Add kern/env.c. + (pupa_emu_SOURCES): Add kern/env.c, commands/ls.c, + commands/terminal.c commands/boot.c commands/cmp.c commands/cat.c, + normal/arg.c. + (pkgdata_MODULES): Add ls.mod, boot.mod, cmp.mod, cat.mod and + terminal.mod. + (normal_mod_SOURCES): Add normal/arg.c and normal/arg.c. + (boot_mod_SOURCES): New variable. + (terminal_mod_SOURCES): Likewise. + (ls_mod_SOURCES): Likewise. + (cmp_mod_SOURCES): Likewise. + (cat_mod_SOURCES): Likewise. + + * normal/arg.c: New file. + * kern/env.c: Likewise. + * include/pupa/arg.h: Likewise. + * include/pupa/env.h: Likewise. + * font/manager.c (font_command): Changed to match argument parsing + interface changes. + (PUPA_MOD_INIT): Likewise. + * hello/hello.c (pupa_cmd_hello): Likewise. + (PUPA_MOD_INIT): Likewise. + * include/pupa/disk.h: Include . + (pupa_print_partinfo): New prototype. + * include/pupa/dl.h (pupa_dl_set_prefix): Prototype removed. + (pupa_dl_get_prefix): Likewise. + * include/pupa/misc.h: Include . + (pupa_isgraph): New prototype. + (pupa_isdigit): Likewise. + (pupa_split_cmdline): Likewise. + * include/pupa/normal.h: Include . + (pupa_command): Changed the prototype of the member `func' to + match the argument parsing interface. Added member `options'. + (pupa_register_command): Updated to match function. + (pupa_arg_parse): New prototype. + (pupa_hello_init) [PUPA_UTIL]: New prototype. + (pupa_hello_fini) [PUPA_UTIL]: Likewise. + (pupa_ls_init) [PUPA_UTIL]: Likewise. + (pupa_ls_fini) [PUPA_UTIL]: Likewise. + (pupa_cat_init) [PUPA_UTIL]: Likewise. + (pupa_cat_fini) [PUPA_UTIL]: Likewise. + (pupa_boot_init) [PUPA_UTIL]: Likewise. + (pupa_boot_fini) [PUPA_UTIL]: Likewise. + (pupa_cmp_init) [PUPA_UTIL]: Likewise. + (pupa_cmp_fini) [PUPA_UTIL]: Likewise. + (pupa_terminal_init) [PUPA_UTIL]: Likewise. + (pupa_terminal_fini) [PUPA_UTIL]: Likewise. + * kern/disk.c: Include . + (pupa_print_partinfo): New function. + * kern/dl.c: Include . + (pupa_dl_dir): Variable removed. + (pupa_dl_load): Use the environment variable `prefix' instead of + the variable pupa_dl_dir. + (pupa_dl_set_prefix): Function removed. + (pupa_dl_get_prefix): Likewise. + * kern/i386/pc/init.c: Include . + (pupa_machine_init): Use the environment variable `prefix' instead of + using pupa_dl_set_prefix to set the prefix. + * kern/main.c: Include . + (pupa_set_root_dev): Use the environment variable `prefix' instead of + using pupa_dl_get_prefix to get the prefix. + * kern/misc.c: Include . + (pupa_isdigit): New function. + (pupa_isgraph): Likewise. + (pupa_ftoa): Likewise. + (pupa_vsprintf): Added support for printing values of the type + `double'. Make it possible to format variable output when using + formatting like `%1.2%f'. + (pupa_split_cmdline): New function. + * kern/rescue.c: Include . + (next_word): Removed function. + (pupa_rescue_cmd_prefix): Likewise. + (pupa_rescue_cmd_set): New function. + (pupa_rescue_cmd_unset): New function. + (pupa_enter_rescue_mode): Use the `pupa_split_cmdline' function to + split the command line instead of splitting it here. Added + support for setting variables using the syntax `foo=bar'. Don't + initialize the prefix command anymore. Initialized the set and + unset commands. + * normal/cmdline.c: Include . + (pupa_tab_complete): Added prototypes for print_simple_completion, + print_partition_completion, add_completion, iterate_commands, + iterate_dev, iterate_part and iterate_dir. Moved code to print + partition information from here to kern/disk.c. + (pupa_cmdline_run): Don't check if the funtion exists anymore. + * normal/main.c: Include . + (pupa_rescue_cmd_normal): Use the environment variable `prefix' + instead of using pupa_dl_get_prefix to get the prefix. + * term/i386/pc/vga.c: Include . + (check_vga_mem): Cast pointers to `void *' to silence a gcc + warning. + (pupa_vga_putchar) [! DEBUG_VGA]: Removed for this case. + (pupa_vga_setcolor): Declare unused variables with `__attribute__ + ((unused))' to silence a gcc warning. + (pupa_vga_setcolor): Likewise. + (debug_command): Changed to match argument parsing + interface changes. + * util/pupa-emu.c: Include . + (options): Added 0's for unused fields to silence a gcc warning. + (argp): Likewise. + (main): Use the environment variable `prefix' instead of using + pupa_dl_set_prefix to set the prefix. Initialize the commands ls, + boot, cmp, cat and terminal. Finish the commands boot, cmp, cat + and terminal. + + * util/i386/pc/getroot.c: Include . + * util/misc.c: Include . + (pupa_malloc): Rewritten so errors are correctly reported. + (pupa_realloc): Likewise. + (pupa_memalign): Likewise. + (pupa_mm_init_region): Declare unused variables with + `__attribute__ ((unused))' to silence a gcc warning. + * normal/i386/setjmp.S: Remove tab at the end of the file to + silence a gcc warning. + * loader/i386/pc/linux.c (pupa_rescue_cmd_initrd): Declare unused + variables with `__attribute__ ((unused))' to silence a gcc + warning. + * loader/i386/pc/multiboot.c (pupa_multiboot_unload): Make the + local variable i unsigned to silence a gcc warning. + + * kern/term.c: Include . + (pupa_more_lines): New variable. + (pupa_more): Likewise. + (pupa_putcode): When the pager is active pause at the end of every + screen. + (pupa_set_more): New function. + * include/pupa/term.h (pupa_set_more): New prototype. + + 2004-03-07 Yoshinori K. Okuji Now this project is GRUB 2 rather than PUPA. The location of diff --git a/commands/boot.c b/commands/boot.c new file mode 100644 index 000000000..f9fec1ef7 --- /dev/null +++ b/commands/boot.c @@ -0,0 +1,65 @@ +/* boot.c - command to boot an operating system */ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2003 Free Software Foundation, Inc. + * + * PUPA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include + +static pupa_err_t +pupa_cmd_boot (struct pupa_arg_list *state __attribute__ ((unused)), + int argc, char **args __attribute__ ((unused))) +{ + if (argc) + return pupa_error (PUPA_ERR_BAD_ARGUMENT, "too many arguments"); + + pupa_loader_boot (); + + return 0; +} + + +#ifdef PUPA_UTIL +void +pupa_boot_init (void) +{ + pupa_register_command ("boot", pupa_cmd_boot, PUPA_COMMAND_FLAG_BOTH, + "boot", "Boot an operating system", 0); +} + +void +pupa_boot_fini (void) +{ + pupa_unregister_command ("boot"); +} +#else /* ! PUPA_UTIL */ +PUPA_MOD_INIT +{ + (void)mod; /* To stop warning. */ + pupa_register_command ("boot", pupa_cmd_boot, PUPA_COMMAND_FLAG_BOTH, + "boot", "Boot an operating system", 0); +} + +PUPA_MOD_FINI +{ + pupa_unregister_command ("boot"); +} +#endif /* ! PUPA_UTIL */ diff --git a/commands/cat.c b/commands/cat.c new file mode 100644 index 000000000..cbccd89b4 --- /dev/null +++ b/commands/cat.c @@ -0,0 +1,97 @@ +/* cat.c - command to show the contents of a file */ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2003 Free Software Foundation, Inc. + * + * PUPA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + +static pupa_err_t +pupa_cmd_cat (struct pupa_arg_list *state __attribute__ ((unused)), + int argc, char **args) + +{ + pupa_file_t file; + char buf[PUPA_DISK_SECTOR_SIZE]; + pupa_ssize_t size; + + if (argc != 1) + return pupa_error (PUPA_ERR_BAD_ARGUMENT, "file name required"); + + file = pupa_file_open (args[0]); + if (! file) + return 0; + + while ((size = pupa_file_read (file, buf, sizeof (buf))) > 0) + { + int i; + + for (i = 0; i < size; i++) + { + unsigned char c = buf[i]; + + if (pupa_isprint (c) || pupa_isspace (c)) + pupa_putchar (c); + else + { + pupa_setcolorstate (PUPA_TERM_COLOR_HIGHLIGHT); + pupa_printf ("<%x>", (int) c); + pupa_setcolorstate (PUPA_TERM_COLOR_STANDARD); + } + } + } + + pupa_putchar ('\n'); + pupa_refresh (); + pupa_file_close (file); + + return 0; +} + + +#ifdef PUPA_UTIL +void +pupa_cat_init (void) +{ + pupa_register_command ("cat", pupa_cmd_cat, PUPA_COMMAND_FLAG_BOTH, + "cat FILE", "Show the contents of a file", 0); +} + +void +pupa_cat_fini (void) +{ + pupa_unregister_command ("cat"); +} +#else /* ! PUPA_UTIL */ +PUPA_MOD_INIT +{ + (void)mod; /* To stop warning. */ + pupa_register_command ("cat", pupa_cmd_cat, PUPA_COMMAND_FLAG_BOTH, + "cat FILE", "Show the contents of a file", 0); +} + +PUPA_MOD_FINI +{ + pupa_unregister_command ("cat"); +} +#endif /* ! PUPA_UTIL */ diff --git a/commands/cmp.c b/commands/cmp.c new file mode 100644 index 000000000..d5af4772e --- /dev/null +++ b/commands/cmp.c @@ -0,0 +1,124 @@ +/* cmd.c - command to cmp an operating system */ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2003 Free Software Foundation, Inc. + * + * PUPA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include + +static pupa_err_t +pupa_cmd_cmp (struct pupa_arg_list *state __attribute__ ((unused)), + int argc, char **args) +{ + pupa_file_t file1; + pupa_file_t file2; + + if (argc != 2) + return pupa_error (PUPA_ERR_BAD_ARGUMENT, "two arguments required"); + + pupa_printf ("Compare `%s' and `%s':\n", args[0], + args[1]); + + file1 = pupa_file_open (args[0]); + if (! file1) + return pupa_errno; + + file2 = pupa_file_open (args[1]); + if (! file2) + { + pupa_file_close (file2); + return pupa_errno; + } + + if (pupa_file_size (file1) != pupa_file_size (file2)) + pupa_printf ("Differ in size: %d [%s], %d [%s]\n", + pupa_file_size (file1), args[0], + pupa_file_size (file2), args[1]); + + else + { + char buf1[512]; + char buf2[512]; + pupa_ssize_t rd1, rd2; + pupa_uint32_t pos = 0; + + do + { + int i; + rd1 = pupa_file_read (file1, buf1, 512); + rd2 = pupa_file_read (file2, buf2, 512); + + if (rd1 != rd2) + return 0; + + for (i = 0; i < 512; i++) + { + if (buf1[i] != buf2[i]) + { + pupa_printf ("Differ at the offset %d: 0x%x [%s], 0x%x [%s]\n", + i + pos, buf1[i], args[0], + buf2[i], args[1]); + + pupa_file_close (file1); + pupa_file_close (file2); + return 0; + } + } + pos += 512; + + } while (rd2); + } + + pupa_file_close (file1); + pupa_file_close (file2); + + pupa_printf ("The files are identical.\n"); + + return 0; +} + + +#ifdef PUPA_UTIL +void +pupa_cmp_init (void) +{ + pupa_register_command ("cmp", pupa_cmd_cmp, PUPA_COMMAND_FLAG_BOTH, + "cmp FILE1 FILE2", "Compare two files", 0); +} + +void +pupa_cmp_fini (void) +{ + pupa_unregister_command ("cmp"); +} +#else /* ! PUPA_UTIL */ +PUPA_MOD_INIT +{ + (void)mod; /* To stop warning. */ + pupa_register_command ("cmp", pupa_cmd_cmp, PUPA_COMMAND_FLAG_BOTH, + "cmp FILE1 FILE2", "Compare two files", 0); +} + +PUPA_MOD_FINI +{ + pupa_unregister_command ("cmp"); +} +#endif /* ! PUPA_UTIL */ diff --git a/commands/ls.c b/commands/ls.c new file mode 100644 index 000000000..cf8b9aa61 --- /dev/null +++ b/commands/ls.c @@ -0,0 +1,262 @@ +/* ls.c - command to list files and devices */ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2003 Free Software Foundation, Inc. + * + * PUPA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const struct pupa_arg_option options[] = + { + {"long", 'l', 0, "Show a long list with more detailed information", 0, 0}, + {"human-readable", 'h', 0, "Print sizes in a human readable format", 0, 0}, + {"all", 'a', 0, "List all files", 0, 0}, + {0, 0, 0, 0, 0, 0} + }; + +static const char pupa_human_sizes[] = {' ', 'K', 'M', 'G', 'T'}; + +static pupa_err_t +pupa_ls_list_disks (int longlist) +{ + auto int pupa_ls_print_disks (const char *name); + int pupa_ls_print_disks (const char *name) + { + pupa_device_t dev; + auto int print_partition (const pupa_partition_t p); + + int print_partition (const pupa_partition_t p) + { + char *pname = pupa_partition_get_name (p); + + if (pname) + { + if (longlist) + pupa_print_partinfo (dev, pname); + else + pupa_printf ("(%s,%s) ", name, pname); + } + + return 0; + } + + dev = pupa_device_open (name); + pupa_errno = PUPA_ERR_NONE; + + if (dev) + { + if (longlist) + pupa_printf ("Disk: %s\n", name); + else + pupa_printf ("(%s) ", name); + + if (dev->disk && dev->disk->has_partitions) + { + pupa_partition_iterate (dev->disk, print_partition); + pupa_errno = PUPA_ERR_NONE; + } + + pupa_device_close (dev); + } + + return 0; + } + + pupa_disk_dev_iterate (pupa_ls_print_disks); + pupa_putchar ('\n'); + pupa_refresh (); + + + return 0; +} + +static pupa_err_t +pupa_ls_list_files (const char *dirname, int longlist, int all, int human) +{ + char *device_name; + pupa_fs_t fs; + char *path; + pupa_device_t dev; + + static int print_files (const char *filename, int dir) + { + if (all || filename[0] != '.') + pupa_printf ("%s%s ", filename, dir ? "/" : ""); + + return 0; + } + + static int print_files_long (const char *filename, int dir) + { + char pathname[pupa_strlen (dirname) + pupa_strlen (filename) + 1]; + + if ((! all) && (filename[0] == '.')) + return 0; + + if (! dir) + { + pupa_file_t file; + + if (dirname[pupa_strlen (dirname) - 1] == '/') + pupa_sprintf (pathname, "%s%s", dirname, filename); + else + pupa_sprintf (pathname, "%s/%s", dirname, filename); + + /* XXX: For ext2fs symlinks are detected as files while they + should be reported as directories. */ + file = pupa_file_open (pathname); + if (! file) + { + pupa_errno = 0; + return 0; + } + + if (! human) + pupa_printf ("%-12d", file->size); + else + { + float fsize = file->size; + int fsz = file->size; + int units = 0; + char buf[20]; + + while (fsz / 1024) + { + fsize /= 1024; + fsz /= 1024; + units++; + } + + if (units) + { + pupa_sprintf (buf, "%0.2f%c", fsize, pupa_human_sizes[units]); + pupa_printf ("%-12s", buf); + } + else + pupa_printf ("%-12d", file->size); + + } + (fs->close) (file); + } + else + pupa_printf ("%-12s", "DIR"); + + pupa_printf ("%s%s\n", filename, dir ? "/" : ""); + + return 0; + } + + device_name = pupa_file_get_device_name (dirname); + dev = pupa_device_open (device_name); + if (! dev) + goto fail; + + fs = pupa_fs_probe (dev); + path = pupa_strchr (dirname, '/'); + + if (! path && ! device_name) + { + pupa_error (PUPA_ERR_BAD_ARGUMENT, "invalid argument"); + goto fail; + } + + if (! path) + { + if (pupa_errno == PUPA_ERR_UNKNOWN_FS) + pupa_errno = PUPA_ERR_NONE; + + pupa_printf ("(%s): Filesystem is %s.\n", + device_name, fs ? fs->name : "unknown"); + } + else if (fs) + { + if (longlist) + (fs->dir) (dev, path, print_files_long); + else + (fs->dir) (dev, path, print_files); + pupa_putchar ('\n'); + pupa_refresh (); + } + + fail: + if (dev) + pupa_device_close (dev); + + pupa_free (device_name); + + return 0; +} + +static pupa_err_t +pupa_cmd_ls (struct pupa_arg_list *state, int argc, char **args) +{ + static int pupa_ls_print_files (const char *filename, int dir) + { + if (state[2].set/*all*/ || filename[0] != '.') + pupa_printf ("%s%s ", filename, dir ? "/" : ""); + + return 0; + } + + if (argc == 0) + pupa_ls_list_disks (state[0].set); + else + pupa_ls_list_files (args[0], state[0].set, state[2].set, + state[1].set); + + return 0; +} + +#ifdef PUPA_UTIL +void +pupa_ls_init (void) +{ + pupa_register_command ("ls", pupa_cmd_ls, PUPA_COMMAND_FLAG_BOTH, + "ls [OPTIONS...] [DIR]", + "List devices and files", options); +} + +void +pupa_ls_fini (void) +{ + pupa_unregister_command ("ls"); +} +#else /* ! PUPA_UTIL */ +PUPA_MOD_INIT +{ + (void)mod; /* To stop warning. */ + pupa_register_command ("ls", pupa_cmd_ls, PUPA_COMMAND_FLAG_BOTH, + "ls [OPTIONS...] [DIR]", + "List devices and files", options); +} + +PUPA_MOD_FINI +{ + pupa_unregister_command ("ls"); +} +#endif /* ! PUPA_UTIL */ diff --git a/commands/terminal.c b/commands/terminal.c new file mode 100644 index 000000000..52c2c85ee --- /dev/null +++ b/commands/terminal.c @@ -0,0 +1,99 @@ +/* terminal.c - command to show and select a terminal */ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2003 Free Software Foundation, Inc. + * + * PUPA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include + +static pupa_err_t +pupa_cmd_terminal (struct pupa_arg_list *state __attribute__ ((unused)), + int argc, char **args) +{ + pupa_term_t term = 0; + + auto int print_terminal (pupa_term_t); + auto int find_terminal (pupa_term_t); + + int print_terminal (pupa_term_t t) + { + pupa_printf (" %s", t->name); + return 0; + } + + int find_terminal (pupa_term_t t) + { + if (pupa_strcmp (t->name, args[0]) == 0) + { + term = t; + return 1; + } + + return 0; + } + + if (argc == 0) + { + pupa_printf ("Available terminal(s):"); + pupa_term_iterate (print_terminal); + pupa_putchar ('\n'); + + pupa_printf ("Current terminal: %s\n", pupa_term_get_current ()->name); + } + else + { + pupa_term_iterate (find_terminal); + if (! term) + return pupa_error (PUPA_ERR_BAD_ARGUMENT, "no such terminal"); + + pupa_term_set_current (term); + } + + return PUPA_ERR_NONE; +} + + +#ifdef PUPA_UTIL +void +pupa_terminal_init (void) +{ + pupa_register_command ("terminal", pupa_cmd_terminal, PUPA_COMMAND_FLAG_BOTH, + "terminal [TERM...]", "Select a terminal.", 0); +} + +void +pupa_terminal_fini (void) +{ + pupa_unregister_command ("terminal"); +} +#else /* ! PUPA_UTIL */ +PUPA_MOD_INIT +{ + (void)mod; /* To stop warning. */ + pupa_register_command ("terminal", pupa_cmd_terminal, PUPA_COMMAND_FLAG_BOTH, + "terminal [TERM...]", "Select a terminal.", 0); +} + +PUPA_MOD_FINI +{ + pupa_unregister_command ("terminal"); +} +#endif /* ! PUPA_UTIL */ diff --git a/conf/i386-pc.mk b/conf/i386-pc.mk index 42ccae248..f0369d1b5 100644 --- a/conf/i386-pc.mk +++ b/conf/i386-pc.mk @@ -55,16 +55,16 @@ kernel_img_SOURCES = kern/i386/pc/startup.S kern/main.c kern/device.c \ kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \ kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c \ kern/i386/dl.c kern/i386/pc/init.c disk/i386/pc/partition.c \ - disk/i386/pc/biosdisk.c \ + kern/env.c disk/i386/pc/biosdisk.c \ term/i386/pc/console.c \ symlist.c -CLEANFILES += kernel.img kernel.exec kernel_img-kern_i386_pc_startup.o kernel_img-kern_main.o kernel_img-kern_device.o kernel_img-kern_disk.o kernel_img-kern_dl.o kernel_img-kern_file.o kernel_img-kern_fs.o kernel_img-kern_err.o kernel_img-kern_misc.o kernel_img-kern_mm.o kernel_img-kern_loader.o kernel_img-kern_rescue.o kernel_img-kern_term.o kernel_img-kern_i386_dl.o kernel_img-kern_i386_pc_init.o kernel_img-disk_i386_pc_partition.o kernel_img-disk_i386_pc_biosdisk.o kernel_img-term_i386_pc_console.o kernel_img-symlist.o -MOSTLYCLEANFILES += kernel_img-kern_i386_pc_startup.d kernel_img-kern_main.d kernel_img-kern_device.d kernel_img-kern_disk.d kernel_img-kern_dl.d kernel_img-kern_file.d kernel_img-kern_fs.d kernel_img-kern_err.d kernel_img-kern_misc.d kernel_img-kern_mm.d kernel_img-kern_loader.d kernel_img-kern_rescue.d kernel_img-kern_term.d kernel_img-kern_i386_dl.d kernel_img-kern_i386_pc_init.d kernel_img-disk_i386_pc_partition.d kernel_img-disk_i386_pc_biosdisk.d kernel_img-term_i386_pc_console.d kernel_img-symlist.d +CLEANFILES += kernel.img kernel.exec kernel_img-kern_i386_pc_startup.o kernel_img-kern_main.o kernel_img-kern_device.o kernel_img-kern_disk.o kernel_img-kern_dl.o kernel_img-kern_file.o kernel_img-kern_fs.o kernel_img-kern_err.o kernel_img-kern_misc.o kernel_img-kern_mm.o kernel_img-kern_loader.o kernel_img-kern_rescue.o kernel_img-kern_term.o kernel_img-kern_i386_dl.o kernel_img-kern_i386_pc_init.o kernel_img-disk_i386_pc_partition.o kernel_img-kern_env.o kernel_img-disk_i386_pc_biosdisk.o kernel_img-term_i386_pc_console.o kernel_img-symlist.o +MOSTLYCLEANFILES += kernel_img-kern_i386_pc_startup.d kernel_img-kern_main.d kernel_img-kern_device.d kernel_img-kern_disk.d kernel_img-kern_dl.d kernel_img-kern_file.d kernel_img-kern_fs.d kernel_img-kern_err.d kernel_img-kern_misc.d kernel_img-kern_mm.d kernel_img-kern_loader.d kernel_img-kern_rescue.d kernel_img-kern_term.d kernel_img-kern_i386_dl.d kernel_img-kern_i386_pc_init.d kernel_img-disk_i386_pc_partition.d kernel_img-kern_env.d kernel_img-disk_i386_pc_biosdisk.d kernel_img-term_i386_pc_console.d kernel_img-symlist.d kernel.img: kernel.exec $(OBJCOPY) -O binary -R .note -R .comment $< $@ -kernel.exec: kernel_img-kern_i386_pc_startup.o kernel_img-kern_main.o kernel_img-kern_device.o kernel_img-kern_disk.o kernel_img-kern_dl.o kernel_img-kern_file.o kernel_img-kern_fs.o kernel_img-kern_err.o kernel_img-kern_misc.o kernel_img-kern_mm.o kernel_img-kern_loader.o kernel_img-kern_rescue.o kernel_img-kern_term.o kernel_img-kern_i386_dl.o kernel_img-kern_i386_pc_init.o kernel_img-disk_i386_pc_partition.o kernel_img-disk_i386_pc_biosdisk.o kernel_img-term_i386_pc_console.o kernel_img-symlist.o +kernel.exec: kernel_img-kern_i386_pc_startup.o kernel_img-kern_main.o kernel_img-kern_device.o kernel_img-kern_disk.o kernel_img-kern_dl.o kernel_img-kern_file.o kernel_img-kern_fs.o kernel_img-kern_err.o kernel_img-kern_misc.o kernel_img-kern_mm.o kernel_img-kern_loader.o kernel_img-kern_rescue.o kernel_img-kern_term.o kernel_img-kern_i386_dl.o kernel_img-kern_i386_pc_init.o kernel_img-disk_i386_pc_partition.o kernel_img-kern_env.o kernel_img-disk_i386_pc_biosdisk.o kernel_img-term_i386_pc_console.o kernel_img-symlist.o $(CC) -o $@ $^ $(LDFLAGS) $(kernel_img_LDFLAGS) kernel_img-kern_i386_pc_startup.o: kern/i386/pc/startup.S @@ -195,6 +195,14 @@ kernel_img-disk_i386_pc_partition.d: disk/i386/pc/partition.c -include kernel_img-disk_i386_pc_partition.d +kernel_img-kern_env.o: kern/env.c + $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $< + +kernel_img-kern_env.d: kern/env.c + set -e; $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -M $< | sed 's,env\.o[ :]*,kernel_img-kern_env.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include kernel_img-kern_env.d + kernel_img-disk_i386_pc_biosdisk.o: disk/i386/pc/biosdisk.c $(CC) -Idisk/i386/pc -I$(srcdir)/disk/i386/pc $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $< @@ -223,7 +231,7 @@ kernel_img_HEADERS = boot.h device.h disk.h dl.h elf.h err.h \ file.h fs.h kernel.h loader.h misc.h mm.h net.h rescue.h symbol.h \ term.h types.h machine/biosdisk.h machine/boot.h \ machine/console.h machine/init.h machine/memory.h \ - machine/loader.h machine/partition.h machine/vga.h + machine/loader.h machine/partition.h machine/vga.h arg.h env.h kernel_img_CFLAGS = $(COMMON_CFLAGS) kernel_img_ASFLAGS = $(COMMON_ASFLAGS) kernel_img_LDFLAGS = -nostdlib -Wl,-N,-Ttext,8200 @@ -281,11 +289,11 @@ pupa_mkimage_LDFLAGS = -llzo pupa_setup_SOURCES = util/i386/pc/pupa-setup.c util/i386/pc/biosdisk.c \ util/misc.c util/i386/pc/getroot.c kern/device.c kern/disk.c \ kern/err.c kern/misc.c disk/i386/pc/partition.c fs/fat.c fs/ext2.c \ - kern/file.c kern/fs.c -CLEANFILES += pupa-setup pupa_setup-util_i386_pc_pupa_setup.o pupa_setup-util_i386_pc_biosdisk.o pupa_setup-util_misc.o pupa_setup-util_i386_pc_getroot.o pupa_setup-kern_device.o pupa_setup-kern_disk.o pupa_setup-kern_err.o pupa_setup-kern_misc.o pupa_setup-disk_i386_pc_partition.o pupa_setup-fs_fat.o pupa_setup-fs_ext2.o pupa_setup-kern_file.o pupa_setup-kern_fs.o -MOSTLYCLEANFILES += pupa_setup-util_i386_pc_pupa_setup.d pupa_setup-util_i386_pc_biosdisk.d pupa_setup-util_misc.d pupa_setup-util_i386_pc_getroot.d pupa_setup-kern_device.d pupa_setup-kern_disk.d pupa_setup-kern_err.d pupa_setup-kern_misc.d pupa_setup-disk_i386_pc_partition.d pupa_setup-fs_fat.d pupa_setup-fs_ext2.d pupa_setup-kern_file.d pupa_setup-kern_fs.d + kern/file.c kern/fs.c kern/env.c +CLEANFILES += pupa-setup pupa_setup-util_i386_pc_pupa_setup.o pupa_setup-util_i386_pc_biosdisk.o pupa_setup-util_misc.o pupa_setup-util_i386_pc_getroot.o pupa_setup-kern_device.o pupa_setup-kern_disk.o pupa_setup-kern_err.o pupa_setup-kern_misc.o pupa_setup-disk_i386_pc_partition.o pupa_setup-fs_fat.o pupa_setup-fs_ext2.o pupa_setup-kern_file.o pupa_setup-kern_fs.o pupa_setup-kern_env.o +MOSTLYCLEANFILES += pupa_setup-util_i386_pc_pupa_setup.d pupa_setup-util_i386_pc_biosdisk.d pupa_setup-util_misc.d pupa_setup-util_i386_pc_getroot.d pupa_setup-kern_device.d pupa_setup-kern_disk.d pupa_setup-kern_err.d pupa_setup-kern_misc.d pupa_setup-disk_i386_pc_partition.d pupa_setup-fs_fat.d pupa_setup-fs_ext2.d pupa_setup-kern_file.d pupa_setup-kern_fs.d pupa_setup-kern_env.d -pupa-setup: pupa_setup-util_i386_pc_pupa_setup.o pupa_setup-util_i386_pc_biosdisk.o pupa_setup-util_misc.o pupa_setup-util_i386_pc_getroot.o pupa_setup-kern_device.o pupa_setup-kern_disk.o pupa_setup-kern_err.o pupa_setup-kern_misc.o pupa_setup-disk_i386_pc_partition.o pupa_setup-fs_fat.o pupa_setup-fs_ext2.o pupa_setup-kern_file.o pupa_setup-kern_fs.o +pupa-setup: pupa_setup-util_i386_pc_pupa_setup.o pupa_setup-util_i386_pc_biosdisk.o pupa_setup-util_misc.o pupa_setup-util_i386_pc_getroot.o pupa_setup-kern_device.o pupa_setup-kern_disk.o pupa_setup-kern_err.o pupa_setup-kern_misc.o pupa_setup-disk_i386_pc_partition.o pupa_setup-fs_fat.o pupa_setup-fs_ext2.o pupa_setup-kern_file.o pupa_setup-kern_fs.o pupa_setup-kern_env.o $(BUILD_CC) -o $@ $^ $(BUILD_LDFLAGS) $(pupa_setup_LDFLAGS) pupa_setup-util_i386_pc_pupa_setup.o: util/i386/pc/pupa-setup.c @@ -392,19 +400,28 @@ pupa_setup-kern_fs.d: kern/fs.c -include pupa_setup-kern_fs.d +pupa_setup-kern_env.o: kern/env.c + $(BUILD_CC) -Ikern -I$(srcdir)/kern $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_setup_CFLAGS) -c -o $@ $< + +pupa_setup-kern_env.d: kern/env.c + set -e; $(BUILD_CC) -Ikern -I$(srcdir)/kern $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_setup_CFLAGS) -M $< | sed 's,env\.o[ :]*,pupa_setup-kern_env.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include pupa_setup-kern_env.d + # For pupa pupa_emu_SOURCES = kern/main.c kern/device.c \ kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \ kern/misc.c kern/loader.c kern/rescue.c kern/term.c \ - disk/i386/pc/partition.c \ + disk/i386/pc/partition.c kern/env.c commands/ls.c \ + commands/terminal.c commands/boot.c commands/cmp.c commands/cat.c \ util/i386/pc/biosdisk.c fs/fat.c fs/ext2.c \ - normal/cmdline.c normal/command.c normal/main.c normal/menu.c \ + normal/cmdline.c normal/command.c normal/main.c normal/menu.c normal/arg.c \ util/console.c util/pupa-emu.c util/misc.c util/i386/pc/getroot.c -CLEANFILES += pupa-emu pupa_emu-kern_main.o pupa_emu-kern_device.o pupa_emu-kern_disk.o pupa_emu-kern_dl.o pupa_emu-kern_file.o pupa_emu-kern_fs.o pupa_emu-kern_err.o pupa_emu-kern_misc.o pupa_emu-kern_loader.o pupa_emu-kern_rescue.o pupa_emu-kern_term.o pupa_emu-disk_i386_pc_partition.o pupa_emu-util_i386_pc_biosdisk.o pupa_emu-fs_fat.o pupa_emu-fs_ext2.o pupa_emu-normal_cmdline.o pupa_emu-normal_command.o pupa_emu-normal_main.o pupa_emu-normal_menu.o pupa_emu-util_console.o pupa_emu-util_pupa_emu.o pupa_emu-util_misc.o pupa_emu-util_i386_pc_getroot.o -MOSTLYCLEANFILES += pupa_emu-kern_main.d pupa_emu-kern_device.d pupa_emu-kern_disk.d pupa_emu-kern_dl.d pupa_emu-kern_file.d pupa_emu-kern_fs.d pupa_emu-kern_err.d pupa_emu-kern_misc.d pupa_emu-kern_loader.d pupa_emu-kern_rescue.d pupa_emu-kern_term.d pupa_emu-disk_i386_pc_partition.d pupa_emu-util_i386_pc_biosdisk.d pupa_emu-fs_fat.d pupa_emu-fs_ext2.d pupa_emu-normal_cmdline.d pupa_emu-normal_command.d pupa_emu-normal_main.d pupa_emu-normal_menu.d pupa_emu-util_console.d pupa_emu-util_pupa_emu.d pupa_emu-util_misc.d pupa_emu-util_i386_pc_getroot.d +CLEANFILES += pupa-emu pupa_emu-kern_main.o pupa_emu-kern_device.o pupa_emu-kern_disk.o pupa_emu-kern_dl.o pupa_emu-kern_file.o pupa_emu-kern_fs.o pupa_emu-kern_err.o pupa_emu-kern_misc.o pupa_emu-kern_loader.o pupa_emu-kern_rescue.o pupa_emu-kern_term.o pupa_emu-disk_i386_pc_partition.o pupa_emu-kern_env.o pupa_emu-commands_ls.o pupa_emu-commands_terminal.o pupa_emu-commands_boot.o pupa_emu-commands_cmp.o pupa_emu-commands_cat.o pupa_emu-util_i386_pc_biosdisk.o pupa_emu-fs_fat.o pupa_emu-fs_ext2.o pupa_emu-normal_cmdline.o pupa_emu-normal_command.o pupa_emu-normal_main.o pupa_emu-normal_menu.o pupa_emu-normal_arg.o pupa_emu-util_console.o pupa_emu-util_pupa_emu.o pupa_emu-util_misc.o pupa_emu-util_i386_pc_getroot.o +MOSTLYCLEANFILES += pupa_emu-kern_main.d pupa_emu-kern_device.d pupa_emu-kern_disk.d pupa_emu-kern_dl.d pupa_emu-kern_file.d pupa_emu-kern_fs.d pupa_emu-kern_err.d pupa_emu-kern_misc.d pupa_emu-kern_loader.d pupa_emu-kern_rescue.d pupa_emu-kern_term.d pupa_emu-disk_i386_pc_partition.d pupa_emu-kern_env.d pupa_emu-commands_ls.d pupa_emu-commands_terminal.d pupa_emu-commands_boot.d pupa_emu-commands_cmp.d pupa_emu-commands_cat.d pupa_emu-util_i386_pc_biosdisk.d pupa_emu-fs_fat.d pupa_emu-fs_ext2.d pupa_emu-normal_cmdline.d pupa_emu-normal_command.d pupa_emu-normal_main.d pupa_emu-normal_menu.d pupa_emu-normal_arg.d pupa_emu-util_console.d pupa_emu-util_pupa_emu.d pupa_emu-util_misc.d pupa_emu-util_i386_pc_getroot.d -pupa-emu: pupa_emu-kern_main.o pupa_emu-kern_device.o pupa_emu-kern_disk.o pupa_emu-kern_dl.o pupa_emu-kern_file.o pupa_emu-kern_fs.o pupa_emu-kern_err.o pupa_emu-kern_misc.o pupa_emu-kern_loader.o pupa_emu-kern_rescue.o pupa_emu-kern_term.o pupa_emu-disk_i386_pc_partition.o pupa_emu-util_i386_pc_biosdisk.o pupa_emu-fs_fat.o pupa_emu-fs_ext2.o pupa_emu-normal_cmdline.o pupa_emu-normal_command.o pupa_emu-normal_main.o pupa_emu-normal_menu.o pupa_emu-util_console.o pupa_emu-util_pupa_emu.o pupa_emu-util_misc.o pupa_emu-util_i386_pc_getroot.o +pupa-emu: pupa_emu-kern_main.o pupa_emu-kern_device.o pupa_emu-kern_disk.o pupa_emu-kern_dl.o pupa_emu-kern_file.o pupa_emu-kern_fs.o pupa_emu-kern_err.o pupa_emu-kern_misc.o pupa_emu-kern_loader.o pupa_emu-kern_rescue.o pupa_emu-kern_term.o pupa_emu-disk_i386_pc_partition.o pupa_emu-kern_env.o pupa_emu-commands_ls.o pupa_emu-commands_terminal.o pupa_emu-commands_boot.o pupa_emu-commands_cmp.o pupa_emu-commands_cat.o pupa_emu-util_i386_pc_biosdisk.o pupa_emu-fs_fat.o pupa_emu-fs_ext2.o pupa_emu-normal_cmdline.o pupa_emu-normal_command.o pupa_emu-normal_main.o pupa_emu-normal_menu.o pupa_emu-normal_arg.o pupa_emu-util_console.o pupa_emu-util_pupa_emu.o pupa_emu-util_misc.o pupa_emu-util_i386_pc_getroot.o $(BUILD_CC) -o $@ $^ $(BUILD_LDFLAGS) $(pupa_emu_LDFLAGS) pupa_emu-kern_main.o: kern/main.c @@ -503,6 +520,54 @@ pupa_emu-disk_i386_pc_partition.d: disk/i386/pc/partition.c -include pupa_emu-disk_i386_pc_partition.d +pupa_emu-kern_env.o: kern/env.c + $(BUILD_CC) -Ikern -I$(srcdir)/kern $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_emu_CFLAGS) -c -o $@ $< + +pupa_emu-kern_env.d: kern/env.c + set -e; $(BUILD_CC) -Ikern -I$(srcdir)/kern $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_emu_CFLAGS) -M $< | sed 's,env\.o[ :]*,pupa_emu-kern_env.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include pupa_emu-kern_env.d + +pupa_emu-commands_ls.o: commands/ls.c + $(BUILD_CC) -Icommands -I$(srcdir)/commands $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_emu_CFLAGS) -c -o $@ $< + +pupa_emu-commands_ls.d: commands/ls.c + set -e; $(BUILD_CC) -Icommands -I$(srcdir)/commands $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_emu_CFLAGS) -M $< | sed 's,ls\.o[ :]*,pupa_emu-commands_ls.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include pupa_emu-commands_ls.d + +pupa_emu-commands_terminal.o: commands/terminal.c + $(BUILD_CC) -Icommands -I$(srcdir)/commands $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_emu_CFLAGS) -c -o $@ $< + +pupa_emu-commands_terminal.d: commands/terminal.c + set -e; $(BUILD_CC) -Icommands -I$(srcdir)/commands $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_emu_CFLAGS) -M $< | sed 's,terminal\.o[ :]*,pupa_emu-commands_terminal.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include pupa_emu-commands_terminal.d + +pupa_emu-commands_boot.o: commands/boot.c + $(BUILD_CC) -Icommands -I$(srcdir)/commands $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_emu_CFLAGS) -c -o $@ $< + +pupa_emu-commands_boot.d: commands/boot.c + set -e; $(BUILD_CC) -Icommands -I$(srcdir)/commands $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_emu_CFLAGS) -M $< | sed 's,boot\.o[ :]*,pupa_emu-commands_boot.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include pupa_emu-commands_boot.d + +pupa_emu-commands_cmp.o: commands/cmp.c + $(BUILD_CC) -Icommands -I$(srcdir)/commands $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_emu_CFLAGS) -c -o $@ $< + +pupa_emu-commands_cmp.d: commands/cmp.c + set -e; $(BUILD_CC) -Icommands -I$(srcdir)/commands $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_emu_CFLAGS) -M $< | sed 's,cmp\.o[ :]*,pupa_emu-commands_cmp.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include pupa_emu-commands_cmp.d + +pupa_emu-commands_cat.o: commands/cat.c + $(BUILD_CC) -Icommands -I$(srcdir)/commands $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_emu_CFLAGS) -c -o $@ $< + +pupa_emu-commands_cat.d: commands/cat.c + set -e; $(BUILD_CC) -Icommands -I$(srcdir)/commands $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_emu_CFLAGS) -M $< | sed 's,cat\.o[ :]*,pupa_emu-commands_cat.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include pupa_emu-commands_cat.d + pupa_emu-util_i386_pc_biosdisk.o: util/i386/pc/biosdisk.c $(BUILD_CC) -Iutil/i386/pc -I$(srcdir)/util/i386/pc $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_emu_CFLAGS) -c -o $@ $< @@ -559,6 +624,14 @@ pupa_emu-normal_menu.d: normal/menu.c -include pupa_emu-normal_menu.d +pupa_emu-normal_arg.o: normal/arg.c + $(BUILD_CC) -Inormal -I$(srcdir)/normal $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_emu_CFLAGS) -c -o $@ $< + +pupa_emu-normal_arg.d: normal/arg.c + set -e; $(BUILD_CC) -Inormal -I$(srcdir)/normal $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_emu_CFLAGS) -M $< | sed 's,arg\.o[ :]*,pupa_emu-normal_arg.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include pupa_emu-normal_arg.d + pupa_emu-util_console.o: util/console.c $(BUILD_CC) -Iutil -I$(srcdir)/util $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DPUPA_UTIL=1 $(pupa_emu_CFLAGS) -c -o $@ $< @@ -612,7 +685,7 @@ genmoddep-util_genmoddep.d: util/genmoddep.c # Modules. pkgdata_MODULES = _chain.mod _linux.mod fat.mod ext2.mod normal.mod hello.mod \ - vga.mod font.mod _multiboot.mod + vga.mod font.mod _multiboot.mod ls.mod boot.mod cmp.mod cat.mod terminal.mod # For _chain.mod. _chain_mod_SOURCES = loader/i386/pc/chainloader.c @@ -772,9 +845,9 @@ _linux_mod_CFLAGS = $(COMMON_CFLAGS) # For normal.mod. normal_mod_SOURCES = normal/cmdline.c normal/command.c normal/main.c \ - normal/menu.c normal/i386/setjmp.S -CLEANFILES += normal.mod mod-normal.o mod-normal.c pre-normal.o normal_mod-normal_cmdline.o normal_mod-normal_command.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_i386_setjmp.o def-normal.lst und-normal.lst -MOSTLYCLEANFILES += normal_mod-normal_cmdline.d normal_mod-normal_command.d normal_mod-normal_main.d normal_mod-normal_menu.d normal_mod-normal_i386_setjmp.d + normal/menu.c normal/arg.c normal/i386/setjmp.S +CLEANFILES += normal.mod mod-normal.o mod-normal.c pre-normal.o normal_mod-normal_cmdline.o normal_mod-normal_command.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_arg.o normal_mod-normal_i386_setjmp.o def-normal.lst und-normal.lst +MOSTLYCLEANFILES += normal_mod-normal_cmdline.d normal_mod-normal_command.d normal_mod-normal_main.d normal_mod-normal_menu.d normal_mod-normal_arg.d normal_mod-normal_i386_setjmp.d DEFSYMFILES += def-normal.lst UNDSYMFILES += und-normal.lst @@ -783,7 +856,7 @@ normal.mod: pre-normal.o mod-normal.o $(LD) -r -o $@ $^ $(STRIP) --strip-unneeded -K pupa_mod_init -K pupa_mod_fini -R .note -R .comment $@ -pre-normal.o: normal_mod-normal_cmdline.o normal_mod-normal_command.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_i386_setjmp.o +pre-normal.o: normal_mod-normal_cmdline.o normal_mod-normal_command.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_arg.o normal_mod-normal_i386_setjmp.o -rm -f $@ $(LD) -r -o $@ $^ @@ -832,6 +905,14 @@ normal_mod-normal_menu.d: normal/menu.c -include normal_mod-normal_menu.d +normal_mod-normal_arg.o: normal/arg.c + $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) $(normal_mod_CFLAGS) -c -o $@ $< + +normal_mod-normal_arg.d: normal/arg.c + set -e; $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) $(normal_mod_CFLAGS) -M $< | sed 's,arg\.o[ :]*,normal_mod-normal_arg.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include normal_mod-normal_arg.d + normal_mod-normal_i386_setjmp.o: normal/i386/setjmp.S $(CC) -Inormal/i386 -I$(srcdir)/normal/i386 $(CPPFLAGS) $(ASFLAGS) $(normal_mod_ASFLAGS) -c -o $@ $< @@ -882,6 +963,201 @@ hello_mod-hello_hello.d: hello/hello.c hello_mod_CFLAGS = $(COMMON_CFLAGS) +# For boot.mod. +boot_mod_SOURCES = commands/boot.c +CLEANFILES += boot.mod mod-boot.o mod-boot.c pre-boot.o boot_mod-commands_boot.o def-boot.lst und-boot.lst +MOSTLYCLEANFILES += boot_mod-commands_boot.d +DEFSYMFILES += def-boot.lst +UNDSYMFILES += und-boot.lst + +boot.mod: pre-boot.o mod-boot.o + -rm -f $@ + $(LD) -r -o $@ $^ + $(STRIP) --strip-unneeded -K pupa_mod_init -K pupa_mod_fini -R .note -R .comment $@ + +pre-boot.o: boot_mod-commands_boot.o + -rm -f $@ + $(LD) -r -o $@ $^ + +mod-boot.o: mod-boot.c + $(CC) $(CPPFLAGS) $(CFLAGS) $(boot_mod_CFLAGS) -c -o $@ $< + +mod-boot.c: moddep.lst genmodsrc.sh + sh $(srcdir)/genmodsrc.sh 'boot' $< > $@ || (rm -f $@; exit 1) + +def-boot.lst: pre-boot.o + $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 boot/' > $@ + +und-boot.lst: pre-boot.o + echo 'boot' > $@ + $(NM) -u -P -p $< | cut -f1 -d' ' >> $@ + +boot_mod-commands_boot.o: commands/boot.c + $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) $(boot_mod_CFLAGS) -c -o $@ $< + +boot_mod-commands_boot.d: commands/boot.c + set -e; $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) $(boot_mod_CFLAGS) -M $< | sed 's,boot\.o[ :]*,boot_mod-commands_boot.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include boot_mod-commands_boot.d + +boot_mod_CFLAGS = $(COMMON_CFLAGS) + +# For terminal.mod. +terminal_mod_SOURCES = commands/terminal.c +CLEANFILES += terminal.mod mod-terminal.o mod-terminal.c pre-terminal.o terminal_mod-commands_terminal.o def-terminal.lst und-terminal.lst +MOSTLYCLEANFILES += terminal_mod-commands_terminal.d +DEFSYMFILES += def-terminal.lst +UNDSYMFILES += und-terminal.lst + +terminal.mod: pre-terminal.o mod-terminal.o + -rm -f $@ + $(LD) -r -o $@ $^ + $(STRIP) --strip-unneeded -K pupa_mod_init -K pupa_mod_fini -R .note -R .comment $@ + +pre-terminal.o: terminal_mod-commands_terminal.o + -rm -f $@ + $(LD) -r -o $@ $^ + +mod-terminal.o: mod-terminal.c + $(CC) $(CPPFLAGS) $(CFLAGS) $(terminal_mod_CFLAGS) -c -o $@ $< + +mod-terminal.c: moddep.lst genmodsrc.sh + sh $(srcdir)/genmodsrc.sh 'terminal' $< > $@ || (rm -f $@; exit 1) + +def-terminal.lst: pre-terminal.o + $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 terminal/' > $@ + +und-terminal.lst: pre-terminal.o + echo 'terminal' > $@ + $(NM) -u -P -p $< | cut -f1 -d' ' >> $@ + +terminal_mod-commands_terminal.o: commands/terminal.c + $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) $(terminal_mod_CFLAGS) -c -o $@ $< + +terminal_mod-commands_terminal.d: commands/terminal.c + set -e; $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) $(terminal_mod_CFLAGS) -M $< | sed 's,terminal\.o[ :]*,terminal_mod-commands_terminal.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include terminal_mod-commands_terminal.d + +terminal_mod_CFLAGS = $(COMMON_CFLAGS) + +# For ls.mod. +ls_mod_SOURCES = commands/ls.c +CLEANFILES += ls.mod mod-ls.o mod-ls.c pre-ls.o ls_mod-commands_ls.o def-ls.lst und-ls.lst +MOSTLYCLEANFILES += ls_mod-commands_ls.d +DEFSYMFILES += def-ls.lst +UNDSYMFILES += und-ls.lst + +ls.mod: pre-ls.o mod-ls.o + -rm -f $@ + $(LD) -r -o $@ $^ + $(STRIP) --strip-unneeded -K pupa_mod_init -K pupa_mod_fini -R .note -R .comment $@ + +pre-ls.o: ls_mod-commands_ls.o + -rm -f $@ + $(LD) -r -o $@ $^ + +mod-ls.o: mod-ls.c + $(CC) $(CPPFLAGS) $(CFLAGS) $(ls_mod_CFLAGS) -c -o $@ $< + +mod-ls.c: moddep.lst genmodsrc.sh + sh $(srcdir)/genmodsrc.sh 'ls' $< > $@ || (rm -f $@; exit 1) + +def-ls.lst: pre-ls.o + $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 ls/' > $@ + +und-ls.lst: pre-ls.o + echo 'ls' > $@ + $(NM) -u -P -p $< | cut -f1 -d' ' >> $@ + +ls_mod-commands_ls.o: commands/ls.c + $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) $(ls_mod_CFLAGS) -c -o $@ $< + +ls_mod-commands_ls.d: commands/ls.c + set -e; $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) $(ls_mod_CFLAGS) -M $< | sed 's,ls\.o[ :]*,ls_mod-commands_ls.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include ls_mod-commands_ls.d + +ls_mod_CFLAGS = $(COMMON_CFLAGS) + +# For cmp.mod. +cmp_mod_SOURCES = commands/cmp.c +CLEANFILES += cmp.mod mod-cmp.o mod-cmp.c pre-cmp.o cmp_mod-commands_cmp.o def-cmp.lst und-cmp.lst +MOSTLYCLEANFILES += cmp_mod-commands_cmp.d +DEFSYMFILES += def-cmp.lst +UNDSYMFILES += und-cmp.lst + +cmp.mod: pre-cmp.o mod-cmp.o + -rm -f $@ + $(LD) -r -o $@ $^ + $(STRIP) --strip-unneeded -K pupa_mod_init -K pupa_mod_fini -R .note -R .comment $@ + +pre-cmp.o: cmp_mod-commands_cmp.o + -rm -f $@ + $(LD) -r -o $@ $^ + +mod-cmp.o: mod-cmp.c + $(CC) $(CPPFLAGS) $(CFLAGS) $(cmp_mod_CFLAGS) -c -o $@ $< + +mod-cmp.c: moddep.lst genmodsrc.sh + sh $(srcdir)/genmodsrc.sh 'cmp' $< > $@ || (rm -f $@; exit 1) + +def-cmp.lst: pre-cmp.o + $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 cmp/' > $@ + +und-cmp.lst: pre-cmp.o + echo 'cmp' > $@ + $(NM) -u -P -p $< | cut -f1 -d' ' >> $@ + +cmp_mod-commands_cmp.o: commands/cmp.c + $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) $(cmp_mod_CFLAGS) -c -o $@ $< + +cmp_mod-commands_cmp.d: commands/cmp.c + set -e; $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) $(cmp_mod_CFLAGS) -M $< | sed 's,cmp\.o[ :]*,cmp_mod-commands_cmp.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include cmp_mod-commands_cmp.d + +cmp_mod_CFLAGS = $(COMMON_CFLAGS) + +# For cat.mod. +cat_mod_SOURCES = commands/cat.c +CLEANFILES += cat.mod mod-cat.o mod-cat.c pre-cat.o cat_mod-commands_cat.o def-cat.lst und-cat.lst +MOSTLYCLEANFILES += cat_mod-commands_cat.d +DEFSYMFILES += def-cat.lst +UNDSYMFILES += und-cat.lst + +cat.mod: pre-cat.o mod-cat.o + -rm -f $@ + $(LD) -r -o $@ $^ + $(STRIP) --strip-unneeded -K pupa_mod_init -K pupa_mod_fini -R .note -R .comment $@ + +pre-cat.o: cat_mod-commands_cat.o + -rm -f $@ + $(LD) -r -o $@ $^ + +mod-cat.o: mod-cat.c + $(CC) $(CPPFLAGS) $(CFLAGS) $(cat_mod_CFLAGS) -c -o $@ $< + +mod-cat.c: moddep.lst genmodsrc.sh + sh $(srcdir)/genmodsrc.sh 'cat' $< > $@ || (rm -f $@; exit 1) + +def-cat.lst: pre-cat.o + $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 cat/' > $@ + +und-cat.lst: pre-cat.o + echo 'cat' > $@ + $(NM) -u -P -p $< | cut -f1 -d' ' >> $@ + +cat_mod-commands_cat.o: commands/cat.c + $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) $(cat_mod_CFLAGS) -c -o $@ $< + +cat_mod-commands_cat.d: commands/cat.c + set -e; $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) $(cat_mod_CFLAGS) -M $< | sed 's,cat\.o[ :]*,cat_mod-commands_cat.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include cat_mod-commands_cat.d + +cat_mod_CFLAGS = $(COMMON_CFLAGS) + # For vga.mod. vga_mod_SOURCES = term/i386/pc/vga.c CLEANFILES += vga.mod mod-vga.o mod-vga.c pre-vga.o vga_mod-term_i386_pc_vga.o def-vga.lst und-vga.lst diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk index 6fec499b0..b50bb1257 100644 --- a/conf/i386-pc.rmk +++ b/conf/i386-pc.rmk @@ -21,14 +21,14 @@ kernel_img_SOURCES = kern/i386/pc/startup.S kern/main.c kern/device.c \ kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \ kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c \ kern/i386/dl.c kern/i386/pc/init.c disk/i386/pc/partition.c \ - disk/i386/pc/biosdisk.c \ + kern/env.c disk/i386/pc/biosdisk.c \ term/i386/pc/console.c \ symlist.c kernel_img_HEADERS = boot.h device.h disk.h dl.h elf.h err.h \ file.h fs.h kernel.h loader.h misc.h mm.h net.h rescue.h symbol.h \ term.h types.h machine/biosdisk.h machine/boot.h \ machine/console.h machine/init.h machine/memory.h \ - machine/loader.h machine/partition.h machine/vga.h + machine/loader.h machine/partition.h machine/vga.h arg.h env.h kernel_img_CFLAGS = $(COMMON_CFLAGS) kernel_img_ASFLAGS = $(COMMON_ASFLAGS) kernel_img_LDFLAGS = -nostdlib -Wl,-N,-Ttext,8200 @@ -56,15 +56,16 @@ pupa_mkimage_LDFLAGS = -llzo pupa_setup_SOURCES = util/i386/pc/pupa-setup.c util/i386/pc/biosdisk.c \ util/misc.c util/i386/pc/getroot.c kern/device.c kern/disk.c \ kern/err.c kern/misc.c disk/i386/pc/partition.c fs/fat.c fs/ext2.c \ - kern/file.c kern/fs.c + kern/file.c kern/fs.c kern/env.c # For pupa pupa_emu_SOURCES = kern/main.c kern/device.c \ kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \ kern/misc.c kern/loader.c kern/rescue.c kern/term.c \ - disk/i386/pc/partition.c \ + disk/i386/pc/partition.c kern/env.c commands/ls.c \ + commands/terminal.c commands/boot.c commands/cmp.c commands/cat.c \ util/i386/pc/biosdisk.c fs/fat.c fs/ext2.c \ - normal/cmdline.c normal/command.c normal/main.c normal/menu.c \ + normal/cmdline.c normal/command.c normal/main.c normal/menu.c normal/arg.c \ util/console.c util/pupa-emu.c util/misc.c util/i386/pc/getroot.c pupa_emu_LDFLAGS = -lncurses @@ -73,7 +74,7 @@ genmoddep_SOURCES = util/genmoddep.c # Modules. pkgdata_MODULES = _chain.mod _linux.mod fat.mod ext2.mod normal.mod hello.mod \ - vga.mod font.mod _multiboot.mod + vga.mod font.mod _multiboot.mod ls.mod boot.mod cmp.mod cat.mod terminal.mod # For _chain.mod. _chain_mod_SOURCES = loader/i386/pc/chainloader.c @@ -93,7 +94,7 @@ _linux_mod_CFLAGS = $(COMMON_CFLAGS) # For normal.mod. normal_mod_SOURCES = normal/cmdline.c normal/command.c normal/main.c \ - normal/menu.c normal/i386/setjmp.S + normal/menu.c normal/arg.c normal/i386/setjmp.S normal_mod_CFLAGS = $(COMMON_CFLAGS) normal_mod_ASFLAGS = $(COMMON_ASFLAGS) @@ -101,6 +102,26 @@ normal_mod_ASFLAGS = $(COMMON_ASFLAGS) hello_mod_SOURCES = hello/hello.c hello_mod_CFLAGS = $(COMMON_CFLAGS) +# For boot.mod. +boot_mod_SOURCES = commands/boot.c +boot_mod_CFLAGS = $(COMMON_CFLAGS) + +# For terminal.mod. +terminal_mod_SOURCES = commands/terminal.c +terminal_mod_CFLAGS = $(COMMON_CFLAGS) + +# For ls.mod. +ls_mod_SOURCES = commands/ls.c +ls_mod_CFLAGS = $(COMMON_CFLAGS) + +# For cmp.mod. +cmp_mod_SOURCES = commands/cmp.c +cmp_mod_CFLAGS = $(COMMON_CFLAGS) + +# For cat.mod. +cat_mod_SOURCES = commands/cat.c +cat_mod_CFLAGS = $(COMMON_CFLAGS) + # For vga.mod. vga_mod_SOURCES = term/i386/pc/vga.c vga_mod_CFLAGS = $(COMMON_CFLAGS) diff --git a/font/manager.c b/font/manager.c index 4b26483ce..6aac232b5 100644 --- a/font/manager.c +++ b/font/manager.c @@ -217,14 +217,16 @@ pupa_font_get_glyph (pupa_uint32_t code, return 0; } -static int -font_command (int argc, char *argv[]) +static pupa_err_t +font_command (struct pupa_arg_list *state __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) { if (argc == 0) return pupa_error (PUPA_ERR_BAD_ARGUMENT, "no font specified"); while (argc--) - if (! add_font (*argv++)) + if (! add_font (*args++)) return 1; return 0; @@ -232,9 +234,9 @@ font_command (int argc, char *argv[]) PUPA_MOD_INIT { + (void) mod; /* Stop warning. */ pupa_register_command ("font", font_command, PUPA_COMMAND_FLAG_BOTH, - "font FILE...", - "Specify a font file to display."); + "font FILE...", "Specify a font file to display.", 0); } PUPA_MOD_FINI diff --git a/hello/hello.c b/hello/hello.c index cfc0e63c7..85fce150f 100644 --- a/hello/hello.c +++ b/hello/hello.c @@ -1,6 +1,7 @@ /* hello.c - test module for dynamic loading */ /* * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2003 Free Software Foundation, Inc. * Copyright (C) 2003 NIIBE Yutaka * * This program is free software; you can redistribute it and/or modify @@ -25,10 +26,11 @@ #include #include -static int -pupa_cmd_hello (int argc, char *argv[]) +static pupa_err_t +pupa_cmd_hello (struct pupa_arg_list *state __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) { - (void)argc; (void)argv; /* To stop warning. */ pupa_printf ("Hello World\n"); return 0; } @@ -37,7 +39,7 @@ PUPA_MOD_INIT { (void)mod; /* To stop warning. */ pupa_register_command ("hello", pupa_cmd_hello, PUPA_COMMAND_FLAG_BOTH, - "hello", "Say hello"); + "hello", "Say hello", 0); } PUPA_MOD_FINI diff --git a/include/grub/arg.h b/include/grub/arg.h new file mode 100644 index 000000000..c2572b3d1 --- /dev/null +++ b/include/grub/arg.h @@ -0,0 +1,66 @@ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2003 Free Software Foundation, Inc. + * + * PUPA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef PUPA_ARG_HEADER +#define PUPA_ARG_HEADER 1 + +#include +#include +#include + +enum pupa_arg_type + { + ARG_TYPE_NONE, + ARG_TYPE_STRING, + ARG_TYPE_INT, + ARG_TYPE_DEVICE, + ARG_TYPE_FILE, + ARG_TYPE_DIR, + ARG_TYPE_PATHNAME + }; + +typedef enum pupa_arg_type pupa_arg_type_t; + +/* Flags for the option field op pupa_arg_option. */ +#define PUPA_ARG_OPTION_OPTIONAL 1 << 1 + +enum pupa_key_type + { + PUPA_KEY_ARG = -1, + PUPA_KEY_END = -2 + }; +typedef enum pupa_key_type pupa_arg_key_type_t; + +struct pupa_arg_option +{ + char *longarg; + char shortarg; + int flags; + char *doc; + char *arg; + pupa_arg_type_t type; +}; + +struct pupa_arg_list +{ + int set; + char *arg; +}; + +#endif /* ! PUPA_ARG_HEADER */ diff --git a/include/grub/disk.h b/include/grub/disk.h index b7d5839ae..f09bcbf5c 100644 --- a/include/grub/disk.h +++ b/include/grub/disk.h @@ -1,6 +1,6 @@ /* * PUPA -- Preliminary Universal Programming Architecture for GRUB - * Copyright (C) 2002 Free Software Foundation, Inc. + * Copyright (C) 2002, 2003 Free Software Foundation, Inc. * * PUPA is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,6 +23,7 @@ #include #include #include +#include struct pupa_disk; @@ -116,4 +117,7 @@ pupa_err_t EXPORT_FUNC(pupa_disk_write) (pupa_disk_t disk, unsigned long size, const char *buf); +pupa_err_t EXPORT_FUNC(pupa_print_partinfo) (pupa_device_t disk, + char *partname); + #endif /* ! PUPA_DISK_HEADER */ diff --git a/include/grub/dl.h b/include/grub/dl.h index 8c974ab1d..070bc4005 100644 --- a/include/grub/dl.h +++ b/include/grub/dl.h @@ -83,8 +83,6 @@ pupa_dl_t EXPORT_FUNC(pupa_dl_get) (const char *name); pupa_err_t EXPORT_FUNC(pupa_dl_register_symbol) (const char *name, void *addr, pupa_dl_t mod); void *EXPORT_FUNC(pupa_dl_resolve_symbol) (const char *name); -void EXPORT_FUNC(pupa_dl_set_prefix) (const char *dir); -const char *EXPORT_FUNC(pupa_dl_get_prefix) (void); int pupa_arch_dl_check_header (void *ehdr, pupa_size_t size); pupa_err_t pupa_arch_dl_relocate_symbols (pupa_dl_t mod, void *ehdr); diff --git a/include/grub/env.h b/include/grub/env.h new file mode 100644 index 000000000..71c087f8c --- /dev/null +++ b/include/grub/env.h @@ -0,0 +1,49 @@ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2003 Free Software Foundation, Inc. + * + * PUPA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef PUPA_ENV_HEADER +#define PUPA_ENV_HEADER 1 + +#include +#include +#include + +struct pupa_env_var +{ + char *name; + char *value; + pupa_err_t (*read_hook) (struct pupa_env_var *var, char **val); + pupa_err_t (*write_hook) (struct pupa_env_var *var); + struct pupa_env_var *next; + struct pupa_env_var **prevp; + struct pupa_env_var *sort_next; + struct pupa_env_var **sort_prevp; +}; + +pupa_err_t EXPORT_FUNC(pupa_env_set) (const char *var, const char *val); +char *EXPORT_FUNC(pupa_env_get) (const char *name); +void EXPORT_FUNC(pupa_env_unset) (const char *name); +void EXPORT_FUNC(pupa_env_iterate) (int (* func) (struct pupa_env_var *var)); +pupa_err_t EXPORT_FUNC(pupa_register_variable_hook) (const char *var, + pupa_err_t (*read_hook) + (struct pupa_env_var *var, char **val), + pupa_err_t (*write_hook) + (struct pupa_env_var *var)); + +#endif /* ! PUPA_ENV_HEADER */ diff --git a/include/grub/misc.h b/include/grub/misc.h index bd2feb53c..d096ac2c2 100644 --- a/include/grub/misc.h +++ b/include/grub/misc.h @@ -24,6 +24,7 @@ #include #include #include +#include /* XXX: If pupa_memmove is too slow, we must implement pupa_memcpy. */ #define pupa_memcpy(d,s,n) pupa_memmove ((d), (s), (n)) @@ -43,6 +44,8 @@ char *EXPORT_FUNC(pupa_strrchr) (const char *s, int c); int EXPORT_FUNC(pupa_isspace) (int c); int EXPORT_FUNC(pupa_isprint) (int c); int EXPORT_FUNC(pupa_isalpha) (int c); +int EXPORT_FUNC(pupa_isgraph) (int c); +int EXPORT_FUNC(pupa_isdigit) (int c); int EXPORT_FUNC(pupa_tolower) (int c); unsigned long EXPORT_FUNC(pupa_strtoul) (const char *str, char **end, int base); char *EXPORT_FUNC(pupa_strdup) (const char *s); @@ -54,5 +57,8 @@ int EXPORT_FUNC(pupa_vprintf) (const char *fmt, va_list args); int EXPORT_FUNC(pupa_sprintf) (char *str, const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); int EXPORT_FUNC(pupa_vsprintf) (char *str, const char *fmt, va_list args); void EXPORT_FUNC(pupa_stop) (void) __attribute__ ((noreturn)); +pupa_err_t EXPORT_FUNC(pupa_split_cmdline) (const char *str, + pupa_err_t (* getline) (char **), + int *argc, char ***argv); #endif /* ! PUPA_MISC_HEADER */ diff --git a/include/grub/normal.h b/include/grub/normal.h index 9a14f5c78..1d1f7edce 100644 --- a/include/grub/normal.h +++ b/include/grub/normal.h @@ -24,6 +24,7 @@ #include #include #include +#include /* The maximum size of a command-line. */ #define PUPA_MAX_CMDLINE 1600 @@ -46,7 +47,7 @@ struct pupa_command const char *name; /* The callback function. */ - int (*func) (int argc, char *argv[]); + pupa_err_t (*func) (struct pupa_arg_list *state, int argc, char **args); /* The flags. */ unsigned flags; @@ -57,6 +58,9 @@ struct pupa_command /* The description of the command. */ const char *description; + /* The argument parser optionlist. */ + const struct pupa_arg_option *options; + /* The next element. */ struct pupa_command *next; }; @@ -120,10 +124,12 @@ void pupa_cmdline_run (int nested); int pupa_cmdline_get (const char *prompt, char cmdline[], unsigned max_len, int echo_char, int readline); void EXPORT_FUNC(pupa_register_command) (const char *name, - int (*func) (int argc, char *argv[]), + pupa_err_t (*func) (struct pupa_arg_list *state, + int argc, char **args), unsigned flags, const char *summary, - const char *description); + const char *description, + const struct pupa_arg_option *parser); void EXPORT_FUNC(pupa_unregister_command) (const char *name); pupa_command_t pupa_command_find (char *cmdline); pupa_err_t pupa_set_history (int newsize); @@ -131,10 +137,25 @@ int pupa_iterate_commands (int (*iterate) (pupa_command_t)); int pupa_command_execute (char *cmdline); void pupa_command_init (void); void pupa_normal_init_page (void); +int pupa_arg_parse (pupa_command_t parser, int argc, char **argv, + struct pupa_arg_list *usr, char ***args, int *argnum); + #ifdef PUPA_UTIL void pupa_normal_init (void); void pupa_normal_fini (void); +void pupa_hello_init (void); +void pupa_hello_fini (void); +void pupa_ls_init (void); +void pupa_ls_fini (void); +void pupa_cat_init (void); +void pupa_cat_fini (void); +void pupa_boot_init (void); +void pupa_boot_fini (void); +void pupa_cmp_init (void); +void pupa_cmp_fini (void); +void pupa_terminal_init (void); +void pupa_terminal_fini (void); #endif #endif /* ! PUPA_NORMAL_HEADER */ diff --git a/include/grub/term.h b/include/grub/term.h index b0f9e6ce2..f1ecdf7af 100644 --- a/include/grub/term.h +++ b/include/grub/term.h @@ -124,6 +124,7 @@ void EXPORT_FUNC(pupa_setcolor) (pupa_uint8_t normal_color, pupa_uint8_t highlight_color); int EXPORT_FUNC(pupa_setcursor) (int on); void EXPORT_FUNC(pupa_refresh) (void); +void EXPORT_FUNC(pupa_set_more) (int onoff); /* For convenience. */ #define PUPA_TERM_ASCII_CHAR(c) ((c) & 0xff) diff --git a/kern/disk.c b/kern/disk.c index f7520b03d..ed514afed 100644 --- a/kern/disk.c +++ b/kern/disk.c @@ -24,6 +24,7 @@ #include #include #include +#include #define PUPA_CACHE_TIMEOUT 2 @@ -498,3 +499,44 @@ pupa_disk_write (pupa_disk_t disk, unsigned long sector, return pupa_errno; } + +pupa_err_t +pupa_print_partinfo (pupa_device_t disk, char *partname) +{ + pupa_fs_t fs = 0; + pupa_device_t part; + char devname[20]; + + pupa_sprintf (devname, "%s,%s", disk->disk->name, partname); + part = pupa_device_open (devname); + if (!part) + pupa_printf ("\tPartition num:%s, Filesystem cannot be accessed", + partname); + else + { + char *label; + + fs = pupa_fs_probe (part); + /* Ignore all errors. */ + pupa_errno = 0; + + pupa_printf ("\tPartition num:%s, Filesystem type %s", + partname, fs ? fs->name : "Unknown"); + + if (fs) + { + (fs->label) (part, &label); + if (pupa_errno == PUPA_ERR_NONE) + { + if (label && pupa_strlen (label)) + pupa_printf (", Label: %s", label); + pupa_free (label); + } + pupa_errno = PUPA_ERR_NONE; + } + pupa_device_close (part); + } + + pupa_printf ("\n"); + return pupa_errno; +} diff --git a/kern/dl.c b/kern/dl.c index 1a05968b9..860c93dc2 100644 --- a/kern/dl.c +++ b/kern/dl.c @@ -1,7 +1,7 @@ /* dl.c - loadable module support */ /* * PUPA -- Preliminary Universal Programming Architecture for GRUB - * Copyright (C) 2002 Free Software Foundation, Inc. + * Copyright (C) 2002, 2003 Free Software Foundation, Inc. * * PUPA is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,6 +27,7 @@ #include #include #include +#include #if PUPA_HOST_SIZEOF_VOID_P == 4 @@ -556,14 +557,13 @@ pupa_dl_load_file (const char *filename) return mod; } -static char *pupa_dl_dir; - /* Load a module using a symbolic name. */ pupa_dl_t pupa_dl_load (const char *name) { char *filename; pupa_dl_t mod; + char *pupa_dl_dir = pupa_env_get ("prefix"); mod = pupa_dl_get (name); if (mod) @@ -664,15 +664,3 @@ pupa_dl_unload_all (void) p->mod->ref_count--; } } - -void -pupa_dl_set_prefix (const char *dir) -{ - pupa_dl_dir = (char *) dir; -} - -const char * -pupa_dl_get_prefix (void) -{ - return pupa_dl_dir; -} diff --git a/kern/env.c b/kern/env.c new file mode 100644 index 000000000..5d667f2fc --- /dev/null +++ b/kern/env.c @@ -0,0 +1,209 @@ +/* env.c - Environment variables */ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2003 Free Software Foundation, Inc. + * + * PUPA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include + +/* XXX: What would be a good size for the hashtable? */ +#define HASHSZ 123 + +/* A hashtable for quick lookup of variables. */ +static struct pupa_env_var *pupa_env[HASHSZ]; + +/* The variables in a sorted list. */ +static struct pupa_env_var *pupa_env_sorted; + +/* Return the hash representation of the string S. */ +static unsigned int pupa_env_hashval (const char *s) +{ + unsigned int i = 0; + + /* XXX: This can be done much more effecient. */ + while (*s) + i += 5 * *(s++); + + return i % HASHSZ; +} + +static struct pupa_env_var * +pupa_env_find (const char *name) +{ + struct pupa_env_var *var; + int idx = pupa_env_hashval (name); + + for (var = pupa_env[idx]; var; var = var->next) + if (! pupa_strcmp (var->name, name)) + return var; + return 0; +} + +pupa_err_t +pupa_env_set (const char *var, const char *val) +{ + int idx = pupa_env_hashval (var); + struct pupa_env_var *env; + struct pupa_env_var *sort; + struct pupa_env_var **sortp; + + /* If the variable does already exist, just update the variable. */ + env = pupa_env_find (var); + if (env) + { + char *old = env->value; + env->value = pupa_strdup (val); + if (! env->name) + { + env->value = old; + return pupa_errno; + } + + if (env->write_hook) + (env->write_hook) (env); + + pupa_free (old); + return 0; + } + + /* The variable does not exist, create it. */ + env = pupa_malloc (sizeof (struct pupa_env_var)); + if (! env) + return pupa_errno; + + pupa_memset (env, 0, sizeof (struct pupa_env_var)); + + env->name = pupa_strdup (var); + if (! env->name) + goto fail; + + env->value = pupa_strdup (val); + if (! env->name) + goto fail; + + /* Insert it in the hashtable. */ + env->prevp = &pupa_env[idx]; + env->next = pupa_env[idx]; + if (pupa_env[idx]) + pupa_env[idx]->prevp = &env->next; + pupa_env[idx] = env; + + /* Insert it in the sorted list. */ + sortp = &pupa_env_sorted; + sort = pupa_env_sorted; + while (sort) + { + if (pupa_strcmp (sort->name, var) > 0) + break; + + sortp = &sort->sort_next; + sort = sort->sort_next; + } + env->sort_prevp = sortp; + env->sort_next = sort; + if (sort) + sort->sort_prevp = &env->sort_next; + *sortp = env; + + fail: + if (pupa_errno) + { + pupa_free (env->name); + pupa_free (env->value); + pupa_free (env); + } + + return 0; +} + +char * +pupa_env_get (const char *name) +{ + struct pupa_env_var *env; + env = pupa_env_find (name); + if (! env) + return 0; + + if (env->read_hook) + { + char *val; + env->read_hook (env, &val); + + return val; + } + + return env->value; +} + +void +pupa_env_unset (const char *name) +{ + struct pupa_env_var *env; + env = pupa_env_find (name); + if (! env) + return; + + /* XXX: It is not possible to unset variables with a read or write + hook. */ + if (env->read_hook || env->write_hook) + return; + + *env->prevp = env->next; + if (env->next) + env->next->prevp = env->prevp; + + *env->sort_prevp = env->sort_next; + if (env->sort_next) + env->sort_next->sort_prevp = env->sort_prevp; + + pupa_free (env->name); + pupa_free (env->value); + pupa_free (env); + return; +} + +void +pupa_env_iterate (int (* func) (struct pupa_env_var *var)) +{ + struct pupa_env_var *env; + + for (env = pupa_env_sorted; env; env = env->sort_next) + if (func (env)) + return; +} + +pupa_err_t +pupa_register_variable_hook (const char *var, + pupa_err_t (*read_hook) (struct pupa_env_var *var, char **), + pupa_err_t (*write_hook) (struct pupa_env_var *var)) +{ + struct pupa_env_var *env = pupa_env_find (var); + + if (! env) + if (pupa_env_set (var, "") != PUPA_ERR_NONE) + return pupa_errno; + + env = pupa_env_find (var); + /* XXX Insert an assertion? */ + + env->read_hook = read_hook; + env->write_hook = write_hook; + + return PUPA_ERR_NONE; +} diff --git a/kern/i386/pc/init.c b/kern/i386/pc/init.c index 020f68506..3ddec9203 100644 --- a/kern/i386/pc/init.c +++ b/kern/i386/pc/init.c @@ -1,6 +1,6 @@ /* * PUPA -- Preliminary Universal Programming Architecture for GRUB - * Copyright (C) 2002 Free Software Foundation, Inc. + * Copyright (C) 2002, 2003 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,6 +29,7 @@ #include #include #include +#include struct mem_region { @@ -222,6 +223,7 @@ pupa_machine_init (void) /* The memory system was initialized, thus register built-in devices. */ pupa_biosdisk_init (); + /* Initialize the prefix. */ - pupa_dl_set_prefix (make_install_device ()); + pupa_env_set ("prefix", make_install_device ()); } diff --git a/kern/main.c b/kern/main.c index 4c6b9066b..4ff5cf03f 100644 --- a/kern/main.c +++ b/kern/main.c @@ -1,7 +1,7 @@ /* main.c - the kernel main routine */ /* * PUPA -- Preliminary Universal Programming Architecture for GRUB - * Copyright (C) 2002 Free Software Foundation, Inc. + * Copyright (C) 2002, 2003 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,6 +27,7 @@ #include #include #include +#include /* Return the end of the core image. */ pupa_addr_t @@ -65,7 +66,7 @@ pupa_set_root_dev (void) { const char *prefix; - prefix = pupa_dl_get_prefix (); + prefix = pupa_env_get ("prefix"); if (prefix) { diff --git a/kern/misc.c b/kern/misc.c index 1c5513fd9..a47adac83 100644 --- a/kern/misc.c +++ b/kern/misc.c @@ -23,6 +23,7 @@ #include #include #include +#include void * pupa_memmove (void *dest, const void *src, pupa_size_t n) @@ -211,6 +212,18 @@ pupa_isalpha (int c) return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); } +int +pupa_isdigit (int c) +{ + return (c >= '0' && c <= '9'); +} + +int +pupa_isgraph (int c) +{ + return (c >= '!' && c <= '~'); +} + int pupa_tolower (int c) { @@ -380,6 +393,24 @@ pupa_itoa (char *str, int c, unsigned n) return p; } +static char * +pupa_ftoa (char *str, double f, int round) +{ + unsigned int intp; + unsigned int fractp; + unsigned int power = 1; + int i; + + for (i = 0; i < round; i++) + power *= 10; + + intp = f; + fractp = (f - (float) intp) * power; + + pupa_sprintf (str, "%d.%d", intp, fractp); + return str; +} + int pupa_vsprintf (char *str, const char *fmt, va_list args) { @@ -387,6 +418,7 @@ pupa_vsprintf (char *str, const char *fmt, va_list args) int count = 0; auto void write_char (unsigned char ch); auto void write_str (const char *s); + auto void write_fill (const char ch, int n); void write_char (unsigned char ch) { @@ -403,6 +435,13 @@ pupa_vsprintf (char *str, const char *fmt, va_list args) while (*s) write_char (*s++); } + + void write_fill (const char ch, int n) + { + int i; + for (i = 0; i < n; i++) + write_char (ch); + } while ((c = *fmt++) != 0) { @@ -412,10 +451,50 @@ pupa_vsprintf (char *str, const char *fmt, va_list args) { char tmp[16]; char *p; + unsigned int format1 = 0; + unsigned int format2 = 3; + char zerofill = ' '; + int rightfill = 0; int n; - c = *fmt++; + if (*fmt && *fmt =='-') + { + rightfill = 1; + fmt++; + } + p = (char *) fmt; + /* Read formatting parameters. */ + while (*p && pupa_isdigit (*p)) + p++; + + if (p > fmt) + { + char s[p - fmt]; + pupa_strncpy (s, fmt, p - fmt); + if (s[0] == '0') + zerofill = '0'; + format1 = pupa_strtoul (s, 0, 10); + fmt = p; + if (*p && *p == '.') + { + p++; + fmt++; + while (*p && pupa_isdigit (*p)) + p++; + + if (p > fmt) + { + char fstr[p - fmt]; + pupa_strncpy (fstr, fmt, p - fmt); + format2 = pupa_strtoul (fstr, 0, 10); + fmt = p; + } + } + } + + c = *fmt++; + switch (c) { case 'p': @@ -427,14 +506,31 @@ pupa_vsprintf (char *str, const char *fmt, va_list args) case 'd': n = va_arg (args, int); pupa_itoa (tmp, c, n); + if (!rightfill && pupa_strlen (tmp) < format1) + write_fill (zerofill, format1 - pupa_strlen (tmp)); write_str (tmp); + if (rightfill && pupa_strlen (tmp) < format1) + write_fill (zerofill, format1 - pupa_strlen (tmp)); break; - + case 'c': n = va_arg (args, int); write_char (n & 0xff); break; + case 'f': + { + float f; + f = va_arg (args, double); + pupa_ftoa (tmp, f, format2); + if (!rightfill && pupa_strlen (tmp) < format1) + write_fill (zerofill, format1 - pupa_strlen (tmp)); + write_str (tmp); + if (rightfill && pupa_strlen (tmp) < format1) + write_fill (zerofill, format1 - pupa_strlen (tmp)); + break; + } + case 'C': { pupa_uint32_t code = va_arg (args, pupa_uint32_t); @@ -488,9 +584,18 @@ pupa_vsprintf (char *str, const char *fmt, va_list args) case 's': p = va_arg (args, char *); if (p) - write_str (p); + { + if (!rightfill && pupa_strlen (p) < format1) + write_fill (zerofill, format1 - pupa_strlen (p)); + + write_str (p); + + if (rightfill && pupa_strlen (p) < format1) + write_fill (zerofill, format1 - pupa_strlen (p)); + } else write_str ("(null)"); + break; default: @@ -521,3 +626,224 @@ pupa_sprintf (char *str, const char *fmt, ...) return ret; } + +pupa_err_t +pupa_split_cmdline (const char *cmdline, pupa_err_t (* getline) (char **), int *argc, char ***argv) +{ + /* XXX: Fixed size buffer, perhaps this buffer should be dynamically + allocated. */ + char buffer[1024]; + char *bp = buffer; + char *rd = (char *) cmdline; + char unputbuf; + int unput = 0; + char *args; + int i; + + auto char getchar (void); + auto void unputc (char c); + auto void getenvvar (void); + auto int getarg (void); + + /* Get one character from the commandline. If the caller reads + beyond the end of the string a new line will be read. This + function will not chech for errors, the caller has to check for + pupa_errno. */ + char getchar (void) + { + int c; + if (unput) + { + unput = 0; + return unputbuf; + } + + if (! rd) + { + getline (&rd); + /* Error is ignored here, the caller will check for this + when it reads beyond the EOL. */ + c = *(rd)++; + return c; + } + + c = *(rd)++; + if (! c) + { + rd = 0; + return '\n'; + } + + return c; + } + + void unputc (char c) + { + unputbuf = c; + unput = 1; + } + + /* Read a variable name from the commandline and insert its content + into the buffer. */ + void getenvvar (void) + { + char varname[100]; + char *p = varname; + char *val; + char c; + + c = getchar (); + if (c == '{') + while ((c = getchar ()) != '}') + *(p++) = c; + else + { + /* XXX: An env. variable can have characters and digits in + its name, are more characters allowed here? */ + while (c && (pupa_isalpha (c) || pupa_isdigit (c))) + { + *(p++) = c; + c = getchar (); + } + unputc (c); + } + *p = '\0'; + + /* The variable does not exist. */ + val = pupa_env_get (varname); + if (! val) + return; + + /* Copy the contents of the variable into the buffer. */ + for (p = val; *p; p++) + *(bp++) = *p; + } + + /* Read one argument. Return 1 if no variables can be read anymore, + otherwise return 0. If there is an error, return 1, the caller + has to check pupa_errno. */ + int getarg (void) + { + char c; + + /* Skip all whitespaces before an argument. */ + do { + c = getchar (); + } while (c == ' ' || c == '\t'); + + do { + switch (c) + { + case '"': + /* Double quote. */ + while ((c = getchar ())) + { + if (pupa_errno) + return 1; + /* Read in an escaped character. */ + if (c == '\\') + { + c = getchar (); + *(bp++) = c; + continue; + } + else if (c == '"') + break; + /* Read a variable. */ + if (c == '$') + { + getenvvar (); + continue; + } + *(bp++) = c; + } + break; + + case '\'': + /* Single quote. */ + while ((c = getchar ()) != '\'') + { + if (pupa_errno) + return 1; + + *(bp++) = c; + } + break; + + case '\n': + /* This was not a argument afterall. */ + return 1; + + default: + /* A normal option. */ + while (c && (pupa_isalpha (c) + || pupa_isdigit (c) || pupa_isgraph (c))) + { + /* Read in an escaped character. */ + if (c == '\\') + { + c = getchar (); + *(bp++) = c; + c = getchar (); + continue; + } + /* Read a variable. */ + if (c == '$') + { + getenvvar (); + c = getchar (); + continue; + } + *(bp++) = c; + c = getchar (); + } + unputc (c); + + break; + } + } while (! pupa_isspace (c) && c != '\'' && c != '"'); + + return 0; + } + + /* Read in all arguments and count them. */ + *argc = 0; + while (1) + { + if (getarg ()) + break; + *(bp++) = '\0'; + (*argc)++; + } + + /* Check if there were no errors. */ + if (pupa_errno) + return pupa_errno; + + /* Reserve memory for the return values. */ + args = pupa_malloc (bp - buffer); + if (! args) + return pupa_errno; + pupa_memcpy (args, buffer, bp - buffer); + + *argv = pupa_malloc (sizeof (char *) * (*argc + 1)); + if (! *argv) + { + pupa_free (args); + return pupa_errno; + } + + /* The arguments are separated with 0's, setup argv so it points to + the right values. */ + bp = args; + for (i = 0; i < *argc; i++) + { + (*argv)[i] = bp; + while (*bp) + bp++; + bp++; + } + + (*argc)--; + return 0; +} diff --git a/kern/rescue.c b/kern/rescue.c index 1a2897f90..9c9382342 100644 --- a/kern/rescue.c +++ b/kern/rescue.c @@ -1,7 +1,7 @@ /* rescue.c - rescue mode */ /* * PUPA -- Preliminary Universal Programming Architecture for GRUB - * Copyright (C) 2002 Free Software Foundation, Inc. + * Copyright (C) 2002, 2003 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,6 +29,7 @@ #include #include #include +#include #define PUPA_RESCUE_BUF_SIZE 256 #define PUPA_RESCUE_MAX_ARGS 20 @@ -116,29 +117,6 @@ pupa_rescue_get_command_line (const char *prompt) pupa_refresh (); } -/* Get the next word in STR and return a next pointer. */ -static char * -next_word (char **str) -{ - char *word; - char *p = *str; - - /* Skip spaces. */ - while (*p && pupa_isspace (*p)) - p++; - - word = p; - - /* Find a space. */ - while (*p && ! pupa_isspace (*p)) - p++; - - *p = '\0'; - *str = p + 1; - - return word; -} - /* boot */ static void pupa_rescue_cmd_boot (int argc __attribute__ ((unused)), @@ -506,27 +484,6 @@ pupa_rescue_cmd_dump (int argc, char *argv[]) } } -/* prefix [DIR] */ -static void -pupa_rescue_cmd_prefix (int argc, char *argv[]) -{ - static char prefix[100]; - - if (argc == 0) - pupa_printf ("%s\n", pupa_dl_get_prefix ()); - else - { - if (pupa_strlen (argv[0]) >= sizeof (prefix)) - { - pupa_error (PUPA_ERR_BAD_ARGUMENT, "too long prefix"); - return; - } - - pupa_strcpy (prefix, argv[0]); - pupa_dl_set_prefix (prefix); - } -} - /* insmod MODULE */ static void pupa_rescue_cmd_insmod (int argc, char *argv[]) @@ -602,6 +559,52 @@ pupa_rescue_cmd_lsmod (int argc __attribute__ ((unused)), pupa_dl_iterate (print_module); } +/* set ENVVAR=VALUE */ +static void +pupa_rescue_cmd_set (int argc, char *argv[]) +{ + char *var; + char *val; + + auto int print_env (struct pupa_env_var *env); + + int print_env (struct pupa_env_var *env) + { + pupa_printf ("%s=%s\n", env->name, env->value); + return 0; + } + + if (argc < 1) + { + pupa_env_iterate (print_env); + return; + } + + var = argv[0]; + val = pupa_strchr (var, '='); + if (! val) + { + pupa_error (PUPA_ERR_BAD_ARGUMENT, "not an assignment"); + return; + } + + val[0] = 0; + pupa_env_set (var, val + 1); + val[0] = '='; +} + +static void +pupa_rescue_cmd_unset (int argc, char *argv[]) +{ + if (argc < 1) + { + pupa_error (PUPA_ERR_BAD_ARGUMENT, "no environment variable specified"); + return; + } + + pupa_env_unset (argv[0]); +} + static void attempt_normal_mode (void) { @@ -621,6 +624,15 @@ attempt_normal_mode (void) void pupa_enter_rescue_mode (void) { + auto pupa_err_t getline (char **line); + + pupa_err_t getline (char **line) + { + pupa_rescue_get_command_line ("> "); + *line = linebuf; + return 0; + } + /* First of all, attempt to execute the normal mode. */ attempt_normal_mode (); @@ -638,14 +650,16 @@ pupa_enter_rescue_mode (void) "set the root device"); pupa_rescue_register_command ("dump", pupa_rescue_cmd_dump, "dump memory"); - pupa_rescue_register_command ("prefix", pupa_rescue_cmd_prefix, - "set the prefix"); pupa_rescue_register_command ("insmod", pupa_rescue_cmd_insmod, "insert a module"); pupa_rescue_register_command ("rmmod", pupa_rescue_cmd_rmmod, "remove a module"); pupa_rescue_register_command ("lsmod", pupa_rescue_cmd_lsmod, "show loaded modules"); + pupa_rescue_register_command ("set", pupa_rescue_cmd_set, + "set an environment variable"); + pupa_rescue_register_command ("unset", pupa_rescue_cmd_unset, + "remove an environment variable"); while (1) { @@ -653,36 +667,42 @@ pupa_enter_rescue_mode (void) char *name; int n; pupa_rescue_command_t cmd; - char *args[PUPA_RESCUE_MAX_ARGS + 1]; + char **args; + + /* Print an error, if any. */ + pupa_print_error (); + pupa_errno = PUPA_ERR_NONE; /* Get a command line. */ pupa_rescue_get_command_line ("pupa rescue> "); + if (pupa_split_cmdline (line, getline, &n, &args)) + continue; + + /* In case of an assignment set the environment accordingly + instead of calling a function. */ + if (n == 0 && pupa_strchr (line, '=')) + { + char *val = pupa_strchr (args[0], '='); + val[0] = 0; + pupa_env_set (args[0], val + 1); + val[0] = '='; + continue; + } + /* Get the command name. */ - name = next_word (&line); + name = args[0]; /* If nothing is specified, restart. */ if (*name == '\0') continue; - /* Get arguments. */ - for (n = 0; n <= PUPA_RESCUE_MAX_ARGS; n++) - { - char *arg = next_word (&line); - - if (*arg) - args[n] = arg; - else - break; - } - args[n] = 0; - /* Find the command and execute it. */ for (cmd = pupa_rescue_command_list; cmd; cmd = cmd->next) { if (pupa_strcmp (name, cmd->name) == 0) { - (cmd->func) (n, args); + (cmd->func) (n, &args[1]); break; } } @@ -693,9 +713,5 @@ pupa_enter_rescue_mode (void) pupa_printf ("Unknown command `%s'\n", name); pupa_printf ("Try `help' for usage\n"); } - - /* Print an error, if any. */ - pupa_print_error (); - pupa_errno = PUPA_ERR_NONE; } } diff --git a/kern/term.c b/kern/term.c index a551444cb..e66f353ed 100644 --- a/kern/term.c +++ b/kern/term.c @@ -20,6 +20,7 @@ #include #include #include +#include /* The list of terminals. */ static pupa_term_t pupa_term_list; @@ -27,6 +28,12 @@ static pupa_term_t pupa_term_list; /* The current terminal. */ static pupa_term_t pupa_cur_term; +/* The amount of lines counted by the pager. */ +static int pupa_more_lines; + +/* If the more pager is active. */ +static int pupa_more; + void pupa_term_register (pupa_term_t term) { @@ -97,7 +104,36 @@ pupa_putcode (pupa_uint32_t code) (pupa_cur_term->putchar) (code); if (code == '\n') - pupa_putcode ('\r'); + { + pupa_putcode ('\r'); + + pupa_more_lines++; + /* XXX: Don't use a fixed height! */ + if (pupa_more && pupa_more_lines == 24 - 1) + { + char key; + int pos = pupa_getxy (); + + /* Show --MORE-- on the lower left side of the screen. */ + pupa_gotoxy (1, 24 - 1); + pupa_setcolorstate (PUPA_TERM_COLOR_HIGHLIGHT); + pupa_printf ("--MORE--"); + pupa_setcolorstate (PUPA_TERM_COLOR_STANDARD); + + key = pupa_getkey (); + + /* Remove the message. */ + pupa_gotoxy (1, 24 -1); + pupa_printf (" "); + pupa_gotoxy (pos >> 8, pos & 0xFF); + + /* Scroll one lines or an entire page, depending on the key. */ + if (key == '\r' || key =='\n') + pupa_more_lines--; + else + pupa_more_lines = 0; + } + } } /* Put a character. C is one byte of a UTF-8 stream. @@ -235,3 +271,14 @@ pupa_refresh (void) if (pupa_cur_term->refresh) (pupa_cur_term->refresh) (); } + +void +pupa_set_more (int onoff) +{ + if (onoff == 1) + pupa_more++; + else + pupa_more--; + + pupa_more_lines = 0; +} diff --git a/loader/i386/pc/linux.c b/loader/i386/pc/linux.c index 5a57eda5e..b66137374 100644 --- a/loader/i386/pc/linux.c +++ b/loader/i386/pc/linux.c @@ -290,7 +290,8 @@ pupa_rescue_cmd_linux (int argc, char *argv[]) } void -pupa_rescue_cmd_initrd (int argc, char *argv[]) +pupa_rescue_cmd_initrd (int argc __attribute__ ((unused)), + char *argv[] __attribute__ ((unused))) { pupa_file_t file = 0; pupa_ssize_t size; diff --git a/loader/i386/pc/multiboot.c b/loader/i386/pc/multiboot.c index a9d9714d5..7757affe8 100644 --- a/loader/i386/pc/multiboot.c +++ b/loader/i386/pc/multiboot.c @@ -61,7 +61,7 @@ pupa_multiboot_unload (void) { if (mbi) { - int i; + unsigned int i; for (i = 0; i < mbi->mods_count; i++) { pupa_free ((void *) diff --git a/normal/arg.c b/normal/arg.c new file mode 100644 index 000000000..01ad717df --- /dev/null +++ b/normal/arg.c @@ -0,0 +1,354 @@ +/* arg.c - argument parser */ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2003, 2004 Free Software Foundation, Inc. + * + * PUPA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "pupa/arg.h" +#include "pupa/misc.h" +#include "pupa/mm.h" +#include "pupa/err.h" +#include "pupa/normal.h" + +/* Build in parser for default options. */ +static const struct pupa_arg_option help_options[] = + { + {"help", 'h', 0, "Display help", 0, ARG_TYPE_NONE}, + {"usage", 'u', 0, "Show how to use this command", 0, ARG_TYPE_NONE}, + {0, 0, 0, 0, 0, 0} + }; + +static struct pupa_arg_option * +find_short (const struct pupa_arg_option *options, char c) +{ + struct pupa_arg_option *found = 0; + auto struct pupa_arg_option *fnd_short (const struct pupa_arg_option *opt); + + struct pupa_arg_option *fnd_short (const struct pupa_arg_option *opt) + { + while (opt->doc) + { + if (opt->shortarg == c) + return (struct pupa_arg_option *) opt; + opt++; + } + return 0; + } + + if (options) + found = fnd_short (options); + if (! found) + found = fnd_short (help_options); + + return found; +} + +static char * +find_long_option (char *s) +{ + char *argpos = pupa_strchr (s, '='); + + if (argpos) + { + *argpos = '\0'; + return ++argpos; + } + return 0; +} + +static struct pupa_arg_option * +find_long (const struct pupa_arg_option *options, char *s) +{ + struct pupa_arg_option *found = 0; + auto struct pupa_arg_option *fnd_long (const struct pupa_arg_option *opt); + + struct pupa_arg_option *fnd_long (const struct pupa_arg_option *opt) + { + while (opt->doc) + { + if (opt->longarg && !pupa_strcmp (opt->longarg, s)) + return (struct pupa_arg_option *) opt; + opt++; + } + return 0; + } + + if (options) + found = fnd_long (options); + if (!found) + found = fnd_long (help_options); + + return found; +} + +static void +show_usage (pupa_command_t cmd) +{ + pupa_printf ("Usage: %s\n", cmd->summary); +} + +static void +show_help (pupa_command_t cmd) +{ + static void showargs (const struct pupa_arg_option *opt) + { + for (; opt->doc; opt++) + { + if (opt->shortarg && pupa_isgraph (opt->shortarg)) + pupa_printf ("-%c%c ", opt->shortarg, opt->longarg ? ',':' '); + else + pupa_printf (" "); + if (opt->longarg) + { + pupa_printf ("--%s", opt->longarg); + if (opt->arg) + pupa_printf ("=%s", opt->arg); + } + else + pupa_printf ("\t"); + + pupa_printf ("\t\t%s\n", opt->doc); + } + } + + show_usage (cmd); + pupa_printf ("%s\n\n", cmd->description); + if (cmd->options) + showargs (cmd->options); + showargs (help_options); + pupa_printf ("\nReport bugs to <%s>.\n", PACKAGE_BUGREPORT); +} + + +static int +parse_option (pupa_command_t cmd, int key, char *arg, struct pupa_arg_list *usr) +{ + switch (key) + { + case 'h': + show_help (cmd); + return -1; + + case 'u': + show_usage (cmd); + return -1; + + default: + { + int found = -1; + int i = 0; + const struct pupa_arg_option *opt = cmd->options; + + while (opt->doc) + { + if (opt->shortarg && key == opt->shortarg) + { + found = i; + break; + } + opt++; + i++; + } + + if (found == -1) + return -1; + + usr[found].set = 1; + usr[found].arg = arg; + } + } + + return 0; +} + +int +pupa_arg_parse (pupa_command_t cmd, int argc, char **argv, + struct pupa_arg_list *usr, char ***args, int *argnum) +{ + int curarg; + char *longarg = 0; + int complete = 0; + char **argl = 0; + int num = 0; + auto pupa_err_t add_arg (char *s); + + pupa_err_t add_arg (char *s) + { + argl = pupa_realloc (argl, (++num) * sizeof (char *)); + if (! args) + return pupa_errno; + argl[num - 1] = s; + return 0; + } + + + for (curarg = 0; curarg < argc; curarg++) + { + char *arg = argv[curarg]; + struct pupa_arg_option *opt; + char *option = 0; + + /* No option is used. */ + if (arg[0] != '-' || pupa_strlen (arg) == 1) + { + if (add_arg (arg) != 0) + goto fail; + + continue; + } + + /* One or more short options. */ + if (arg[1] != '-') + { + char *curshort = arg + 1; + + while (1) + { + opt = find_short (cmd->options, *curshort); + if (!opt) + { + pupa_error (PUPA_ERR_BAD_ARGUMENT, + "Unknown argument `-%c'\n", *curshort); + goto fail; + } + + curshort++; + + /* Parse all arguments here except the last one because + it can have an argument value. */ + if (*curshort) + { + if (parse_option (cmd, opt->shortarg, 0, usr) || pupa_errno) + goto fail; + } + else + { + if (opt->type != ARG_TYPE_NONE) + { + if (curarg + 1 < argc) + { + char *nextarg = argv[curarg + 1]; + if (!(opt->flags & PUPA_ARG_OPTION_OPTIONAL) + || (pupa_strlen (nextarg) < 2 || nextarg[0] != '-')) + option = argv[++curarg]; + } + } + break; + } + } + + } + else /* The argument starts with "--". */ + { + /* If the argument "--" is used just pass the other + arguments. */ + if (pupa_strlen (arg) == 2) + { + for (curarg++; curarg < argc; curarg++) + if (add_arg (arg) != 0) + goto fail; + break; + } + + longarg = (char *) pupa_strdup (arg); + if (! longarg) + goto fail; + + option = find_long_option (longarg); + arg = longarg; + + opt = find_long (cmd->options, arg + 2); + if (!opt) + { + pupa_error (PUPA_ERR_BAD_ARGUMENT, "Unknown argument `%s'\n", arg); + goto fail; + } + } + + if (! (opt->type == ARG_TYPE_NONE + || (!option && (opt->flags & PUPA_ARG_OPTION_OPTIONAL)))) + { + if (!option) + { + pupa_error (PUPA_ERR_BAD_ARGUMENT, + "Missing mandatory option for `%s'\n", opt->longarg); + goto fail; + } + + switch (opt->type) + { + case ARG_TYPE_NONE: + /* This will never happen. */ + break; + + case ARG_TYPE_STRING: + /* No need to do anything. */ + break; + + case ARG_TYPE_INT: + { + char *tail; + + pupa_strtoul (option, &tail, 0); + if (tail == 0 || tail == option || *tail != '\0' || pupa_errno) + { + pupa_error (PUPA_ERR_BAD_ARGUMENT, + "The argument `%s' requires an integer.", + arg); + + goto fail; + } + break; + } + + case ARG_TYPE_DEVICE: + case ARG_TYPE_DIR: + case ARG_TYPE_FILE: + case ARG_TYPE_PATHNAME: + /* XXX: Not implemented. */ + break; + } + if (parse_option (cmd, opt->shortarg, option, usr) || pupa_errno) + goto fail; + } + else + { + if (option) + { + pupa_error (PUPA_ERR_BAD_ARGUMENT, + "A value was assigned to the argument `%s' while it " + "doesn't require an argument\n", arg); + goto fail; + } + + if (parse_option (cmd, opt->shortarg, 0, usr) || pupa_errno) + goto fail; + } + pupa_free (longarg); + longarg = 0; + } + + complete = 1; + + *args = argl; + *argnum = num; + + fail: + pupa_free (longarg); + + return complete; +} diff --git a/normal/cmdline.c b/normal/cmdline.c index 17990a833..9491517ee 100644 --- a/normal/cmdline.c +++ b/normal/cmdline.c @@ -26,6 +26,7 @@ #include #include #include +#include static char *kill_buf; @@ -156,6 +157,18 @@ pupa_tab_complete (char *buf, int *restore) /* String that is added when matched. */ char *matchstr; + auto void print_simple_completion (char *comp); + auto void print_partition_completion (char *comp); + auto int NESTED_FUNC_ATTR add_completion (const char *comp, const char *match, + const char *what, + void (*print_completion) (char *)); + auto int iterate_commands (pupa_command_t cmd); + auto int iterate_dev (const char *devname); + auto int iterate_part (const pupa_partition_t p); + auto int iterate_dir (const char *filename, int dir); + + + void print_simple_completion (char *comp) { pupa_printf (" %s", comp); @@ -163,39 +176,8 @@ pupa_tab_complete (char *buf, int *restore) void print_partition_completion (char *comp) { - pupa_fs_t fs = 0; - pupa_device_t part; - char devname[20]; - - pupa_sprintf (devname, "%s,%s", partdev->disk->name, comp); - part = pupa_device_open (devname); - if (!part) - pupa_printf ("\n\tPartition num:%s, Filesystem cannot be accessed", - comp); - else - { - char *label; - - fs = pupa_fs_probe (part); - /* Ignore all errors. */ - pupa_errno = 0; - - pupa_printf ("\n\tPartition num:%s, Filesystem type %s", - comp, fs ? fs->name : "Unknown"); - - if (fs) - { - (fs->label) (part, &label); - if (pupa_errno == PUPA_ERR_NONE) - { - if (label && pupa_strlen (label)) - pupa_printf (", Label: %s", label); - pupa_free (label); - } - pupa_errno = PUPA_ERR_NONE; - } - pupa_device_close (part); - } + pupa_print_partinfo (partdev, comp); + pupa_errno = 0; } /* Add a string to the list of possible completions. COMP is the @@ -206,9 +188,9 @@ pupa_tab_complete (char *buf, int *restore) multiple matches. XXX: Because of a bug in gcc it is required to use __regparm__ in some cases. */ - int NESTED_FUNC_ATTR - add_completion (const char *comp, const char *match, const char *what, - void (*print_completion) (char *)) + int NESTED_FUNC_ATTR add_completion (const char *comp, const char *match, + const char *what, + void (*print_completion) (char *)) { /* Bug in strncmp then len ==0. */ if (!len || pupa_strncmp (pos, comp, len) == 0) @@ -460,7 +442,6 @@ pupa_cmdline_run (int nested) while (1) { static char cmdline[PUPA_MAX_CMDLINE]; - pupa_command_t cmd; pupa_print_error (); pupa_errno = PUPA_ERR_NONE; @@ -473,17 +454,6 @@ pupa_cmdline_run (int nested) if (! *cmdline) continue; - cmd = pupa_command_find (cmdline); - if (! cmd) - continue; - - if (! (cmd->flags & PUPA_COMMAND_FLAG_CMDLINE)) - { - pupa_error (PUPA_ERR_UNKNOWN_COMMAND, - "invalid command `%s'", cmd->name); - continue; - } - pupa_command_execute (cmdline); } } diff --git a/normal/command.c b/normal/command.c index 800073a60..a75f0c468 100644 --- a/normal/command.c +++ b/normal/command.c @@ -22,15 +22,19 @@ #include #include #include +#include +#include static pupa_command_t pupa_command_list; void pupa_register_command (const char *name, - int (*func) (int argc, char *argv[]), + pupa_err_t (*func) (struct pupa_arg_list *state, + int argc, char **args), unsigned flags, const char *summary, - const char *description) + const char *description, + const struct pupa_arg_option *options) { pupa_command_t cmd, *p; @@ -43,6 +47,7 @@ pupa_register_command (const char *name, cmd->flags = flags; cmd->summary = summary; cmd->description = description; + cmd->options = options; /* Keep the list sorted for simplicity. */ p = &pupa_command_list; @@ -107,66 +112,69 @@ pupa_iterate_commands (int (*iterate) (pupa_command_t)) int pupa_command_execute (char *cmdline) { - pupa_command_t cmd; - char *p; - char **args; - int num = 0; - int i; - int ret; + auto pupa_err_t cmdline_get (char **s); + pupa_err_t cmdline_get (char **s) + { + *s = pupa_malloc (PUPA_MAX_CMDLINE); + *s[0] = '\0'; + return pupa_cmdline_get (">", *s, PUPA_MAX_CMDLINE, 0, 1); + } - cmd = pupa_command_find (cmdline); + pupa_command_t cmd; + pupa_err_t ret = 0; + char *pager; + int num; + char **args; + struct pupa_arg_list *state; + struct pupa_arg_option *parser; + int maxargs = 0; + char **arglist; + int numargs; + + if (pupa_split_cmdline (cmdline, cmdline_get, &num, &args)) + return 0; + + /* In case of an assignment set the environment accordingly instead + of calling a function. */ + if (num == 0 && pupa_strchr (args[0], '=')) + { + char *val = pupa_strchr (args[0], '='); + val[0] = 0; + pupa_env_set (args[0], val + 1); + val[0] = '='; + return 0; + } + + cmd = pupa_command_find (args[0]); if (! cmd) return -1; - /* Count arguments. */ - p = cmdline; - while (1) - { - while (*p && *p != ' ') - p++; + /* Enable the pager if the environment pager is set to 1. */ + pager = pupa_env_get ("pager"); + if (pager && (! pupa_strcmp (pager, "1"))) + pupa_set_more (1); + + parser = (struct pupa_arg_option *) cmd->options; + while (parser && (parser++)->doc) + maxargs++; - if (! *p) - break; - - while (*p == ' ') - p++; - - num++; - } - - args = (char **) pupa_malloc (sizeof (char *) * (num + 1)); - if (! args) - return -1; - - /* Fill arguments. */ - for (i = 0, p = pupa_strchr (cmdline, ' '); i < num && p; i++) - { - if (! p) - break; - - while (*p == ' ') - p++; - - args[i] = p; - - while (*p && *p != ' ') - p++; - - *p++ = '\0'; - } - - /* Terminate the array with NULL. */ - args[i] = 0; - - ret = (cmd->func) (num, args); + state = pupa_malloc (sizeof (struct pupa_arg_list) * maxargs); + pupa_memset (state, 0, sizeof (struct pupa_arg_list) * maxargs); + if (pupa_arg_parse (cmd, num, &args[1], state, &arglist, &numargs)) + ret = (cmd->func) (state, numargs, arglist); + pupa_free (state); + if (pager && (! pupa_strcmp (pager, "1"))) + pupa_set_more (0); + pupa_free (args); return ret; } -static int -rescue_command (int argc __attribute__ ((unused)), - char *argv[] __attribute__ ((unused))) +static pupa_err_t +rescue_command (struct pupa_arg_list *state __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) { pupa_longjmp (pupa_exit_env, 0); @@ -174,61 +182,145 @@ rescue_command (int argc __attribute__ ((unused)), return 0; } -static int -terminal_command (int argc, char *argv[]) + +static pupa_err_t +set_command (struct pupa_arg_list *state __attribute__ ((unused)), + int argc, char **args) { - pupa_term_t term = 0; - - auto int print_terminal (pupa_term_t); - auto int find_terminal (pupa_term_t); - - int print_terminal (pupa_term_t t) + char *var; + char *val; + + auto int print_env (struct pupa_env_var *env); + int print_env (struct pupa_env_var *env) { - pupa_printf (" %s", t->name); + pupa_printf ("%s=%s\n", env->name, env->value); return 0; } - - int find_terminal (pupa_term_t t) + + if (! argc) { - if (pupa_strcmp (t->name, argv[0]) == 0) - { - term = t; - return 1; - } - + pupa_env_iterate (print_env); return 0; } + var = args[0]; + val = pupa_strchr (var, '='); + if (! val) + { + pupa_error (PUPA_ERR_BAD_ARGUMENT, "not an assignment"); + return pupa_errno; + } + + val[0] = 0; + pupa_env_set (var, val + 1); + val[0] = '='; + return 0; +} + +static pupa_err_t +unset_command (struct pupa_arg_list *state __attribute__ ((unused)), + int argc, char **args) +{ + if (argc < 1) + return pupa_error (PUPA_ERR_BAD_ARGUMENT, + "no environment variable specified"); + + pupa_env_unset (args[0]); + return 0; +} + +static pupa_err_t +insmod_command (struct pupa_arg_list *state __attribute__ ((unused)), + int argc, char **args) +{ + char *p; + pupa_dl_t mod; + if (argc == 0) - { - pupa_printf ("Available terminal(s):"); - pupa_term_iterate (print_terminal); - pupa_putchar ('\n'); - - pupa_printf ("Current terminal: %s\n", pupa_term_get_current ()->name); - } + return pupa_error (PUPA_ERR_BAD_ARGUMENT, "no module specified"); + + p = pupa_strchr (args[0], '/'); + if (! p) + mod = pupa_dl_load (args[0]); else - { - pupa_term_iterate (find_terminal); - if (! term) - return pupa_error (PUPA_ERR_BAD_ARGUMENT, "no such terminal"); + mod = pupa_dl_load_file (args[0]); - pupa_term_set_current (term); + if (mod) + pupa_dl_ref (mod); + + return 0; +} + +static pupa_err_t +rmmod_command (struct pupa_arg_list *state __attribute__ ((unused)), + int argc, char **args) +{ + pupa_dl_t mod; + + if (argc == 0) + return pupa_error (PUPA_ERR_BAD_ARGUMENT, "no module specified"); + + mod = pupa_dl_get (args[0]); + if (! mod) + return pupa_error (PUPA_ERR_BAD_ARGUMENT, "no such module"); + + if (! pupa_dl_unref (mod)) + pupa_dl_unload (mod); + + return 0; +} + +static pupa_err_t +lsmod_command (struct pupa_arg_list *state __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + auto int print_module (pupa_dl_t mod); + + int print_module (pupa_dl_t mod) + { + pupa_dl_dep_t dep; + + pupa_printf ("%s\t%d\t\t", mod->name, mod->ref_count); + for (dep = mod->dep; dep; dep = dep->next) + { + if (dep != mod->dep) + pupa_putchar (','); + + pupa_printf ("%s", dep->mod->name); + } + pupa_putchar ('\n'); + pupa_refresh (); + + return 0; } - return PUPA_ERR_NONE; + pupa_printf ("Name\tRef Count\tDependencies\n"); + pupa_dl_iterate (print_module); + return 0; } void pupa_command_init (void) { /* This is a special command, because this never be called actually. */ - pupa_register_command ("title", 0, PUPA_COMMAND_FLAG_TITLE, 0, 0); + pupa_register_command ("title", 0, PUPA_COMMAND_FLAG_TITLE, 0, 0, 0); pupa_register_command ("rescue", rescue_command, PUPA_COMMAND_FLAG_BOTH, - "rescue", - "Enter into the rescue mode."); - pupa_register_command ("terminal", terminal_command, PUPA_COMMAND_FLAG_BOTH, - "terminal [TERM...]", - "Select a terminal."); + "rescue", "Enter into the rescue mode.", 0); + + pupa_register_command ("set", set_command, PUPA_COMMAND_FLAG_BOTH, + "unset ENVVAR", "Set an environment variable.", 0); + + pupa_register_command ("unset", unset_command, PUPA_COMMAND_FLAG_BOTH, + "set [ENVVAR=VALUE]", "Remove an environment variable.", 0); + + pupa_register_command ("insmod", insmod_command, PUPA_COMMAND_FLAG_BOTH, + "insmod MODULE|FILE", "Insert a module.", 0); + + pupa_register_command ("rmmod", rmmod_command, PUPA_COMMAND_FLAG_BOTH, + "rmmod MODULE", "Remove a module.", 0); + + pupa_register_command ("lsmod", lsmod_command, PUPA_COMMAND_FLAG_BOTH, + "lsmod", "Show loaded modules.", 0); } diff --git a/normal/main.c b/normal/main.c index 2a0b08bc0..ddbbfa9da 100644 --- a/normal/main.c +++ b/normal/main.c @@ -26,6 +26,7 @@ #include #include #include +#include pupa_jmp_buf pupa_exit_env; @@ -315,7 +316,7 @@ pupa_rescue_cmd_normal (int argc, char *argv[]) char *config; const char *prefix; - prefix = pupa_dl_get_prefix (); + prefix = pupa_env_get ("prefix"); if (prefix) { config = pupa_malloc (pupa_strlen (prefix) + sizeof ("/pupa.cfg")); diff --git a/term/i386/pc/vga.c b/term/i386/pc/vga.c index 6666c9512..ca750c6af 100644 --- a/term/i386/pc/vga.c +++ b/term/i386/pc/vga.c @@ -25,6 +25,7 @@ #include #include #include +#include #define DEBUG_VGA 0 @@ -215,7 +216,7 @@ invalidate_char (struct colored_char *p) static int check_vga_mem (void *p) { - return p >= VGA_MEM && p <= VGA_MEM + VGA_WIDTH * VGA_HEIGHT / 8; + return p >= (void *) VGA_MEM && p <= (void *) (VGA_MEM + VGA_WIDTH * VGA_HEIGHT / 8); } static void @@ -310,7 +311,9 @@ scroll_up (void) static void pupa_vga_putchar (pupa_uint32_t c) { +#if DEBUG_VGA static int show = 1; +#endif if (c == '\a') /* FIXME */ @@ -469,7 +472,8 @@ pupa_vga_putchar (pupa_uint32_t c) } static void - pupa_vga_setcolor (pupa_uint8_t normal_color, pupa_uint8_t highlight_color) + pupa_vga_setcolor (pupa_uint8_t normal_color __attribute__ ((unused)), + pupa_uint8_t highlight_color __attribute__ ((unused))) { /* FIXME */ } @@ -506,8 +510,10 @@ pupa_vga_putchar (pupa_uint32_t c) .next = 0 }; -static int -debug_command (int argc, char *argv[]) +static pupa_err_t +debug_command (struct pupa_arg_list *state __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) { pupa_printf ("???????กใ??n"); @@ -519,7 +525,7 @@ PUPA_MOD_INIT my_mod = mod; pupa_term_register (&pupa_vga_term); pupa_register_command ("debug", debug_command, PUPA_COMMAND_FLAG_CMDLINE, - "debug", "Debug it!"); + "debug", "Debug it!", 0); } PUPA_MOD_FINI diff --git a/util/grub-emu.c b/util/grub-emu.c index 19cdbc0b0..dc765f5c0 100644 --- a/util/grub-emu.c +++ b/util/grub-emu.c @@ -33,6 +33,7 @@ #include #include #include +#include #ifdef __NetBSD__ /* NetBSD uses /boot for its boot block. */ @@ -77,11 +78,11 @@ const char *argp_program_bug_address = PACKAGE_BUGREPORT; static char doc[] = "PUPA emulator"; static struct argp_option options[] = { - {"root-device", 'r', "DEV", 0, "use DEV as the root device [default=guessed]"}, - {"device-map", 'm', "FILE", 0, "use FILE as the device map"}, - {"directory", 'd', "DIR", 0, "use PUPA files in the directory DIR"}, - {"verbose", 'v', 0 , 0, "print verbose messages"}, - { 0 } + {"root-device", 'r', "DEV", 0, "use DEV as the root device [default=guessed]", 0}, + {"device-map", 'm', "FILE", 0, "use FILE as the device map", 0}, + {"directory", 'd', "DIR", 0, "use PUPA files in the directory DIR", 0}, + {"verbose", 'v', 0 , 0, "print verbose messages", 0}, + { 0, 0, 0, 0, 0, 0 } }; struct arguments @@ -118,7 +119,7 @@ parse_opt (int key, char *arg, struct argp_state *state) return 0; } -static struct argp argp = {options, parse_opt, 0, doc}; +static struct argp argp = {options, parse_opt, 0, doc, 0, 0, 0}; int @@ -148,7 +149,8 @@ main (int argc, char *argv[]) prefix = pupa_get_prefix (args.dir ? : DEFAULT_DIRECTORY); sprintf (rootprefix, "%s%s", args.root_dev, prefix); - pupa_dl_set_prefix (rootprefix); + + pupa_env_set ("prefix", rootprefix); /* XXX: This is a bit unportable. */ pupa_util_biosdisk_init (args.dev_map); @@ -156,6 +158,11 @@ main (int argc, char *argv[]) /* Initialize the default modules. */ pupa_fat_init (); pupa_ext2_init (); + pupa_ls_init (); + pupa_boot_init (); + pupa_cmp_init (); + pupa_cat_init (); + pupa_terminal_init (); /* XXX: Should normal mode be started by default? */ pupa_normal_init (); @@ -167,6 +174,10 @@ main (int argc, char *argv[]) pupa_normal_fini (); pupa_ext2_fini (); pupa_fat_fini (); + pupa_boot_fini (); + pupa_cmp_fini (); + pupa_cat_fini (); + pupa_terminal_fini (); return 0; } diff --git a/util/i386/pc/getroot.c b/util/i386/pc/getroot.c index 9e67a6db7..7dbb2da39 100644 --- a/util/i386/pc/getroot.c +++ b/util/i386/pc/getroot.c @@ -24,6 +24,7 @@ #include #include +#include static void strip_extra_slashes (char *dir) diff --git a/util/misc.c b/util/misc.c index 798994dca..ac2415258 100644 --- a/util/misc.c +++ b/util/misc.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -173,7 +174,7 @@ pupa_util_write_image (const char *img, size_t size, FILE *out) void * pupa_malloc (unsigned size) { - return malloc (size); + return xmalloc (size); } void @@ -185,18 +186,25 @@ pupa_free (void *ptr) void * pupa_realloc (void *ptr, unsigned size) { - return realloc (ptr, size); + return xrealloc (ptr, size); } void * pupa_memalign (pupa_size_t align, pupa_size_t size) { - return memalign (align, size); + void *p; + + p = memalign (align, size); + if (! p) + pupa_util_error ("out of memory"); + + return p; } /* Some functions that we don't use. */ void -pupa_mm_init_region (void *addr, pupa_size_t size) +pupa_mm_init_region (void *addr __attribute__ ((unused)), + pupa_size_t size __attribute__ ((unused))) { }