Bình luận

Thông báo

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Test link

Hust-OS-TinyShell Bài Tập Lớn Môn Nguyên Lý Hệ Điều Hành

Hust-OS-TinyShell Bài Tập Lớn Môn Nguyên Lý Hệ Điều Hành, TinyShell, Nguyên Lý Hệ Điều Hành, Bài Tập Lớn, TinyShell Hệ Điều Hành.
263 min read

Hust - OS - TinyShell

Chào các bạn lại đến với bài viết của mình. Sau hơn một tuần tìm hiểu cũng như là tham khảo các bài trên mạng và các khóa đi trước thì mình cùng mấy đứa trong nhóm đã làm được một chiếc TinyShell nên hôm nay mình quyết định đăng lên đây để chia sẻ cho mọi người cũng như lưu lại những công sức mà chúng mình đã làm được.

Hust-OS-TinyShell Bài Tập Lớn Môn Nguyên Lý Hệ Điều Hành

Nội Dung

Công cụ Shell ra đời từ đó dưới dạng giả lập hệ điều hành MS-DOS của Microsoft trên Windows. Dự án Tiny Shell là một dự án giúp sinh viên có thể tìm hiểu cách quản lý tiến trình đó.

Giới Thiệu Về TinyShell:

Đề Tài:

  • TinyShell: tìm hiểu về quản lý tiến trình sử dụng Win32 API
  • Ngôn ngữ: C/C++
  • Phát hành: 05/06/2021

Tính Năng:

  • Shell nhận lệnh ,phân tích và tạo tiến trình con thực hiện
  • Shell chứa các câu lệnh quản lý tiến trình
  • Shell thực hiện một số lệnh đặc biệt
  • Shell nhận tín hiệu từ bàn phím để hủy bỏ Foreground Processes đang thực hiện (CTRL +C)
  • Shell có thể thực thi được file *.bat

Tác Giả:

  • Phạm Văn Linh - 20194094
  • Lê Trọng Khánh - 20194082
  • Nguyễn Văn An - 20193974
  • Lê Hồng Ưng - 20194211
  • Hà Mạnh Hùng - 20194066

Video Demo:

Youtube videoYoutube video

Mã Nguồn:

TinyShell.cpp

Như Command Prompt hay PowerShell thì TinyShell cũng cần có phần nhập vào từ bàn phím.

/******************************************************************
* ------------------- WELCOME TO OUR TINYSHELL -------------------
* @author: Le Trong Khanh,
* Pham Van Linh,
* Nguyen Van An,
* Ha Manh Hung,
* Le Hong Ung
* @name of Program: Tiny Shell
* @IT1-01-K64
* @05-06-2021
* ----------------------------------------------------------------
******************************************************************/
#include "Analyse.h"
#include "Command.h"
#include "Process.h"
using namespace std;
int main (int argc, char** argv) {
char cur_dir[MAX_CWD_LENS];
/* Ctrl + C => STOP */
signal(SIGINT, sighandler);
/* set màu chữ cho shell */
char color[] = "green";
setColor(color);
char *cmd = (char*)calloc(MAX_BUFFER_SIZE,sizeof(char)); /*Cấp phát bộ nhớ để nhập dòng lệnh command VD: cd, dir, ....*/
int stop = 0; /**/
while(!stop) { /* Nếu vẫn chưa stop thì thực hiện nhập và chạy lệnh */
if(printPrompt(cur_dir) == -1){ /* Kiểm tra, in ra đường dẫn VD: C:\Users\Admin\> $ .....*/
break;
}
fflush(stdin);
cin.getline(cmd, MAX_BUFFER_SIZE); /* Nhập lệnh command */
cin.clear();
// cout << "HUST" << endl;
// sleep(1);
// fixCmd(cmd); /* Chỉnh sửa câu lệnh tránh các lỗi nhập cách khoảng */
char **args = separate_line(cmd); /* Chia câu lệnh */
/**
* VD: dir C:\Users\Admin .....
* => args[0] : dir
* => args[1] : C:\Users\Admin
* .....
**/
stop = execute(args); /* Thực hiện lệnh, trả về 0 nếu tiếp tục, trả về 1 để thoát*/
free(args); /*Giải phóng các con trỏ lệnh*/
}
free(cmd); /*Giải phóng lệnh*/
return EXIT_SUCCESS;
}
view raw TinyShell.cpp hosted with ❤ by GitHub

Analyse.cpp

Tiếp theo là phần này để xử lí câu lệnh vừa nhập ở trên VD: tách các câu lệnh đã nhập, xóa bỏ các dấu cách thừa, ghép lại các câu lệnh để thực hiện các bước tiếp theo.

