房屋建模软件,wordpress 伪静态seo,河南seo公司,文创产品有哪些1.打印提示符并获取命令行
我们在使用shell的时候#xff0c;发现我们在输入命令是#xff0c;前面会有#xff1a;有用户名#xff0c;版本#xff0c;当前路径等信息#xff0c;这里我们可以用环境变量去获取: 1 #include stdio.h2 #include stdlib.h…1.打印提示符并获取命令行
我们在使用shell的时候发现我们在输入命令是前面会有有用户名版本当前路径等信息这里我们可以用环境变量去获取: 1 #include stdio.h2 #include stdlib.h3 4 const char* getUsername()5 {6 const char* name getenv(USER);7 if(name) return name;8 else return none;9 }10 11 const char* getHostname()12 {13 const char* hostname getenv(HOSTNAME);14 if(hostname) return hostname;15 else return none;16 }17 18 const char* getCwd()19 {20 const char* cwd getenv(PWD);21 if(cwd) return cwd;22 else return none;23 }24 25 int main()26 {27 printf(%s%s %s\n,getUsername(),getHostname(),getCwd()); 28 return 0;29 }写。 看到我们打印出来的是绝对路径, 而shell显示的相对路径, 但为了区分先这样不去裁剪. 1 #include stdio.h2 #include stdlib.h3 #include string.h4 5 #define NUM 1024 6 7 const char* getUsername() 8 { 9 const char* name getenv(USER); 10 if(name) return name; 11 else return none; 12 } 13 14 const char* getHostname() 15 { 16 const char* hostname getenv(HOSTNAME); 17 if(hostname) return hostname; 18 else return none; 19 } 20 21 const char* getCwd() 22 { 23 const char* cwd getenv(PWD); 24 if(cwd) return cwd; 25 else return none; 26 } 27 28 int getUsercommand(char* command, int num) 29 { 30 printf([%s%s %s],getUsername(),getHostname(),getCwd()); 31 char* r fgets(command,num,stdin);//最终还是会输入\n32 if(r NULL) return 1;33 34 command[strlen(command)-1] \0;//去除输入的换行35 return 0; 36 } 37 38 int main() 39 { 40 char usercommand[NUM];41 //1.打印提示符并且获取命令字符串42 getUsercommand(usercommand,sizeof(usercommand));43 //2. 44 //3. 45 printf(%s,usercommand);//回显命令,用于测试46 return 0;47 }由于用scanf接收的遇到空格就会停止读取, 所以用fgets, 而且用户输入完命令一定会输入回车, 所以把最后一个回车符删掉. 2.解析命令行
我们在输入命令时, 可能不仅仅只是一段比如说ls -a -l 。但是命令行解释器内部在解析指令时应该传递的是ls -a -l这样的多个个字符串, 所以我们还需要以空格来分割字符串。 1 #include stdio.h2 #include stdlib.h3 #include string.h4 5 #define DEBUG 16 #define NUM 10247 #define SIZE 648 #define SEP 41 void commandSplit(char* in, char* out[])42 {43 int argc 1;44 out[0] strtok(in,SEP);
W 45 while(out[argc] strtok(NULL,SEP));//报警不需要处理46 47 #ifdef DEBUG 48 for(int i 0; out[i]; i)49 printf(%d:%s\n,i,out[i]);50 #endif51 }52 53 int main()54 {55 char usercommand[NUM];56 char* argv[SIZE];57 //1.打印提示符并且获取命令字符串58 getUsercommand(usercommand,sizeof(usercommand));59 //2.分割字符串60 commandSplit(usercommand, argv); 61 //3. 62 return 0;63 } 3.执行对应的命令
创建子进程和进程替换, 为了不影响shell, 我们将大部分指令的执行让子进程去完成, 父进程只要阻塞等待子进程完成就好了。 1 #include stdio.h2 #include stdlib.h3 #include string.h4 #include unistd.h5 #include sys/types.h6 #include sys/wait.h7 8 //#define DEBUG 19 #define NUM 102410 #define SIZE 6411 #define SEP 12 13 const char* getUsername()14 {15 const char* name getenv(USER);16 if(name) return name;17 else return none;18 }19 20 const char* getHostname()21 {22 const char* hostname getenv(HOSTNAME);23 if(hostname) return hostname;24 else return none;25 }26 27 const char* getCwd()28 {29 const char* cwd getenv(PWD);30 if(cwd) return cwd;31 else return none;32 }33 34 int getUsercommand(char* command, int num) 35 {36 printf([%s%s %s],getUsername(),getHostname(),getCwd()); 37 char* r fgets(command,num,stdin);//最终还是会输入\n38 if(r NULL) return -1;39 40 command[strlen(command)-1] \0;//去除输入的换行41 return strlen(command);42 }43 44 void commandSplit(char* in, char* out[])45 {46 int argc 1;47 out[0] strtok(in,SEP);
W 48 while(out[argc] strtok(NULL,SEP));//报警不需要处理49 50 #ifdef DEBUG 51 for(int i 0; out[i]; i)52 printf(%d:%s\n,i,out[i]);53 #endif54 }55 56 int execute(char* argv[])57 {58 pid_t id fork();59 if(id 0) return 1;60 else if(id 0)61 {62 //child63 //exec commond64 execvp(argv[0],argv);65 exit(1);66 }67 68 else69 {70 //father71 pid_t rid waitpid(id,NULL,0);72 if(rid 0)73 printf(wait fail\n);74 }75 76 return 0;77 }78 79 int main()80 {81 while(1)82 {83 char usercommand[NUM];84 char* argv[SIZE];85 //1.打印提示符并且获取命令字符串86 int n getUsercommand(usercommand,sizeof(usercommand));87 if(n 0) continue;//如果得到的是空串或者获取失败,不要往后执行88 //2.分割字符串89 commandSplit(usercommand, argv);90 //3.执行命令91 execute(argv); 92 }93 return 0;94 }由于shell要一直运行, 所以要循环执行, 这里程序替换用execvp函数比较合适, 因为argv数组就是我们分割出的一个个命令的子串, argv[0]就是程序名, argv就是指令集. 父进程只进行wait即可. 此外, getUsercommand函数可以优化一下, 返回的是输入的指令的长度, 如果接收失败(返回值为-1或者返回值是0只打印了空行)就不需要往下执行了, 直接continue进行下一轮. 4.特殊处理 有一批命令, 不能让子进程执行, 必须让父进程自己执行, 这些命令叫内建命令.
1) cd指令 可以看到cd .. 之后并没有发生什么异常, 但是pwd之后发现路径没有发生变化.
我们为什么能在linux中进入某个目录, 就是因为我们改变了shell的工作目录. 每个进程都有自己的工作目录, 我们想让父进程的工作目录发生改变, 但是程序替换之后都是子进程在执行cd .., 改变的都是子进程的工作目录, 子进程改变完了又被回收了, 父进程完全没发生变化, 所以cd应该实现成内建命令。 79 void cd(const char* path)80 {81 chdir(path);82 }83 84 //1-yes,0-no85 int doBuildin(char* argv[])86 {87 if(strcmp(argv[0],cd) 0)88 {89 char* path NULL;
W 90 if(argv[1] NULL) path .;91 else path argv[1];92 cd(path);93 return 1;94 }95 else if(strcmp(argv[0],ls)0)96 {97 return 1;98 }99 return 0; 100 }101 102 int main()103 {104 while(1)105 {106 char usercommand[NUM];107 char* argv[SIZE];108 //1.打印提示符并且获取命令字符串109 int n getUsercommand(usercommand,sizeof(usercommand));110 if(n 0) continue;//如果得到的是空串或者获取失败,不要往后执行111 //2.分割字符串112 commandSplit(usercommand, argv);113 //3.检查是不是内建命令,是的话直接执行114 n doBuildin(argv);115 if(n) continue;//是内建命令不用往后执行了116 //4.执行命令117 execute(argv);118 }119 return 0;120 }所以在执行命令前先检查是不是内建命令, 用返回值接收, 如果是就直接执行并返回1, continue不往下执行, 如果不是就返回0, 执行命令. 既然当前的工作目录改变了, 那么环境变量PWD也要改变: chdir改变当前工作目录, getcwd获取当前的工作路径, sprintf将tmp中的内容输出到cwd中, putenv将cwd导入环境变量. 2) export命令 创建一个数组env储存要导入的环境变量, 设置size指向导入到第几个环境变量. 如果argv[1]是空就直接返回, 否则就导入环境变量, 注意不能直接把argv[1]导入进去, 因为argv[1]随着指令的输入时刻在变化, 需要开辟额外的空间去存储. 3echo指令 4ls指令
我们执行的ls指令中不同的文件都有不同的颜色所以对于ls我们可以在分割命令的时候加上一个“--colorauto”.