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("[%s@%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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值