linux c语言向终端输入字符,linux下C语言实现myshell模拟shell终端

/*********************************************

* 文件名:myShell.c

* 功能描述:模拟终端shell并实现shell外部命令

* 编辑人:王廷云

* 编辑时间:2017-8-21

* 修改时间:2018-1-23

*********************************************/

#include

#include

#include

#include

#include

#include

#include

#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("\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);            // 刷新终端提示符

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值