1244158Sdteske\ Copyright (c) 2006-2012 Devin Teske <dteske@FreeBSD.org> 2222417Sjulian\ All rights reserved. 3222417Sjulian\ 4222417Sjulian\ Redistribution and use in source and binary forms, with or without 5222417Sjulian\ modification, are permitted provided that the following conditions 6222417Sjulian\ are met: 7222417Sjulian\ 1. Redistributions of source code must retain the above copyright 8222417Sjulian\ notice, this list of conditions and the following disclaimer. 9222417Sjulian\ 2. Redistributions in binary form must reproduce the above copyright 10222417Sjulian\ notice, this list of conditions and the following disclaimer in the 11222417Sjulian\ documentation and/or other materials provided with the distribution. 12222417Sjulian\ 13222417Sjulian\ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14222417Sjulian\ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15222417Sjulian\ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16222417Sjulian\ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17222417Sjulian\ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18222417Sjulian\ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19222417Sjulian\ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20222417Sjulian\ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21222417Sjulian\ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22222417Sjulian\ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23222417Sjulian\ SUCH DAMAGE. 24222417Sjulian\ 25222417Sjulian\ $FreeBSD$ 26222417Sjulian 27222417Sjulianmarker task-check-password.4th 28222417Sjulian 29222417Sjulianinclude /boot/screen.4th 30222417Sjulian 31222417Sjulian13 constant enter_key \ The decimal ASCII value for Enter key 32222417Sjulian8 constant bs_key \ The decimal ASCII value for Backspace key 33222417Sjulian16 constant readmax \ Maximum number of characters for the password 34222417Sjulian 35222417Sjulianvariable readX \ Current X offset (column)(used by read) 36222417Sjulianvariable read-start \ Starting X offset (column)(used by read) 37222417Sjulian 38222417Sjuliancreate readval 16 allot \ input obtained (maximum 16 characters) 39222417Sjulianvariable readlen \ input length 40222417Sjulian 41222417Sjulian\ This function blocks program flow (loops forever) until a key is pressed. 42222417Sjulian\ The key that was pressed is added to the top of the stack in the form of its 43222417Sjulian\ decimal ASCII representation. Note: the stack cannot be empty when this 44222417Sjulian\ function starts or an underflow exception will occur. Simplest way to prevent 45222417Sjulian\ this is to pass 0 as a stack parameter (ie. `0 sgetkey'). This function is 46222417Sjulian\ called by the read function. You need not call it directly. NOTE: arrow keys 47222417Sjulian\ show as 0 on the stack 48222417Sjulian\ 49222417Sjulian: sgetkey ( -- ) 50222417Sjulian 51222417Sjulian begin \ Loop forever 52222417Sjulian key? if \ Was a key pressed? (see loader(8)) 53222417Sjulian 54222417Sjulian drop \ Remove stack-cruft 55222417Sjulian key \ Get the key that was pressed 56222417Sjulian 57222417Sjulian \ Check key pressed (see loader(8)) and input limit 58222417Sjulian dup 0<> if ( and ) readlen @ readmax < if 59222417Sjulian 60222417Sjulian \ Echo an asterisk (unless Backspace/Enter) 61222417Sjulian dup bs_key <> if ( and ) dup enter_key <> if 62222417Sjulian ." *" \ Echo an asterisk 63222417Sjulian then then 64222417Sjulian 65222417Sjulian exit \ Exit from the function 66222417Sjulian then then 67222417Sjulian 68222417Sjulian \ Always allow Backspace and Enter 69222417Sjulian dup bs_key = if exit then 70222417Sjulian dup enter_key = if exit then 71222417Sjulian 72222417Sjulian then 73222417Sjulian 50 ms \ Sleep for 50 milliseconds (see loader(8)) 74222417Sjulian again 75222417Sjulian; 76222417Sjulian 77244158Sdteske: read ( String prompt -- ) 78222417Sjulian 79222417Sjulian 0 25 at-xy \ Move the cursor to the bottom-left 80222417Sjulian dup 1+ read-start ! \ Store X offset after the prompt 81222417Sjulian read-start @ readX ! \ copy value to the current X offset 82222417Sjulian 0 readlen ! \ Initialize the read length 83222417Sjulian type \ Print the prompt 84222417Sjulian 85222417Sjulian begin \ Loop forever 86222417Sjulian 87222417Sjulian 0 sgetkey \ Block here, waiting for a key to be pressed 88222417Sjulian 89222417Sjulian \ We are not going to echo the password to the screen (for 90222417Sjulian \ security reasons). If Enter is pressed, we process the 91222417Sjulian \ password, otherwise augment the key to a string. 92222417Sjulian 93222417Sjulian \ If the key that was entered was not Enter, advance 94222417Sjulian dup enter_key <> if 95222417Sjulian readX @ 1+ readX ! \ Advance the column 96222417Sjulian readlen @ 1+ readlen ! \ Increment input length 97222417Sjulian then 98222417Sjulian 99222417Sjulian \ Handle backspacing 100222417Sjulian dup bs_key = if 101222417Sjulian readX @ 2 - readX ! \ Set new cursor position 102222417Sjulian readlen @ 2 - readlen ! \ Decrement input length 103222417Sjulian 104222417Sjulian \ Don't move behind starting position 105222417Sjulian readX @ read-start @ < if 106222417Sjulian read-start @ readX ! 107222417Sjulian then 108222417Sjulian readlen @ 0< if 109222417Sjulian 0 readlen ! 110222417Sjulian then 111222417Sjulian 112222417Sjulian \ Reposition cursor and erase character 113222417Sjulian readX @ 25 at-xy 1 spaces readX @ 25 at-xy 114222417Sjulian then 115222417Sjulian 116222417Sjulian dup enter_key = if 117222417Sjulian drop \ Clean up stack cruft 118222417Sjulian 10 emit \ Echo new line 119222417Sjulian exit 120222417Sjulian then 121222417Sjulian 122222417Sjulian \ If not Backspace or Enter, store the character 123222417Sjulian dup bs_key <> if ( and ) dup enter_key <> if 124222417Sjulian 125222417Sjulian \ store the character in our buffer 126222417Sjulian dup readval readlen @ 1- + c! 127222417Sjulian 128222417Sjulian then then 129222417Sjulian 130222417Sjulian drop \ drop the last key that was entered 131222417Sjulian 132222417Sjulian again \ Enter was not pressed; repeat 133222417Sjulian; 134222417Sjulian 135222417Sjulian: check-password ( -- ) 136222417Sjulian 137244158Sdteske \ Do not allow the user to proceed beyond this point if a boot-lock 138244158Sdteske \ password has been set (preventing even boot from proceeding) 139244158Sdteske s" bootlock_password" getenv dup -1 <> if 140244158Sdteske begin 141244158Sdteske s" Boot Password: " read ( prompt -- ) 142244158Sdteske 2dup readval readlen @ compare 0<> 143244158Sdteske while 144244158Sdteske 3000 ms ." loader: incorrect password" 10 emit 145244158Sdteske repeat 146244158Sdteske 2drop ( c-addr/u ) 147244158Sdteske else 148244158Sdteske drop ( -1 ) \ getenv cruft 149222417Sjulian then 150222417Sjulian 151244158Sdteske \ Exit if a password was not set 152244158Sdteske s" password" getenv -1 = if exit else drop then 153222417Sjulian 154244158Sdteske \ We should prevent the user from visiting the menu or dropping to the 155244158Sdteske \ interactive loader(8) prompt, but still allow the machine to boot... 156222417Sjulian 157244158Sdteske 0 autoboot 158244158Sdteske 159244158Sdteske \ Only reached if autoboot fails for any reason (including if/when 160244158Sdteske \ the user aborts/escapes the countdown sequence leading to boot). 161244158Sdteske 162244158Sdteske s" password" getenv 163244158Sdteske begin 164244158Sdteske s" Password: " read ( prompt -- ) 165222417Sjulian 2dup readval readlen @ compare 0= if 166222417Sjulian 2drop exit \ Correct password 167222417Sjulian then 168244158Sdteske 3000 ms ." loader: incorrect password" 10 emit 169244158Sdteske again 170222417Sjulian; 171