Linux_shell編寫


title: Linux_4 shell編寫

shell

pwd (/root/A/2025_7/19/myshell)

首先需要設計命令行提示 (MakeCommandLine())

首先獲取相關信息

getenv(“name”)

// 獲取用戶名
const char* GetUserName() {const char* name = getenv("USER");if (name == NULL) {return "None";}return name;
}// 獲取主機名
const char* GetHostName() {static char hostname[256];if (gethostname(hostname, sizeof(hostname)) == 0) {return hostname;}return "None";
}// 獲取當前路徑
const char* GetCwd() {const char* cwd = getenv("PWD");if (cwd == NULL) {return "None";}return cwd;
}

制作命令行提示

// 制作命令提示行
void MakeCommandLine() {// 內容char commandline[SIZE];const char* username = GetUserName();const char* hostname = GetHostName();const char* cwd = GetCwd();// printf("%s\n", username);// printf("%s\n", cwd);// printf("%s\n", hostname);// 拼接snprintf(commandline, sizeof(commandline), "[%s@%s %s]> ", username, hostname, cwd);printf("%s", commandline);fflush(stdout);
}
獲取用戶命令行字符串(GetUserCommand(char usercommand[], size_t n))

使用fgets() 函數

// 獲取用戶輸入字符串
// 返回值 > 0進行后續處理
int GetUserCommand(char usercommand[], size_t n) {char *s = fgets(usercommand, n, stdin);if (s == NULL) {return -1;}// 去掉末尾 換行符usercommand[strlen(usercommand) - 1] = ZERO;return strlen(usercommand);
}
分割用戶輸入字符串 (SplitCommand(char command[], size_t n))
// 存放命令
char *gArgv[NUM];
// 分割輸入命令
void SplitCommand(char command[], size_t n){//ls - a -l -n// SEP " " 表示使用 strtok函數 按照SEP分割字符串gArgv[0] = strtok(command, SEP);int index = 1;while (gArgv[index++] = strtok(NULL, SEP));
}
執行命令 (ExecuteCommand())

執行命令時, 不能自己去執行, 需要子進程去執行

