122028508SToomas Soome\ 222028508SToomas Soome\ This file and its contents are supplied under the terms of the 322028508SToomas Soome\ Common Development and Distribution License ("CDDL"), version 1.0. 422028508SToomas Soome\ You may only use this file in accordance with the terms of version 522028508SToomas Soome\ 1.0 of the CDDL. 622028508SToomas Soome\ 722028508SToomas Soome\ A full copy of the text of the CDDL should have accompanied this 822028508SToomas Soome\ source. A copy of the CDDL is also available via the Internet at 922028508SToomas Soome\ http://www.illumos.org/license/CDDL. 1022028508SToomas Soome 1122028508SToomas Soome\ Copyright 2017 Toomas Soome <tsoome@me.com> 1222028508SToomas Soome\ Copyright 2019 OmniOS Community Edition (OmniOSce) Association. 1322028508SToomas Soome\ Copyright 2019 Joyent, Inc. 1422028508SToomas Soome 1522028508SToomas Soome\ This module is implementing the beadm user command to support listing 1622028508SToomas Soome\ and switching Boot Environments (BE) from command line and 1722028508SToomas Soome\ support words to provide data for BE menu in loader menu system. 1822028508SToomas Soome\ Note: this module needs an update to provide proper BE vocabulary. 1922028508SToomas Soome 2022028508SToomas Soomeonly forth also support-functions also file-processing 2122028508SToomas Soomealso file-processing definitions also parser 2222028508SToomas Soomealso line-reading definitions also builtins definitions 2322028508SToomas Soome 2422028508SToomas Soomevariable page_count 2522028508SToomas Soomevariable page_remainder 2622028508SToomas Soome0 page_count ! 2722028508SToomas Soome0 page_remainder ! 2822028508SToomas Soome 2922028508SToomas Soome\ from menu.4th 3022028508SToomas Soome: +c! ( N C-ADDR/U K -- C-ADDR/U ) 3122028508SToomas Soome 3 pick 3 pick ( n c-addr/u k -- n c-addr/u k n c-addr ) 3222028508SToomas Soome rot + c! ( n c-addr/u k n c-addr -- n c-addr/u ) 3322028508SToomas Soome rot drop ( n c-addr/u -- c-addr/u ) 3422028508SToomas Soome; 3522028508SToomas Soome 3622028508SToomas Soome: get_value ( -- ) 3722028508SToomas Soome eat_space 3822028508SToomas Soome line_pointer 3922028508SToomas Soome skip_to_end_of_line 4022028508SToomas Soome line_pointer over - 4122028508SToomas Soome strdup value_buffer strset 4222028508SToomas Soome ['] exit to parsing_function 4322028508SToomas Soome; 4422028508SToomas Soome 4522028508SToomas Soome: get_name ( -- ) 4622028508SToomas Soome read_name 4722028508SToomas Soome ['] get_value to parsing_function 4822028508SToomas Soome; 4922028508SToomas Soome 5022028508SToomas Soome: get_name_value 5122028508SToomas Soome line_buffer strget + to end_of_line 5222028508SToomas Soome line_buffer .addr @ to line_pointer 5322028508SToomas Soome ['] get_name to parsing_function 5422028508SToomas Soome begin 5522028508SToomas Soome end_of_line? 0= 5622028508SToomas Soome while 5722028508SToomas Soome parsing_function execute 5822028508SToomas Soome repeat 5922028508SToomas Soome; 6022028508SToomas Soome 6122028508SToomas Soome\ beadm support 6222028508SToomas Soome: beadm_longest_title ( addr len -- width ) 6322028508SToomas Soome 0 to end_of_file? 6422028508SToomas Soome O_RDONLY fopen fd ! 6522028508SToomas Soome reset_line_reading 6622028508SToomas Soome fd @ -1 = if EOPEN throw then 6722028508SToomas Soome 0 >r \ length into return stack 6822028508SToomas Soome begin 6922028508SToomas Soome end_of_file? 0= 7022028508SToomas Soome while 7122028508SToomas Soome free_buffers 7222028508SToomas Soome read_line 7322028508SToomas Soome get_name_value 7422028508SToomas Soome value_buffer .len @ r@ > if r> drop value_buffer .len @ >r then 7522028508SToomas Soome free_buffers 7622028508SToomas Soome read_line 7722028508SToomas Soome repeat 7822028508SToomas Soome fd @ fclose 7922028508SToomas Soome r> 1 + \ space between columns 8022028508SToomas Soome; 8122028508SToomas Soome 8222028508SToomas Soome\ Pretty print BE list 8322028508SToomas Soome: beadm_list ( width addr len -- ) 8422028508SToomas Soome 0 to end_of_file? 8522028508SToomas Soome O_RDONLY fopen fd ! 8622028508SToomas Soome reset_line_reading 8722028508SToomas Soome fd @ -1 = if EOPEN throw then 8822028508SToomas Soome ." BE" dup 2 - spaces ." Type Device" cr 8922028508SToomas Soome begin 9022028508SToomas Soome end_of_file? 0= 9122028508SToomas Soome while 9222028508SToomas Soome free_buffers 9322028508SToomas Soome read_line 9422028508SToomas Soome get_name_value 9522028508SToomas Soome value_buffer strget type 9622028508SToomas Soome dup value_buffer .len @ - spaces 9722028508SToomas Soome free_buffers 9822028508SToomas Soome read_line 9922028508SToomas Soome get_name_value 10022028508SToomas Soome name_buffer strget type 10122028508SToomas Soome name_buffer strget s" bootfs" compare 0= if 2 spaces then 10222028508SToomas Soome name_buffer strget s" chain" compare 0= if 3 spaces then 10322028508SToomas Soome value_buffer strget type cr 10422028508SToomas Soome free_buffers 10522028508SToomas Soome repeat 10622028508SToomas Soome fd @ fclose 10722028508SToomas Soome drop 10822028508SToomas Soome; 10922028508SToomas Soome 110*28703145SToomas Soome\ we are called with strings be_name menu_file, to simplify the stack 11122028508SToomas Soome\ management, we open the menu and free the menu_file. 11222028508SToomas Soome: beadm_bootfs ( be_addr be_len maddr mlen -- addr len taddr tlen flag | flag ) 11322028508SToomas Soome 0 to end_of_file? 11422028508SToomas Soome 2dup O_RDONLY fopen fd ! 11522028508SToomas Soome drop free-memory 11622028508SToomas Soome fd @ -1 = if EOPEN throw then 11722028508SToomas Soome reset_line_reading 11822028508SToomas Soome begin 11922028508SToomas Soome end_of_file? 0= 12022028508SToomas Soome while 12122028508SToomas Soome free_buffers 12222028508SToomas Soome read_line 12322028508SToomas Soome get_name_value 12422028508SToomas Soome 2dup value_buffer strget compare 12522028508SToomas Soome 0= if ( title == be ) 12622028508SToomas Soome 2drop \ drop be_name 12722028508SToomas Soome free_buffers 12822028508SToomas Soome read_line 12922028508SToomas Soome get_name_value 13022028508SToomas Soome value_buffer strget strdup 13122028508SToomas Soome name_buffer strget strdup -1 13222028508SToomas Soome free_buffers 13322028508SToomas Soome 1 to end_of_file? \ mark end of file to skip the rest 13422028508SToomas Soome else 13522028508SToomas Soome read_line \ skip over next line 13622028508SToomas Soome then 13722028508SToomas Soome repeat 13822028508SToomas Soome fd @ fclose 13922028508SToomas Soome line_buffer strfree 14022028508SToomas Soome read_buffer strfree 14122028508SToomas Soome dup -1 > if ( be_addr be_len ) 14222028508SToomas Soome 2drop 14322028508SToomas Soome 0 14422028508SToomas Soome then 14522028508SToomas Soome; 14622028508SToomas Soome 14722028508SToomas Soome: current-dev ( -- addr len ) \ return current dev 14822028508SToomas Soome s" currdev" getenv 14922028508SToomas Soome 2dup [char] / strchr nip 15022028508SToomas Soome dup 0> if ( strchr '/' != NULL ) - else drop then 15122028508SToomas Soome \ we have now zfs:pool or diskname: 15222028508SToomas Soome; 15322028508SToomas Soome 15422028508SToomas Soome\ chop trailing ':' 15522028508SToomas Soome: colon- ( addr len -- addr len - 1 | addr len ) 15622028508SToomas Soome 2dup 1 - + C@ [char] : = if ( string[len-1] == ':' ) 1 - then 15722028508SToomas Soome; 15822028508SToomas Soome 15922028508SToomas Soome\ add trailing ':' 16022028508SToomas Soome: colon+ ( addr len -- addr len+1 ) 16122028508SToomas Soome 2dup + \ addr len -- addr+len 16222028508SToomas Soome [char] : swap c! \ save ':' at the end of the string 16322028508SToomas Soome 1+ \ addr len -- addr len+1 16422028508SToomas Soome; 16522028508SToomas Soome 16622028508SToomas Soome\ make menu.lst path 16722028508SToomas Soome: menu.lst ( addr len -- addr' len' ) 16822028508SToomas Soome colon- 16922028508SToomas Soome \ need to allocate space for len + 16 17022028508SToomas Soome dup 16 + allocate if ENOMEM throw then 17122028508SToomas Soome swap 2dup 2>R \ copy of new addr len to return stack 17222028508SToomas Soome move 2R> 17322028508SToomas Soome s" :/boot/menu.lst" strcat 17422028508SToomas Soome; 17522028508SToomas Soome 17622028508SToomas Soome\ list be's on device 17722028508SToomas Soome: list-dev ( addr len -- ) 17822028508SToomas Soome menu.lst 2dup 2>R 17922028508SToomas Soome beadm_longest_title 18022028508SToomas Soome line_buffer strfree 18122028508SToomas Soome read_buffer strfree 18222028508SToomas Soome R@ swap 2R> \ addr width addr len 18322028508SToomas Soome beadm_list free-memory 18422028508SToomas Soome ." Current boot device: " s" currdev" getenv type cr 18522028508SToomas Soome line_buffer strfree 18622028508SToomas Soome read_buffer strfree 18722028508SToomas Soome; 18822028508SToomas Soome 18922028508SToomas Soome\ activate be on device. 19022028508SToomas Soome\ if be name was not given, set currdev 19122028508SToomas Soome\ otherwize, we query device:/boot/menu.lst for bootfs and 19222028508SToomas Soome\ if found, and bootfs type is chain, attempt chainload. 19322028508SToomas Soome\ set currdev to bootfs. 19422028508SToomas Soome\ if we were able to set currdev, reload the config 19522028508SToomas Soome 19622028508SToomas Soome: activate-dev ( dev.addr dev.len be.addr be.len -- ) 19722028508SToomas Soome 19822028508SToomas Soome dup 0= if 19922028508SToomas Soome 2drop 20022028508SToomas Soome colon- \ remove : at the end of the dev name 20122028508SToomas Soome dup 1+ allocate if ENOMEM throw then 20222028508SToomas Soome dup 2swap 0 -rot strcat 20322028508SToomas Soome colon+ 20422028508SToomas Soome s" currdev" setenv \ setenv currdev = device 20522028508SToomas Soome free-memory 20622028508SToomas Soome else 20722028508SToomas Soome 2swap menu.lst 20822028508SToomas Soome beadm_bootfs if ( addr len taddr tlen ) 20922028508SToomas Soome 2dup s" chain" compare 0= if 21022028508SToomas Soome drop free-memory \ free type 21122028508SToomas Soome 2dup 21222028508SToomas Soome dup 6 + allocate if ENOMEM throw then 21322028508SToomas Soome dup >R 21422028508SToomas Soome 0 s" chain " strcat 21522028508SToomas Soome 2swap strcat ['] evaluate catch drop 21622028508SToomas Soome \ We are still there? 21722028508SToomas Soome R> free-memory \ free chain command 21822028508SToomas Soome drop free-memory \ free addr 21922028508SToomas Soome exit 22022028508SToomas Soome then 22122028508SToomas Soome drop free-memory \ free type 22222028508SToomas Soome \ check last char in the name 22322028508SToomas Soome 2dup + c@ [char] : <> if 22422028508SToomas Soome \ have dataset and need to get zfs:pool/ROOT/be: 22522028508SToomas Soome dup 5 + allocate if ENOMEM throw then 22622028508SToomas Soome 0 s" zfs:" strcat 22722028508SToomas Soome 2swap strcat 22822028508SToomas Soome colon+ 22922028508SToomas Soome then 23022028508SToomas Soome 2dup s" currdev" setenv 23122028508SToomas Soome drop free-memory 23222028508SToomas Soome else 23322028508SToomas Soome ." No such BE in menu.lst or menu.lst is missing." cr 23422028508SToomas Soome exit 23522028508SToomas Soome then 23622028508SToomas Soome then 23722028508SToomas Soome 23822028508SToomas Soome \ reset BE menu 23922028508SToomas Soome 0 page_count ! 24022028508SToomas Soome \ need to do: 24122028508SToomas Soome 0 unload drop 24222028508SToomas Soome free-module-options 24322028508SToomas Soome \ unset the env variables with kernel arguments 24422028508SToomas Soome s" acpi-user-options" unsetenv 24522028508SToomas Soome s" boot-args" unsetenv 24622028508SToomas Soome s" boot_ask" unsetenv 24722028508SToomas Soome s" boot_single" unsetenv 24822028508SToomas Soome s" boot_verbose" unsetenv 24922028508SToomas Soome s" boot_kmdb" unsetenv 25022028508SToomas Soome s" boot_drop_into_kmdb" unsetenv 25122028508SToomas Soome s" boot_reconfigure" unsetenv 252519c7dc9SToomas Soome s" boot_noncluster" unsetenv 25322028508SToomas Soome start \ load config, kernel and modules 25422028508SToomas Soome ." Current boot device: " s" currdev" getenv type cr 25522028508SToomas Soome; 25622028508SToomas Soome 25722028508SToomas Soome\ beadm list [device] 25822028508SToomas Soome\ beadm activate BE [device] | device 25922028508SToomas Soome\ 26022028508SToomas Soome\ lists BE's from current or specified device /boot/menu.lst file 26122028508SToomas Soome\ activates specified BE by unloading modules, setting currdev and 26222028508SToomas Soome\ running start to load configuration. 26322028508SToomas Soome: beadm ( -- ) ( throws: abort ) 26422028508SToomas Soome 0= if ( interpreted ) get_arguments then 26522028508SToomas Soome 26622028508SToomas Soome dup 0= if 26722028508SToomas Soome ." Usage:" cr 26822028508SToomas Soome ." beadm activate {beName [device] | device}" cr 26922028508SToomas Soome ." beadm list [device]" cr 27022028508SToomas Soome ." Use lsdev to get device names." cr 27122028508SToomas Soome drop exit 27222028508SToomas Soome then 27322028508SToomas Soome \ First argument is 0 when we're interprated. See support.4th 27422028508SToomas Soome \ for get_arguments reading the rest of the line and parsing it 27522028508SToomas Soome \ stack: argN lenN ... arg1 len1 N 27622028508SToomas Soome \ rotate arg1 len1, dont use argv[] as we want to get arg1 out of stack 27722028508SToomas Soome -rot 2dup 27822028508SToomas Soome 27922028508SToomas Soome s" list" compare-insensitive 0= if ( list ) 28022028508SToomas Soome 2drop 28122028508SToomas Soome argc 1 = if ( list currdev ) 28222028508SToomas Soome \ add dev to list of args and switch to case 2 28322028508SToomas Soome current-dev rot 1 + 28422028508SToomas Soome then 28522028508SToomas Soome 2 = if ( list device ) list-dev exit then 28622028508SToomas Soome ." too many arguments" cr abort 28722028508SToomas Soome then 28822028508SToomas Soome s" activate" compare-insensitive 0= if ( activate ) 28922028508SToomas Soome argc 1 = if ( missing be ) 29022028508SToomas Soome drop ." missing bName" cr abort 29122028508SToomas Soome then 29222028508SToomas Soome argc 2 = if ( activate be ) 29322028508SToomas Soome \ need to set arg list into proper order 29422028508SToomas Soome 1+ >R \ save argc+1 to return stack 29522028508SToomas Soome 29622028508SToomas Soome \ if the prefix is fd, cd, net or disk and we have : 29722028508SToomas Soome \ in the name, it is device and inject empty be name 29822028508SToomas Soome over 2 s" fd" compare 0= >R 29922028508SToomas Soome over 2 s" cd" compare 0= R> or >R 30022028508SToomas Soome over 3 s" net" compare 0= R> or >R 30122028508SToomas Soome over 4 s" disk" compare 0= R> or 30222028508SToomas Soome if ( prefix is fd or cd or net or disk ) 30322028508SToomas Soome 2dup [char] : strchr nip 30422028508SToomas Soome if ( its : in name ) 30522028508SToomas Soome true 30622028508SToomas Soome else 30722028508SToomas Soome false 30822028508SToomas Soome then 30922028508SToomas Soome else 31022028508SToomas Soome false 31122028508SToomas Soome then 31222028508SToomas Soome 31322028508SToomas Soome if ( it is device name ) 31422028508SToomas Soome 0 0 R> 31522028508SToomas Soome else 31622028508SToomas Soome \ add device, swap with be and receive argc 31722028508SToomas Soome current-dev 2swap R> 31822028508SToomas Soome then 31922028508SToomas Soome then 32022028508SToomas Soome 3 = if ( activate be device ) activate-dev exit then 32122028508SToomas Soome ." too many arguments" cr abort 32222028508SToomas Soome then 32322028508SToomas Soome ." Unknown argument" cr abort 32422028508SToomas Soome; 32522028508SToomas Soome 32622028508SToomas Soomealso forth definitions also builtins 32722028508SToomas Soome 32822028508SToomas Soome\ make beadm available as user command. 32922028508SToomas Soomebuiltin: beadm 33022028508SToomas Soome 33122028508SToomas Soome\ count the pages of BE list 33222028508SToomas Soome\ leave FALSE in stack in case of error 33322028508SToomas Soome: be-pages ( -- flag ) 33422028508SToomas Soome 1 local flag 33522028508SToomas Soome 0 0 2local currdev 33622028508SToomas Soome 0 0 2local title 33722028508SToomas Soome end-locals 33822028508SToomas Soome 33922028508SToomas Soome current-dev menu.lst 2dup 2>R 34022028508SToomas Soome 0 to end_of_file? 34122028508SToomas Soome O_RDONLY fopen fd ! 34222028508SToomas Soome 2R> drop free-memory 34322028508SToomas Soome reset_line_reading 34422028508SToomas Soome fd @ -1 = if FALSE else 34522028508SToomas Soome s" currdev" getenv 34622028508SToomas Soome over ( addr len addr ) 34722028508SToomas Soome 4 s" zfs:" compare 0= if 34822028508SToomas Soome 5 - \ len -= 5 34922028508SToomas Soome swap 4 + \ addr += 4 35022028508SToomas Soome swap to currdev 35122028508SToomas Soome then 35222028508SToomas Soome 35322028508SToomas Soome 0 35422028508SToomas Soome begin 35522028508SToomas Soome end_of_file? 0= 35622028508SToomas Soome while 35722028508SToomas Soome read_line 35822028508SToomas Soome get_name_value 35922028508SToomas Soome s" title" name_buffer strget compare 36022028508SToomas Soome 0= if 1+ then 36122028508SToomas Soome 36222028508SToomas Soome flag if \ check for title 36322028508SToomas Soome value_buffer strget strdup to title free_buffers 36422028508SToomas Soome read_line \ get bootfs 36522028508SToomas Soome get_name_value 36622028508SToomas Soome value_buffer strget currdev compare 0= if 36722028508SToomas Soome title s" zfs_be_active" setenv 36822028508SToomas Soome 0 to flag 36922028508SToomas Soome then 37022028508SToomas Soome title drop free-memory 0 0 to title 37122028508SToomas Soome free_buffers 37222028508SToomas Soome else 37322028508SToomas Soome free_buffers 37422028508SToomas Soome read_line \ get bootfs 37522028508SToomas Soome then 37622028508SToomas Soome repeat 37722028508SToomas Soome fd @ fclose 37822028508SToomas Soome line_buffer strfree 37922028508SToomas Soome read_buffer strfree 38022028508SToomas Soome 5 /mod swap dup page_remainder ! \ save remainder 38122028508SToomas Soome if 1+ then 38222028508SToomas Soome dup page_count ! \ save count 38322028508SToomas Soome n2s s" zfs_be_pages" setenv 38422028508SToomas Soome TRUE 38522028508SToomas Soome then 38622028508SToomas Soome; 38722028508SToomas Soome 38822028508SToomas Soome: be-set-page { | entry count n device -- } 38922028508SToomas Soome page_count @ 0= if 39022028508SToomas Soome be-pages 39122028508SToomas Soome page_count @ 0= if exit then 39222028508SToomas Soome then 39322028508SToomas Soome 39422028508SToomas Soome 0 to device 39522028508SToomas Soome 1 s" zfs_be_currpage" getenvn 39622028508SToomas Soome 5 * 39722028508SToomas Soome page_count @ 5 * 39822028508SToomas Soome page_remainder @ if 39922028508SToomas Soome 5 page_remainder @ - - 40022028508SToomas Soome then 40122028508SToomas Soome swap - 40222028508SToomas Soome dup to entry 40322028508SToomas Soome 0 < if 40422028508SToomas Soome entry 5 + to count 40522028508SToomas Soome 0 to entry 40622028508SToomas Soome else 40722028508SToomas Soome 5 to count 40822028508SToomas Soome then 40922028508SToomas Soome current-dev menu.lst 2dup 2>R 41022028508SToomas Soome 0 to end_of_file? 41122028508SToomas Soome O_RDONLY fopen fd ! 41222028508SToomas Soome 2R> drop free-memory 41322028508SToomas Soome reset_line_reading 41422028508SToomas Soome fd @ -1 = if EOPEN throw then 41522028508SToomas Soome 0 to n 41622028508SToomas Soome begin 41722028508SToomas Soome end_of_file? 0= 41822028508SToomas Soome while 41922028508SToomas Soome n entry < if 42022028508SToomas Soome read_line \ skip title 42122028508SToomas Soome read_line \ skip bootfs 42222028508SToomas Soome n 1+ to n 42322028508SToomas Soome else 42422028508SToomas Soome \ Use reverse loop to display descending order 42522028508SToomas Soome \ for BE list. 42622028508SToomas Soome 0 count 1- do 42722028508SToomas Soome read_line \ read title line 42822028508SToomas Soome get_name_value 42922028508SToomas Soome value_buffer strget 43022028508SToomas Soome 52 i + \ ascii 4 + i 43122028508SToomas Soome s" bootenvmenu_caption[4]" 20 +c! setenv 43222028508SToomas Soome value_buffer strget 43322028508SToomas Soome 52 i + \ ascii 4 + i 43422028508SToomas Soome s" bootenvansi_caption[4]" 20 +c! setenv 43522028508SToomas Soome 43622028508SToomas Soome free_buffers 43722028508SToomas Soome read_line \ read value line 43822028508SToomas Soome get_name_value 43922028508SToomas Soome 44022028508SToomas Soome \ set menu entry command 44122028508SToomas Soome name_buffer strget s" chain" compare 44222028508SToomas Soome 0= if 44322028508SToomas Soome s" set_be_chain" 44422028508SToomas Soome else 44522028508SToomas Soome s" set_bootenv" 44622028508SToomas Soome then 44722028508SToomas Soome 52 i + \ ascii 4 + i 44822028508SToomas Soome s" bootenvmenu_command[4]" 20 +c! setenv 44922028508SToomas Soome 45022028508SToomas Soome \ set device name 45122028508SToomas Soome name_buffer strget s" chain" compare 45222028508SToomas Soome 0= if 453*28703145SToomas Soome \ for chain, use the value as is 45422028508SToomas Soome value_buffer strget 45522028508SToomas Soome else 45622028508SToomas Soome \ check last char in the name 45722028508SToomas Soome value_buffer strget 2dup + c@ 45822028508SToomas Soome [char] : <> if 45922028508SToomas Soome \ make zfs device name 46022028508SToomas Soome swap drop 46122028508SToomas Soome 5 + allocate if 46222028508SToomas Soome ENOMEM throw 46322028508SToomas Soome then 46422028508SToomas Soome s" zfs:" ( addr addr' len' ) 46522028508SToomas Soome 2 pick swap move ( addr ) 46622028508SToomas Soome dup to device 46722028508SToomas Soome 4 value_buffer strget 46822028508SToomas Soome strcat ( addr len ) 46922028508SToomas Soome s" :" strcat 47022028508SToomas Soome then 47122028508SToomas Soome then 47222028508SToomas Soome 47322028508SToomas Soome 52 i + \ ascii 4 + i 47422028508SToomas Soome s" bootenv_root[4]" 13 +c! setenv 47522028508SToomas Soome device free-memory 0 to device 47622028508SToomas Soome free_buffers 47722028508SToomas Soome -1 47822028508SToomas Soome +loop 47922028508SToomas Soome 48022028508SToomas Soome 5 count do \ unset unused entries 48122028508SToomas Soome 52 i + \ ascii 4 + i 48222028508SToomas Soome dup s" bootenvmenu_caption[4]" 20 +c! unsetenv 48322028508SToomas Soome dup s" bootenvansi_caption[4]" 20 +c! unsetenv 48422028508SToomas Soome dup s" bootenvmenu_command[4]" 20 +c! unsetenv 48522028508SToomas Soome s" bootenv_root[4]" 13 +c! unsetenv 48622028508SToomas Soome loop 48722028508SToomas Soome 48822028508SToomas Soome 1 to end_of_file? \ we are done 48922028508SToomas Soome then 49022028508SToomas Soome repeat 49122028508SToomas Soome fd @ fclose 49222028508SToomas Soome line_buffer strfree 49322028508SToomas Soome read_buffer strfree 49422028508SToomas Soome; 495