linux下C语言实现myshell模拟shell终端
2018-03-21 11:04
423 查看
/********************************************* * 文件名:myShell.c * 功能描述:模拟终端shell并实现shell外部命令 * 编辑人:王廷云 * 编辑时间:2017-8-21 * 修改时间:2018-1-23 *********************************************/ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <pwd.h> #include <sys/types.h> #include <sys/wait.h> #define SIZE 1024 // 缓冲区大小 /* 功能函数声明 */ void getCmd(char *buff, char *cmd[]); // 获取命令 void showShell(void); // 显示终端提示符 void getInput(char buff[]); // 获取输入 void insertChar(char buff[], char ch, int *idx); // 字符插入 void deleteChar(char buff[], int *idx); // 字符删除 void moveRight(char buff[], int *idx); // 光标右移 void moveLeft(char buff[], int *idx); // 光标左移 /* * 程序从主函数开始 * 思路: * 1.打印终端提示符 * 2.获取用户输入的命令 * 3.创建子进程执行命令 * 4.执行完毕回到终端提示符 */ int main(void) { char buff[SIZE] = {0}; // 用户输入 char *cmd[20]; // 把输入转换为终端命令 /* 配置界面 */ system("stty -echo"); // 关闭回显 system("stty -icanon"); // 关闭缓冲 /* 进入终端循环 */ while (1) { /* 显示终端提示符 */ showShell(); /* 获取用户输入 */ getInput(buff); /* 把用户输入转换为终端命令 */ getCmd(buff,cmd); if (NULL == cmd[0]) // 用户输入的回车 { continue; } /* 命令为exit则退出终端 */ else if (strcmp(cmd[0],"exit") == 0) { putchar('\n'); // 退出前换行 system("stty echo"); // 恢复回显 system("stty icanon"); // 恢复缓冲 return 0; } /* 创建子进程执行用户输入命令 */ if (0 == fork()) { putchar('\n'); // 把命令执行结果换行显示 execvp(cmd[0], cmd); perror(cmd[0]); // 如果返回则说明执行错误 exit(EXIT_FAILURE); } wait(NULL); // 回收子进程 } } /* * 函数名:getInput * 函数功能:获取用户输入,采用字符串保存方式使得支持光标移动 * 参数:用于保存用户输入的字符数组 * 返回值:无 */ void getInput(char buff[]) { char ch; int idx = 0; // 光标索引 buff[0] = '\0'; /* 保存光标位置 */ printf("\033[s"); fflush(stdout); /* 进入获取用户输入循环,直到输入完成 */ while (1) { ch = getchar(); if ('\033' == ch && getchar() == '[') // 方向键 { switch (ch = getchar()) { case 'C': moveRight(buff,&idx); break; case 'D': moveLeft(buff,&idx); break; default : break; } continue; } /* 其它键 */ switch (ch) { case 127 : deleteChar(buff, &idx); break; case '\n': return; default : insertChar(buff, ch, &idx);break; } /* 恢复光标-清除光标至行末尾-打印命令-恢复光标位置 */ printf("\033[u\033[K%s\033[u", buff); /* 光标与下标关联 */ if (idx > 0) { printf( 4000 "\033[%dC", idx); } fflush(stdout); } } /* * 函数名:insertChar * 函数功能:在光标出插入字符 * 参数:1.存储用户输入的字符串 2.待插入的字符 3.光标索引值 * 返回值:无 */ void insertChar(char buff[], char ch, int *idx) { /* 越界问题由光标移动解决 */ if (strlen(buff) < SIZE-1) { /* 光标以后的字符右移 */ memmove(buff+*idx+1,buff+*idx,strlen(buff)-*idx+1); buff[*idx] = ch; // 光标处插入字符 (*idx)++; } } /* * 函数名:deleteChar * 函数功能:删除光标前的字符 * 参数:1.用户输入的字符串 2.光标索引值 * 返回值:无 */ void deleteChar(char buff[], int *idx) { if (idx > 0) { /* 通过移动覆盖达到删除的目的 */ memmove(buff+*idx-1,buff+*idx,strlen(buff)-*idx+1); } (*idx)--; } /* * 函数名:moveRight * 函数功能:光标右移 * 参数:1.用户输入的字符串 2.光标索引值 * 返回值:无 */ void moveRight(char buff[], int *idx) { if (*idx < strlen(buff)) (*idx)++; } /* * 函数名:moveLeft * 函数功能:光标左移 * 参数:1.用户输入的字符串 2.光标索引值 * 返回值:无 */ void moveLeft(char buff[], int *idx) { if (*idx > 0) (*idx)--; } /* * 函数名:getCmd * 函数功能:把用户输入的字符串转换为终端命令 * 参数:1.字符串地址 2.指针数组-保存转换后的命令 * 返回值:无 */ void getCmd(char *buff, char *cmd[]) { int idx = 0; char *ret; ret = strtok(buff," \t\n"); // 分割命令 while (1) { cmd[idx++] = ret; if (NULL == ret) // 分割命令结束 return; ret = strtok(NULL," \t\n"); } } /* * 函数名:showShell * 函数功能:打印终端提示符 * 参数:无 * 返回值:无 */ void showShell(void) { /* 终端提示符组成:[用户名+@+主机名+当前目录]+用户提示符 */ uid_t uid; char *ret; struct passwd *user; char hostname[100]; char cwd[120]; /* 获取用户id */ uid = getuid(); /* 根据uid获取用户的passwd结构体 */ user = getpwuid(uid); printf("[%s@",user->pw_name); // 打印用户名 /* 获取主机名 */ gethostname(hostname, 100); printf("%s:", hostname); // 打印主机名 /* 获取当前工作目录 */ getcwd(cwd, 120); if (strcmp(cwd,user->pw_dir) == 0) { printf("~"); // 家目录特殊处理 } else { ret = strrchr(cwd,'/'); // 获取路径的最后一个目录 if (ret[1] == '\0') { printf("/]"); // 根目录 } else { printf("%s]",ret+1); } } /* 打印用户提示符 */ if (0 == uid) { printf("# "); // 超级用户 } else { printf("$ "); // 普通用户 } fflush(stdout); // 刷新终端提示符 }
相关文章推荐
- 使用C实现模拟实现一个shell解释器(一)
- Linux中模拟shell实现ls命令(不加参数)
- Android自动化测试初探(五): 再述模拟键盘鼠标事件(adb shell 实现)
- 【操作系统】进程程序替换之模拟实现一个简易的Shell
- shell脚本实现简单的模拟用户操作,未加检查点。
- Android自动化测试初探(五): 再述模拟键盘鼠标事件(adb shell 实现)
- Android自动化测试初探(五): 再述模拟键盘鼠标事件(adb shell 实现)
- 模拟实现shell
- expect模拟伪终端来实现免人机交互
- 模拟实现myshell
- shell脚本实现堆栈(模拟合服)
- Android查询:模拟键盘鼠标事件(adb shell 实现)
- Mac 上使用 Shell 脚本 + adb shell 实现简单的 Android 模拟点击自动化测试
- CentOS6.8 x86_64bit shell脚本实现模拟nginx服务启动与关闭
- 模拟shell实现su命令(切换用户)
- Android查询:模拟键盘鼠标事件(adb shell 实现)
- 实现shell终端代码分享(可用户登录 实现系统命令)
- 王晓博 2010.12.22-3-模拟linux shell 终端环境 执行所有shell命令
- Android自动化测试初探(五): 再述模拟键盘鼠标事件(adb shell 实现)