【Linux庖丁解牛】—自定義shell的編寫!

1. 打印命令行提示符

在我們使用系統提供的shell時,每次都會打印出一行字符串,這其實就是命令行提示符,那我們自定義的shell當然也需要這一行字符串。

這一行字符串包含用戶名,主機名,當前工作路徑,所以,我們在打印這行字符串時,需要獲取這些信息。根據我們之前學過的知識,我們可以用getenv系統調用來獲取!

這里有一個接口gethostname,我試過了用getenv來獲取系統的主機名,但是,在我的系統上似乎無法獲取,這可能和系統有關,但是我們用gethostname這個接口也可以很安全的獲得主機名,具體用法用man手冊看一看也就會了。?

?結果沒有問題:

2. 獲取用戶輸入

當我們解決了命令行提示符的問題后,接下來我們就會注意到每次執行指令都會有一個光標在閃爍等待用戶輸入指令!所以我們現在就要解決這個問題!

如果用scanf來獲取緩沖區的字符串坑定是不行的,因為scanf默認以空格作為分隔符,而我們在輸入指令帶選項時,就會有空格!

那我們就用fgets:

?可是為什么回顯時有兩次換行呢?

原因含很簡單:我們在輸入指令時,最后輸入的換行也在緩沖區中被fges獲取保留在數組commandline的最后一個字符,解決方法也很簡單,只需要把最后一個字符置為0即可!

現在寫的代碼還是不夠優雅,我們稍微封裝一下:

  1 #include <iostream>2 #include <cstdlib>3 #include <cstdio>4 #include <unistd.h>5 #include <cstring>6 7 using namespace std;8 9 #define COMMAND_SIZE 102410 #define FORMAT "%s@%s:%s$ "11 12 const char* get_user_name()13 {14     const char* user=getenv("USER");15     return user==NULL?"NONE":user;16     //return user;17 }18 19 const char* get_pwd()20 {21     const char* pwd=getenv("PWD");22     return pwd==NULL?"NONE":pwd;23 }24 25 //制作命令行提示符Command Prompt26 void make_command_prompt(char cmd_prompt[],int size)27{28     char hostname[256];29     gethostname(hostname,sizeof(hostname));30     snprintf(cmd_prompt,size,FORMAT,get_user_name(),hostname,get_pwd());31 }                                                                                                                                               32 33 //打印命令行提示符34 void print_cmd_prompt()35 {36     char prompt[COMMAND_SIZE];37     make_command_prompt(prompt,sizeof(prompt));38     printf("%s",prompt);39     fflush(stdout);40 }41 42 //獲取用戶輸入的命令43 bool get_command(char* out,int size)44 {45     char* c=fgets(out,size,stdin);46     if(c==NULL) return false;47     out[strlen(out)-1]=0;48     //如果用戶什么都沒有輸入則返回false49     if(strlen(out)==0) return false;50     return true;51 }52 53 int main()54 {55     //1.打印命令行提示法56     print_cmd_prompt();57     //2.獲取用戶輸入的命令58     char commandline[COMMAND_SIZE];59     if(get_command(commandline,sizeof(commandline)))60     {61         printf("%s\n",commandline);62     }63     return 0;64 }

我們使用的shell是不斷在獲取用戶的指令的,也就是說shell一旦跑起來就是一個死循環,直到我們退出shell!所以我們還應該將我們的主體邏輯改一下!

3. 解析命令行

我們獲取了用戶輸入的字符串后【ls -a -l】,我們不可能用這一長串字符串去執行我們的指令,我們需要做的下一步就是將我們獲取的字符串按空格切割!具體如何做到如下:

我們先在全局定義一個命令行參數表char* ?g_argv[MAXARGC]來記錄我們切割的命令行參數

接下來,我們封裝一個函數來完成我們的切割任務:

測試函數:

?測試結果:

4. 執行命令?

執行命令也非常簡單,這需要用到我們之前學過的知識,創建子進程,將子進程進行程序替換!

5.簡化工作路徑的顯示?

通過上圖我們可以觀察到我們自定義的shell顯示的工作路徑太長了,為了和原shell盡可能保持一致,所以我們封裝一個函數來解決這個問題!

?6. 檢測并處理內建命令

我們在輸入ls,pwd等命令時,我們自定義的shell雀氏可以很好的幫我們完成工作。但是,當我們輸入cd,export等命令時,此時的shell就不再適用了。cd命令是改變當前的工作路徑,但是我們自定義的shell是子進程通過進程替換的方式幫我們執行命令,而cd這類命令是去環境變量表中那到當前的工作路徑,我們需要更改父進程bash的環境變量。所以對于cd這類的命令,我們需要用父進程去執行。而cd這類的命令我們又稱為內建命令,因此,在執行命令之前,我們需要一個檢測并處理內建命令的操作!

?

?下面是測試結果:

?我們發現工作路徑果然發生改變了,但是命令行顯示的路徑為什么沒有發生改變呢?