#include <iostream>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <windows.h>
#include <time.h>
#include <sys/types.h>
#include <psapi.h>
#include <tlhelp32.h>
#include "Command.h"
#define MAX_CWD_LENS 128
#define MAX_BUFFER_SIZE 64
#define MAX_TOK_BUFSIZE 64
#define TOKEN_DELIMETERS " \t\r\n\a"
using namespace std;
/////////////////////////////////////
////////// Xử lý câu lệnh ///////////
/////////////////////////////////////
/**
* Sửa lỗi gõ cách câu lệnh
* VD: C:\Users\Admin> $ cd E:\
* ==> C:\Users\Admin> $ cd E:\
*
**/
void fixCmd(char* cmd){
/**
* Sửa lỗi gõ cách câu lệnh
* VD: C:\Users\Admin> $ cd E:\
* ==> C:\Users\Admin> $ cd E:\
*
**/
int length = strlen(cmd);
int first;
for(int i=0; i<length; i++){
if((cmd)[i] != ' '){
first = i;
break;
}
}
int real_len = length - first, i=0;
// " Ta Ton" -> "Ta Tona Ton"
while(real_len--){
(cmd)[i] = (cmd)[i+first];
i++;
}
(cmd)[length - first] = '\0'; //"Ta Tona Ton" -> "Ta Ton"
}
/**
* In ra màn hình console đường dẫn
* (VD: C:\Users\Admin\.....> $ *phần tiếp này là lệnh*)
**/
int printPrompt(char *cur_directory){
/**
* In ra màn hình console đường dẫn
* (VD: C:\Users\Admin\.....> $ *phần tiếp này là lệnh*)
**/
if(GetCurrentDirectory(MAX_CWD_LENS,cur_directory) == 0){
cout << "Reading of current working directory failed.\n";
return -1;
}
cout << cur_directory << "> $";
return 1;
}
/**
* Chia câu lệnh thành các đoạn ngăn cách bởi ký tự ngăn (" ","\t","\r","\n","\a")
*
**/
char **separate_line(char *line){
/**
* Chia câu lệnh thành các đoạn ngăn cách bởi ký tự ngăn (" ","\t","\r","\n","\a")
*
**/
int bufsize = MAX_TOK_BUFSIZE;
int position = 0;
char **tokens = (char**)malloc(bufsize*sizeof(char*));
char *token;
if(!tokens){
cout << "Allocation Failed" << endl; /* Không đủ bộ nhớ cấp phát */
exit(EXIT_FAILURE);
}
token = strtok(line, TOKEN_DELIMETERS); /*Con trỏ trỏ tới args[0] của lệnh cmd VD: cd, dir*/
while(token != NULL){
tokens[position] = token; /* Lưu các con trỏ chứa thành phần của lệnh cmd */
// cout << tokens[position] << endl;
position++;
if(position >= bufsize){ /* số thành phần args[i] trong lệnh cmd lớn hơn số bufsize dự tính*/
bufsize += MAX_TOK_BUFSIZE; /* Tăng số bufsize */
tokens = (char**)realloc(tokens, bufsize); /* Cấp phát thêm bộ nhớ cho tokens */
if(!tokens){
cout << "Allocation Failed" << endl; /* Không đủ bộ nhớ cấp phát */
exit(EXIT_FAILURE);
}
}
token = strtok(NULL,TOKEN_DELIMETERS); /* Trỏ token tới thành phần args tiếp theo trong của cmd*/
}
tokens[position] = NULL; /*Kết thúc danh sách mã*/
return tokens;
}
/**
* Chuẩn hóa đường dẫn [path], tránh trường hợp như:
* VD: cd E:\New folder\ => [path] = 'E:\New'
**/
char *combinePath(char **args, int start){
/**
* Chuẩn hóa đường dẫn [path], tránh trường hợp có dấu ngăn cách như:
* VD: cd E:\New folder\ => [path] = 'E:\New'
**/
char *path = (char *)calloc(MAX_CWD_LENS,sizeof(char)); /*Các thành phần không bị ngăn cách*/
char *pivot = (char*)" "; /* Dấu ngăn cách */
/* Kết hợp từng thành phần trong path */
path = strcat(path, args[start]);
int i = start + 1;
while(args[i] != NULL){
path = strcat(path,pivot);
path = strcat(path, args[i]);
++i;
}
return path;
}
/**
* Đổi màu chữ (Có thể có hoặc k cơ bản là cũng k có ảnh hưởng gì chỉ là trang trí )
*
**/
void setColor(char* color) {
/*
* Đổi màu lời gọi đầu
*/
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
WORD saved_attributes;
/* Lưu các thuộc tính */
// GetConsoleScreenBufferInfo(hConsole, &consoleInfo);
// saved_attributes = consoleInfo.wAttributes;
if (strcmp(color,"green")==0) {
SetConsoleTextAttribute(hConsole,FOREGROUND_GREEN | FOREGROUND_INTENSITY);
}
}
view raw Analyse.cpp hosted with ❤ by GitHub
#pragma once
#ifndef _ANALYSE_H
#define _ANALYSE_H
#include <iostream>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <windows.h>
#include <time.h>
#include <sys/types.h>
#include <psapi.h>
#include <tlhelp32.h>
#include "Command.h"
#define MAX_CWD_LENS 128
#define MAX_BUFFER_SIZE 64
#define MAX_TOK_BUFSIZE 64
#define TOKEN_DELIMETERS " \t\r\n\a"
void fixCmd(char *cmd);
void sighandler(int);
void setColor(char* color);
char **separate_line(char *line);
char *combinePath(char **args, int start);
#endif
view raw Analyse.h hosted with ❤ by GitHub

Command.cpp

Sau khi có câu lệnh thì phần này sẽ đọc câu lệnh và thực hiện các lệnh đó trên Shell. VD: cd, dir, help, date, time, pc, ... các bạn dùng câu lệnh help để biết các câu lệnh mà Shell hỗ trợ cũng như chức năng của nó.

