summaryrefslogtreecommitdiff
path: root/Source/Kernel/Shell/KernelShell.class.cpp
blob: 7f57f8b7a45aad9dc64254480bdc05049ad6cad3 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#include "KernelShell.class.h"
#include <VTManager/ScrollableVT.class.h>
#include <DeviceManager/Kbd.ns.h>
#include <SimpleList.class.h>
#include <MemoryManager/PhysMem.ns.h>
#include <VFS/VFS.ns.h>
#include <FileSystems/RamFS/RamFS.class.h>
#include <TaskManager/Task.ns.h>

u32int KernelShell::m_instances = 0;

u32int shellRun(void* ks) {
	KernelShell* sh = (KernelShell*)ks;
	u32int ret = sh->run();
	delete sh;
	return ret;
}

void KernelShell::setup(DirectoryNode* cwd, VirtualTerminal *vt) {
	m_vt = vt;
	Task::currProcess()->setInVT(vt);
	Task::currProcess()->setOutVT(vt);
	m_cwd = cwd;
	*m_vt << "Welcome to Melon's kernel shell !\n";
	m_thread = new Thread(shellRun, (void*)this, true);
	m_instances++;
}

KernelShell::KernelShell(DirectoryNode* cwd, VirtualTerminal* vt) {
	setup(cwd, vt);
}

KernelShell::KernelShell(DirectoryNode* cwd) {
	ScrollableVT* vt = new ScrollableVT(15, 76, 200, KVT_FGCOLOR, KVT_BGCOLOR);
	vt->map(9);
	Kbd::setFocus(vt);
	setup(cwd, vt);
}

KernelShell::~KernelShell() {
	delete m_vt;
	m_instances--;
}

u32int KernelShell::run() {
	struct {
		const char* name;
		void (KernelShell::*cmd)(Vector<String>&);
	} commands[]= {
		{"ls",    &KernelShell::ls},
		{"cd",    &KernelShell::cd},
		{"pwd",   &KernelShell::pwd},
		{"cat",   &KernelShell::cat},
		{"mkdir", &KernelShell::mkdir},
		{"rm",    &KernelShell::rm},
		{"wf",    &KernelShell::wf},
		{"run",	  &KernelShell::run},

		{"devices", &KernelShell::devices},
		{"loadkeys", &KernelShell::loadkeys},
		{"free", &KernelShell::free},
		{"uptime", &KernelShell::uptime},
		{"part", &KernelShell::part},

		{0, 0}
	};
	
	while (1) {
		m_vt->setColor(KVT_LIGHTCOLOR);
		*m_vt << VFS::path(m_cwd) << " # ";
		m_vt->setColor(KVT_ENTRYCOLOR);
		Vector<String> tokens = m_vt->readLine().split(" ");
		m_vt->setColor(KVT_FGCOLOR);
		if (tokens[0] == "help") {
			*m_vt << " - Command list for integrated kernel shell:\n";
			*m_vt << "  - help       shows this help screen\n";
			*m_vt << "  - reboot     reboots your computer\n";
			*m_vt << "  - halt       shuts down your computer\n";
			*m_vt << "  - panic      causes a kernel panic\n";
			*m_vt << "  - devices    shows all detected devices on your computer\n";
			*m_vt << "  - loadkeys   loads specified kekymap\n";
			*m_vt << "  - free       shows memory usage (frames and kheap)\n";
			*m_vt << "  - uptime     shows seconds since boot\n";
			*m_vt << "  - part       shows all detected block devs and partitions\n";
			*m_vt << "  - Standard UNIX commands : ls cd cat pwd rm mkdir wf\n";
			*m_vt << " - Scroll up with shift+pgup !\n";
		} else if (tokens[0] == "reboot") {
			Sys::reboot();
		} else if (tokens[0] == "halt") {
			Sys::halt();
		} else if (tokens[0] == "panic") {
			PANIC("This is what happens when you say 'panic'.");
		} else if (tokens[0] == "exit") {
			if (tokens.size() == 1) return 0;
			return tokens[1].toInt();
		} else if (tokens[0] == "mount") {
			if (tokens.size() == 1) {
				for (u32int i = 0; i < VFS::filesystems.size(); i++) {
					*m_vt << VFS::path(VFS::filesystems[i]->getRootNode()) << "\n";
				}
			} else if (tokens.size() == 3) {
				if (tokens[1] == "ramfs") {
					FSNode* n = VFS::find(tokens[2], m_cwd);
					if (n == 0) {
						*m_vt << "No such directory.\n";
					} else if (n->type() != NT_DIRECTORY) {
						*m_vt << "Not a directory.\n";
					} else {
						if (RamFS::mount(100000, (DirectoryNode*)n) != 0) {
							*m_vt << "Ok...\n";
						} else {
							*m_vt << "Error !\n";
						}
					}
				} else {
					*m_vt << "Not supported yet.\n";
				}
			} else {
				*m_vt << "Usage: mount [<device> <mountpoint>\n";
			}
		} else if (tokens[0] == "unmount") {
			if (tokens.size() == 2) {
				FSNode* n = VFS::find(tokens[1], m_cwd);
				bool ok = false;
				if (n == 0) {
					ok = false;
				} else {
					String p = VFS::path(n);
					for (u32int i = 0; i < VFS::filesystems.size(); i++) {
						if (VFS::path(VFS::filesystems[i]->getRootNode()) == p) {
							ok = VFS::unmount(VFS::filesystems[i]);
							break;
						}
					}
				}
				if (ok) *m_vt << "Ok, filesystem unmounted.\n";
				else *m_vt << "Error.\n";
			} else {
				*m_vt << "Usage: unmount <mountpoint>\n";
			}
		} else if (tokens[0] != "" or tokens.size() != 1) {
			u32int i = 0;
			bool found = false;
			while (commands[i].name != 0) {
				if (tokens[0] == (const char*)commands[i].name) {
					found = true;
					if (commands[i].cmd != 0) {
						(this->*(commands[i].cmd))(tokens);	//Call command
					} else {
						*m_vt << "This command isn't enabled... yet !\n";
					}
					break;
				}
				i++;
			}
			if (!found) *m_vt << "Unknown command : " << tokens[0] << "\n";
		}
	}
	return 1337;
}