但cd命令執行時,先是進程的工作路徑發生改變,然后環境變量中記錄的工作路徑再改變,而這個工作也是由shell來完成的,但是目前我們的自定義shell還沒有實現這個功能!并且,我們獲取當前工作路徑是通過獲取環境變量的方式拿到的,所以我們在命令行中顯示的工作路徑永遠是久的!

因此,獲取當前工作路徑有一個更好的方式->系統調用【getcwd】!

下面的測試就符合預期了!?

但是,環境變量中的pwd是實實在在發生了變化的,所以我們自定義的shell也應該實現這一個功能!

所以,我們僅需要在獲取當前工作路徑之后,用puenv導入到環境變量中即可!

?當然,還有許多內建命令,比如echo,我們可以完善這些內建命令,這里就不寫了【比較懶】。

7. 完善環境變量表

目前這里自定義的shell只有命令行參數表,還缺少一張環境變量表。父進程bash在啟動時,從配置文件中獲取環境變量,子進程則繼承父進程的環境變量。如果我們要模擬bash獲取環境變量的方式,就必須從配置文件中那數據。但是,這里目前是做不到的【沒辦法到配置文件中拿數據】。

不過,我們自定義的shell本質上還是bash的子進程,所以我們可以到父進程中獲取環境變量!

?

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

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

相關文章

應用案例 | 設備分布廣, 現場維護難? 宏集Cogent DataHub助力分布式鍋爐遠程運維, 讓現場變“透明”

在日本&#xff0c;能源利用與環保問題再次成為社會關注的焦點。越來越多的工業用戶開始尋求更高效、可持續的方式來運營設備、管理能源。而作為一家專注于節能與自動化系統集成的企業&#xff0c;日本大阪的TESS工程公司給出了一個值得借鑒的答案。 01 鍋爐遠程監控難題如何破…

【OSG學習筆記】Day 16: 骨骼動畫與蒙皮(osgAnimation)

骨骼動畫基礎 骨骼動畫是 3D 計算機圖形中常用的技術&#xff0c;它通過以下兩個主要組件實現角色動畫。 骨骼系統 (Skeleton)&#xff1a;由層級結構的骨頭組成&#xff0c;類似于人體骨骼蒙皮 (Mesh Skinning)&#xff1a;將模型網格頂點綁定到骨骼上&#xff0c;使骨骼移動…

jdk同時安裝多個版本并自由切換

一、安裝不同版本的JDK 二、配置環境變量&#xff08;多版本JDK&#xff09; 1. 新建版本專用環境變量&#xff08;用于切換&#xff09; 操作位置&#xff1a;系統變量 > 新建 變量名&#xff1a;JAVA_HOME_1.8 變量值&#xff1a;JDK 8安裝路徑變量名&#xff1a;JAVA1…

java中裝飾模式

目錄 一 裝飾模式案例說明 1.1 說明 1.2 代碼 1.2.1 定義數據服務接口 1.2.2 定義基礎數據庫服務實現 1.2.3 日志裝飾器 1.2.4 緩存裝飾器 1.2.5 主程序調用 1.3 裝飾模式的特點 一 裝飾模式案例說明 1.1 說明 本案例是&#xff1a;數據查詢增加緩存&#xff0c;使用…

【論文閱讀】YOLOv8在單目下視多車目標檢測中的應用

Application of YOLOv8 in monocular downward multiple Car Target detection????? 原文真離譜&#xff0c;文章都不全還發上來 引言 自動駕駛技術是21世紀最重要的技術發展之一&#xff0c;有望徹底改變交通安全和效率。任何自動駕駛系統的核心都依賴于通過精確物體檢…

在uni-app中如何從Options API遷移到Composition API?

uni-app 從 Options API 遷移到 Composition API 的詳細指南 一、遷移前的準備 升級環境&#xff1a; 確保 HBuilderX 版本 ≥ 3.2.0項目 uni-app 版本 ≥ 3.0.0 了解 Composition API 基礎&#xff1a; 響應式系統&#xff1a;ref、reactive生命周期鉤子&#xff1a;onMount…

408第一季 - 數據結構 - 圖

圖的概念 完全圖 無向圖的完全圖可以這么想&#xff1a;如果有4個點&#xff0c;每個點都會連向3個點&#xff0c;每個點也都會有來回的邊&#xff0c;所以除以2 有向圖就不用除以2 連通分量 不多解釋 極大連通子圖的意思就是讓你把所有連起來的都圈出來 強連通圖和強連通…

31.2linux中Regmap的API驅動icm20608實驗(編程)_csdn

regmap 框架就講解就是上一個文章&#xff0c;接下來學習編寫的 icm20608 驅動改為 regmap 框架。 icm20608 驅動我們在之前的文章就已經編寫了&#xff01; 因為之前已經對icm20608的設備樹進行了修改&#xff0c;所以大家可以看到之前的文章&#xff01;當然這里我們還是帶領…

Vue速查手冊

Vue速查手冊 CSS deep用法 使用父class進行限定&#xff0c;控制影響范圍&#xff1a; <template><el-input class"my-input" /> </template><style scoped> /* Vue 3 推薦寫法 */ .my-input :deep(.el-input__inner) {background-color…

振動力學:無阻尼多自由度系統(受迫振動)

本文從頻域分析和時域分析揭示系統的運動特性&#xff0c;并給出系統在一般形式激勵下的響應。主要討論如下問題&#xff1a;頻域分析、頻響函數矩陣、反共振、振型疊加法等。 根據文章1中的式(1.7)&#xff0c;可知無阻尼受迫振動的初值問題為&#xff1a; M u ( t ) K u …

真實案例分享,Augment Code和Cursor那個比較好用?

你有沒有遇到過這種情況&#xff1f;明明知道自己想要什么&#xff0c;寫出來的提示詞卻讓AI完全理解錯了。 讓AI翻譯一篇文章&#xff0c;結果生成的中文不倫不類&#xff0c;機器僵硬&#xff0c;詞匯不同&#xff0c;雞同鴨講。中國人看不懂&#xff0c;美國人表示聳肩。就…

zotero及其插件安裝

zotero官網&#xff1a;Zotero | Your personal research assistant zotero中文社區&#xff1a;快速開始 | Zotero 中文社區 插件下載鏡像地址&#xff1a;Zotero 插件商店 | Zotero 中文社區 翻譯&#xff1a;Translate for Zotero 接入騰訊翻譯API&#xff1a;總覽 - 控制…

【SSM】SpringMVC學習筆記8:攔截器

這篇學習筆記是Spring系列筆記的第8篇&#xff0c;該筆記是筆者在學習黑馬程序員SSM框架教程課程期間的筆記&#xff0c;供自己和他人參考。 Spring學習筆記目錄 筆記1&#xff1a;【SSM】Spring基礎&#xff1a; IoC配置學習筆記-CSDN博客 對應黑馬課程P1~P20的內容。 筆記2…

從認識AI開始-----變分自編碼器:從AE到VAE

前言 之前的文章里&#xff0c;我已經介紹了傳統的AE能夠將高維輸入壓縮成低維表示&#xff0c;并重建出來&#xff0c;但是它的隱空間結構并沒有概率意義&#xff0c;這就導致了傳統的AE無法自行生成新的數據&#xff08;比如新圖像&#xff09;。因此&#xff0c;我們希望&a…

智慧賦能:移動充電樁的能源供給革命與便捷服務升級

在城市化進程加速與新能源汽車普及的雙重推動下&#xff0c;移動充電樁正成為能源供給領域的一場革命。傳統固定充電設施受限于布局與效率&#xff0c;難以滿足用戶即時、靈活的充電需求&#xff0c;而移動充電樁通過技術創新與服務升級&#xff0c;打破了時空壁壘&#xff0c;…

發版前后的調試對照實踐:用 WebDebugX 與多工具構建上線驗證閉環

每次產品發版都是一次“高壓時刻”。版本升級帶來的不僅是新功能上線&#xff0c;更常伴隨隱藏 bug、兼容性差異與環境同步問題。 為了降低上線風險&#xff0c;我們逐步構建了一套以 WebDebugX 為核心、輔以 Charles、Postman、ADB、Sentry 的發版調試與驗證流程&#xff0c;…

如何安裝huaweicloud-sdk-core-3.1.142.jar到本地倉庫?

如何安裝huaweicloud-sdk-core-3.1.142.jar到本地倉庫&#xff1f; package com.huaweicloud.sdk.core.auth does not exist 解決方案 # 下載huaweicloud-sdk-core-3.1.142.jar wget https://repo1.maven.org/maven2/com/huaweicloud/sdk/huaweicloud-sdk-core/3.1.142/huawe…

Python學習(7) ----- Python起源

&#x1f40d;《Python 的誕生》&#xff1a;一段圣誕假期的奇妙冒險 &#x1f4cd;時間&#xff1a;1989 年圣誕節 在荷蘭阿姆斯特丹的一個寒冷冬夜&#xff0c;燈光昏黃、窗外飄著雪。一個程序員 Guido van Rossum 正窩在家里度假——沒有會議、沒有項目、沒有 bug&#xf…

DiMTAIC 2024 數字醫學技術及應用創新大賽-甲狀腺B超靜態及動態影像算法賽-參賽項目

參賽成績 項目介紹 去年參加完這個比賽之后&#xff0c;整理了項目文件和代碼&#xff0c;雖然比賽沒有獲獎&#xff0c;但是參賽過程中自己也很有收獲&#xff0c;自己一個人搭建了完整的pipeline并基于此提交了多次提高成績&#xff0c;現在把這個項目梳理成博客&#xff0c…

繪制餅圖詳細過程

QtCharts繪制餅圖 說明&#xff1a;qcustomplot模塊沒有繪制餅圖的接口和模塊&#xff0c;所以用Qt官方自帶的QtCharts進行繪制。繪制出來還挺美觀。 1 模塊導入 QT chartsQT_BEGIN_NAMESPACE以上這兩行代碼必須得加 2 總體代碼 widget.h #ifndef WIDGET_H #defin…