实现简易版shell
操作系统小组作业,实现一个简易shell,shell实现了下列命令
exit------退出终端命令
clr-------清屏命令
time-----时间命令
myshell----欢迎命令
quit-----终止命令
pwd-----路径命令
cat-----查看文件命令
help---帮助命令
help [参数]---查看某个具体的命令的注释
ls -l-----查看目录下的文件命令
只实现了简单的几个命令,仅做参考,代码如下
1 #include<bits/stdc++.h> 2 #include<unistd.h> 3 #include<stdio.h> 4 #include<sys/types.h> 5 #include<pwd.h> 6 #include<time.h> 7 #include<dirent.h> 8 #include<stdlib.h> 9 #include<sys/stat.h> 10 #include<fcntl.h> 11 #include <grp.h> 12 #include <sys/wait.h> 13 #include<memory.h> 14 using namespace std; 15 #define MAX_LINE 80 16 #define MAX_NAME_LEN 50 17 #define MAX_PATH_LEN 1000 18 int cmd_cnt; 19 char *cmd_array[MAX_LINE/2+1]; 20 string st; 21 void mytime(){ 22 int weekday; 23 int month; 24 time_t tvar; 25 struct tm *tp; 26 time(&tvar); 27 tp=localtime(&tvar);//获取本地时间 28 weekday=tp->tm_wday; 29 switch(weekday){//根据不同的值打印不同的星期 30 case 1: 31 printf("Mon "); 32 break; 33 case 2: 34 printf("Tues "); 35 break; 36 case 3: 37 printf("Wed "); 38 break; 39 case 4: 40 printf("Thur "); 41 break; 42 case 5: 43 printf("Fri "); 44 break; 45 case 6: 46 printf("Sat "); 47 break; 48 case 7: 49 printf("Sun "); 50 break; 51 default: 52 break; 53 } 54 month=1+tp->tm_mon;//必须要加1,经过查阅资料:tm_mon比实际的值少了1 55 switch(month){//根据不同的值打印月份名 56 case 1: 57 printf("Jan "); 58 break; 59 case 2: 60 printf("Feb "); 61 break; 62 case 3: 63 printf("Mar "); 64 break; 65 case 4: 66 printf("Apr "); 67 break; 68 case 5: 69 printf("May "); 70 break; 71 case 6: 72 printf("Jun "); 73 break; 74 case 7: 75 printf("Jul "); 76 break; 77 case 8: 78 printf("Aug "); 79 break; 80 case 9: 81 printf("Sep "); 82 break; 83 case 10: 84 printf("Oct "); 85 break; 86 case 11: 87 printf("Nov "); 88 break; 89 case 12: 90 printf("Dec "); 91 break; 92 default: 93 break; 94 } 95 printf("%d ",tp->tm_mday);//日期 96 printf("%d:",tp->tm_hour);//小时 97 printf("%d:",tp->tm_min);//分钟 98 printf("%d ",tp->tm_sec);//秒 99 printf("CST ");//CST,意思是China Standard Time 100 printf("%d\n",1900+tp->tm_year);//必须加上1900,返回的值并不是完整的年份,比真实值少了1900 101 } 102 void welcome(){ 103 //如下是欢迎信息 104 //为了是程序更友好,加入了颜色 105 //颜色是紫色,背景色与shell相同 106 printf("\e[32mwelcome to myshell\e[0m\n"); 107 printf("\e[32mit's a Lunix-like shell program made by us\e[0m\n"); 108 printf("\e[32mhope you have a good time with it :-)\e[0m\n"); 109 } 110 void mypwd(){ 111 char pathname[MAX_PATH_LEN]; 112 if(getcwd(pathname,MAX_PATH_LEN)){//获取路径名 113 printf("%s\n",pathname); 114 } 115 else{//如果出错 116 perror("myshell: getcwd");//报错 117 exit(1); 118 } 119 } 120 121 void myquit(){ 122 printf("Thanks for your using,bye-bye!\n"); 123 sleep(1);//暂停1s,看上去视觉效果好一些 124 exit(0); 125 } 126 void exit(){ 127 exit(0); 128 } 129 void myclr(){ 130 cout << "\033[2J"; 131 cout << "\033[H"; 132 133 } 134 135 void printprompt(){//实现命令提示符 136 137 char hostname[MAX_NAME_LEN]; 138 char pathname[MAX_PATH_LEN]; 139 struct passwd *pwd; 140 pwd=getpwuid(getuid()); 141 gethostname(hostname,MAX_NAME_LEN); 142 printf("\e[34m%s@%s:\e[0m",pwd->pw_name,hostname); 143 144 printf("$"); 145 146 147 } 148 149 150 //*****************************************************获得文件权限属性 151 void getPower(mode_t mod) 152 { 153 for(int n=8; n>=0; n--) 154 { 155 if(mod&(1<<n))//移位运算,1左移位n位 156 { 157 switch(n%3) 158 { 159 case 2: 160 printf("r"); 161 break; 162 case 1: 163 printf("w"); 164 break; 165 case 0: 166 printf("x"); 167 break; 168 default: 169 break; 170 } 171 } 172 else 173 { 174 printf("-"); 175 } 176 } 177 } 178 179 180 181 void cat(string filename){ 182 ifstream fin( filename); 183 char str[200]; 184 while ( fin.getline(str,200) ) 185 { 186 cout << str << endl; 187 } 188 } 189 190 191 192 193 void ls(string allstr,string substr){ 194 195 /******************************ls************************* 196 * 197 *dirName[] :store single filename 198 *dir :point to currnt directory 199 *rent :指针变量 200 *st :文件基本操作 201 **********************************************************/ 202 203 204 struct stat st; 205 char dirName[100]; 206 207 DIR *dir; 208 struct dirent *rent;//struct 209 dir = opendir("."); 210 211 212 if(allstr== "ls"){ 213 214 if(dir != NULL) 215 { 216 while((rent=readdir(dir))) 217 { 218 219 strcpy(dirName,rent->d_name); 220 if (dirName[0]!='.' && dirName) 221 { 222 cout << dirName<<'\t'; 223 } 224 } 225 } 226 227 cout << endl; 228 } 229 else if(dir == NULL) 230 { 231 cout << "*****empty*****"<<endl; 232 } 233 else if(allstr != "ls -l") 234 { 235 cout << substr+": "+ "unrecognized option "+"'"+allstr.substr(substr.length())+"'"<<endl; 236 cout << "Try 'ls -l' "<<endl; 237 } 238 239 /******************************************ls -l*************************/ 240 241 else if(allstr == "ls -l") 242 { 243 while( rent = readdir(dir) ) 244 { 245 strcpy(dirName,rent->d_name); 246 if (dirName[0]!='.' && dirName) 247 { 248 if(-1 != stat(rent->d_name, &st) )//get fileInfomation from filename p->d_name and save it in structure stat 249 { 250 getPower(st.st_mode); //get r-w-d 251 cout <<" "<<st.st_nlink<<" ";//get number of file links 252 cout <<" "<<getpwuid(st.st_uid)->pw_name<<" ";//owner name 253 cout <<getgrgid(st.st_gid)->gr_name<<'\t'; //group name 254 cout << st.st_size<<'\t'; //get total size , in bytes 255 256 //printf 12 char and align = left 257 printf("%.12s ",4+ctime(&st.st_mtime)); //the last time of changing file 258 cout << dirName; 259 cout << endl; 260 } 261 } 262 } 263 } 264 265 closedir(dir); 266 } 267 268 269 270 271 //****************************************************获得输入字符 272 string strInput() 273 { 274 string str; 275 string res; 276 char c; 277 while( (c = getchar()) != '\n') 278 str += c; 279 280 vector<string> arr; 281 istringstream istr(str); 282 string word; 283 while(istr>>word) { 284 arr.push_back(word);//添加元素到尾部 285 } 286 287 for(int i=0; i<arr.size(); i++) { 288 if(i != arr.size() - 1) 289 res += arr[i]+" "; 290 else 291 res += arr[i]; 292 } 293 294 return res; 295 } 296 ///////////////////////////////////////////////////////////help命令 297 void print_manual(){ 298 printf("welcome to the manual of myshell, hope it's useful for you\n"); 299 printf("the following are the BUILT-IN commands supported by myshell\n"); 300 printf("\n"); 301 302 printf("exit: exit quit the shell directly\n"); 303 printf("clr: clr clear the screen\n"); 304 printf("time: time show the current time in an elegant format\n"); 305 printf("myshell: myshell [filename] execute a batchfile\n"); 306 printf("quit: quit quit the shell with thank-you\n"); 307 printf("pwd: pwd print the current working directory\n"); 308 printf("help: help/help [command] show the manual of help/get help info of a sepcified command\n"); 309 310 } 311 void print_cmdinfo(string cmdname){ 312 313 if(cmdname=="exit"){ 314 printf("usage:quit the shell directly\n"); 315 printf("options descriptions\n"); 316 printf("none see the manual,plz\n"); 317 } 318 else if(cmdname=="pwd"){ 319 printf("usage:print the current working directory\n"); 320 printf("options descriptions\n"); 321 printf("none see the manual,plz\n"); 322 } 323 else if(cmdname=="time"){ 324 printf("usage:show the current time in an elegant format\n"); 325 printf("options descriptions\n"); 326 printf("none see the manual,plz\n"); 327 } 328 else if(cmdname=="clr"){ 329 printf("usage:clear screen\n"); 330 printf("options descriptions\n"); 331 printf("none see the manual,pls\n"); 332 } 333 else if(cmdname=="myshell"){ 334 printf("usage:execute a batchfile\n"); 335 printf("options descriptions\n"); 336 printf("none see the manual,plz\n"); 337 } 338 else if(cmdname=="help"){ 339 printf("usage:show the manual of help/get help info of a sepcified command\n"); 340 printf("options descriptions\n"); 341 printf("none see the manual,plz\n"); 342 } 343 else if(cmdname=="quit"){ 344 printf("usage:quit the shell with thank-you information\n"); 345 printf("options descriptions\n"); 346 printf("none see the manual,plz\n"); 347 } 348 else {//如果有错 349 printf("myshell: help: Invalid use of help command\n");//打印提示信息 350 } 351 352 } 353 void myhelp(){ 354 if(cmd_cnt==1){//如果是不带参数的help 355 print_manual();//调用子函数print_manual打印用户帮助手册 356 } 357 else if(cmd_cnt==2){//如果格式是"help [command]" 358 print_cmdinfo(st);//打印单个命令的帮助信息 359 } 360 361 } 362 void help(string str){ 363 if(str=="help"){ 364 cmd_cnt=1; 365 } 366 else if(str.length()>5){ 367 368 cmd_cnt=2; 369 st=str.substr(5,str.length()); 370 } 371 372 myhelp(); 373 } 374 ///////////////////////////////////////////////////////////////////////////////// 375 int main() 376 { 377 string n; 378 string str1; //first str !=include space 379 string str2; 380 381 382 while(true){ 383 printprompt(); 384 n=strInput(); 385 386 istringstream istr(n); 387 istr >> str1>>str2; 388 389 if(str1 == "ls"){ 390 ls(n,str1); 391 continue; 392 } 393 if(n=="exit")//退出 394 exit(); 395 else if(n=="clr"){ 396 myclr(); 397 } 398 else if(n=="time") 399 { 400 mytime(); 401 } 402 else if(n=="myshell") 403 { 404 welcome(); 405 } 406 else if(n=="quit") 407 { 408 myquit(); 409 } 410 else if(n=="pwd") 411 { 412 mypwd(); 413 } 414 else if(str1 == "cat"){ 415 cat(str2); 416 } 417 else if(str1=="help"){ 418 help(n); 419 } 420 else 421 cout << "invaild command" << endl; 422 423 } 424 425 return 0; 426 }
如果需要的话,下面链接里面有我对该代码的部分不常见的函数和结构体的注释,如需要的可以看一下
https://files-cdn.cnblogs.com/files/henuliulei/shellzhushi.zip
作者:你的雷哥
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。