// 執行命令
void ExecuteCommand() {pid_t id = fork();if (id < 0) {exit(1);} else if (id == 0) {// 子進程執行進程替換execvp(gArgv[0], gArgv);exit(errno);} else {int status = 0;pid_t rid = waitpid(id, &status, 0);}
}

第一版 shell 代碼

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>#define ZERO '\0'// 提示行 / ()大小
#define SIZE 512// 分割命令個數
#define NUM 32
// 按照SEP分割字符串
#define SEP " "// 獲取用戶名
const char* GetUserName() {const char* name = getenv("USER");if (name == NULL) {return "None";}return name;
}// 獲取主機名
const char* GetHostName() {static char hostname[256];if (gethostname(hostname, sizeof(hostname)) == 0) {return hostname;}return "None";
}// 獲取當前路徑
const char* GetCwd() {const char* cwd = getenv("PWD");if (cwd == NULL) {return "None";}return cwd;
}// 制作命令提示行
void MakeCommandLine() {// 內容char commandline[SIZE];const char* username = GetUserName();const char* hostname = GetHostName();const char* cwd = GetCwd();// printf("%s\n", username);// printf("%s\n", cwd);// printf("%s\n", hostname);// 拼接snprintf(commandline, sizeof(commandline), "[%s@%s %s]> ", username, hostname, cwd);printf("%s", commandline);fflush(stdout);
}// 獲取用戶輸入字符串
int GetUserCommand(char usercommand[], size_t n) {char *s = fgets(usercommand, n, stdin);if (s == NULL) {return -1;}// 去掉末尾 換行符usercommand[strlen(usercommand) - 1] = ZERO;return strlen(usercommand);
}// 存放命令
char *gArgv[NUM];
// 分割輸入命令
void SplitCommand(char command[], size_t n){//ls - a -l -n// SEP " " 表示使用 strtok函數 按照SEP分割字符串gArgv[0] = strtok(command, SEP);int index = 1;while (gArgv[index++] = strtok(NULL, SEP));
}// 執行命令
void ExecuteCommand() {pid_t id = fork();if (id < 0) {// 創建進程失敗exit(1);} else if (id == 0) {// 子進程執行進程替換execvp(gArgv[0], gArgv);exit(errno);} else {// 進程等待int status = 0;pid_t rid = waitpid(id, &status, 0);}
}int main() {while (1) {// 制作一個命令行MakeCommandLine();// 獲取用戶輸入字符串char usercommand[SIZE];int n = GetUserCommand(usercommand, sizeof(usercommand));// 命令行字符串的分割SplitCommand(usercommand, sizeof(usercommand));// 執行命令ExecuteCommand();}return 0;
}

上述代碼無法切換路徑, 是子進程在切換路徑

檢查命令是否是內建命令 (CheckBuildir())
char cwd[SIZE];// 執行cd命令
void Cd() {const char* path = gArgv[1];if (path == NULL) {path = GetHome();}// 改變路徑chdir(path);// 更新環境變量char temp[SIZE];getcwd(temp, sizeof(temp));snprintf(cwd, sizeof(cwd), "PWD=%s", temp);putenv(cwd);
}// 判斷是否內建命令
int CheckBuildir() {int yes = 0;const char* enter_cwd = gArgv[0];// 一個個比較if (strcmp(enter_cwd, "cd") == 0) {yes = 1;Cd();}return yes;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/90196.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/90196.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/90196.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【數據結構】棧的深入解析--用C語言實現

文章目錄1.棧的概念2.棧的底層結構3.棧的功能4.棧的實現4.1.棧結構的定義4.2.棧的初始化4.3.棧的銷毀4.4.入棧4.5.出棧4.6.取棧頂元素4.7.獲取棧中有效元素個數5.完整代碼Stack.hStack.cmain.c運行結果1.棧的概念 是一種特殊的線性表&#xff0c;只允許數據在固定的一段進行插…

Git倉庫核心概念與工作流程詳解:從入門到精通

Git倉庫的基本概念版本庫&#xff08;Repository&#xff09;是Git的核心概念&#xff0c;你可以簡單理解為一個被Git管理的目錄。這個目錄里的所有文件都能被Git跟蹤&#xff0c;記錄每次修改和刪除&#xff0c;讓你可以隨時追溯歷史或在未來某個時刻"還原"文件。Gi…

Web開發 05

1 React庫&#xff08;人話詳解版&#xff09;別慌&#xff0c;React 剛接觸時是會有點懵&#xff0c;咱們用 “人話 類比” 一步步拆&#xff1a;核心概念先抓牢組件&#xff08;Component&#xff09;把它想成 “樂高積木”&#xff0c;比如做個社交 App&#xff0c;頂部導航…

RustDesk 自建中繼服務器教程(Mac mini)

&#x1f4d6; 教程目標 在家里的 Mac mini 上部署 RustDesk 中繼服務器 (hbbs hbbr)&#xff0c;讓你從辦公室、筆電或手機 低延遲、安全 地遠程控制家里的 Windows 和 Mac mini。 ? 不依賴第三方服務器 ? 支持 P2P 和中繼雙模式 ? 全流量可控、跨平臺 &#x1f3d7;? 架…

數據庫—修改某字段默認值

前言有時候&#xff0c;數據庫的字段默認值沒有正確設置&#xff0c;這時候需要改默認值。以下是我做的改默認值的記錄&#xff0c;希望對網友有所幫助。1.SQL SERVER下面的示例假設你要修改名為 YourColumnName 的字段&#xff0c;并為其設置一個新的默認值 NewDefaultValue。…

Spring快速整合Mybatis

MyBatis是一個優秀的持久層框架&#xff0c;Spring則是廣泛使用的Java應用框架。可以將兩者整合可以充分發揮各自的優勢。 1、Spring整合MyBatis的基本配置 添加依賴&#xff1a; <dependency><groupId>org.springframework</groupId><artifactId>spri…

基于深度學習的語音識別:從音頻信號到文本轉錄

前言 語音識別&#xff08;Automatic Speech Recognition, ASR&#xff09;是人工智能領域中一個極具挑戰性和應用前景的研究方向。它通過將語音信號轉換為文本&#xff0c;為人們提供了更加自然和便捷的人機交互方式。近年來&#xff0c;深度學習技術在語音識別領域取得了顯著…

本地部署Nacos開源服務平臺,并簡單操作實現外部訪問,Windows 版本

Nacos 是一款阿里開源的動態服務發現、配置、管理平臺&#xff0c;擁有易于集成、高可用與可擴展等特點。它提供了動態服務注冊和發現能力&#xff0c;使得服務自動注冊到服務器并且消費真能夠發現提供者。本文將詳細介紹如何在本地安裝 Nacos &#xff0c;以及結合nat123端口映…

數據結構:反轉字符串(Reversing a String)

目錄 方法一&#xff1a;雙指針法 方法二&#xff1a;輔助數組 方法對比總結&#xff1a; 問題定義 給定一個字符串&#xff0c;例如&#xff1a; char str[] "hello";我們的目標是把它反轉成&#xff1a; "olleh"&#x1f4cc; 輸入特點&#xff…

Redis Copy-on-Write機制:

Copy-on-Write機制&#xff1a; 父子進程共享內存頁 當父進程修改數據時&#xff0c;內核會復制被修改的頁 這可能導致內存使用量暫時增加 通俗的話描述一下可以用一個生活中的例子來通俗解釋 Copy-on-Write&#xff08;寫時復制&#xff09; 機制&#xff1a;&#x1f4d6; 比…

iOS加固工具有哪些?從零源碼到深度混淆的全景解讀

在iOS安全加固領域&#xff0c;不同項目類型對保護需求有著本質差異&#xff1a;“我有源碼”與“我只有IPA”兩條路徑決定了你該用什么工具。本文將從 無需源碼處理整個IPA包 到 源碼級編譯期混淆&#xff0c;分層探討主流工具如何發揮價值&#xff0c;并附上適配方案建議。工…

Composer 可以通過指定 PHP 版本運行

是的&#xff0c;Composer 可以通過指定 PHP 版本運行&#xff0c;尤其是在服務器上有多個 PHP 版本時&#xff08;如 PHP 7.x 和 PHP 8.x&#xff09;。以下是幾種常見方法&#xff1a;方法 1&#xff1a;使用 php 命令指定版本 Composer 依賴系統中的 php 命令&#xff0c;因…

vscode文件顏色,只顯示自己更改的文件顏色

這個主要是因為你github git下來以后&#xff0c;用vscode打開會默認顯示更改了&#xff0c;你只要在這里先手動取消更改就行了&#xff0c;注意不要把你自己更改的取消了

記錄我coding印象比較深刻的BUG

4778&#xff1a;我的BUG噩夢問題描述&#xff1a;DAB播放中關ACC掉電后開ACC&#xff0c;手動切到FM/AM(有時第一次切換出現問題/有時第二次切換出現問題)&#xff0c;FM/AM不記憶關ACC前電臺或者FM/AM關ACC掉電后開ACC&#xff0c;手動切到DAB再回到FM/AM&#xff0c;FM/AM不…

Kubernetes集群中Istio mTLS握手失敗問題排查與解決方案

Kubernetes集群中Istio mTLS握手失敗問題排查與解決方案 在微服務架構中&#xff0c;Istio 提供了基于 Envoy 的服務網格能力&#xff0c;其中 mTLS&#xff08;雙向 TLS&#xff09;是確保服務間通信安全的重要機制。但在生產環境中&#xff0c;開發者常常會遇到 mTLS 握手失敗…

antd+react+可輸入的下拉選擇組件

該組件是一個可輸入的下拉選擇組件&#xff0c;支持從預設選項中選擇或手動輸入自定義值。組件基于 React 和 Ant Design 實現&#xff0c;具有良好的交互體驗和靈活的配置選項。 &#x1f9e0; 核心邏輯分析 1. 狀態管理 const [isInput, setIsInput] useState(false); con…

React 面試題庫

openAI React 面試題庫 以下題庫按模塊分類&#xff08;React 架構與運行機制、核心 API、Diff 算法與事件機制、Fiber 架構與調度、并發模式與過渡、生命周期及新版生命周期對照、綜合源碼題、擴展專題、React 與 Vue 對比&#xff09;&#xff0c;并按難度&#xff08;初級…

查看兩個tv and 手機模擬器的ip

要查看 Android 模擬器 的 IP 地址&#xff0c;你可以使用 ADB shell 命令來獲取。下面是詳細步驟&#xff1a;步驟 1&#xff1a;查看已連接的模擬器首先&#xff0c;確保你連接的模擬器已經啟動并且連接到 ADB。你可以運行以下命令來查看已連接的設備&#xff1a;adb devices…

從零到一:用C語言構建貪吃蛇(一)- 基礎框架與數據結構

資料合集下載鏈接: ??https://pan.quark.cn/s/472bbdfcd014? 第一步:繪制游戲世界 - 定義地圖邊界 任何游戲都需要一個舞臺。在貪吃蛇中,這個舞臺就是一個有明確邊界的矩形地圖。 1. 確定尺寸 根據筆記,我們首先要確定地圖的尺寸。使用宏定義(??#define??)是…

AWS RDS 排查性能問題

AWS RDS 排查數據庫問題 1.查看當前橫在執行的SQL select id,user,time,left(info,100) from information_schema.processlist where time>0 and info is not null order by time desc ;2.AWS RDS 查看性能詳情查看 Top SQL&#xff0c;AAS最高的幾個sql&#xff0c;然后看這…