flat assembler
Message board for the users of flat assembler.

Index > Linux > a shell and some questions

Author
Thread Post new topic Reply to topic
gens



Joined: 18 Feb 2013
Posts: 161
gens
hello Smile

i'v been making this linux shell for a while now
plan is for it to some day replace bash on my computer, some day Smile
for now i got some basic IO, "cd" command, it searches for executable in PATH:, and a couple more little things

now the problem i got is... well, in higher level design

next up is IO redirection and process control ( | > < & and if any more ) what i was thinking of putting into the loop that makes tokens so it leaves hints in some scratch array to be processed later by process control

i can do that, but later i plan to add loadable modules (like a debugger for example) and dont want to have to write another parser in each module

so i guess the question is;
is there a simpler way to add functionality to a parser then bluntly extending it

best i got is to make a struct like:

dq pointer_to_null_terminated_string_representing_a_command
dq pointer_to_function_to_call


then compare strings to tokens and if equal call paired function


hope you understand as i'm not rly good at explaining things Smile

also here's the code
the input parser and the tokeniser are messy for now, but the general idea is to have simple code

Code:
;reads from stdin 256 bytes into a buffer then parses it
;fork and exec ;TODO then take care of children

format ELF64 executable 3
;use64
entry main

align 16
segment readable writeable
kaksetozove db "ish: "

align 16
line: rb 256
master_pid: rq 1
current_cwd: rb 128
tokens: rb 128
argv: rb 128
envp: rb 8
filename: rb 128
fileproperties: rb 128
tmp: rb 128
align 16
sigaction: 
rb 4*8
align 16
termios:
rb 3*8
align 16
termios_old:
rb 3*8

align 16
segment readable executable

main:
mov rcx, [rsp] ;argc
mov rax, rsp
add rax, 8 ;argv
shl rcx, 3
add rcx, 8
add rax, rcx ;envp
mov [envp], rax
;jmp debug

mov rax, 39 ;getpid
syscall
mov [master_pid], rax

mov rsi, 128
mov rdi, current_cwd
mov rax, 79 ;getcwd
syscall

;setup terminal IO
mov rdx, termios
mov rsi, 0x5401
mov rdi, 0
mov rax, 16 ;ioctl
syscall
xor rcx, rcx
backup_termios:
mov rax, [termios+rcx]
mov [termios_old+rcx], rax
add rcx,8
cmp rcx, 3*8
jnz backup_termios
;set new terminal IO
mov eax, 0000012o
not eax
and dword [termios+12], eax ;-echo -icanon
mov rdx, termios
mov rsi, 0x5402
mov rdi, 0
mov rax, 16 ;ioctl
syscall

;setup SIGINT handler
mov rax, sigact
mov dword [sigaction], sigact
mov rax, sigrest
or rax, 0x04000000
mov [sigaction+8], rax
mov r10, 8
mov rdx, 0
mov rsi, sigaction
mov rdi, 2
mov rax, 13 ;sigaction
syscall

;anounce ourselfs
mov rdx, 5    ; message string length
mov rsi, kaksetozove    ; message address
mov rdi, 1        ; stdout
mov rax, 1        ; sys_write
syscall