#include <iostream>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <windows.h>
#include <time.h>
#include <sys/types.h>
#include <psapi.h>
#include <tlhelp32.h>
#include "Analyse.h"
#include "Process.h"
#define MAX_CWD_LENS 128
#define MAX_BUFFER_SIZE 64
#define MAX_TOK_BUFSIZE 64
#define TOKEN_DELIMETERS " \t\r\n\a"
using namespace std;
/* Mảng các câu lệnh command được hỗ trợ */
const char *command[] = {
"cd",
"cls",
"echo",
"exit",
"help",
"del",
"dir",
"mkdir",
"date",
"time",
"pc",
"calc",
"run"
};
/* Mảng các lệnh command*/
int (*activate_command[])(char **) = {
&cd,
&cls,
&echo,
&exit,
&help,
&del,
&dir,
&mk_dir,
&date,
&time_cmd,
&pc,
&calc,
&runbat
};
/**
* Chạy lệnh với lệnh là arg[0] như cd, dir, exit, help
**/
int execute(char ** args){
/**
* Chạy lệnh với lệnh là arg[0] như cd, dir, exit, help
**/
if (args[0] == NULL){
return 0;
}
for(int i=0; i < size_of_command() ; i++){
if(strcmp(args[0],command[i]) == 0){ /* Kiểm tra xem người dùng nhập lệnh nào trong tập lệnh */
return (*activate_command[i])(args);
}
}
return 0;
}
/**
* Trả về số câu lệnh trong tập các lệnh
**/
int size_of_command(){
/**
* Trả về số câu lệnh trong tập các lệnh
**/
return sizeof(command) / sizeof(char *);
}
//////////////////////////////////////////
////////// Danh sách câu lệnh ////////////
//////////////////////////////////////////
int help(char **args){
if (args[1] == NULL) {
printf("Type \"help [command]\" for more information about a specific command.\n");
printf("Suppoted commands:\n cd\n date\n time\n dir\n cls\n echo\n del\n mkdir\n pc\n exit\n ");
printf("Usage:\n\t <command> [option]\n\tEXAMPLE: help cd\n");
printf("%-30s%s\n%-30s%s", " cd",
"Change the current directory. You must write the new directory after this command.",
" ", "EXAMPLES: \"cd C:/\"\n\n");
printf("%-30s%s\n%-30s%s", " date",
"Show the today's date.",
" ", "EXAMPLES: \"date\"\n\n");
printf("%-30s%s\n%-30s%s", " time",
"Show the current time.",
" ", "EXAMPLES: \"time\"\n\n");
printf("%-30s%s\n%-30s%s", " dir",
"Show all files and folders in the current directory.",
" ", "EXAMPLES: \"dir\"\n\n");
printf("%-30s%s\n%-30s%s", " cls",
"Clear the console screen.",
" ", "EXAMPLES: \"cls\"\n\n");
printf("%-30s%s\n%-30s%s", " echo",
"Print a message on the screen.",
" ", "EXAMPLES: \"echo [message]\"\n\n");
printf("%-30s%s\n%-30s%s", " del",
"Delete a file or folder in the current directory.",
" ", "EXAMPLES: \"del [Folder/Filename]\"\n\n");
printf("%-30s%s\n%-30s%s", " mkdir",
"Make a new directory.",
" ", "EXAMPLES: \"mkdir[Foldername]\"\n\n");
printf("%-30s%s\n%-30s%s", " run",
"Run .bat file only.",
" ", "EXAMPLES: \"run [filename.bat]\"\n\n");
printf("%-30s%s\n%-30s%s\n%-30s%s", " pc",
"Process.", " ",
"You must enter the options in the 2nd argument, such as fg, bg, all, find, kill, killid, suspend, resume",
" ", "EXAMPLES: \"pc bg\"\n\n");
printf("%-30s%s", " exit", "Exit this tiny shell :((((\n");
}
else if(!strcmp(args[1],"cd")) {
cout << "Change the current directory." << endl;
cout << " cd : Show the current directory" << endl;
cout << " cd .. : Show the parent directory of the current directory" << endl;
cout << " cd [path] : Change the current directory to [path]" << endl;
cout << "EXAMPLE: cd C:\\Users\\Admin\\ => change current directory to C:\\User\\Admin" << endl;
}
else if(!strcmp(args[1],"date")) {
cout << "Display the current date to screen." << endl;
cout << "This command does not support any options." << endl;
}
else if(!strcmp(args[1],"time")){
cout << "Diplay the current time to screen." << endl;
cout << "This command does not support any options." << endl;
}
else if(!strcmp(args[1],"dir")){
cout << "Display the list of files and folder in the directory to the screen." << endl;
cout << " dir : Show the files and folders in the current directory" << endl;
cout << " dir [path] : Show the files and folders in the [path]" << endl;
cout << "EXAMPLE: \"dir\", \"dir C:\\Users\\Admin\"" << endl;
}
else if(!strcmp(args[1],"cls")){
cout << "Clear all line displaying on the console screen." << endl;
cout << "This command does not support any options." << endl;
}
else if(!strcmp(args[1],"echo")){
cout << "Print the message on the screen." << endl;
cout << "This command does not support any options." << endl;
cout << "EXAMPLE: \"echo Hello World\"" << endl;
cout << " => \"Hello World\"" << endl;
}
else if(!strcmp(args[1],"del")){
cout << "Delete file or folder in the current directory." << endl;
cout << "Recommend: Folder/File name contains no space." << endl;
cout << " del [Folder/Filename] : Delete folder/file (Folder/Filename) in the current dirrectory" << endl;
cout << "EXAMPLE: \"del ABC\"" << endl;
}
else if(!strcmp(args[1],"mkdir")){
cout << "Make a new directory in the current directory." << endl;
cout << "Recommend: Foldername contains no space." << endl;
cout << " mkdir [Foldername] : Make folder [Foldername] in the current directory" << endl;
cout << "EXAMPLE: \"mkdir ABC\"" << endl;
}
else if (!strcmp(args[1], "run")){
cout << "Run .bat file only with commands which our shell supports" << endl;
cout << " run [Filename.bat] : Run .bat file with commands which our shell supports " << endl;
cout << "EXAMPLE: \"run command.bat\"" << endl;
}
else if(!strcmp(args[1],"pc")){
cout << "Supported options:" << endl;
cout << " all Show list of all running processes" << endl;
cout << " find Get pid of specific program(s) by name" << endl;
cout << " suspend Suspend a program by process id" << endl;
cout << " resume Resume a program by process id" << endl;
cout << " kill Terminate all program by name" << endl;
cout << " killid Terminate a program by process id" << endl;
cout << " bg Run a program in background mode by path to program" << endl;
cout << " fg Run a program in foregound mode by path to program" << endl;
cout << "EXAMPLE: \"pc fg C:\\Users\\Admin\\ABC\"" << endl;
}
else if(!strcmp(args[1],"exit")){
cout << "Exit the TinyShell." << endl;
cout << "This command does not support any options." << endl;
}
return 0;
}
/**
* Chuyển directory hiện tại sang directory mới
* Câu lệnh: cd [path]
* cd : trả về đường dẫn directory hiện tại
* cd .. :trả về đường dẫn directory cha
* cd [path]: chuyển current working directory sang directory mới
*
**/
int cd(char **args){
/**
* Chuyển directory hiện tại sang directory mới
* Câu lệnh: cd [path]
* cd : trả về đường dẫn directory hiện tại
* cd .. :trả về đường dẫn directory cha
* cd [path]: chuyển current working directory sang directory mới
*
**/
if(args[1] == NULL){ /* Nếu chỉ gõ lệnh cd */
system("cd"); /* Dùng luôn lệnh cd có sẵn của Windows (Chơi bẩn nhưng kệ) */
cout << endl;
return EXIT_SUCCESS;
}
/* Nếu cd [path] */
else {
char* path = combinePath(args,1); /* Chuẩn hóa path */
if(SetCurrentDirectory(path)==FALSE){ /* Tìm đường dẫn nếu có */
// cout << args[1] << endl;
fprintf(stdout,"Not able to set current working directory\n");
}
}
return 0;
}
/**
* Liệt kê các folder, file trong directory
* Câu lệnh: dir [path]
*
**/
int dir(char **args){
/**
* Liệt kê các folder, file trong directory
* Câu lệnh: dir [path]
*
**/
/* Đống này chôm chỉa về sửa một chút t cx chưa hiểu hết :)))))) */
char *cur_dir = (char*)malloc(MAX_CWD_LENS*sizeof(char));
GetCurrentDirectory(MAX_CWD_LENS, cur_dir);
WIN32_FIND_DATA data;
_FILETIME time_lastwrite;
_SYSTEMTIME convert_time;
string date;
string time;
char *char_date = (char *)calloc(15, sizeof(char));
char *char_time = (char *)calloc(15, sizeof(char));
const char add[] = "\\*";
char *path = (char*)malloc(MAX_CWD_LENS*sizeof(char));
if(args[1] == NULL){
strcpy(path, cur_dir);
strcat(path,"\\*");
}
else {
path = combinePath(args,1);
strcat(path,"\\*");
}
HANDLE han = FindFirstFile(path, &data);
printf("%-15s%-15s%-15s%-15s\n", "Date", "Time", "Type", "Name");
printf("=========================================================================\n");
if (han != INVALID_HANDLE_VALUE) {
do {
time_lastwrite = data.ftLastWriteTime;
FileTimeToSystemTime(&time_lastwrite, &convert_time);
date = to_string(convert_time.wDay) + '/' + to_string(convert_time.wMonth) + '/' + to_string(convert_time.wYear);
time = to_string(convert_time.wHour) + ':' + to_string(convert_time.wMinute);
strcpy(char_date, date.c_str());
strcpy(char_time, time.c_str());
if (data.dwFileAttributes == FILE_ATTRIBUTE_ARCHIVE) {
printf("%-15s%-15s%-15s%-15s\n", char_date, char_time, "<FILE>", data.cFileName);
}
if (data.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY) {
printf("%-15s%-15s%-15s%-15s\n", char_date, char_time, "<FOLDER>", data.cFileName);
}
} while (FindNextFileA(han, &data) != 0);
FindClose(han);
delete char_time;
delete char_date;
return EXIT_SUCCESS;
}
else{
return EXIT_FAILURE;
}
}
/**
* Tạo folder trong directory hiện tại
* Câu lệnh: mkdir [foldername]
*
**/
int mk_dir(char **args){
/**
* Tạo folder trong directory hiện tại
* Câu lệnh: mkdir [foldername]
*
**/
if(args[1] == NULL){ /* Chỉ gõ lệnh mkdir */
cout << "ERROR: Command mk_dir need filename" << endl;
cout << "Command: mkdir [filename]" << endl;
cout << "Recommend: filename should not have any space" << endl;
return 0;
}
mkdir(args[1]); /* Lệnh mkdir tạo folder có sẵn */
return 0;
}
/**
* In ra message đi kèm với echo
* Câu lệnh: echo [message]
*
**/
int echo(char **args){
/**
* In ra message đi kèm với echo
* Câu lệnh: echo [message]
*
**/
if(args[1] == NULL){
cout << "ERROR: Echo + [message]" << endl;
return 0;
}
int i=0;
while(args[++i] != NULL){
for(int j=0; j<strlen(args[i]); j++){
cout << args[i][j];
}
cout << " ";
}
cout << endl;
return 0;
}
/**
* Clear toàn màn hình console
* Câu lệnh: cls
**/
int cls(char **args){
/**
* Clear toàn màn hình console
* Câu lệnh: cls
*
* Cũng chôm chỉa về nốt :)))
**/
if(strcmp(args[0],"cls") == 0){
HANDLE hConsole;
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO csbi;
SMALL_RECT scrollRect;
COORD scrollTarget;
CHAR_INFO fill;
// Get the number of character cells in the current buffer.
if (!GetConsoleScreenBufferInfo(hConsole, &csbi))
{
return 0;
}
// Scroll the rectangle of the entire buffer.
scrollRect.Left = 0;
scrollRect.Top = 0;
scrollRect.Right = csbi.dwSize.X;
scrollRect.Bottom = csbi.dwSize.Y;
// Scroll it upwards off the top of the buffer with a magnitude of the entire height.
scrollTarget.X = 0;
scrollTarget.Y = (SHORT)(0 - csbi.dwSize.Y);
// Fill with empty spaces with the buffer's default text attribute.
fill.Char.UnicodeChar = TEXT(' ');
fill.Attributes = csbi.wAttributes;
// Do the scroll
ScrollConsoleScreenBuffer(hConsole, &scrollRect, NULL, scrollTarget, &fill);
// Move the cursor to the top left corner too.
csbi.dwCursorPosition.X = 0;
csbi.dwCursorPosition.Y = 0;
SetConsoleCursorPosition(hConsole, csbi.dwCursorPosition);
}
return 0;
}
/**
* In ra màn hình ngày hiện tại
* Câu lệnh: date
*
**/
int date(char **args){
if (args[1] != NULL)
{
cout << "Command \"date\" does not support any option !\n";
return EXIT_FAILURE;
}
time_t t = time(0);
struct tm * now = localtime(&t);
cout << "Current Date: " << now->tm_mday << '/'
<< (now->tm_mon + 1) << '/'
<< (now->tm_year + 1900)
<< endl;
return 0;
}
/**
* In ra màn hình thời gian (giờ:phút:giây) hiện tại
* Câu lệnh: time
*
*/
int time_cmd(char **args){
if (args[1] != NULL)
{
cout << "Command \"time\" does not support any option !\n";
return EXIT_FAILURE;
}
time_t t = time(0);
struct tm * now = localtime(&t);
cout << "Current time: " << now->tm_hour << ':' << now->tm_min << ':' << now->tm_sec << endl;
return 0;
}
/**
* Delete file hoặc folder
* Câu lệnh: del [file/foldername]
*
**/
int del(char **args){
/**
* Delete file hoặc folder
* Câu lệnh: del [file/foldername]
*
**/
if(args[1] == NULL){
cout << "ERROR: Command 'del' need path" << endl;
cout << "Command: del [path]" << endl;
return 0;
}
else if (args[2] != NULL){
cout << "ERROR: Command 'del' cannot delete more than 1 file" << endl;
cout << "Command: del [path]" << endl;
return 0;
}
if(remove(args[1]) == -1 && rmdir(args[1]) == -1){ /* Nếu arg[1] là file thì xóa file, folder thì xóa folder. Nếu k có thì in chỗ dưới */
cout << "ERROR: Unable to find file to be deleted. Try again" << endl;
cout << "Command: del [path]" << endl;
return 0;
}
return 0;
}
/**
* Thoát chương trình
* Câu lệnh: exit
*
**/
int exit(char **args){
/**
* Thoát chương trình
* Câu lệnh: exit
*
**/
char* term = (char*)malloc(64*sizeof(char));
if(args[1] != NULL){
term = combinePath(args,1);
cout << "ERROR: Term " << term << "is not recognized for EXIT" << endl;
cout << "Command: exit" << endl;
return 0;
}
/* Trả 1 về cho biết stop trong main */
return 1;
}
/**
* Các lệnh với tiến trình
* Câu lệnh: pc (Process)
*
**/
int pc(char **args) {
if (args[1] == NULL) {
cout << "ERROR: Too few argument" << endl;
return 0;
}
if (strcmp(args[1], "all") == 0) {
if (getProcessListAll()) {
return 0;
}
return 1;
}
if (strcmp(args[1], "find") == 0){
if (args[2] == NULL)
{
printf("ERROR: Too few arguments\n");
return 0;
}
// Tìm ID Process
if (findProcessID(args[2]))
return 0;
return 1;
}
if (strcmp(args[1], "kill") == 0) {
if (args[2] == NULL) {
cout << "ERROR: Too few argument" << endl;
return 0;
}
if (killProcess(args[2])) {
return 0;
}
return 1;
}
if (strcmp(args[1], "killid") == 0) {
if (args[2] == NULL) {
cout << "ERROR: Too few argument" << endl;
return 0;
}
DWORD process_id = atoi(args[2]);
if (killProcessID(process_id)) {
return 0;
}
return 1;
}
if (strcmp(args[1], "suspend") == 0) {
if (args[2] == NULL) {
cout << "ERROR: Too few argument" << endl;
return 0;
}
DWORD process_id = atoi(args[2]);
suspendProcess(process_id);
return 0;
}
if (strcmp(args[1], "resume") == 0) {
if (args[2] == NULL) {
cout << "ERROR: Too few argument" << endl;
return 0;
}
DWORD process_id = atoi(args[2]);
resumeProcess(process_id);
return 0;
}
if (strcmp(args[1], "bg") == 0 || strcmp(args[1], "fg") == 0) {
if(args[2] == NULL) {
cout << "ERROR: Too few argument" << endl;
return 0;
} else {
createNewProcess(args);
}
return 0;
}
else {
cout << "ERROR: Too few argument" << endl;
return 0;
}
}
int calc(char **args){
system("calc");
return 0;
}
//////////////////////////////////////////
//////// Dành riêng cho file .bat ////////
//////////////////////////////////////////
/**
* Kiểm tra xem câu lệnh có được hỗ trợ trong shell không
*
**/
bool cmdCheck(char **args){
if (args[0] == NULL){
return 0;
}
for(int i=0; i < size_of_command() ; i++){
if(strcmp(args[0],command[i]) == 0){ /* Kiểm tra xem người dùng nhập lệnh nào trong tập lệnh */
return true;
}
}
return false;
}
/**
* Chạy riêng cho file .bat
* Câu lệnh: run [Filename.bat]
*
**/
int runbat(char **args){
char w[255],a[255];
char *run_file = combinePath(args, 1);
FILE *f=fopen(run_file,"rt");
if(f==NULL) {
printf("\nLoi doc file.\n");
// getch();
return 0;
}
else {
while(!feof(f)) {
fgets(w,255,f);
strcpy(a,w);
char **arg = separate_line(a);
printf("");
// cout << w << endl;
if(cmdCheck(arg)){
int stop = execute(arg); // system ???
}
else {
system(w);
}
}
fclose(f);
}
return 0;
}
view raw Command.cpp hosted with ❤ by GitHub
#pragma once
#ifndef _COMMAND_H
#define _COMMAND_H
#include <iostream>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <windows.h>
#include <time.h>
#include <sys/types.h>
#include <psapi.h>
#include <tlhelp32.h>
#define MAX_CWD_LENS 128
#define MAX_BUFFER_SIZE 64
#define MAX_TOK_BUFSIZE 64
#define TOKEN_DELIMETERS " \t\r\n\a"
// char cur_directory[MAX_CWD_LENS];
/* Các câu lệnh thực hiện command */
int cd(char **args);
int cls(char **args);
int dir(char **args);
int echo(char **args);
int exit(char **args);
int help(char **args);
int mk_dir(char **args);
int del(char **args);
int date(char **args);
int time_cmd(char **args);
int pc(char **args);
int calc(char **args);
int runbat(char **args);
bool cmdCheck(char **args);
int execute(char ** args);
int size_of_command();
int printPrompt(char* cur_dir);
#endif
view raw Command.h hosted with ❤ by GitHub

