mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 11:12:45 +00:00 
			
		
		
		
	Shell: Move the Shell to a separate directory and let's call it "Shell" :^)
This commit is contained in:
		
							parent
							
								
									e63cc38861
								
							
						
					
					
						commit
						fe73543d41
					
				
					 7 changed files with 217 additions and 180 deletions
				
			
		|  | @ -65,9 +65,9 @@ static void make_shell(int ptm_fd) | |||
|             perror("ioctl(TIOCSCTTY)"); | ||||
|             exit(1); | ||||
|         } | ||||
|         char* args[] = { "/bin/sh", nullptr }; | ||||
|         char* args[] = { "/bin/Shell", nullptr }; | ||||
|         char* envs[] = { "TERM=xterm", "PATH=/bin:/usr/bin", nullptr }; | ||||
|         rc = execve("/bin/sh", args, envs); | ||||
|         rc = execve("/bin/Shell", args, envs); | ||||
|         if (rc < 0) { | ||||
|             perror("execve"); | ||||
|             exit(1); | ||||
|  |  | |||
|  | @ -75,6 +75,8 @@ cp -v ../Games/Minesweeper/Minesweeper mnt/bin/Minesweeper | |||
| ln -s Minesweeper mnt/bin/ms | ||||
| cp -v ../Games/Snake/Snake mnt/bin/Snake | ||||
| ln -s Snake mnt/bin/sn | ||||
| cp -v ../Shell/Shell mnt/bin/Shell | ||||
| ln -s Shell mnt/bin/sh | ||||
| cp -v kernel.map mnt/ | ||||
| 
 | ||||
| # Run local sync script, if it exists | ||||
|  |  | |||
							
								
								
									
										3
									
								
								Shell/.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								Shell/.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,3 @@ | |||
| *.o | ||||
| *.d | ||||
| Shell | ||||
							
								
								
									
										23
									
								
								Shell/Makefile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								Shell/Makefile
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,23 @@ | |||
| include ../Makefile.common | ||||
| 
 | ||||
| OBJS = \
 | ||||
|     Parser.o \
 | ||||
|     main.o | ||||
| 
 | ||||
| APP = Shell | ||||
| 
 | ||||
| DEFINES += -DUSERLAND | ||||
| 
 | ||||
| all: $(APP) | ||||
| 
 | ||||
| $(APP): $(OBJS) | ||||
| 	$(LD) -o $(APP) $(LDFLAGS) $(OBJS) -lcore -lc | ||||
| 
 | ||||
| .cpp.o: | ||||
| 	@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $< | ||||
| 
 | ||||
| -include $(OBJS:%.o=%.d) | ||||
| 
 | ||||
| clean: | ||||
| 	@echo "CLEAN"; rm -f $(APPS) $(OBJS) *.d | ||||
| 
 | ||||
							
								
								
									
										140
									
								
								Shell/Parser.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								Shell/Parser.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,140 @@ | |||
| #include "Parser.h" | ||||
| #include <stdio.h> | ||||
| #include <unistd.h> | ||||
| 
 | ||||
| void Parser::commit_token() | ||||
| { | ||||
|     if (m_token.is_empty()) | ||||
|         return; | ||||
|     if (m_state == InRedirectionPath) { | ||||
|         m_redirections.last().path = String::copy(m_token); | ||||
|         m_token.clear_with_capacity(); | ||||
|         return; | ||||
|     } | ||||
|     m_tokens.append(String::copy(m_token)); | ||||
|     m_token.clear_with_capacity(); | ||||
| }; | ||||
| 
 | ||||
| void Parser::commit_subcommand() | ||||
| { | ||||
|     if (m_tokens.is_empty()) | ||||
|         return; | ||||
|     m_subcommands.append({ move(m_tokens), move(m_redirections) }); | ||||
| } | ||||
| 
 | ||||
| void Parser::do_pipe() | ||||
| { | ||||
|     m_redirections.append({ Redirection::Pipe, STDOUT_FILENO }); | ||||
|     commit_subcommand(); | ||||
| } | ||||
| 
 | ||||
| void Parser::begin_redirect_read(int fd) | ||||
| { | ||||
|     m_redirections.append({ Redirection::FileRead, fd }); | ||||
| } | ||||
| 
 | ||||
| void Parser::begin_redirect_write(int fd) | ||||
| { | ||||
|     m_redirections.append({ Redirection::FileWrite, fd }); | ||||
| } | ||||
| 
 | ||||
| Vector<Subcommand> Parser::parse() | ||||
| { | ||||
|     for (int i = 0; i < m_input.length(); ++i) { | ||||
|         char ch = m_input.characters()[i]; | ||||
|         switch (m_state) { | ||||
|         case State::Free: | ||||
|             if (ch == ' ') { | ||||
|                 commit_token(); | ||||
|                 break; | ||||
|             } | ||||
|             if (ch == '|') { | ||||
|                 commit_token(); | ||||
|                 if (m_tokens.is_empty()) { | ||||
|                     fprintf(stderr, "Syntax error: Nothing before pipe (|)\n"); | ||||
|                     return { }; | ||||
|                 } | ||||
|                 do_pipe(); | ||||
|                 break; | ||||
|             } | ||||
|             if (ch == '>') { | ||||
|                 commit_token(); | ||||
|                 begin_redirect_write(STDOUT_FILENO); | ||||
|                 m_state = State::InRedirectionPath; | ||||
|                 break; | ||||
|             } | ||||
|             if (ch == '<') { | ||||
|                 commit_token(); | ||||
|                 begin_redirect_read(STDIN_FILENO); | ||||
|                 m_state = State::InRedirectionPath; | ||||
|                 break; | ||||
|             } | ||||
|             if (ch == '\'') { | ||||
|                 m_state = State::InSingleQuotes; | ||||
|                 break; | ||||
|             } | ||||
|             if (ch == '\"') { | ||||
|                 m_state = State::InDoubleQuotes; | ||||
|                 break; | ||||
|             } | ||||
|             m_token.append(ch); | ||||
|             break; | ||||
|         case State::InRedirectionPath: | ||||
|             if (ch == '<') { | ||||
|                 commit_token(); | ||||
|                 begin_redirect_read(STDIN_FILENO); | ||||
|                 m_state = State::InRedirectionPath; | ||||
|                 break; | ||||
|             } | ||||
|             if (ch == '>') { | ||||
|                 commit_token(); | ||||
|                 begin_redirect_read(STDOUT_FILENO); | ||||
|                 m_state = State::InRedirectionPath; | ||||
|                 break; | ||||
|             } | ||||
|             if (ch == '|') { | ||||
|                 commit_token(); | ||||
|                 if (m_tokens.is_empty()) { | ||||
|                     fprintf(stderr, "Syntax error: Nothing before pipe (|)\n"); | ||||
|                     return { }; | ||||
|                 } | ||||
|                 do_pipe(); | ||||
|                 m_state = State::Free; | ||||
|                 break; | ||||
|             } | ||||
|             if (ch == ' ') | ||||
|                 break; | ||||
|             m_token.append(ch); | ||||
|             break; | ||||
|         case State::InSingleQuotes: | ||||
|             if (ch == '\'') { | ||||
|                 commit_token(); | ||||
|                 m_state = State::Free; | ||||
|                 break; | ||||
|             } | ||||
|             m_token.append(ch); | ||||
|             break; | ||||
|         case State::InDoubleQuotes: | ||||
|             if (ch == '\"') { | ||||
|                 commit_token(); | ||||
|                 m_state = State::Free; | ||||
|                 break; | ||||
|             } | ||||
|             m_token.append(ch); | ||||
|             break; | ||||
|         }; | ||||
|     } | ||||
|     commit_token(); | ||||
|     commit_subcommand(); | ||||
| 
 | ||||
|     if (!m_subcommands.is_empty()) { | ||||
|         for (auto& redirection : m_subcommands.last().redirections) { | ||||
|             if (redirection.type == Redirection::Pipe) { | ||||
|                 fprintf(stderr, "Syntax error: Nothing after last pipe (|)\n"); | ||||
|                 return { }; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return move(m_subcommands); | ||||
| } | ||||
							
								
								
									
										46
									
								
								Shell/Parser.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								Shell/Parser.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,46 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <AK/AKString.h> | ||||
| #include <AK/Vector.h> | ||||
| 
 | ||||
| struct Redirection { | ||||
|     enum Type { Pipe, FileWrite, FileRead, Rewire }; | ||||
|     Type type; | ||||
|     int fd { -1 }; | ||||
|     int rewire_fd { -1 }; | ||||
|     String path { }; | ||||
| }; | ||||
| 
 | ||||
| struct Subcommand { | ||||
|     Vector<String> args; | ||||
|     Vector<Redirection> redirections; | ||||
| }; | ||||
| 
 | ||||
| class Parser { | ||||
| public: | ||||
|     explicit Parser(const String& input) : m_input(input) { } | ||||
| 
 | ||||
|     Vector<Subcommand> parse(); | ||||
| 
 | ||||
| private: | ||||
|     void commit_token(); | ||||
|     void commit_subcommand(); | ||||
|     void do_pipe(); | ||||
|     void begin_redirect_read(int fd); | ||||
|     void begin_redirect_write(int fd); | ||||
| 
 | ||||
|     enum State { | ||||
|         Free, | ||||
|         InSingleQuotes, | ||||
|         InDoubleQuotes, | ||||
|         InRedirectionPath, | ||||
|     }; | ||||
|     State m_state { Free }; | ||||
|     String m_input; | ||||
| 
 | ||||
|     Vector<Subcommand> m_subcommands; | ||||
|     Vector<String> m_tokens; | ||||
|     Vector<Redirection> m_redirections; | ||||
|     Vector<char> m_token; | ||||
| }; | ||||
| 
 | ||||
|  | @ -13,6 +13,7 @@ | |||
| #include <sys/utsname.h> | ||||
| #include <AK/FileSystemPath.h> | ||||
| #include <LibCore/CElapsedTimer.h> | ||||
| #include "Parser.h" | ||||
| 
 | ||||
| //#define SH_DEBUG
 | ||||
| 
 | ||||
|  | @ -144,184 +145,6 @@ static bool handle_builtin(int argc, char** argv, int& retval) | |||
|     return false; | ||||
| } | ||||
| 
 | ||||
| struct Redirection { | ||||
|     enum Type { Pipe, FileWrite, FileRead, Rewire }; | ||||
|     Type type; | ||||
|     int fd { -1 }; | ||||
|     int rewire_fd { -1 }; | ||||
|     String path { }; | ||||
| }; | ||||
| 
 | ||||
| struct Subcommand { | ||||
|     Vector<String> args; | ||||
|     Vector<Redirection> redirections; | ||||
| }; | ||||
| 
 | ||||
| class Parser { | ||||
| public: | ||||
|     explicit Parser(const String& input) : m_input(input) { } | ||||
| 
 | ||||
|     Vector<Subcommand> parse(); | ||||
| 
 | ||||
| private: | ||||
|     void commit_token(); | ||||
|     void commit_subcommand(); | ||||
|     void do_pipe(); | ||||
|     void begin_redirect_read(int fd); | ||||
|     void begin_redirect_write(int fd); | ||||
| 
 | ||||
|     enum State { | ||||
|         Free, | ||||
|         InSingleQuotes, | ||||
|         InDoubleQuotes, | ||||
|         InRedirectionPath, | ||||
|     }; | ||||
|     State m_state { Free }; | ||||
|     String m_input; | ||||
| 
 | ||||
|     Vector<Subcommand> m_subcommands; | ||||
|     Vector<String> m_tokens; | ||||
|     Vector<Redirection> m_redirections; | ||||
|     Vector<char> m_token; | ||||
| }; | ||||
| 
 | ||||
| void Parser::commit_token() | ||||
| { | ||||
|     if (m_token.is_empty()) | ||||
|         return; | ||||
|     if (m_state == InRedirectionPath) { | ||||
|         m_redirections.last().path = String::copy(m_token); | ||||
|         m_token.clear_with_capacity(); | ||||
|         return; | ||||
|     } | ||||
|     m_tokens.append(String::copy(m_token)); | ||||
|     m_token.clear_with_capacity(); | ||||
| }; | ||||
| 
 | ||||
| void Parser::commit_subcommand() | ||||
| { | ||||
|     if (m_tokens.is_empty()) | ||||
|         return; | ||||
|     m_subcommands.append({ move(m_tokens), move(m_redirections) }); | ||||
| } | ||||
| 
 | ||||
| void Parser::do_pipe() | ||||
| { | ||||
|     m_redirections.append({ Redirection::Pipe, STDOUT_FILENO }); | ||||
|     commit_subcommand(); | ||||
| } | ||||
| 
 | ||||
| void Parser::begin_redirect_read(int fd) | ||||
| { | ||||
|     m_redirections.append({ Redirection::FileRead, fd }); | ||||
| } | ||||
| 
 | ||||
| void Parser::begin_redirect_write(int fd) | ||||
| { | ||||
|     m_redirections.append({ Redirection::FileWrite, fd }); | ||||
| } | ||||
| 
 | ||||
| Vector<Subcommand> Parser::parse() | ||||
| { | ||||
|     for (int i = 0; i < m_input.length(); ++i) { | ||||
|         char ch = m_input.characters()[i]; | ||||
|         switch (m_state) { | ||||
|         case State::Free: | ||||
|             if (ch == ' ') { | ||||
|                 commit_token(); | ||||
|                 break; | ||||
|             } | ||||
|             if (ch == '|') { | ||||
|                 commit_token(); | ||||
|                 if (m_tokens.is_empty()) { | ||||
|                     fprintf(stderr, "Syntax error: Nothing before pipe (|)\n"); | ||||
|                     return { }; | ||||
|                 } | ||||
|                 do_pipe(); | ||||
|                 break; | ||||
|             } | ||||
|             if (ch == '>') { | ||||
|                 commit_token(); | ||||
|                 begin_redirect_write(STDOUT_FILENO); | ||||
|                 m_state = State::InRedirectionPath; | ||||
|                 break; | ||||
|             } | ||||
|             if (ch == '<') { | ||||
|                 commit_token(); | ||||
|                 begin_redirect_read(STDIN_FILENO); | ||||
|                 m_state = State::InRedirectionPath; | ||||
|                 break; | ||||
|             } | ||||
|             if (ch == '\'') { | ||||
|                 m_state = State::InSingleQuotes; | ||||
|                 break; | ||||
|             } | ||||
|             if (ch == '\"') { | ||||
|                 m_state = State::InDoubleQuotes; | ||||
|                 break; | ||||
|             } | ||||
|             m_token.append(ch); | ||||
|             break; | ||||
|         case State::InRedirectionPath: | ||||
|             if (ch == '<') { | ||||
|                 commit_token(); | ||||
|                 begin_redirect_read(STDIN_FILENO); | ||||
|                 m_state = State::InRedirectionPath; | ||||
|                 break; | ||||
|             } | ||||
|             if (ch == '>') { | ||||
|                 commit_token(); | ||||
|                 begin_redirect_read(STDOUT_FILENO); | ||||
|                 m_state = State::InRedirectionPath; | ||||
|                 break; | ||||
|             } | ||||
|             if (ch == '|') { | ||||
|                 commit_token(); | ||||
|                 if (m_tokens.is_empty()) { | ||||
|                     fprintf(stderr, "Syntax error: Nothing before pipe (|)\n"); | ||||
|                     return { }; | ||||
|                 } | ||||
|                 do_pipe(); | ||||
|                 m_state = State::Free; | ||||
|                 break; | ||||
|             } | ||||
|             if (ch == ' ') | ||||
|                 break; | ||||
|             m_token.append(ch); | ||||
|             break; | ||||
|         case State::InSingleQuotes: | ||||
|             if (ch == '\'') { | ||||
|                 commit_token(); | ||||
|                 m_state = State::Free; | ||||
|                 break; | ||||
|             } | ||||
|             m_token.append(ch); | ||||
|             break; | ||||
|         case State::InDoubleQuotes: | ||||
|             if (ch == '\"') { | ||||
|                 commit_token(); | ||||
|                 m_state = State::Free; | ||||
|                 break; | ||||
|             } | ||||
|             m_token.append(ch); | ||||
|             break; | ||||
|         }; | ||||
|     } | ||||
|     commit_token(); | ||||
|     commit_subcommand(); | ||||
| 
 | ||||
|     if (!m_subcommands.is_empty()) { | ||||
|         for (auto& redirection : m_subcommands.last().redirections) { | ||||
|             if (redirection.type == Redirection::Pipe) { | ||||
|                 fprintf(stderr, "Syntax error: Nothing after last pipe (|)\n"); | ||||
|                 return { }; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return move(m_subcommands); | ||||
| } | ||||
| 
 | ||||
| class FileDescriptorCollector { | ||||
| public: | ||||
|     FileDescriptorCollector() { } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling