1. 程式人生 > >Linux環境下模擬shell終端:mybash、mysu、myclear

Linux環境下模擬shell終端:mybash、mysu、myclear

通常shell中執行命令的流程都是bash程序建立了一個子程序,然後子程序程序替換,替換為可執行的命令檔案。
1、mybash函式:輸出資訊的格式是:[使用者名稱@主機名所在檔案]$(root使用者:[使用者名稱@主機名所在檔案]#)。當所在檔案就是當前使用者的家目錄時顯示“~”。
這裡寫圖片描述
那麼,該如何得到使用者名稱,主機名和當前所在檔名呢?
我們需要藉助下面這些函式:
uid_t geteuid(void)函式取得執行目前程序有效的使用者識別碼。有效的使用者識別碼用來決定程序執行的許可權,改變此值,程序可以獲得額外的許可權。
struct passwd *getpwuid(uid_t uid)函式通過使用者的uid查詢使用者的passwd資料。如果出錯時,它們都返回一個空指標並設定errno的值,使用者可以根據perror函式查看出錯的資訊。
struct passwd *getpwnam(const char *name)函式獲取使用者登入相關資訊,其中name是當前登入的使用者名稱。若成功,返回指標;若出錯或者達到檔案尾端,返回NULL。
int uname(struct utsname *name)函式把主機資訊寫入name引數指向的結構體中。
char *getcwd(char *buf, size_t size)函式把當前目錄的絕對地址儲存到 buff中,buff 的大小為 size。如果 size太小無法儲存該地址,返回 NULL 並設定 errno 為 ERANGE。可以採取令 buff 為 NULL並使 size 為負值來使 getcwd 呼叫 malloc 動態給 buff 分配,但是這種情況要特別注意使用後釋放緩衝以防止記憶體洩漏。
需注意的是:1.使用函式uname()得到的主機名“.”之後的部分是多餘的,需要進行額外的處理。2.getcwd()函式得到的是函式的絕對路徑,在顯示的資訊中只需要當前目錄的名字,需要進行處理。
程式碼實現:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <signal.h>

#define LENTH 20
char *cmdArr[LENTH]={NULL};
int count = 0;

void out_flag()
{
    char path[128] = {0};
    if(NULL == getcwd(path, 128))
    {
        printf
("getcwd error\n"); return; } char dir[128] = {0}; char *p = strtok(path, "/"); while(p != NULL) { strcpy(dir, p); p = strtok(NULL, "/"); } if(strlen(dir) == 0) { strcpy(dir, "/"); } struct passwd *pw = getpwuid(getuid()); if(pw == NULL) { printf
("error\n"); return; } if(strcmp(pw->pw_dir, getcwd(path, 128)) == 0) { memset(dir, 0, 128); strcpy(dir, "~"); } struct utsname host; uname(&host); char *hname = strtok(host.nodename, "."); if(hname == NULL) { printf("error\n"); return; } char flag = '$'; if(pw->pw_uid == 0) { flag = '#'; } printf("[%[email protected]%s %s]%c ", pw->pw_name, hname, dir, flag); fflush(stdout); }

2、mysu函式:su命令切換使用者成功後,su程序會新建一個子程序並把它替換為bash程序,su之後的命令都是在新建的bash裡執行的。
程式碼實現

int main(int argc,char *argv[])
{
    char *user="root";//指標
    if(argv[1]!=NULL)
    {
        user=argv[1];
        struct passwd *p=NULL;
        p=getpwnam(user);
        if(p==NULL)
        {
            printf("not find username!\n");
            return;
        }
    }
    struct passwd *pw=getpwuid(getuid());
    if(strcmp(pw->pw_name,"root")!=0)  
    {
        char passwd[128]={0};
        printf("Passwd:");
        struct termios old,new;
        tcgetattr(0,&old);
        new=old;
        new.c_lflag &= ~ECHO;   
        new.c_lflag &= ~ICANON; 
        tcsetattr(0,TCSANOW,&new);
        char c=0;
        int num=0;
        while((c=getchar())!='\n')
        {
            if(c==127)
            {
                if(num>0)
                {
                    passwd[--num]=0;
                    printf("\033[1D");
                    printf("\033[K");
                }
                continue;
            }
            printf("*");
            fflush(stdout);
            passwd[num++]=c;
        }
        tcsetattr(0,TCSANOW,&old);

        printf("\n");
        struct spwd *sp=getspnam(user);
        assert(sp!=NULL);
        char salt[128]={0}; 
        int i=0;
        int count =0;
        for(;sp->sp_pwdp[i]!=0;i++)
        {
             salt[i]=sp->sp_pwdp[i];
             if(salt[i]=='$')
             {
                 count++;             
                 if(count==3)
                 break;
             }
        }
        char* p=crypt(passwd,salt);
        assert(p!=NULL);

        if(strcmp(p,sp->sp_pwdp)!=0)
        {
            printf("passwd error\n");
            exit(0);
        }
    }
    pid_t pid=fork();
    assert(pid!=-1);
    if(pid==0)
    {
        struct passwd *pw=getpwnam(user);
        assert(pw!=NULL);
        setuid(pw->pw_uid);
        setenv("HOME",pw->pw_dir,1);
        execl(pw->pw_shell,pw->pw_shell,(char *)0);
        printf("error\n");
        exit(0);
    }

    else
    {
        wait(NULL);
    }
    return 0;
}

3.myclear函式:printf(“033[%d;%dH”,0,0)代表清屏且回到原點(0,0)。
程式碼實現:

#include <stdio.h>

void main()
{
    printf("033\[2J");
    printf("033[%d;%dH",0,0);
}

注:mysu函式編譯時要用gcc -o su su.c -lcrypt

相關推薦

Linux環境模擬shell終端mybashmysumyclear

通常shell中執行命令的流程都是bash程序建立了一個子程序,然後子程序程序替換,替換為可執行的命令檔案。 1、mybash函式:輸出資訊的格式是:[使用者名稱@主機名所在檔案]$(root使用者:[使用者名稱@主機名所在檔案]#)。當所在檔案就是當前使用者

python 和linux環境音訊處理變頻變調的方法和框架

前戲——音樂基礎 聲音是靠波來傳播的,區別任何的聲音需要依據三個來區分:響度、音高和音色響度 音高:聲音具有確定的音高,聲音就可以使空氣以篤定的方式執行。低音就是頻率低。 一個樂音訊率是另外一個樂音的頻率的2倍,我就就稱為比它高八度,聲音的震動頻率=音源的振動頻率

Linux環境編寫簡單的Shell

使用程序建立、等待、終止等知識自主實現簡單的Linuxshell命令列,Linux環境:CentOS7.3 程序建立 建立程序的方式 通常使用fork()函式來建立一個新程序,新程序為子程序,而原來的程序即為父程序。在Linux中fork()是一個非常重要的函式

Linux環境Shell調用MySQL並實現定時任務

usr .sql 操作 default char star ted 空格 rontab 對於一些周期性事務,我們可以在Linux下,使用shell腳本調用mysql數據庫存儲過程,並設置定時任務。 本來是要mysql數據庫中創建事件任務來,定時執行存儲過程,做數據傳輸的。

Nginx 之一 伺服器的安裝部署(一) LInux 環境 Nginx 伺服器的安裝和基本配置

一、編譯和安裝前的準備工作 本部落格依賴環境: Linux Ubuntu 16.04 1.1 足夠的磁碟空間 能夠裝得下 Nginx 的軟體包和安裝檔案, 這個基本都能滿足。 1.2 需要的工具 為了編譯 Nginx 原始碼, 需要安裝標準的 GCC 編譯器。

Linux環境JDK配置

因為最近需要在Linux環境下搭建CTS測試環境,查了好多次資料後總結了以下一些東西,寫點筆記留著以後自己看。 Linux環境下JDK配置: 1.獲取root許可權 sudo -s 或者sudo -i 2.在usr目錄下建立java安裝目錄 cd /usr mkdir java

Linux學習】Linux環境利用wget下載https連結內容時報錯無法本地校驗頒發者的許可權。 要以不安全的方式連線至 ,使用“--no-check-certificate”

一、問題描述 今天在CenterOS系統上使用wget命令下載一個https連結的內容時報錯,如下所示: [[email protected] /]# wget https://mirrors.tuna.tsinghua.edu.cn/gitlab-

Linux環境原始碼編譯和執行常用的兩個命令pkg-config和ldconfig

        最近一段時間在研究linux伺服器叢集的相關知識,打算基於corosync和pacemaker來搭建一個linux高可用叢集, 通過編譯原始碼包來了解其依賴的動態庫,在編譯的過程中遇到一些問題,總結一些,供大家以後參考(很通用哦):        我們

Linux環境gcc靜態編譯/usr/bin/ld: cannot find -lc錯誤原因及解決方法 原因

原因: 一般出現這個問題的時候,Makefile中肯定有-static選項。這其實是靜態連結時沒有找到libc.a。 解決方案: 需要安裝glibc-static.xxx.rpm,如glibc-static-2.12-1.107.el6_4.2.i686.rpm,或是yum install gli

Linux 環境 Java jdk 安裝方法 注此方法為 jdk.bin型別的jdk檔案

1、將jdk檔案放到一個目錄下  例如:jdk.bin   例如  /usr/java  放到了這個這個目錄下 2、然後利用命令檢視目錄下是否有此檔案 # cd /usr/java # ls 如果顯示檔案  jdk.bin 3、解壓jdk.bin檔案 # chmod 755 jdk.bin # ./jdk.b

Linux 環境eclipse啟動出現錯誤jvm terminated. exit code=13

想在Linux下啟動eclipse出現如題的錯誤,在網上找了很多資料,有很多是誤導。在stackoverflow上找到了正確解決方法,英文連線:http://stackoverflow.com/questions/4945178/cannot-run-eclipse-jvm

Linux環境啟動jar包的shell

#! /bin/sh name="beautifulDistrict" Xmx=1024m Xms=1024m Xmn=512m PermSize=256m MaxPermSize=512m pid=${name}".pid" logName="all" jarName=`l

【Redis學習】Linux環境的Redis安裝與配置

安裝環境 redis是C語言開發的,安裝redis需要先將官網上下載的原始碼進行編譯,編譯依賴gcc環境,如果沒有gcc環境,需要安裝gcc。這個最好使用yum安裝,因為依賴關係比較多,自己不好找

在Ubuntu/Linux環境使用MySQL啟動和關閉MySQL服務

作業系統:Ubuntu 17.04 64位 MySQL版本:MySQL 5.7 一、啟動MySQL服務 使用以下命令來啟動MySQL: service mysql start 順便提一下,serv

linux環境搭建Jenkins持續整合(Jenkins+git+shell+maven+tomact)

準備環境   jenkins.war包 ,jdk1.8  ,tomact , maven,git 1.Jenkins  war包,下載地址https://jenkins.io/zh/download/  ,當然你可以通過wget 下載, 也可以通過xftp遠端傳輸 2.

Linux環境的 pyenv的安裝

pyenvCentOS上安裝pyenv:在安裝pyenv前,需要先安裝如下的依賴包:在 CentOS/RHEL/Fedora 下:yum install readline readline-devel readline-static yum install openssl openssl-devel open

linux環境部署zabbix3.2模板郵件告警詳細過程

-1 ice erer without zlib zip ever native item 服務端部署: 系統環境及軟件版本: Linux:release 6.3 zabbix:zabbix-3.2.5.tar.gz nginx:nginx-1.12.0.tar.gz ph

2.Linux環境配置Solr4.10.3

margin 內容 src source -type alt 技術 tgz 安裝包 1.準備階段 操作系統:CentOS 6.8 安裝包:/home/test solr-4.10.3.tgz.tar IK Analyzer 2012FF_hf1.zip jdk-8u12

由一個簡單需求到Linux環境的syslogunix domain socket

message python domain 服務器 import 需求:回到頂部  工作中有一個在Linux(debian8)環境下運行的服務器程序,用python語言實現,代碼中有不同優先級的日誌需要記錄,開發的時候都是使用python的logging模塊輸出到文件,示例代碼如下:  

(1)Jenkins Linux環境的簡單搭建

linux java jenkins安裝部署 jdk apache-maven (1)Jenkins Linux環境下的簡單搭建 Jenkins是一個開源軟件項目,旨在提供一個開放易用的軟件平臺,使軟件的持續集成變成可能。----百度百科 這是一款基於Java開發的工具。種種