shell.c
上传用户:hmmeiri
上传日期:2021-11-11
资源大小:2k
文件大小:10k
源码类别:

Shell编程

开发平台:

C/C++

  1. #include<stdio.h>
  2. #include<ctype.h>
  3. #include<string.h>
  4. #include<unistd.h>
  5. #include<sys/types.h>
  6. #include<sys/stat.h>
  7. #include<fcntl.h>
  8. #include<sys/wait.h>
  9. #include<math.h>
  10. #include<signal.h>
  11. #include<stdlib.h>
  12. struct command_struct{  //表示命令的结构
  13. char *argv[20];
  14. int mark;   //表示输入指令类型的标记
  15. int numargv;//参数及指令数
  16. }*command;
  17. char *paths;
  18. struct path_struct{    //表路径的结构
  19. char *enpath[20]; //路径的数组
  20. int numpath;  //路径数目
  21. }*path;
  22. char *command_line;  //存放输入命令的字符串
  23. void get_command();  //解析命令函数
  24. void get_path();     //获得环境路径
  25. void common_shell(); //普通SHELL的实现
  26. void pipe_shell();   //实现管道
  27. void redirectIn_shell(); //实现输入重定向
  28. void redirectOut_shell();//实现输出重定向
  29. void back_shell(int);//实现后台
  30. main()
  31. {
  32. char *nowpath;
  33. int i;
  34. /*-----------------*/
  35. while(1){
  36. /*打印提示符*/
  37. nowpath = get_current_dir_name();
  38. printf("<ymf  %s>", nowpath);
  39. command_line = (char*)malloc(100);
  40. gets(command_line);
  41. get_command();
  42. get_path();
  43. /*普通SHELL的实现*/
  44. if(command->mark == 0)
  45. {
  46. common_shell();
  47. }
  48. /*管道的处理*/
  49. if(command->mark == 1)
  50. {
  51. pipe_shell();
  52. }
  53. /*输出重定向*/
  54. if(command->mark == 2)
  55. {
  56. redirectOut_shell();
  57. }
  58. /*输入重定向*/
  59. if(command->mark == 3)
  60. {
  61. redirectIn_shell();
  62. }
  63. /*后台*/
  64. if(command->mark == 4)
  65. {
  66. //printf("%dn", command->mark);
  67. back_shell(command->mark);
  68. }
  69. }
  70. }
  71. /*实现后台的函数*/
  72. void back_shell(int back)
  73. {
  74. int status;
  75. int i, pid;
  76. char *p;
  77. /*吃掉指中'&'*/
  78. for(i = 0;i<command->numargv;i++)
  79. {
  80. if(strstr(command->argv[i], "&")!=NULL)
  81. break;
  82. }
  83. p = (char *)malloc(100);
  84. p = strrchr(command->argv[i], '&');
  85. (*p) = '';
  86. /*处理./a.out指令
  87. *若为./a.out则无需与环境路径相接,直接处理即可
  88. */
  89. if((strstr(command->argv[0], ".out"))!=NULL){
  90. pid = fork();
  91. if(pid == 0){
  92. printf("%sn", command->argv[0]);
  93. execvp("./a.out", command->argv);
  94. }
  95. else{
  96. if(back == 0)
  97. waitpid(pid, 0, 0);
  98. else
  99. printf("%dn", pid);
  100. }
  101. return;
  102. }
  103. //指令与环境路径相接成绝对路径
  104. for(i = 0;i<path->numpath;i++)
  105. {
  106. strcat(path->enpath[i], "/");
  107. strcat(path->enpath[i], command->argv[0]);
  108. //printf("%snn", path[i]);
  109. }
  110. for(i = 0;i<path->numpath;i++)
  111. {
  112. //判断该路径是否存在
  113. if(access(path->enpath[i], F_OK)==0){
  114. //创建进程
  115. pid = fork();
  116. if(pid == 0){
  117. //printf("child programenn");
  118. execvp(path->enpath[i], command->argv);
  119. }
  120. else{
  121. //实现后台
  122. if(back == 0)
  123. waitpid(pid, 0, 0);
  124. }
  125. }
  126. }
  127. }
  128. void redirectIn_shell()
  129. {
  130. int fid;
  131. int status;
  132. int i, num1;
  133. char *nowpath;
  134. char *file;
  135. int path_i;
  136. struct command_struct *command1;
  137. command1 = (struct command_struct *)malloc(sizeof(struct command_struct));
  138. for(i = 0;i<path->numpath;i++)
  139. {
  140. strcat(path->enpath[i], "/");
  141. strcat(path->enpath[i], command->argv[0]);
  142. }
  143. for(i = 0;i<path->numpath;i++)
  144. {
  145. if(access(path->enpath[i], F_OK)==0)
  146. break;
  147. }
  148. path_i = i;
  149. if(i==path->numpath)
  150. printf("error!");
  151. nowpath = get_current_dir_name();;
  152. for(i = 0;i<command->numargv;i++)
  153. {
  154. if(strstr(command->argv[i], "<")!=NULL)
  155. break;
  156. }
  157. num1 = i;
  158. file = command->argv[num1] + 1;
  159. strcat(nowpath, "/");
  160. strcat(nowpath, file);
  161. for(i = 0;i<num1;i++)
  162. {
  163. command1->argv[i] = command->argv[i];
  164. }
  165. if(fork() == 0)
  166. {
  167. fid = open(nowpath, O_RDONLY);
  168. close(0);
  169. dup(fid);
  170. close(fid);
  171. execvp(path->enpath[path_i], command1->argv);
  172. }
  173. else
  174. {
  175. wait(&status);
  176. }
  177. }
  178. void redirectOut_shell()
  179. {
  180. int fid;
  181. int status;
  182. int i, num1;
  183. char *nowpath;
  184. char *file;
  185. int path_i;
  186. struct command_struct *command1;
  187. command1 = (struct command_struct *)malloc(sizeof(struct command_struct));
  188. for(i = 0;i<path->numpath;i++)
  189. {
  190. strcat(path->enpath[i], "/");
  191. strcat(path->enpath[i], command->argv[0]);
  192. }
  193. for(i = 0;i<path->numpath;i++)
  194. {
  195. if(access(path->enpath[i], F_OK)==0)
  196. break;
  197. }
  198. path_i = i;
  199. if(i==path->numpath)
  200. printf("error!");
  201. nowpath = get_current_dir_name();
  202. for(i = 0;i<command->numargv;i++)
  203. {
  204. if(strstr(command->argv[i], ">")!=NULL)
  205. break;
  206. }
  207. num1 = i;
  208. file = command->argv[num1] + 1;
  209. strcat(nowpath, "/");
  210. strcat(nowpath, file);
  211. for(i = 0;i<num1;i++)
  212. {
  213. command1->argv[i] = command->argv[i];
  214. }
  215. if(fork() == 0)
  216. {
  217. fid = open(nowpath, O_WRONLY|O_CREAT);
  218. close(1);
  219. dup(fid);
  220. close(fid);
  221. execvp(path->enpath[path_i], command1->argv);
  222. }
  223. else
  224. {
  225. wait(&status);
  226. }
  227. }
  228. void pipe_shell()
  229. {
  230. int i, num1, j;
  231. int status;
  232. int pid[2];
  233. int pipe_fd[2];
  234. char *p;
  235. struct command_struct *command1,*command2;
  236. struct path_struct *path1, *path2;
  237. command1 = (struct command_struct *)malloc(sizeof(struct command_struct));
  238. command2 = (struct command_struct *)malloc(sizeof(struct command_struct));
  239. path1 = (struct path_struct*)malloc(sizeof(struct path_struct));
  240. path2 = (struct path_struct*)malloc(sizeof(struct path_struct));
  241. //printf("tmdnnn");
  242. for(i = 0;i<command->numargv;i++)
  243. {
  244. if(strstr(command->argv[i], "|")!=NULL)
  245. break;
  246. }
  247. num1 = i;
  248. command->argv[num1] = command->argv[num1] + 1;
  249. /*----------command1------------*/
  250. for(i = 0;i<num1;i++)
  251. {
  252. command1->argv[i] = command->argv[i];
  253. }
  254. /*-------------command2----------*/
  255. for(j = 0, i = num1;i<command->numargv;i++, j++)
  256. {
  257. command2->argv[j] = command->argv[i];
  258. //printf("%sn", command2->argv[j]);
  259. }
  260. //printf("%dnnn", j);
  261. //command2->argv[j + 1] = NULL;
  262. for(i = 0;i<path->numpath;i++)
  263. {
  264. path1->enpath[i] = (char *)malloc(50);
  265. strcpy(path1->enpath[i],path->enpath[i]);
  266. strcat(path1->enpath[i], "/");
  267. strcat(path1->enpath[i], command1->argv[0]);
  268. //printf(":::%snnn", path1->enpath[i]);
  269. path2->enpath[i] = (char *)malloc(50);
  270. strcpy(path2->enpath[i], path->enpath[i]);
  271. strcat(path2->enpath[i], "/");
  272. strcat(path2->enpath[i], command2->argv[0]);
  273. //printf("%snnn", path2->enpath[i]);
  274. }
  275. //查找路径
  276. for(i = 0;i<path->numpath;i++)
  277. if(access(path1->enpath[i], F_OK)==0)
  278. break;
  279. for(j = 0;j<path->numpath;j++)
  280. if(access(path2->enpath[j], F_OK)==0)
  281. break;
  282. //创建管道
  283. if(pipe(pipe_fd)<0)
  284. {
  285. printf("pipe failedn");
  286. exit(0);
  287. }
  288. //创建进程
  289. if((pid[0]=fork())<0)
  290. {
  291. printf("fork failedn");
  292. exit(0);
  293. }
  294. //进程1
  295. if(pid[0]==0)
  296. {
  297. close(pipe_fd[0]);   //关闭管道输出
  298. dup2(pipe_fd[1], 1); //进程1输出接到管道输入端
  299. close(pipe_fd[1]);  //关闭管道输入
  300. execvp(path1->enpath[i], command1->argv);//执行
  301. }
  302. if(pid[0])
  303. {
  304. if((pid[1]=fork())<0)
  305. {
  306. printf("fork failesn");
  307. exit(0);
  308. }
  309. if(!pid[1])
  310. {
  311. close(pipe_fd[1]);//关闭管道输入
  312. dup2(pipe_fd[0], 0);//进程2输入端接到管道输出端
  313. close(pipe_fd[0]);//关闭管道输出
  314. execvp(path2->enpath[j], command2->argv);
  315. }
  316. close(pipe_fd[0]);
  317. close(pipe_fd[1]);
  318. waitpid(pid[1], &status, 0);
  319. }
  320. }
  321. void common_shell()
  322. {
  323. int status;
  324. int i;
  325. char *p, *nowpath;
  326. if((strstr(command->argv[0], ".out"))!=NULL){
  327. if(fork()==0){
  328. execvp("./a.out", command->argv);
  329. }
  330. else{
  331. wait(&status);
  332. }
  333. return;
  334. }
  335. //printf("%sn", path->enpath[0]);
  336. //printf("%sn", command->argv[0]);
  337. for(i = 0;i<path->numpath;i++)
  338. {
  339. strcat(path->enpath[i], "/");
  340. strcat(path->enpath[i], command->argv[0]);
  341. //printf("%snn", path[i]);
  342. }
  343. //printf("%sn", path->enpath[0]);
  344. //printf("%sn", command->argv[0]);
  345. //for(i = 0;i<path->numpath;i++)
  346. //printf("%sn", path->enpath[i]);
  347. for(i = 0;i<path->numpath;i++)
  348. {
  349. if(access(path->enpath[i], F_OK)==0)
  350. break;
  351. }
  352. //printf("%sn", path->enpath[i]);
  353. if(i == path-> numpath)
  354. printf("ERROR !!");
  355. else{
  356. if(fork() == 0){
  357. execvp(path->enpath[i], command->argv);
  358. }
  359. else{
  360. wait(&status);
  361. }
  362. }
  363. }
  364. void get_path()
  365. {
  366. int num, i;
  367. char*word;
  368. char *stay_pointer, *move_pointer;
  369. paths = (char *)getenv("PATH");
  370. //printf("%sn", paths);
  371. stay_pointer = paths;
  372. move_pointer = paths;
  373. path = (struct path_struct*)malloc(sizeof(struct path_struct));
  374. num = 0;
  375. i = 0;
  376. while((*move_pointer)!='')
  377. {
  378. stay_pointer = move_pointer;
  379. while((*move_pointer)!=':'&&(*move_pointer)!=''){
  380. num++;
  381. move_pointer ++;
  382. }
  383. word = (char*)malloc(num + 1);
  384. strncpy(word, stay_pointer, num);
  385. strcat(word, "");
  386. path->enpath[i] = word;
  387. i++;
  388. num = 0;
  389. if((*move_pointer)=='')
  390. break;
  391. move_pointer++; 
  392. if((*move_pointer)=='')
  393. break;
  394. }
  395. path->numpath = i;
  396. }
  397. void get_command()
  398. {
  399. char *word;
  400. char *move_pointer, *stay_pointer;
  401. int num, i;
  402. //printf("adfsadfann");
  403. /*----------------*/
  404. command = (struct command_struct *)malloc(sizeof(struct command_struct));
  405. /*结构体中变量赋初值*/
  406. command->mark = 0;
  407. command->numargv = 0;
  408. num = 0;
  409. i = 0;
  410. //该指针移动,读过整个指令字符串
  411. move_pointer = command_line;
  412. //指向每个以空格分隔开来的字符的头指针
  413. stay_pointer = command_line;
  414. while((*move_pointer)!=''){
  415. if((*move_pointer) == '')
  416. break;
  417. while((*move_pointer)==' ')
  418. move_pointer++;
  419. if((*move_pointer) == '')
  420. break;
  421. stay_pointer = move_pointer;
  422. //printf("%snn", stay_pointer);
  423. while(((*move_pointer)!=' ')&&((*move_pointer)!='')){
  424. /*标记赋值*/
  425. if((*move_pointer)=='|')
  426. command->mark = 1;
  427. if((*move_pointer)=='>')
  428. command->mark = 2;
  429. if((*move_pointer)=='<')
  430. command->mark = 3;
  431. if((*move_pointer)=='&')
  432. command->mark = 4;
  433. move_pointer++;
  434. num++;
  435. }
  436. //获得以空格分隔开的一个字符串
  437. word = (char*)malloc(num + 1);
  438. strncpy(word, stay_pointer, num);
  439. strcat(word, "");
  440. command->argv[i] = word;
  441. num = 0;
  442. i++;
  443. if((*move_pointer) == '')
  444. break;
  445. }
  446. command->numargv=i;
  447. }