;ioctl TCSETSW and pointer to termios struct
ish_loop:
mov rbp, 0
mov rax, 0
getline:
add rbp, rax
no_char:
mov rsi, rbp
mov rdx, 1    ; message string length
add rsi, line    ; message address
mov rdi, 0        ; stdin
mov rax, 0        ; sys_read
syscall
;Its a tarp!
cmp byte [line+rbp], 4
jz exit
cmp byte [line+rbp], 27 ;ESC
jnz esc_char
mov rdx, 2
mov rsi, tmp
mov rdi, 0
mov rax, 0
syscall
;cmp byte [line+rbp], 91 ;[
;jz no_char
;cmp byte [line+rbp], 65 ;up
;jz no_char
jmp no_char
esc_char:
cmp byte [line+rbp], 127 ;del
jz del_char
cmp byte [line+rbp], 8 ;backspace
jnz delete_char
del_char:
cmp rbp, 0
jz no_char
dec rbp
mov dword [line+rbp], 0x4B5B1B08 ;backspace+some esc sequence to delete
mov rdx, 4
mov rsi, rbp
add rsi, line
mov rdi, 1
mov rax, 1
syscall
jmp no_char
delete_char:
;asdasdasdasdasd
mov rdx, 1
mov rsi, rbp
add rsi, line
mov rdi, 1
mov rax, 1
syscall
mov bl, byte [line+rbp] ;quick UTF hax, TODO move and not forget
shr bl, 6
cmp bl, 2
jnz no_utf
dec rbp
;mov bl, byte [line+rbp]
;shr bl, 6
;cmp bl, 3
;jnz no_char
no_utf:
cmp byte [line+rbp], 10
jnz getline
cmp rbp, 0
jz no_char
mov byte [line+rbp], 0 ;for hax (newline haxed out)
;autocomplete uses getdents
;ctrl+c uses SIGINT

;break by tokens
tokenize:
mov rdx, line
mov rax, tokens
mov [argv], qword rax
mov rcx, 0
dec rdx
toke_loop:
inc rdx
cmp [rdx], byte " "
jz toke_loop
cmp [rdx], byte 0
jz toke_end
store_token:
mov [argv+rcx], rax
add rcx, 8
copy_token:
movzx r9, byte [rdx]
mov [rax], qword r9
inc rdx
inc rax
cmp [rdx], byte 92 ; its "\"
jz toke_esc_char
cmp [rdx], byte " "
jz toke_add_null
cmp [rdx], byte 0
jz toke_end
jmp copy_token
toke_esc_char:
add rdx, 1
jmp copy_token
toke_add_null:
mov [rax], byte 0
inc rax
jmp toke_loop
toke_end:
mov [argv+rcx], dword 0

;check if builtin
mov rax, [argv]
cmp [rax], word "cd"
jnz not_cd
jmp chdir ;hax, later path concatenateing
xor rdx, rdx
mov rax, [argv+8]
get_chdir:
mov cl, [rax+rdx]
mov [current_cwd+rdx], cl
cmp cl, 0
jz chdir
inc rdx
jmp get_chdir
chdir:
mov rdi, [argv+8]
mov rax, 80 ;chdir
syscall
cmp rax, 0
;jz ish_loop
jmp print ;add error checking
not_cd:

;call fork
mov rax, 57 ;fork
syscall
;check if child, if not save child pid !
cmp rax, 0
jnz wait_child
;remember pid ?

prepare_file_name:
mov rax, [envp]
sub rax, 8
filename_find_PATH:
add rax, 8
cmp [rax], dword 0
jz filename_path ;TODO should be PATH NOT FOUND
mov rcx, [rax]
cmp [rcx], dword "PATH"
jnz filename_find_PATH
mov rdi, [rax+8] ;TODO check if 0
filename_path:
add rcx, 4
find_path:
push rdi
mov rax, filename
xor rsi, rsi
fn_path_loop:
add rcx, 1
mov dl, [rcx]
mov [rax+rsi], dl
inc rsi
cmp rcx, rdi
jne last_char_in_path
dec rax
jmp last_path
last_char_in_path:
jg not_found
cmp dl, ":"
jnz fn_path_loop
last_path:
push rcx
add rax, rsi
mov [rax-1], byte "/"
;path inserting should be different maybe
mov rsi, -1
cat_name_to_path:
inc rsi
mov dl, [line+rsi]
cmp dl, 0
jz cat_name_end
cmp dl, " "
jz cat_name_end
mov [rax+rsi], dl
jmp cat_name_to_path
cat_name_end:
mov [rax+rsi], byte 0
;check if exists, can check lots of things
mov rsi, fileproperties
mov rdi, filename
mov rax, 4 ;stat
syscall
pop rcx
pop rdi
cmp rax, -2 ;ENOENT
jz find_path

;set enviroment
;set pipes
execve_sys:
mov rdx, [envp]
mov rsi, argv
mov rdi, filename
mov rax, 59 ;execve
syscall

not_found:
;if anything exit
mov rdi, -99
mov rax, 60
syscall

;move to process controll Smile
wait_child:
mov rcx, 0
mov rdx, 0
mov rsi, 0
mov rdi, -1
mov rax, 61
syscall

jmp print
debug:
mov rdx, 100
mov rsi, rax
mov rdi, 1
mov rax, 1
syscall
;ret

print:
mov rdx, 5
mov rsi, kaksetozove
mov rdi, 1 ;stdout
mov rax, 1 ;sys_write
syscall

jmp ish_loop

align 16
sigrest:
mov rax, 15
syscall
align 16
sigact:
jmp ish_loop

exit:
;restore terminal IO
mov rdx, termios_old
mov rsi, 0x5402
mov rdi, 0
mov rax, 16
syscall
;print newline
mov byte [line], 10
mov rdx, 1
mov rsi, line
mov rdi, 1
mov rax, 1
syscall
mov rax, 60
syscall
    


bdw, i call it ishell
feel free to use it or whatever
Post 20 Feb 2013, 17:13
View user's profile Send private message Reply with quote
sleepsleep



Joined: 05 Oct 2006
Posts: 8904
Location: ˛                             ⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣Posts: 334455
sleepsleep
i think i want to join you,
build my own fasm linux shell too!!
wow,

interesting idea!
Post 27 Jun 2013, 10:10
View user's profile Send private message Reply with quote
typedef



Joined: 25 Jul 2010
Posts: 2913
Location: 0x77760000
typedef
Use hashes.

For example.

Code:
; Hash function for Strings in JAVA.
function hash, string_cmd
{
   h = 0;
   for(c in string_cmd){
     h = h * 31 + c;
  }
   return h;
}


; Define a table of hashes to look up
hashes:
.cd     dd 0x12345
.exec  dd 0x6789A
    


Then you get the string to the left of the first space and hash it. Walk the hash table (you can pre-sort your hash table also and use binary search for performance). The index the hash was found at is the index to a function table for that command. Any other strings after the space will be treated as parameters.

So.
Code:
>> Enter command: cd "usr/bin" 
i = find_index(hash("cd"))

if i >= 0
   call_fn_by_index, i, substr(strstr("cd ")+1) ; get everything after 1st space
else
  print "Command not found"
endif
    
Post 27 Jun 2013, 11:36
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 17287
Location: In your JS exploiting you and your system
revolution
Hashes don't allow partial matching. For unambiguous inputs you can use shortened entry if you do standard text scanning matches. Saves typing.

Hashes just confuse things and make source code more difficult to follow and/or understand IMO.

Keep it simple, just do normal string comparisons.
Post 27 Jun 2013, 11:45
View user's profile Send private message Visit poster's website Reply with quote
sleepsleep



Joined: 05 Oct 2006
Posts: 8904
Location: ˛                             ⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣Posts: 334455
sleepsleep
i only want my shell to support maximum 5 or 7 chars command,
and i want my shell to function in 2 window,
1 command window
1 info window
the screen will split into half, maybe 3 (3 is great number)

press hold [space] + j will do window jump

lots of ideas actually,

press hold [space] + d will do directory listing

maybe, logical short cut for logical tasks,
aim is, short cut, as it introduces some sort of easier way (hopefully) and give users a sense that they got something new, and push them to explore a different way to control a system.
Post 27 Jun 2013, 13:08
View user's profile Send private message Reply with quote
cod3b453



Joined: 25 Aug 2004
Posts: 619
cod3b453
You'll always have a "string"->code mapping the question is how complex you want your syntax to be. If you want the same level of power as bash et al. I'd recommend you look at using LALR(1) parsing; this is more complex but works well when you have a large grammar*. Instead of a simple <string,pointer> pair, you have a state machine that processes the command line - basically lots of lookup tables and switch statements that accept or reject the line.

*You can get tools that help in constructing rules and testing them such as GOLD (http://goldparser.org/); yacc and bison might have something similar Question
Post 27 Jun 2013, 17:10
View user's profile Send private message Reply with quote
gens



Joined: 18 Feb 2013
Posts: 161
gens
thx for the tips people

LALR looks interesting
shell scripts are mostly just sequential logic thou, with a couple variables
(dont have nothing to patch variables either)


sleep, its not that hard to make a shell
basically its setup the environment, bit of text processing then fork+exec
things like split "screen" and such is just manipulating the console with escape characters (check ncurses)
Post 29 Jun 2013, 23:50
View user's profile Send private message Reply with quote
sleepsleep



Joined: 05 Oct 2006
Posts: 8904
Location: ˛                             ⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣Posts: 334455
sleepsleep
thanks gens,

one idea just struck me,
i dont want to ENTER in my shell,

eg,
cp /a1 /a2
during the spacebar,eg,
# cp[spacebar]
# options:-a -b -c -d -e -f [-a]:[spacebar]
# options:-a -b -c -d -e -f [-a]:?-a[spacebar] // to know more about -a switch info ~ will dump the info in info window.
# source : /a1[spacebar]
# destination : /a2[spacebar]

this works like a wizard shell,
since [spacebar] is a must pressed key in classic shell, why not implement it wizard mode.
Post 30 Jun 2013, 03:35
View user's profile Send private message Reply with quote
gens



Joined: 18 Feb 2013
Posts: 161
gens
that would get annoying fast when you have hundreds of files Smile
but you can do it np, you'd just have to do it for every program
maybe better just displaying a help box in the top right corner or something

if you plan to do a linux shell, you'ld probably have to read (some) POSIX specs
POSIX among other things specifies just that switches for standard UNIX programs (ls, cd, cp etc.) so its easy to know without help
(also theres mc)

bdw, most terminals support mouse clicking
Post 30 Jun 2013, 18:15
View user's profile Send private message Reply with quote
sleepsleep



Joined: 05 Oct 2006
Posts: 8904
Location: ˛                             ⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣Posts: 334455
sleepsleep
maybe it would probably works as linux beginner wizard shell,
Post 01 Jul 2013, 00:05
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2020, Tomasz Grysztar. Also on YouTube, Twitter.

Website powered by rwasa.