Process.cpp

Sau khi nhận được câu lệnh liên quan đến xử lí tiến trình pc ở phần command ta sẽ có phần process để xử lí tiếp các câu lệnh đằng sau. Để biết các câu lệnh được hỗ trợ các bạn nhập help pc.

#include <iostream>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <windows.h>
#include <time.h>
#include <sys/types.h>
#include <psapi.h>
#include <tlhelp32.h>
#include "Analyse.h"
#include "Command.h"
using namespace std;
#define MAX_CWD_LENS 128
#define MAX_BUFFER_SIZE 64
#define MAX_TOK_BUFSIZE 64
#define TOKEN_DELIMETERS " \t\r\n\a"
HANDLE hForeProcess;
///////////////////////////////////
//////// Xử lí tiến trình /////////
///////////////////////////////////
/**
* Đón tín hiệu ngắt Ctrl + C
**/
void sighandler(int signum) {
/**
* Đón tín hiệu ngắt Ctrl + C
**/
// printf("Caught signal %d, coming out...\n", signum);
if (hForeProcess != NULL) {
TerminateProcess(hForeProcess, 0);
hForeProcess = NULL;
}
exit(1);
}
/**
* In ra các tiến trình đang hoạt động
* In ra màn hình tên tiến trình, Process ID, Parent PID
* Câu lệnh: pc all
*
**/
int getProcessListAll() {
HANDLE hProcessSnap;
PROCESSENTRY32 pe32; // Cấu trúc của tiến trình khi được gọi snapshot
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); // Chụp lại các tiến trình
// Nếu hProcessSnap trả về lỗi return 0
if (hProcessSnap == INVALID_HANDLE_VALUE) {
cout << "ERROR: CreateToolhelp32Snapshot Fail " << GetLastError() << endl;
return 0;
}
pe32.dwSize = sizeof(PROCESSENTRY32);
// Kiểm tra thằng đầu tiên
if (!Process32First(hProcessSnap, &pe32)) {
// Nếu lỗi in ra...
cout << "ERROR: Process32First Fail " << GetLastError() << endl;
return 0;
}
printf("%-50s%-20s%-20s\n", "Process Name", "Process ID", "Parent Process ID");
printf("%-50s%-20s%-20s\n", "----------------------------------", "----------", "-----------");
do {
printf("%-50s%-20d%-20d\n", pe32.szExeFile, pe32.th32ProcessID, pe32.th32ParentProcessID);
} while (Process32Next(hProcessSnap, &pe32)); CloseHandle(hProcessSnap);
return 1;
}
/**
* Tìm tiến trình bằng tên
* In ra màn hình tên tiến trình, Process ID, Parent PID
* Câu lệnh pc find [name_process]
*
**/
int findProcessID(char *name_process) {
HANDLE hProcessSnap;
PROCESSENTRY32 pe32; // Cấu trúc của tiến trình khi được gọi snap
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); // Chụp lại các tiến trình
// Nếu trả về lỗi return 0
if (hProcessSnap == INVALID_HANDLE_VALUE) {
return 0;
}
pe32.dwSize = sizeof(PROCESSENTRY32);
// Kiểm tra thằng đầu tiên
if (!Process32First(hProcessSnap, &pe32)) {
return 0;
}
printf("%-50s%-20s%-20s\n", "Process Name", "Process ID", "Parent Process ID");
printf("%-50s%-20s%-20s\n", "----------------------------------", "----------", "-----------");
do {
if (strcmp(name_process, pe32.szExeFile) == 0) {
// Nếu pe32.szExeFile trùng với tên tiến trình thì in ra
printf("%-50s%-20d%-20d\n", pe32.szExeFile, pe32.th32ProcessID, pe32.th32ParentProcessID);
}
} while (Process32Next(hProcessSnap, &pe32)); CloseHandle(hProcessSnap);
return 1;
}
/**
* Đóng tiến trình bằng Process ID
* Câu lệnh: pc kill [process_id]
*
**/
int killProcessID(DWORD process_id) {
// Mở tiến trình đang chạy có Process ID là...
HANDLE hprocess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process_id);
// Nếu hProcess trả về NULL thì báo lỗi
if (hprocess == NULL) {
cout << "ERROR: Failed!" << endl;
return 1;
}
// Đóng tiến trình hProcess
if (!TerminateProcess(hprocess, 0)) {
return 0;
}
return 1;
}
/**
* Đóng tất cả tiến trình có tên là name_process
* Câu lệnh pc kill [Name_Process]
*
* */
int killProcess(char *name_process) {
HANDLE hProcessSnap;
PROCESSENTRY32 pe32; // Cấu trúc của tiến trình khi được gọi snapshot
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); // Chụp lại các tiến trình
// Nếu trả về lỗi return 0
if (hProcessSnap == INVALID_HANDLE_VALUE) {
return 0;
}
pe32.dwSize = sizeof(PROCESSENTRY32);
// Kiểm tra thằng đầu tiên
if (!Process32First(hProcessSnap, &pe32)) {
return 0;
}
do {
if (strcmp(name_process, pe32.szExeFile) == 0) {
killProcessID(pe32.th32ProcessID);
}
} while (Process32Next(hProcessSnap, &pe32));
CloseHandle(hProcessSnap);
return 1;
}
/**
* Đình chỉ một tiến trình đang thực hiện
* Câu lệnh pc suspend [process_id]
*
**/
int suspendProcess(DWORD process_id) {
// Chụp lại tất cả các luồng
HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
THREADENTRY32 th32; // Cấu trúc của luồng khi được gọi snapshot
HANDLE hthread;
// Kiểm tra xem hThreadSnap có lỗi không nếu có thì in ra lỗi
if (hThreadSnap == INVALID_HANDLE_VALUE) {
cout << "ERROR: CreateToolhelp32Snapshot" << GetLastError();
return 0;
}
th32.dwSize = sizeof(THREADENTRY32);
// Kiểm tra thông tin của luồng đầu tiên
if (!Thread32First(hThreadSnap, &th32)) {
cout << "Thread32First Fail " << GetLastError(); // Nếu lỗi in ra lỗi
CloseHandle(hThreadSnap); // Đóng Handle snapshot
return 0;
}
// Duyệt các luồng khác
do {
// Kiểm tra xem các luồng này có thuộc tiến trình cần dừng không
if (th32.th32OwnerProcessID == process_id) {
hthread = OpenThread(THREAD_ALL_ACCESS, FALSE, th32.th32ThreadID); // Mở một luồng đang chạy
// Đình chỉ luồng đó
if (SuspendThread(hthread) == -1) {
return 0;
}
}
} while (Thread32Next(hThreadSnap, &th32)); CloseHandle(hThreadSnap);
return 1;
}
/**
* Tiếp tục một tiến trình bị đình chỉ
* Câu lệnh pc resume [process_id]
*
**/
int resumeProcess(DWORD process_id) {
// Chụp lại tất cả các luồng
HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
THREADENTRY32 th32; // Cấu trúc của luồng khi được gọi snapshot
HANDLE hthread;
// Kiểm tra xem hThreadSnap có lỗi không nếu có thì in ra lỗi
if (hThreadSnap == INVALID_HANDLE_VALUE) {
cout << "ERROR: CreateToolhelp32Snapshot" << GetLastError();
return 0;
}
th32.dwSize = sizeof(THREADENTRY32);
// Kiểm tra thông tin của luồng đầu tiên
if (!Thread32First(hThreadSnap, &th32) {
cout << "Thread32First Fail " << GetLastError(); // Nếu lỗi in ra lỗi
CloseHandle(hThreadSnap); // Đóng Handle snapshot
return 0;
}
// Duyệt các luồng khác
do {
// Kiểm tra xem các luồng này có thuộc tiến trình cần dừng không
if (th32.th32OwnerProcessID == process_id) {
hthread = OpenThread(THREAD_ALL_ACCESS, FALSE, th32.th32ThreadID); // Mở một luồng đang chạy
// Đình chỉ luồng đó
if (ResumeThread(hthread) == -1) {
return 0;
}
}
} while (Thread32Next(hThreadSnap, &th32)); CloseHandle(hThreadSnap);
return 1;
}
/**
* Tạo một tiến trình con
* Câu lệnh: pc bg [name_process/path](background mode)
* pc fg [name_process/path](foreground mode)
*
**/
int createNewProcess(char **args) {
// Cài wait time cho các tiến trình
int wait_time;
if (strcmp(args[1], "bg") == 0) {
wait_time = 0;
} else {
wait_time = INFINITE;
}
char *run_file = combinePath(args, 2); // Ghép lại tên tiến trình hoặc đường dẫn
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
si.wShowWindow = SW_SHOW;
si.dwFlags = STARTF_USESHOWWINDOW;
si.lpTitle = args[1];
ZeroMemory(&pi, sizeof(pi));
// Khởi tạo tiến trình con
if (!CreateProcess(NULL, run_file, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) {
int error = GetLastError(); // Kiểm tra lỗi
if (error == 2)
cout << "The batch file or execute file '" << run_file << "' is not found." << endl;
else
cout << "Can't run this file" << endl;
return 1;
}
// gán handle cho tiến trình con vừa tạo
if (strcmp(args[1], "fg") == 0) {
hForeProcess = pi.hProcess;
}
// Thời gian đợi 1 tiến trình con
WaitForSingleObject(pi.hProcess, wait_time);
// Đóng các handle
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return 1;
}
view raw Process.cpp hosted with ❤ by GitHub
#pragma once
#ifndef _PROCESS_H
#define _PROCESS_H
#include <iostream>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <windows.h>
#include <time.h>
#include <sys/types.h>
#include <psapi.h>
#include <tlhelp32.h>
#include "Analyse.h"
#define MAX_CWD_LENS 128
#define MAX_BUFFER_SIZE 64
#define MAX_TOK_BUFSIZE 64
#define TOKEN_DELIMETERS " \t\r\n\a"
/* Các câu lệnh liên quan đến tiến trình */
int findProcessID(char *name_process);
int getProcessListAll();
int killProcessID(DWORD process_id);
int killProcess(char *name_process);
int suspendProcess(DWORD process_id);
int resumeProcess(DWORD process_id);
int createNewProcess(char **args);
#endif
view raw Process.h hosted with ❤ by GitHub

Lời Kết

Cảm ơn các bạn đã đọc tới đây vì bài viết khá là dài. Nếu thấy thích bài viết này thì hãy comment ở bên dưới để mình có động lực viết tiếp các bài tiếp theo !
Nguồn: @Phạm Văn Linh
Đánh Giá Bài Viết:
No pain, no gain !

You may like these posts

  • THUẬT TOÁN PRIM Có bao giờ bao giờ bạn hỏi vì sao giữa các địa điểm trong một thành phố lại có nhiều đường đi đến như vậy. Vậy có cách nào vừa đảm bảo có đường đi giữa mọi đ…
  • Hust - OS - TinyShell Chào các bạn lại đến với bài viết của mình. Sau hơn một tuần tìm hiểu cũng như là tham khảo các bài trên mạng và các khóa đi trước thì mình cùng mấy đứ…
  • THUẬT TOÁN DUYỆT CHIỀU SÂU DFS Thuật toán DFS (Depth First Search) là thuật toán tìm kiếm theo chiều sâu bắt đầu từ một đỉnh bất kì trong một đồ thì vô hướng, có hướng hoặc tr…
  • Thuật Toán Sắp Xếp Hế lô các bạn. Tiếp tục series thuật toán chúng ta sẽ tìm hiểu tiếp về thuật toán sắp xếp. Hôm nay mình sẽ chia sẻ tiếp cho các bạn thêm 2 cách sắp xếp nữ…
  • THUẬT TOÁN DIJKSTRA Cho một đồ thị vô hướng liên thông, thuật toán Dijkstra sẽ giúp bạn tìm ra đường đi ngắn nhất từ một đỉnh bất kì đến các đỉnh còn lại. …
  • THUẬT TOÁN DUYỆT CHIỀU RỘNG BFS Bài trước mình đã đăng về thuật toán DFS thì bài này sẽ là BFS (Breadth First Search) duyệt đồ thị theo chiều rộng. …

5 comments

  1. second ago
    quả thumbnail cháy đấy =))
    1. second ago
      Cháy khét nẹt luôn chư nị =))
  2. second ago
    Cho e hỏi là thư viên unistd.h muốn sử dụng thì phải chạy trên máy ảo linux ạ
  3. second ago
    ah cho em link github đc k ạ
    1. second ago
      Em tìm phamvanlinhxyz nhé
© 2025Phạm Văn Linh. All rights reserved. Developed by Jago Desain

Đã phát hiện Ad Blocker

Vui lòng tắt trình chặn quảng cáo của bạn để tiếp tục!

  1. Click on the AdBlock icon in your browser.
    Nhấp vào biểu tượng AdBlock trong trình duyệt của bạn.
    Adblock
  2. Choose, Don't run on pages on this domain.
    Chọn "Always".
    Adblock
  3. The browser icon should have turned green.
    Biểu tượng trình duyệt phải chuyển sang màu xanh lá.
    Adblock
  4. Refresh the page if it didn't refresh automatically. Thanks!
    Làm mới trang nếu nó không tự động làm mới. Cảm ơn bạn rất nhiều!
  1. Click on the AdBlock Plus icon in your browser.
    Nhấp vào biểu tượng AdBlock Plus trong trình duyệt của bạn.
    Adblock
  2. Click the "This Website" button.
    Nhấp vào nút "Trang web này".
    Adblock
  3. The browser icon should have turned grey.
    Biểu tượng trình duyệt phải chuyển sang màu xám.
    Adblock