diff --git a/AUTHORS b/AUTHORS index 88daf5cc0..517459ba4 100644 --- a/AUTHORS +++ b/AUTHORS @@ -2,15 +2,15 @@ VaX#n8 (real name unknown) wrote shared_src/fsys_ext2fs.c. Heiko Schroeder rewrote shared_src/stage1.S to be more readable. -Gordon Matzigkeit adopted GRUB into the GNU Project. He fixed several -bugs, added symbolic link support to shared_src/fsys_ext2fs.c, and -began the implementation of /sbin/grub. - The following authors assigned copyright on their work to the Free Software Foundation: Erich Stefan Boleyn originally designed and implemented GRUB. +Gordon Matzigkeit adopted GRUB into the GNU Project. He fixed several +bugs, added symbolic link support to shared_src/fsys_ext2fs.c, and +began the implementation of /sbin/grub. He was an official maintainer. + Yoshinori K. Okuji contributed many bugfixes and new features, such as working LBA support, /sbin/grub support for configuration files, the script /sbin/grub-install, the utility /bin/mbchk, the new engine for @@ -18,7 +18,8 @@ builtin commands, disk swapping support, keyboard configuration support, network support, online help support, command-line history support, hidden menu support, the new Linux loader, serial terminal support, single-line editing support, the utility /sbin/grub-md5-crypt, the new -GRUB manual, and several new commands. +GRUB manual, and several new commands. He is the current official +maintainer. Peter Astrand added support for a color menu. @@ -42,3 +43,5 @@ Serguei Tzukanov added JFS and XFS support. Jason Thomas added Linux DAC960 support and support for hiding/unhiding logical partitions, and did a significant bugfix for the terminal stuff. + +Tilmann Bubeck added support for vt100-incompatible terminals. diff --git a/ChangeLog b/ChangeLog index 1e278ad6b..b7ecaf6bc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,38 @@ +2002-11-30 Yoshinori K. Okuji + + * docs/Makefile.am (man_MANS): Added grub-terminfo.8. + ($(srcdir)/grub_terminfo.8): New target. + * utils/grub-terminfo.in: New file. + * util/Makefile.am (sbin_SCRIPTS): Added grub-terminfo. + * configure.in (AC_OUTPUT): Added util/grub-terminfo. + + * docs/grub.texi (terminfo): New subsection. + (Invoking grub-terminfo): New chapter. + + From Tilmann Bubeck : + * stage2/Makefile.am (noinst_HEADERS): Added terminfo.h and + tparm.h. + (libgrub_a_SOURCES): Added terminfo.c and tparm.c. + (pre_stage2_exe_SOURCES): Likewise. + * stage2/terminfo.c: New file. + * stage2/terminfo.h: Likewise. + * stage2/tparm.c: Likewise. + * stage2/tparm.h: Likewise. + * stage2/stage2.c (get_line_from_config): Fix handling of + backslashes. + * stage2/char_io.c (grub_putstr): New function. + (grub_printf): Use grub_putstr. + (substring): Add const into both arguments. + * stage2/builtins.c [SUPPORT_SERIAL]: Include terminfo.h. + [SUPPORT_SERIAL] (terminfo_func): New function. + [SUPPORT_SERIAL] (builtin_terminfo): New variable. + (builtin_table) [SUPPORT_SERIAL]: Added a pointer to + BUILTIN_TERMINFO. + * stage2/serial.c (serial_gotoxy): Use ti_cursor_address. + (serial_cls): Use ti_clear_screen. + (serial_highlight): use ti_enter_standout_mode and + ti_exit_standout_mode. + 2002-11-30 Yoshinori K. Okuji * stage2/disk_io.c (rawread): Make sure that SECTOR is valid. diff --git a/NEWS b/NEWS index 182347166..36c0d8b76 100644 --- a/NEWS +++ b/NEWS @@ -6,8 +6,7 @@ New in 0.93: Also, add the support into GRUB. * Finally, we have a Bug Tracking System on Savannah! Now the preferable way to report bugs is to use the BTS rather than sending e-mail to - bug-grub. See , for more - details. + bug-grub. See , for more details. * The appendix "FAQ" in the manual is removed. See the GNU GRUB FAQ on the web instead. * The terminal handling code is rewritten radically, and many bugfixes @@ -23,6 +22,7 @@ New in 0.93: * Support for booting Linux is rewritten, so GRUB now supports large-EBDA systems. * The menu interfaces supports Page Up, Page Down, and Right Key. +* New command "terminfo", for vt100-incompatible terminals. New in 0.92 - 2002-04-30: * The command "displaymem" uses only hex digits for consistency. diff --git a/THANKS b/THANKS index f0f0d6b08..b423e8ada 100644 --- a/THANKS +++ b/THANKS @@ -91,6 +91,7 @@ Takehiro Suzuki Thierry DELHAISE Thierry Laronde Thomas Schweikle +Tilmann Bubeck Torsten Duwe Uwe Dannowski VaX#n8 diff --git a/configure b/configure index a49106f36..afdb8cace 100644 --- a/configure +++ b/configure @@ -5287,7 +5287,7 @@ ASFLAGS='$(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)' -ac_config_files="$ac_config_files Makefile stage1/Makefile stage2/Makefile docs/Makefile lib/Makefile util/Makefile grub/Makefile netboot/Makefile util/grub-image util/grub-install util/grub-md5-crypt" +ac_config_files="$ac_config_files Makefile stage1/Makefile stage2/Makefile docs/Makefile lib/Makefile util/Makefile grub/Makefile netboot/Makefile util/grub-image util/grub-install util/grub-md5-crypt util/grub-terminfo" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure @@ -5781,6 +5781,7 @@ do "util/grub-image" ) CONFIG_FILES="$CONFIG_FILES util/grub-image" ;; "util/grub-install" ) CONFIG_FILES="$CONFIG_FILES util/grub-install" ;; "util/grub-md5-crypt" ) CONFIG_FILES="$CONFIG_FILES util/grub-md5-crypt" ;; + "util/grub-terminfo" ) CONFIG_FILES="$CONFIG_FILES util/grub-terminfo" ;; "default-1" ) CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;; "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 diff --git a/configure.in b/configure.in index c33b5a971..aa79d9b94 100644 --- a/configure.in +++ b/configure.in @@ -628,4 +628,4 @@ dnl Output. AC_OUTPUT([Makefile stage1/Makefile stage2/Makefile docs/Makefile \ lib/Makefile util/Makefile grub/Makefile \ netboot/Makefile util/grub-image util/grub-install \ - util/grub-md5-crypt]) + util/grub-md5-crypt util/grub-terminfo]) diff --git a/docs/Makefile.am b/docs/Makefile.am index 3251c4caa..db99e2d87 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -2,7 +2,7 @@ info_TEXINFOS = grub.texi multiboot.texi grub_TEXINFOS = internals.texi EXAMPLES = boot.S kernel.c multiboot.h multiboot_TEXINFOS = boot.S.texi kernel.c.texi multiboot.h.texi -man_MANS = grub.8 mbchk.1 grub-install.8 grub-md5-crypt.8 +man_MANS = grub.8 mbchk.1 grub-install.8 grub-md5-crypt.8 grub-terminfo.8 HELP2MAN = help2man SRC2TEXI = src2texi noinst_SCRIPTS = $(HELP2MAN) $(SRC2TEXI) @@ -56,4 +56,10 @@ $(srcdir)/grub-md5-crypt.8: ../util/grub-md5-crypt $(srcdir)/$(HELP2MAN) $(PERL) $(srcdir)/$(HELP2MAN) \ --name="Encrypt a password in MD5 format" \ --section=8 --output=$@ $< + +$(srcdir)/grub-terminfo.8: ../util/grub-terminfo $(srcdir)/$(HELP2MAN) + chmod 755 $< + $(PERL) $(srcdir)/$(HELP2MAN) \ + --name="Generate a terminfo command from a terminfo name" \ + --section=8 --output=$@ $< endif diff --git a/docs/Makefile.in b/docs/Makefile.in index 4c6a1ba29..88da3f5fa 100644 --- a/docs/Makefile.in +++ b/docs/Makefile.in @@ -90,7 +90,7 @@ info_TEXINFOS = grub.texi multiboot.texi grub_TEXINFOS = internals.texi EXAMPLES = boot.S kernel.c multiboot.h multiboot_TEXINFOS = boot.S.texi kernel.c.texi multiboot.h.texi -man_MANS = grub.8 mbchk.1 grub-install.8 grub-md5-crypt.8 +man_MANS = grub.8 mbchk.1 grub-install.8 grub-md5-crypt.8 grub-terminfo.8 HELP2MAN = help2man SRC2TEXI = src2texi noinst_SCRIPTS = $(HELP2MAN) $(SRC2TEXI) @@ -575,6 +575,12 @@ uninstall-man: uninstall-man1 uninstall-man8 @MAINTAINER_MODE_TRUE@ $(PERL) $(srcdir)/$(HELP2MAN) \ @MAINTAINER_MODE_TRUE@ --name="Encrypt a password in MD5 format" \ @MAINTAINER_MODE_TRUE@ --section=8 --output=$@ $< + +@MAINTAINER_MODE_TRUE@$(srcdir)/grub-terminfo.8: ../util/grub-terminfo $(srcdir)/$(HELP2MAN) +@MAINTAINER_MODE_TRUE@ chmod 755 $< +@MAINTAINER_MODE_TRUE@ $(PERL) $(srcdir)/$(HELP2MAN) \ +@MAINTAINER_MODE_TRUE@ --name="Generate a terminfo command from a terminfo name" \ +@MAINTAINER_MODE_TRUE@ --section=8 --output=$@ $< # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: diff --git a/docs/grub-terminfo.8 b/docs/grub-terminfo.8 new file mode 100644 index 000000000..ea4238647 --- /dev/null +++ b/docs/grub-terminfo.8 @@ -0,0 +1,29 @@ +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.23. +.TH GRUB-TERMINFO "8" "November 2002" "grub-terminfo (GNU GRUB 0.93)" FSF +.SH NAME +grub-terminfo \- Generate a terminfo command from a terminfo name +.SH SYNOPSIS +.B grub-terminfo +\fITERMNAME\fR +.SH DESCRIPTION +Generate a terminfo command from a terminfo name. +.TP +\fB\-h\fR, \fB\-\-help\fR +print this message and exit +.TP +\fB\-v\fR, \fB\-\-version\fR +print the version information and exit +.SH "REPORTING BUGS" +Report bugs to . +.SH "SEE ALSO" +The full documentation for +.B grub-terminfo +is maintained as a Texinfo manual. If the +.B info +and +.B grub-terminfo +programs are properly installed at your site, the command +.IP +.B info grub-terminfo +.PP +should give you access to the complete manual. diff --git a/docs/grub.texi b/docs/grub.texi index db4dee035..83460d624 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -24,6 +24,9 @@ * grub-install: (grub)Invoking grub-install. Install GRUB on your drive * grub-md5-crypt: (grub)Invoking grub-md5-crypt. Encrypt a password in MD5 format +* grub-terminfo: (grub)Invoking grub-terminfo. Generate a terminfo + command from a + terminfo name * mbchk: (grub)Invoking mbchk. Check for the format of a Multiboot kernel @end direntry @@ -109,6 +112,7 @@ This edition documents version @value{VERSION}. * Invoking the grub shell:: How to use the grub shell * Invoking grub-install:: How to use the GRUB installer * Invoking grub-md5-crypt:: How to generate a cryptic password +* Invoking grub-terminfo:: How to generate a terminfo command * Invoking mbchk:: How to use the Multiboot checker * Obtaining and Building GRUB:: How to obtain and build GRUB * Reporting bugs:: Where you should send a bug report @@ -1908,6 +1912,7 @@ Commands usable both in the menu and in the command-line. * serial:: Set up a serial device * setkey:: Configure the key map * terminal:: Choose a terminal +* terminfo:: Define escape sequences for a terminal * tftpserver:: Specify a TFTP server * unhide:: Unhide a partition @end menu @@ -2318,6 +2323,21 @@ The option @option{--no-edit} disables the BASH-like editing feature. @end deffn +@node terminfo +@subsection terminfo + +@deffn Command terminfo @option{--name=name} @option{--cursor-address=seq} [@option{--clear-screen=seq}] [@option{--enter-standout-mode=seq}] [@option{--exit-standout-mode=seq}] +Define the capabilities of your terminal. Use this command to define +escape sequences, unless it is vt100-compatible. You may use @samp{\e} +for @key{ESC} and @samp{^X} for a control character. + +You can use the utility @command{grub-terminfo} to generate +appropriate arguments to this command. @xref{Invoking grub-terminfo}. + +If no option is specified, the current settings are printed. +@end deffn + + @node tftpserver @subsection tftpserver @@ -3413,6 +3433,32 @@ Use @var{file} as the grub shell. @end table +@node Invoking grub-terminfo +@chapter Invoking grub-md5-crypt + +The program @command{grub-terminfo} generates a terminfo command from +a terminfo name (@pxref{terminfo}). The result can be used in the +configuration file, to define escape sequences. Because GRUB assumes +that your terminal is vt100-compatible by default, this would be +useful only if your terminal is uncommon (such as vt52). + +@command{grub-terminfo} accepts the following options: + +@table @option +@item --help +Print a summary of the command-line options and exit. + +@item --version +Print the version information and exit. +@end table + +You must specify one argument to this command. For example: + +@example +@kbd{grub-terminfo vt52} +@end example + + @node Invoking mbchk @chapter Invoking mbchk @@ -3552,7 +3598,7 @@ thing. @end enumerate If you realize the guideline above, submit a report to the -@uref{http://savannah.gnu.org/bugs/?group=grub, Bug Tracking System}. +@uref{http://bugcomm.enbug.org, Bug Tracking System}. Alternatively, you can submit a report via electronic mail to @email{bug-grub@@gnu.org}, but we strongly recommend that you use the Bug Tracking System, because e-mail can be passed over easily. diff --git a/docs/stamp-vti b/docs/stamp-vti index f30f6a0b6..9e026a1eb 100644 --- a/docs/stamp-vti +++ b/docs/stamp-vti @@ -1,4 +1,4 @@ -@set UPDATED 15 November 2002 +@set UPDATED 30 November 2002 @set UPDATED-MONTH November 2002 @set EDITION 0.93 @set VERSION 0.93 diff --git a/docs/version.texi b/docs/version.texi index f30f6a0b6..9e026a1eb 100644 --- a/docs/version.texi +++ b/docs/version.texi @@ -1,4 +1,4 @@ -@set UPDATED 15 November 2002 +@set UPDATED 30 November 2002 @set UPDATED-MONTH November 2002 @set EDITION 0.93 @set VERSION 0.93 diff --git a/stage2/Makefile.am b/stage2/Makefile.am index 7b0c13f35..3c4dc4c4c 100644 --- a/stage2/Makefile.am +++ b/stage2/Makefile.am @@ -6,8 +6,8 @@ noinst_SCRIPTS = $(TESTS) noinst_HEADERS = apic.h defs.h dir.h disk_inode.h disk_inode_ffs.h \ fat.h filesys.h freebsd.h fs.h hercules.h i386-elf.h \ imgact_aout.h jfs.h mb_header.h mb_info.h md5.h nbi.h \ - pc_slice.h serial.h shared.h smp-imps.h term.h nbi.h vstafs.h \ - xfs.h + pc_slice.h serial.h shared.h smp-imps.h term.h terminfo.h \ + tparm.h nbi.h vstafs.h xfs.h EXTRA_DIST = setjmp.S apm.S $(noinst_SCRIPTS) # For . @@ -18,7 +18,7 @@ noinst_LIBRARIES = libgrub.a libgrub_a_SOURCES = boot.c builtins.c char_io.c cmdline.c common.c \ disk_io.c fsys_ext2fs.c fsys_fat.c fsys_ffs.c fsys_jfs.c \ fsys_minix.c fsys_reiserfs.c fsys_vstafs.c fsys_xfs.c gunzip.c \ - md5.c serial.c stage2.c + md5.c serial.c stage2.c terminfo.c tparm.c libgrub_a_CFLAGS = $(GRUB_CFLAGS) -I$(top_srcdir)/lib \ -DGRUB_UTIL=1 -DFSYS_EXT2FS=1 -DFSYS_FAT=1 -DFSYS_FFS=1 \ -DFSYS_JFS=1 -DFSYS_MINIX=1 -DFSYS_REISERFS=1 -DFSYS_VSTAFS=1 \ @@ -86,7 +86,7 @@ pre_stage2_exec_SOURCES = asm.S bios.c boot.c builtins.c char_io.c \ cmdline.c common.c console.c disk_io.c fsys_ext2fs.c \ fsys_fat.c fsys_ffs.c fsys_jfs.c fsys_minix.c fsys_reiserfs.c \ fsys_vstafs.c fsys_xfs.c gunzip.c hercules.c md5.c serial.c \ - smp-imps.c stage2.c + smp-imps.c stage2.c terminfo.c tparm.c pre_stage2_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS) pre_stage2_exec_ASFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS) pre_stage2_exec_LDFLAGS = $(PRE_STAGE2_LINK) diff --git a/stage2/Makefile.in b/stage2/Makefile.in index e70f05bf1..46e78a746 100644 --- a/stage2/Makefile.in +++ b/stage2/Makefile.in @@ -97,8 +97,8 @@ noinst_SCRIPTS = $(TESTS) noinst_HEADERS = apic.h defs.h dir.h disk_inode.h disk_inode_ffs.h \ fat.h filesys.h freebsd.h fs.h hercules.h i386-elf.h \ imgact_aout.h jfs.h mb_header.h mb_info.h md5.h nbi.h \ - pc_slice.h serial.h shared.h smp-imps.h term.h nbi.h vstafs.h \ - xfs.h + pc_slice.h serial.h shared.h smp-imps.h term.h terminfo.h \ + tparm.h nbi.h vstafs.h xfs.h EXTRA_DIST = setjmp.S apm.S $(noinst_SCRIPTS) @@ -110,7 +110,7 @@ noinst_LIBRARIES = libgrub.a libgrub_a_SOURCES = boot.c builtins.c char_io.c cmdline.c common.c \ disk_io.c fsys_ext2fs.c fsys_fat.c fsys_ffs.c fsys_jfs.c \ fsys_minix.c fsys_reiserfs.c fsys_vstafs.c fsys_xfs.c gunzip.c \ - md5.c serial.c stage2.c + md5.c serial.c stage2.c terminfo.c tparm.c libgrub_a_CFLAGS = $(GRUB_CFLAGS) -I$(top_srcdir)/lib \ -DGRUB_UTIL=1 -DFSYS_EXT2FS=1 -DFSYS_FAT=1 -DFSYS_FFS=1 \ @@ -170,7 +170,7 @@ pre_stage2_exec_SOURCES = asm.S bios.c boot.c builtins.c char_io.c \ cmdline.c common.c console.c disk_io.c fsys_ext2fs.c \ fsys_fat.c fsys_ffs.c fsys_jfs.c fsys_minix.c fsys_reiserfs.c \ fsys_vstafs.c fsys_xfs.c gunzip.c hercules.c md5.c serial.c \ - smp-imps.c stage2.c + smp-imps.c stage2.c terminfo.c tparm.c pre_stage2_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS) pre_stage2_exec_ASFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS) @@ -320,7 +320,8 @@ am_libgrub_a_OBJECTS = libgrub_a-boot.$(OBJEXT) \ libgrub_a-fsys_reiserfs.$(OBJEXT) \ libgrub_a-fsys_vstafs.$(OBJEXT) libgrub_a-fsys_xfs.$(OBJEXT) \ libgrub_a-gunzip.$(OBJEXT) libgrub_a-md5.$(OBJEXT) \ - libgrub_a-serial.$(OBJEXT) libgrub_a-stage2.$(OBJEXT) + libgrub_a-serial.$(OBJEXT) libgrub_a-stage2.$(OBJEXT) \ + libgrub_a-terminfo.$(OBJEXT) libgrub_a-tparm.$(OBJEXT) libgrub_a_OBJECTS = $(am_libgrub_a_OBJECTS) EXTRA_PROGRAMS = nbloader.exec$(EXEEXT) pxeloader.exec$(EXEEXT) \ diskless.exec$(EXEEXT) @@ -365,7 +366,8 @@ am_diskless_exec_OBJECTS = diskless_exec-asm.$(OBJEXT) \ diskless_exec-fsys_xfs.$(OBJEXT) diskless_exec-gunzip.$(OBJEXT) \ diskless_exec-hercules.$(OBJEXT) diskless_exec-md5.$(OBJEXT) \ diskless_exec-serial.$(OBJEXT) diskless_exec-smp-imps.$(OBJEXT) \ - diskless_exec-stage2.$(OBJEXT) + diskless_exec-stage2.$(OBJEXT) diskless_exec-terminfo.$(OBJEXT) \ + diskless_exec-tparm.$(OBJEXT) diskless_exec_OBJECTS = $(am_diskless_exec_OBJECTS) diskless_exec_DEPENDENCIES = ../netboot/libdrivers.a am_e2fs_stage1_5_exec_OBJECTS = e2fs_stage1_5_exec-start.$(OBJEXT) \ @@ -447,7 +449,9 @@ am_pre_stage2_exec_OBJECTS = pre_stage2_exec-asm.$(OBJEXT) \ pre_stage2_exec-hercules.$(OBJEXT) \ pre_stage2_exec-md5.$(OBJEXT) pre_stage2_exec-serial.$(OBJEXT) \ pre_stage2_exec-smp-imps.$(OBJEXT) \ - pre_stage2_exec-stage2.$(OBJEXT) + pre_stage2_exec-stage2.$(OBJEXT) \ + pre_stage2_exec-terminfo.$(OBJEXT) \ + pre_stage2_exec-tparm.$(OBJEXT) pre_stage2_exec_OBJECTS = $(am_pre_stage2_exec_OBJECTS) @NETBOOT_SUPPORT_TRUE@pre_stage2_exec_DEPENDENCIES = \ @NETBOOT_SUPPORT_TRUE@ ../netboot/libdrivers.a @@ -525,6 +529,8 @@ depcomp = $(SHELL) $(top_srcdir)/depcomp @AMDEP_TRUE@ $(DEPDIR)/diskless_exec-serial.Po \ @AMDEP_TRUE@ $(DEPDIR)/diskless_exec-smp-imps.Po \ @AMDEP_TRUE@ $(DEPDIR)/diskless_exec-stage2.Po \ +@AMDEP_TRUE@ $(DEPDIR)/diskless_exec-terminfo.Po \ +@AMDEP_TRUE@ $(DEPDIR)/diskless_exec-tparm.Po \ @AMDEP_TRUE@ $(DEPDIR)/e2fs_stage1_5_exec-bios.Po \ @AMDEP_TRUE@ $(DEPDIR)/e2fs_stage1_5_exec-char_io.Po \ @AMDEP_TRUE@ $(DEPDIR)/e2fs_stage1_5_exec-common.Po \ @@ -567,6 +573,8 @@ depcomp = $(SHELL) $(top_srcdir)/depcomp @AMDEP_TRUE@ $(DEPDIR)/libgrub_a-md5.Po \ @AMDEP_TRUE@ $(DEPDIR)/libgrub_a-serial.Po \ @AMDEP_TRUE@ $(DEPDIR)/libgrub_a-stage2.Po \ +@AMDEP_TRUE@ $(DEPDIR)/libgrub_a-terminfo.Po \ +@AMDEP_TRUE@ $(DEPDIR)/libgrub_a-tparm.Po \ @AMDEP_TRUE@ $(DEPDIR)/minix_stage1_5_exec-bios.Po \ @AMDEP_TRUE@ $(DEPDIR)/minix_stage1_5_exec-char_io.Po \ @AMDEP_TRUE@ $(DEPDIR)/minix_stage1_5_exec-common.Po \ @@ -595,6 +603,8 @@ depcomp = $(SHELL) $(top_srcdir)/depcomp @AMDEP_TRUE@ $(DEPDIR)/pre_stage2_exec-serial.Po \ @AMDEP_TRUE@ $(DEPDIR)/pre_stage2_exec-smp-imps.Po \ @AMDEP_TRUE@ $(DEPDIR)/pre_stage2_exec-stage2.Po \ +@AMDEP_TRUE@ $(DEPDIR)/pre_stage2_exec-terminfo.Po \ +@AMDEP_TRUE@ $(DEPDIR)/pre_stage2_exec-tparm.Po \ @AMDEP_TRUE@ $(DEPDIR)/reiserfs_stage1_5_exec-bios.Po \ @AMDEP_TRUE@ $(DEPDIR)/reiserfs_stage1_5_exec-char_io.Po \ @AMDEP_TRUE@ $(DEPDIR)/reiserfs_stage1_5_exec-common.Po \ @@ -668,6 +678,8 @@ libgrub_a-gunzip.$(OBJEXT): gunzip.c libgrub_a-md5.$(OBJEXT): md5.c libgrub_a-serial.$(OBJEXT): serial.c libgrub_a-stage2.$(OBJEXT): stage2.c +libgrub_a-terminfo.$(OBJEXT): terminfo.c +libgrub_a-tparm.$(OBJEXT): tparm.c libgrub.a: $(libgrub_a_OBJECTS) $(libgrub_a_DEPENDENCIES) -rm -f libgrub.a $(libgrub_a_AR) libgrub.a $(libgrub_a_OBJECTS) $(libgrub_a_LIBADD) @@ -698,6 +710,8 @@ diskless_exec-md5.$(OBJEXT): md5.c diskless_exec-serial.$(OBJEXT): serial.c diskless_exec-smp-imps.$(OBJEXT): smp-imps.c diskless_exec-stage2.$(OBJEXT): stage2.c +diskless_exec-terminfo.$(OBJEXT): terminfo.c +diskless_exec-tparm.$(OBJEXT): tparm.c diskless.exec$(EXEEXT): $(diskless_exec_OBJECTS) $(diskless_exec_DEPENDENCIES) @rm -f diskless.exec$(EXEEXT) $(LINK) $(diskless_exec_LDFLAGS) $(diskless_exec_OBJECTS) $(diskless_exec_LDADD) $(LIBS) @@ -783,6 +797,8 @@ pre_stage2_exec-md5.$(OBJEXT): md5.c pre_stage2_exec-serial.$(OBJEXT): serial.c pre_stage2_exec-smp-imps.$(OBJEXT): smp-imps.c pre_stage2_exec-stage2.$(OBJEXT): stage2.c +pre_stage2_exec-terminfo.$(OBJEXT): terminfo.c +pre_stage2_exec-tparm.$(OBJEXT): tparm.c pre_stage2.exec$(EXEEXT): $(pre_stage2_exec_OBJECTS) $(pre_stage2_exec_DEPENDENCIES) @rm -f pre_stage2.exec$(EXEEXT) $(LINK) $(pre_stage2_exec_LDFLAGS) $(pre_stage2_exec_OBJECTS) $(pre_stage2_exec_LDADD) $(LIBS) @@ -856,6 +872,8 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/diskless_exec-serial.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/diskless_exec-smp-imps.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/diskless_exec-stage2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/diskless_exec-terminfo.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/diskless_exec-tparm.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/e2fs_stage1_5_exec-bios.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/e2fs_stage1_5_exec-char_io.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/e2fs_stage1_5_exec-common.Po@am__quote@ @@ -898,6 +916,8 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/libgrub_a-md5.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/libgrub_a-serial.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/libgrub_a-stage2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/libgrub_a-terminfo.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/libgrub_a-tparm.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/minix_stage1_5_exec-bios.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/minix_stage1_5_exec-char_io.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/minix_stage1_5_exec-common.Po@am__quote@ @@ -926,6 +946,8 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/pre_stage2_exec-serial.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/pre_stage2_exec-smp-imps.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/pre_stage2_exec-stage2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/pre_stage2_exec-terminfo.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/pre_stage2_exec-tparm.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/reiserfs_stage1_5_exec-bios.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/reiserfs_stage1_5_exec-char_io.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/reiserfs_stage1_5_exec-common.Po@am__quote@ @@ -1308,6 +1330,30 @@ libgrub_a-stage2.obj: stage2.c @AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgrub_a_CFLAGS) $(CFLAGS) -c -o libgrub_a-stage2.obj `cygpath -w stage2.c` +libgrub_a-terminfo.o: terminfo.c +@AMDEP_TRUE@ source='terminfo.c' object='libgrub_a-terminfo.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/libgrub_a-terminfo.Po' tmpdepfile='$(DEPDIR)/libgrub_a-terminfo.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgrub_a_CFLAGS) $(CFLAGS) -c -o libgrub_a-terminfo.o `test -f terminfo.c || echo '$(srcdir)/'`terminfo.c + +libgrub_a-terminfo.obj: terminfo.c +@AMDEP_TRUE@ source='terminfo.c' object='libgrub_a-terminfo.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/libgrub_a-terminfo.Po' tmpdepfile='$(DEPDIR)/libgrub_a-terminfo.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgrub_a_CFLAGS) $(CFLAGS) -c -o libgrub_a-terminfo.obj `cygpath -w terminfo.c` + +libgrub_a-tparm.o: tparm.c +@AMDEP_TRUE@ source='tparm.c' object='libgrub_a-tparm.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/libgrub_a-tparm.Po' tmpdepfile='$(DEPDIR)/libgrub_a-tparm.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgrub_a_CFLAGS) $(CFLAGS) -c -o libgrub_a-tparm.o `test -f tparm.c || echo '$(srcdir)/'`tparm.c + +libgrub_a-tparm.obj: tparm.c +@AMDEP_TRUE@ source='tparm.c' object='libgrub_a-tparm.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/libgrub_a-tparm.Po' tmpdepfile='$(DEPDIR)/libgrub_a-tparm.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgrub_a_CFLAGS) $(CFLAGS) -c -o libgrub_a-tparm.obj `cygpath -w tparm.c` + diskless_exec-bios.o: bios.c @AMDEP_TRUE@ source='bios.c' object='diskless_exec-bios.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/diskless_exec-bios.Po' tmpdepfile='$(DEPDIR)/diskless_exec-bios.TPo' @AMDEPBACKSLASH@ @@ -1572,6 +1618,30 @@ diskless_exec-stage2.obj: stage2.c @AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(diskless_exec_CFLAGS) $(CFLAGS) -c -o diskless_exec-stage2.obj `cygpath -w stage2.c` +diskless_exec-terminfo.o: terminfo.c +@AMDEP_TRUE@ source='terminfo.c' object='diskless_exec-terminfo.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/diskless_exec-terminfo.Po' tmpdepfile='$(DEPDIR)/diskless_exec-terminfo.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(diskless_exec_CFLAGS) $(CFLAGS) -c -o diskless_exec-terminfo.o `test -f terminfo.c || echo '$(srcdir)/'`terminfo.c + +diskless_exec-terminfo.obj: terminfo.c +@AMDEP_TRUE@ source='terminfo.c' object='diskless_exec-terminfo.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/diskless_exec-terminfo.Po' tmpdepfile='$(DEPDIR)/diskless_exec-terminfo.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(diskless_exec_CFLAGS) $(CFLAGS) -c -o diskless_exec-terminfo.obj `cygpath -w terminfo.c` + +diskless_exec-tparm.o: tparm.c +@AMDEP_TRUE@ source='tparm.c' object='diskless_exec-tparm.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/diskless_exec-tparm.Po' tmpdepfile='$(DEPDIR)/diskless_exec-tparm.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(diskless_exec_CFLAGS) $(CFLAGS) -c -o diskless_exec-tparm.o `test -f tparm.c || echo '$(srcdir)/'`tparm.c + +diskless_exec-tparm.obj: tparm.c +@AMDEP_TRUE@ source='tparm.c' object='diskless_exec-tparm.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/diskless_exec-tparm.Po' tmpdepfile='$(DEPDIR)/diskless_exec-tparm.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(diskless_exec_CFLAGS) $(CFLAGS) -c -o diskless_exec-tparm.obj `cygpath -w tparm.c` + e2fs_stage1_5_exec-common.o: common.c @AMDEP_TRUE@ source='common.c' object='e2fs_stage1_5_exec-common.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/e2fs_stage1_5_exec-common.Po' tmpdepfile='$(DEPDIR)/e2fs_stage1_5_exec-common.TPo' @AMDEPBACKSLASH@ @@ -2196,6 +2266,30 @@ pre_stage2_exec-stage2.obj: stage2.c @AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-stage2.obj `cygpath -w stage2.c` +pre_stage2_exec-terminfo.o: terminfo.c +@AMDEP_TRUE@ source='terminfo.c' object='pre_stage2_exec-terminfo.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/pre_stage2_exec-terminfo.Po' tmpdepfile='$(DEPDIR)/pre_stage2_exec-terminfo.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-terminfo.o `test -f terminfo.c || echo '$(srcdir)/'`terminfo.c + +pre_stage2_exec-terminfo.obj: terminfo.c +@AMDEP_TRUE@ source='terminfo.c' object='pre_stage2_exec-terminfo.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/pre_stage2_exec-terminfo.Po' tmpdepfile='$(DEPDIR)/pre_stage2_exec-terminfo.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-terminfo.obj `cygpath -w terminfo.c` + +pre_stage2_exec-tparm.o: tparm.c +@AMDEP_TRUE@ source='tparm.c' object='pre_stage2_exec-tparm.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/pre_stage2_exec-tparm.Po' tmpdepfile='$(DEPDIR)/pre_stage2_exec-tparm.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-tparm.o `test -f tparm.c || echo '$(srcdir)/'`tparm.c + +pre_stage2_exec-tparm.obj: tparm.c +@AMDEP_TRUE@ source='tparm.c' object='pre_stage2_exec-tparm.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/pre_stage2_exec-tparm.Po' tmpdepfile='$(DEPDIR)/pre_stage2_exec-tparm.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-tparm.obj `cygpath -w tparm.c` + reiserfs_stage1_5_exec-common.o: common.c @AMDEP_TRUE@ source='common.c' object='reiserfs_stage1_5_exec-common.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@ depfile='$(DEPDIR)/reiserfs_stage1_5_exec-common.Po' tmpdepfile='$(DEPDIR)/reiserfs_stage1_5_exec-common.TPo' @AMDEPBACKSLASH@ diff --git a/stage2/builtins.c b/stage2/builtins.c index d91bd8994..8c7a1191a 100644 --- a/stage2/builtins.c +++ b/stage2/builtins.c @@ -35,6 +35,7 @@ #ifdef SUPPORT_SERIAL # include +# include #endif #ifdef GRUB_UTIL @@ -4140,6 +4141,97 @@ static struct builtin builtin_terminal = }; #endif /* SUPPORT_SERIAL || SUPPORT_HERCULES */ + +#ifdef SUPPORT_SERIAL +static int +terminfo_func (char *arg, int flags) +{ + struct terminfo term; + + if (*arg) + { + struct + { + const char *name; + char *var; + } + options[] = + { + {"--name=", term.name}, + {"--cursor-address=", term.cursor_address}, + {"--clear-screen=", term.clear_screen}, + {"--enter-standout-mode=", term.enter_standout_mode}, + {"--exit-standout-mode=", term.exit_standout_mode} + }; + + grub_memset (&term, 0, sizeof (term)); + + while (*arg) + { + int i; + char *next = skip_to (0, arg); + + nul_terminate (arg); + + for (i = 0; i < sizeof (options) / sizeof (options[0]); i++) + { + const char *name = options[i].name; + int len = grub_strlen (name); + + if (! grub_memcmp (arg, name, len)) + { + grub_strcpy (options[i].var, arg + len); + break; + } + } + + if (i == sizeof (options) / sizeof (options[0])) + { + errnum = ERR_BAD_ARGUMENT; + return errnum; + } + + arg = next; + } + + if (term.name[0] == 0 || term.cursor_address[0] == 0) + { + errnum = ERR_BAD_ARGUMENT; + return errnum; + } + + ti_set_term (term); + } + else + { + /* No option specifies printing out current settings. */ + term = ti_get_term (); + + grub_printf ("name=%s\n", term.name); + grub_printf ("cursor_address=%s\n", term.cursor_address); + grub_printf ("clear_screen=%s\n", term.clear_screen); + grub_printf ("enter_standout_mode=%s\n", term.enter_standout_mode); + grub_printf ("exit_standout_mode=%s\n", term.exit_standout_mode); + } + + return 0; +} + +static struct builtin builtin_terminfo = +{ + "terminfo", + terminfo_func, + BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST, + "terminfo [--name=NAME --cursor-address=SEQ [--clear-screen=SEQ]" + " [--enter-standout-mode=SEQ] [--exit-standout-mode=SEQ]]", + + "Define the capabilities of your terminal. Use this command to" + " define escape sequences, unless it is vt100-compatible." + " You may use \\e for ESC and ^X for a control character." + " If no option is specified, the current settings are printed." +}; +#endif /* SUPPORT_SERIAL */ + /* testload */ static int @@ -4633,6 +4725,9 @@ struct builtin *builtin_table[] = #if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) &builtin_terminal, #endif /* SUPPORT_SERIAL || SUPPORT_HERCULES */ +#ifdef SUPPORT_SERIAL + &builtin_terminfo, +#endif /* SUPPORT_SERIAL */ &builtin_testload, &builtin_testvbe, #ifdef SUPPORT_NETBOOT diff --git a/stage2/char_io.c b/stage2/char_io.c index e38a0db3a..52a115520 100644 --- a/stage2/char_io.c +++ b/stage2/char_io.c @@ -142,11 +142,18 @@ convert_to_ascii (char *buf, int c,...) return ptr; } +void +grub_putstr (const char *str) +{ + while (*str) + grub_putchar (*str++); +} + void grub_printf (const char *format,...) { int *dataptr = (int *) &format; - char c, *ptr, str[16]; + char c, str[16]; unsigned long mask = 0xFFFFFFFF; dataptr++; @@ -169,11 +176,7 @@ grub_printf (const char *format,...) case 'u': *convert_to_ascii (str, c, *((unsigned long *) dataptr++) & mask) = 0; - - ptr = str; - - while (*ptr) - grub_putchar (*(ptr++)); + grub_putstr (str); break; #ifndef STAGE1_5 @@ -182,10 +185,7 @@ grub_printf (const char *format,...) break; case 's': - ptr = (char *) (*(dataptr++)); - - while ((c = *(ptr++)) != 0) - grub_putchar (c); + grub_putstr ((char *) *(dataptr++)); break; #endif } @@ -1087,7 +1087,7 @@ nocursor (void) #endif /* ! STAGE1_5 */ int -substring (char *s1, char *s2) +substring (const char *s1, const char *s2) { while (*s1 == *s2) { diff --git a/stage2/serial.c b/stage2/serial.c index 973015e42..1920738cf 100644 --- a/stage2/serial.c +++ b/stage2/serial.c @@ -23,6 +23,7 @@ #include #include #include +#include /* An input buffer. */ static char input_buf[8]; @@ -401,7 +402,7 @@ void serial_gotoxy (int x, int y) { keep_track = 0; - grub_printf ("\e[%d;%dH", y + 1, x + 1); + ti_cursor_address (x, y); keep_track = 1; serial_x = x; @@ -412,7 +413,7 @@ void serial_cls (void) { keep_track = 0; - grub_printf ("\e[H\e[J"); + ti_clear_screen (); keep_track = 1; serial_x = serial_y = 0; @@ -422,7 +423,10 @@ void serial_setcolorstate (color_state state) { keep_track = 0; - grub_printf ("\e[%cm", (state == COLOR_STATE_HIGHLIGHT) ? '7' : '0'); + if (state == COLOR_STATE_HIGHLIGHT) + ti_enter_standout_mode (); + else + ti_exit_standout_mode (); keep_track = 1; } diff --git a/stage2/shared.h b/stage2/shared.h index 97e6a9abe..27d59a59a 100644 --- a/stage2/shared.h +++ b/stage2/shared.h @@ -890,11 +890,12 @@ void print_error (void); char *convert_to_ascii (char *buf, int c, ...); int get_cmdline (char *prompt, char *cmdline, int maxlen, int echo_char, int history); -int substring (char *s1, char *s2); +int substring (const char *s1, const char *s2); int nul_terminate (char *str); int get_based_digit (int c, int base); int safe_parse_maxint (char **str_ptr, int *myint_ptr); int memcheck (int start, int len); +void grub_putstr (const char *str); #ifndef NO_DECOMPRESSION /* Compression support. */ diff --git a/stage2/stage2.c b/stage2/stage2.c index 90fd03b7c..960c30d9e 100644 --- a/stage2/stage2.c +++ b/stage2/stage2.c @@ -762,19 +762,34 @@ get_line_from_config (char *cmdline, int maxlen, int read_from_file) if (! read_from_preset_menu (&c, 1)) break; } - - /* translate characters first! */ - if (c == '\\' && ! literal) - { - literal = 1; - continue; - } + + /* Skip all carriage returns. */ if (c == '\r') continue; - if ((c == '\t') || (literal && (c == '\n'))) + + /* Replace tabs with spaces. */ + if (c == '\t') c = ' '; - literal = 0; + /* The previous is a backslash, then... */ + if (literal) + { + /* If it is a newline, replace it with a space and continue. */ + if (c == '\n') + { + c = ' '; + + /* Go back to overwrite a backslash. */ + if (pos > 0) + pos--; + } + + literal = 0; + } + + /* translate characters first! */ + if (c == '\\' && ! literal) + literal = 1; if (comment) { diff --git a/stage2/terminfo.c b/stage2/terminfo.c new file mode 100644 index 000000000..79088c9a4 --- /dev/null +++ b/stage2/terminfo.c @@ -0,0 +1,259 @@ +/* terminfo.c - read a terminfo entry from the command line */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002 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 + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * ###################################################################### + * + * This file contains various functions dealing with different + * terminal capabilities. It knows the difference between a vt52 and vt100 + * terminal (and much more) and is mainly used the terminal emulation + * in the serial driver. + */ + +#include +#include "terminfo.h" +#include "tparm.h" +#include "serial.h" + +/* Current terminal capabilities. Default is "vt100". */ +struct terminfo term = + { + .name "vt100", + .cursor_address "\e[%i%p1%d;%p2%dH", + .clear_screen "\e[H\e[J", + .enter_standout_mode "\e[7m", + .exit_standout_mode "\e[m" + }; + +/* A number of escape sequences are provided in the string valued + capabilities for easy encoding of characters there. Both \E and \e + map to an ESCAPE character, ^x maps to a control-x for any + appropriate x, and the sequences \n \l \r \t \b \f \s give a + newline, line-feed, return, tab, backspace, form-feed, and space. + Other escapes include \^ for ^, \\ for \, \, for comma, \: for :, + and \0 for null. (\0 will produce \200, which does not terminate a + string but behaves as a null character on most terminals, provid­ + ing CS7 is specified. See stty(1).) Finally, characters may be + given as three octal digits after a \. */ + +char * +ti_unescape_memory (const char *in, const char *end) +{ + static char out_buffer[256]; + char c; + char *out; + + out = out_buffer; + do + { + c = *(in++); + switch (c) + { + case '^': + if (*in >= 'A' && *in <= 'Z') + { + *out = (*in) - 'A'; + in++; + } + else + { + *out = '^'; + } + break; + case '\\': + c = *(in++); + if (c >= '0' && c <= '9') + { + // octal number + int n = 0; + do + { + n = (n << 4) | (c - '0'); + c = *(in++); + } + while (c >= '0' && c <= '9'); + + *out++ = (char)(n & 0xff); + + // redo last character + in--; + + break; + } + + switch (c) + { + case 'e': + case 'E': + *out++ = '\e'; + break; + case 'n': + *out++ = '\n'; + break; + case 'r': + *out++ = '\r'; + break; + case 't': + *out++ = '\t'; + break; + case 'b': + *out++ = '\b'; + break; + case 'f': + *out++ = '\f'; + break; + case 's': + *out++ = ' '; + break; + case '\\': + *out++ = '\\'; + break; + case '^': + *out++ = '^'; + break; + case ',': + *out++ = ','; + break; + case ':': + *out++ = ':'; + break; + case '0': + *out++ = '\200'; + break; + } + break; + default: + *out++ = c; + break; + } + } + while (in <= end); + + return out_buffer; +} + +char * +ti_unescape_string (const char *in) +{ + return ti_unescape_memory (in, in + grub_strlen (in)); +} + +/* convert a memory region containing binary character into an external + * ascii representation. The binary characters will be replaced by an + * "ecsape notation". E.g. "033" will become "\e". */ +char * +ti_escape_memory (const char *in, const char *end) +{ + static char out_buffer[256]; + char c; + char *out; + + out = out_buffer; + do + { + c = *(in++); + switch (c) + { + case '\e': + *out++ = '\\'; *out++ = 'e'; break; + case ' ': + *out++ = '\\'; *out++ = 's'; break; + case '\\': + *out++ = '\\'; *out++ = '\\'; break; + case '0' ... '9': + case 'a' ... 'z': + case 'A' ... 'Z': + case '%': + case '+': + case '-': + case '*': + case '/': + case ';': + case ':': + case '{': + case '}': + case '[': + case ']': + *out++ = c; break; + case 0 ... 25: + *out++ = '^'; *out++ = 'A' + c; break; + default: + *out++ = '\\'; + *out++ = ((c >> 8) & 7) + '0'; + *out++ = ((c >> 4) & 7) + '0'; + *out++ = ((c >> 0) & 7) + '0'; + break; + } + } + while (in < end); + + *out++ = 0; + + return out_buffer; +} + +/* convert a string containing binary character into an external ascii + * representation. */ +char * +ti_escape_string (const char *in) +{ + return ti_escape_memory (in, in + grub_strlen (in)); +} + +/* move the cursor to the given position starting with "0". */ +void +ti_cursor_address (int x, int y) +{ + grub_putstr (grub_tparm (term.cursor_address, y, x)); +} + +/* clear the screen. */ +void +ti_clear_screen (void) +{ + grub_putstr (grub_tparm (term.clear_screen)); +} + +/* enter reverse video */ +void +ti_enter_standout_mode (void) +{ + grub_putstr (grub_tparm (term.enter_standout_mode)); +} + +/* exit reverse video */ +void +ti_exit_standout_mode (void) +{ + grub_putstr (grub_tparm (term.exit_standout_mode)); +} + +/* set the current terminal emulation to use */ +void +ti_set_term (struct terminfo new) +{ + term = new; +} + +/* return the current terminal emulation */ +struct terminfo +ti_get_term(void) +{ + return term; +} + diff --git a/stage2/terminfo.h b/stage2/terminfo.h new file mode 100644 index 000000000..28c832e3c --- /dev/null +++ b/stage2/terminfo.h @@ -0,0 +1,51 @@ +/* terminfo.h - read a terminfo entry from the command line */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002 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 + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef GRUB_TERMCAP_HEADER +#define GRUB_TERMCAP_HEADER 1 + +#define TERMINFO_LEN 32 + +typedef struct terminfo +{ + char name[TERMINFO_LEN]; + char cursor_address[TERMINFO_LEN]; + char clear_screen[TERMINFO_LEN]; + char enter_standout_mode[TERMINFO_LEN]; + char exit_standout_mode[TERMINFO_LEN]; +} +terminfo; + + +/* Function prototypes. */ +char *ti_escape_memory (const char *in, const char *end); +char *ti_escape_string (const char *in); +char *ti_unescape_memory (const char *in, const char *end); +char *ti_unescape_string (const char *in); + +void ti_set_term (struct terminfo term); +struct terminfo ti_get_term (void); + +void ti_cursor_address (int x, int y); +void ti_clear_screen (void); +void ti_enter_standout_mode (void); +void ti_exit_standout_mode (void); + +#endif /* ! GRUB_TERMCAP_HEADER */ diff --git a/stage2/tparm.c b/stage2/tparm.c new file mode 100644 index 000000000..bd95df8f9 --- /dev/null +++ b/stage2/tparm.c @@ -0,0 +1,726 @@ +/**************************************************************************** + * Copyright (c) 1998,2000,2002 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/********************************************************************** + * This code is a modification of lib_tparm.c found in ncurses-5.2. The + * modification are for use in grub by replacing all libc function through + * special grub functions. This also meant to delete all dynamic memory + * allocation and replace it by a number of fixed buffers. + * + * Modifications by Tilmann Bubeck 2002 + **********************************************************************/ + +/**************************************************************************** + * Author: Zeyd M. Ben-Halim 1992,1995 * + * and: Eric S. Raymond * + ****************************************************************************/ + +/* + * tparm.c + * + */ + +#include "shared.h" + +#include "tparm.h" + +/* + * Common/troublesome character definitions + */ +typedef char grub_bool; +#define isdigit(c) ((c) >= '0' && (c) <= '9') +#ifndef FALSE +# define FALSE (0) +#endif +#ifndef TRUE +# define TRUE (!FALSE) +#endif +#define MAX_FORMAT_LEN 256 +#define max(a,b) ((a) > (b) ? (a) : (b)) + +//MODULE_ID("$Id$") + +/* + * char * + * tparm(string, ...) + * + * Substitute the given parameters into the given string by the following + * rules (taken from terminfo(5)): + * + * Cursor addressing and other strings requiring parame- + * ters in the terminal are described by a parameterized string + * capability, with like escapes %x in it. For example, to + * address the cursor, the cup capability is given, using two + * parameters: the row and column to address to. (Rows and + * columns are numbered from zero and refer to the physical + * screen visible to the user, not to any unseen memory.) If + * the terminal has memory relative cursor addressing, that can + * be indicated by + * + * The parameter mechanism uses a stack and special % + * codes to manipulate it. Typically a sequence will push one + * of the parameters onto the stack and then print it in some + * format. Often more complex operations are necessary. + * + * The % encodings have the following meanings: + * + * %% outputs `%' + * %c print pop() like %c in printf() + * %s print pop() like %s in printf() + * %[[:]flags][width[.precision]][doxXs] + * as in printf, flags are [-+#] and space + * The ':' is used to avoid making %+ or %- + * patterns (see below). + * + * %p[1-9] push ith parm + * %P[a-z] set dynamic variable [a-z] to pop() + * %g[a-z] get dynamic variable [a-z] and push it + * %P[A-Z] set static variable [A-Z] to pop() + * %g[A-Z] get static variable [A-Z] and push it + * %l push strlen(pop) + * %'c' push char constant c + * %{nn} push integer constant nn + * + * %+ %- %* %/ %m + * arithmetic (%m is mod): push(pop() op pop()) + * %& %| %^ bit operations: push(pop() op pop()) + * %= %> %< logical operations: push(pop() op pop()) + * %A %O logical and & or operations for conditionals + * %! %~ unary operations push(op pop()) + * %i add 1 to first two parms (for ANSI terminals) + * + * %? expr %t thenpart %e elsepart %; + * if-then-else, %e elsepart is optional. + * else-if's are possible ala Algol 68: + * %? c1 %t b1 %e c2 %t b2 %e c3 %t b3 %e c4 %t b4 %e b5 %; + * + * For those of the above operators which are binary and not commutative, + * the stack works in the usual way, with + * %gx %gy %m + * resulting in x mod y, not the reverse. + */ + +#define STACKSIZE 20 + +typedef struct { + union { + unsigned int num; + char *str; + } data; + grub_bool num_type; +} stack_frame; + +static stack_frame stack[STACKSIZE]; +static int stack_ptr; + +static char out_buff[256]; +static int out_size = 256; +static int out_used; + +static inline void +get_space(int need) +{ + need += out_used; + if (need > out_size) { + // FIX ME! buffer full, what now? + ; + } +} + +static inline void +save_text(const char *fmt, const char *s, int len) +{ + int s_len = grub_strlen(s); + if (len > (int) s_len) + s_len = len; + + get_space(s_len + 1); + + (void) grub_sprintf(out_buff + out_used, fmt, s); + out_used += grub_strlen(out_buff + out_used); +} + +static inline void +save_number(const char *fmt, int number, int len) +{ + if (len < 30) + len = 30; /* actually log10(MAX_INT)+1 */ + + get_space(len + 1); + + (void) grub_sprintf(out_buff + out_used, fmt, number); + out_used += grub_strlen(out_buff + out_used); +} + +static inline void +save_char(int c) +{ + if (c == 0) + c = 0200; + get_space(1); + out_buff[out_used++] = c; +} + +static inline void +npush(int x) +{ + if (stack_ptr < STACKSIZE) { + stack[stack_ptr].num_type = TRUE; + stack[stack_ptr].data.num = x; + stack_ptr++; + } +} + +static inline int +npop(void) +{ + int result = 0; + if (stack_ptr > 0) { + stack_ptr--; + if (stack[stack_ptr].num_type) + result = stack[stack_ptr].data.num; + } + return result; +} + +static inline void +spush(char *x) +{ + if (stack_ptr < STACKSIZE) { + stack[stack_ptr].num_type = FALSE; + stack[stack_ptr].data.str = x; + stack_ptr++; + } +} + +static inline char * +spop(void) +{ + static char dummy[] = ""; /* avoid const-cast */ + char *result = dummy; + if (stack_ptr > 0) { + stack_ptr--; + if (!stack[stack_ptr].num_type && stack[stack_ptr].data.str != 0) + result = stack[stack_ptr].data.str; + } + return result; +} + +static inline const char * +parse_format(const char *s, char *format, int *len) +{ + grub_bool done = FALSE; + grub_bool allowminus = FALSE; + grub_bool dot = FALSE; + grub_bool err = FALSE; + char *fmt = format; + int prec = 0; + int width = 0; + int value = 0; + + *len = 0; + *format++ = '%'; + while (*s != '\0' && !done) { + switch (*s) { + case 'c': /* FALLTHRU */ + case 'd': /* FALLTHRU */ + case 'o': /* FALLTHRU */ + case 'x': /* FALLTHRU */ + case 'X': /* FALLTHRU */ + case 's': + *format++ = *s; + done = TRUE; + break; + case '.': + *format++ = *s++; + if (dot) { + err = TRUE; + } else { + dot = TRUE; + prec = value; + } + value = 0; + break; + case '#': + *format++ = *s++; + break; + case ' ': + *format++ = *s++; + break; + case ':': + s++; + allowminus = TRUE; + break; + case '-': + if (allowminus) { + *format++ = *s++; + } else { + done = TRUE; + } + break; + default: + if (isdigit(*s)) { + value = (value * 10) + (*s - '0'); + if (value > 10000) + err = TRUE; + *format++ = *s++; + } else { + done = TRUE; + } + } + } + + /* + * If we found an error, ignore (and remove) the flags. + */ + if (err) { + prec = width = value = 0; + format = fmt; + *format++ = '%'; + *format++ = *s; + } + + if (dot) + width = value; + else + prec = value; + + *format = '\0'; + /* return maximum string length in print */ + *len = (prec > width) ? prec : width; + return s; +} + +#define isUPPER(c) ((c) >= 'A' && (c) <= 'Z') +#define isLOWER(c) ((c) >= 'a' && (c) <= 'z') + +static inline char * +tparam_internal(const char *string, int *dataptr) +{ +#define NUM_VARS 26 + char *p_is_s[9]; + int param[9]; + int lastpop; + int popcount; + int number; + int len; + int level; + int x, y; + int i; + int len2; + register const char *cp; + static int len_fmt = MAX_FORMAT_LEN; + static char dummy[] = ""; + static char format[MAX_FORMAT_LEN]; + static int dynamic_var[NUM_VARS]; + static int static_vars[NUM_VARS]; + + out_used = 0; + if (string == NULL) + return NULL; + + if ((len2 = grub_strlen(string)) > len_fmt) { + return NULL; + } + + /* + * Find the highest parameter-number referred to in the format string. + * Use this value to limit the number of arguments copied from the + * variable-length argument list. + */ + + number = 0; + lastpop = -1; + popcount = 0; + grub_memset(p_is_s, 0, sizeof(p_is_s)); + + /* + * Analyze the string to see how many parameters we need from the varargs + * list, and what their types are. We will only accept string parameters + * if they appear as a %l or %s format following an explicit parameter + * reference (e.g., %p2%s). All other parameters are numbers. + * + * 'number' counts coarsely the number of pop's we see in the string, and + * 'popcount' shows the highest parameter number in the string. We would + * like to simply use the latter count, but if we are reading termcap + * strings, there may be cases that we cannot see the explicit parameter + * numbers. + */ + for (cp = string; (cp - string) < (int) len2;) { + if (*cp == '%') { + cp++; + cp = parse_format(cp, format, &len); + switch (*cp) { + default: + break; + + case 'd': /* FALLTHRU */ + case 'o': /* FALLTHRU */ + case 'x': /* FALLTHRU */ + case 'X': /* FALLTHRU */ + case 'c': /* FALLTHRU */ + number++; + lastpop = -1; + break; + + case 'l': + case 's': + if (lastpop > 0) + p_is_s[lastpop - 1] = dummy; + ++number; + break; + + case 'p': + cp++; + i = (*cp - '0'); + if (i >= 0 && i <= 9) { + lastpop = i; + if (lastpop > popcount) + popcount = lastpop; + } + break; + + case 'P': + case 'g': + cp++; + break; + + case '\'': + cp += 2; + lastpop = -1; + break; + + case '{': + cp++; + while (*cp >= '0' && *cp <= '9') { + cp++; + } + break; + + case '+': + case '-': + case '*': + case '/': + case 'm': + case 'A': + case 'O': + case '&': + case '|': + case '^': + case '=': + case '<': + case '>': + case '!': + case '~': + lastpop = -1; + number += 2; + break; + + case 'i': + lastpop = -1; + if (popcount < 2) + popcount = 2; + break; + } + } + if (*cp != '\0') + cp++; + } + + if (number > 9) + number = 9; + for (i = 0; i < max(popcount, number); i++) { + /* + * A few caps (such as plab_norm) have string-valued parms. + * We'll have to assume that the caller knows the difference, since + * a char* and an int may not be the same size on the stack. + */ + if (p_is_s[i] != 0) { + p_is_s[i] = (char *)(*(dataptr++)); + } else { + param[i] = (int)(*(dataptr++)); + } + } + + /* + * This is a termcap compatibility hack. If there are no explicit pop + * operations in the string, load the stack in such a way that + * successive pops will grab successive parameters. That will make + * the expansion of (for example) \E[%d;%dH work correctly in termcap + * style, which means tparam() will expand termcap strings OK. + */ + stack_ptr = 0; + if (popcount == 0) { + popcount = number; + for (i = number - 1; i >= 0; i--) + npush(param[i]); + } + + while (*string) { + /* skip delay timings */ + if (*string == '$' && *(string + 1) == '<') { + while( *string && *string != '>') + string++; + if ( *string == '>' ) string++; + } else if ( *string == '%') { + string++; + string = parse_format(string, format, &len); + switch (*string) { + default: + break; + case '%': + save_char('%'); + break; + + case 'd': /* FALLTHRU */ + case 'o': /* FALLTHRU */ + case 'x': /* FALLTHRU */ + case 'X': /* FALLTHRU */ + case 'c': /* FALLTHRU */ + save_number(format, npop(), len); + break; + + case 'l': + save_number("%d", strlen(spop()), 0); + break; + + case 's': + save_text(format, spop(), len); + break; + + case 'p': + string++; + i = (*string - '1'); + if (i >= 0 && i < 9) { + if (p_is_s[i]) + spush(p_is_s[i]); + else + npush(param[i]); + } + break; + + case 'P': + string++; + if (isUPPER(*string)) { + i = (*string - 'A'); + static_vars[i] = npop(); + } else if (isLOWER(*string)) { + i = (*string - 'a'); + dynamic_var[i] = npop(); + } + break; + + case 'g': + string++; + if (isUPPER(*string)) { + i = (*string - 'A'); + npush(static_vars[i]); + } else if (isLOWER(*string)) { + i = (*string - 'a'); + npush(dynamic_var[i]); + } + break; + + case '\'': + string++; + npush(*string); + string++; + break; + + case '{': + number = 0; + string++; + while (*string >= '0' && *string <= '9') { + number = number * 10 + *string - '0'; + string++; + } + npush(number); + break; + + case '+': + npush(npop() + npop()); + break; + + case '-': + y = npop(); + x = npop(); + npush(x - y); + break; + + case '*': + npush(npop() * npop()); + break; + + case '/': + y = npop(); + x = npop(); + npush(y ? (x / y) : 0); + break; + + case 'm': + y = npop(); + x = npop(); + npush(y ? (x % y) : 0); + break; + + case 'A': + npush(npop() && npop()); + break; + + case 'O': + npush(npop() || npop()); + break; + + case '&': + npush(npop() & npop()); + break; + + case '|': + npush(npop() | npop()); + break; + + case '^': + npush(npop() ^ npop()); + break; + + case '=': + y = npop(); + x = npop(); + npush(x == y); + break; + + case '<': + y = npop(); + x = npop(); + npush(x < y); + break; + + case '>': + y = npop(); + x = npop(); + npush(x > y); + break; + + case '!': + npush(!npop()); + break; + + case '~': + npush(~npop()); + break; + + case 'i': + if (p_is_s[0] == 0) + param[0]++; + if (p_is_s[1] == 0) + param[1]++; + break; + + case '?': + break; + + case 't': + x = npop(); + if (!x) { + /* scan forward for %e or %; at level zero */ + string++; + level = 0; + while (*string) { + if (*string == '%') { + string++; + if (*string == '?') + level++; + else if (*string == ';') { + if (level > 0) + level--; + else + break; + } else if (*string == 'e' && level == 0) + break; + } + + if (*string) + string++; + } + } + break; + + case 'e': + /* scan forward for a %; at level zero */ + string++; + level = 0; + while (*string) { + if (*string == '%') { + string++; + if (*string == '?') + level++; + else if (*string == ';') { + if (level > 0) + level--; + else + break; + } + } + + if (*string) + string++; + } + break; + + case ';': + break; + + } /* endswitch (*string) */ + } else { /* endelse (*string == '%') */ + save_char(*string); + } + + if (*string == '\0') + break; + + string++; + } /* endwhile (*string) */ + + get_space(1); + out_buff[out_used] = '\0'; + + return (out_buff); +} + +char * +grub_tparm(const char *string,...) +{ + char *result; + int *dataptr = (int *) &string; + + dataptr++; + + result = tparam_internal(string, dataptr); + + return result; +} diff --git a/stage2/tparm.h b/stage2/tparm.h new file mode 100644 index 000000000..e2c1b68e6 --- /dev/null +++ b/stage2/tparm.h @@ -0,0 +1,28 @@ +/* tparm.h - parameter formatting of terminfo */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002 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 + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef GRUB_TPARM_HEADER +#define GRUB_TPARM_HEADER 1 + + +/* Function prototypes. */ +char *grub_tparm (const char *string, ...); + +#endif /* ! GRUB_TERMCAP_HEADER */ diff --git a/util/Makefile.am b/util/Makefile.am index de26673a3..0c36c532d 100644 --- a/util/Makefile.am +++ b/util/Makefile.am @@ -1,5 +1,5 @@ bin_PROGRAMS = mbchk -sbin_SCRIPTS = grub-install grub-md5-crypt +sbin_SCRIPTS = grub-install grub-md5-crypt grub-terminfo noinst_SCRIPTS = grub-image #noinst_DATA = menu.lst diff --git a/util/Makefile.in b/util/Makefile.in index eb9a38e0f..a62f58fa6 100644 --- a/util/Makefile.in +++ b/util/Makefile.in @@ -87,7 +87,7 @@ host_vendor = @host_vendor@ install_sh = @install_sh@ bin_PROGRAMS = mbchk -sbin_SCRIPTS = grub-install grub-md5-crypt +sbin_SCRIPTS = grub-install grub-md5-crypt grub-terminfo noinst_SCRIPTS = grub-image #noinst_DATA = menu.lst @@ -101,7 +101,8 @@ mbchk_LDADD = ../lib/libcommon.a subdir = util mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = grub-image grub-install grub-md5-crypt +CONFIG_CLEAN_FILES = grub-image grub-install grub-md5-crypt \ + grub-terminfo bin_PROGRAMS = mbchk$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) @@ -126,7 +127,7 @@ LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ CFLAGS = @CFLAGS@ DIST_SOURCES = $(mbchk_SOURCES) DIST_COMMON = Makefile.am Makefile.in grub-image.in grub-install.in \ - grub-md5-crypt.in + grub-md5-crypt.in grub-terminfo.in SOURCES = $(mbchk_SOURCES) all: all-am @@ -146,6 +147,8 @@ grub-install: $(top_builddir)/config.status grub-install.in cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= CONFIG_LINKS= $(SHELL) ./config.status grub-md5-crypt: $(top_builddir)/config.status grub-md5-crypt.in cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= CONFIG_LINKS= $(SHELL) ./config.status +grub-terminfo: $(top_builddir)/config.status grub-terminfo.in + cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= CONFIG_LINKS= $(SHELL) ./config.status install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(bindir) diff --git a/util/grub-terminfo.in b/util/grub-terminfo.in new file mode 100644 index 000000000..e41b41836 --- /dev/null +++ b/util/grub-terminfo.in @@ -0,0 +1,95 @@ +#! /bin/sh +# Generate a terminfo command from a terminfo name. +# +# Copyright (C) 2002 Free Software Foundation, Inc. +# +# This file 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 this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +VERSION=@VERSION@ + +usage () { + cat <. +EOF +} + +error () { + echo "grub-terminfo: error: $1" 1>&2 +} + +termname= + +for option in "$@"; do + case "$option" in + -h | --help) + usage + exit 0 ;; + -v | --version) + echo "grub-terminfo (GNU GRUB ${VERSION})" + exit 0 ;; + -*) + error "Unrecognized option \`$option'" + usage + exit 1 ;; + *) + if test "x$termname" != x; then + error "More than one terminfo names?" + usage + exit 1 + fi + termname="$option" ;; + esac +done + +if test "x$termname" = x; then + error "termname not specified" + usage + exit 1 +fi + +get_seq () { + infocmp -L -1 -g $termname | sed -n -e "/$1/s/^[^=]*=\\(.*\\),\$/\\1/p" +} + +cursor_address="`get_seq cursor_address`" +if test "x$cursor_address" = x; then + error "cursor_address not found" + exit 1 +fi +cursor_address="--cursor-address=$cursor_address" + +clear_screen="`get_seq clear_screen`" +if test "x$clear_screen" != x; then + clear_screen="--clear-screen=$clear_screen" +fi + +enter_standout_mode="`get_seq enter_standout_mode`" +if test "x$enter_standout_mode" != x; then + enter_standout_mode="--enter-standout-mode=$enter_standout_mode" +fi + +exit_standout_mode="`get_seq exit_standout_mode`" +if test "x$exit_standout_mode" != x; then + exit_standout_mode="--exit-standout-mode=$exit_standout_mode" +fi + +echo "terminfo --name=$termname" $cursor_address $clear_screen \ + $enter_standout_mode $exit_standout_mode