parsecmd.l
上传用户:htgj9999
上传日期:2021-10-02
资源大小:4k
文件大小:9k
源码类别:

Shell编程

开发平台:

C/C++

  1. %{
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <sys/types.h>
  5. #include <sys/wait.h>
  6. #include <sys/stat.h>
  7. #include <unistd.h>
  8. #include <errno.h>
  9. #include <fcntl.h>
  10. extern char buf[];
  11. extern char* myptr;
  12. extern char* mylim;
  13. extern void display_history_list();
  14. extern void history_finish();
  15. static int my_yyinput(char* buf, int max);
  16. static int file_exist(const char* file, char* buffer);
  17. static void free_resource();
  18. static int do_exit(int, char**);
  19. static int do_export(int, char**);
  20. static int do_echo(int, char**);
  21. static int do_cd(int, char**);
  22. static int do_history(int, char**);
  23. static void add_arg(const char* xarg);
  24. static void add_simple_arg(const char* xarg);
  25. static void reset_args();
  26. static void do_list_cmd();
  27. static int do_pipe_cmd(int argc, char** argv);
  28. static int do_simple_cmd(int argc, char** argv, int prefd[], int postfd[]);
  29. #undef  YY_INPUT
  30. #define YY_INPUT(b, r, ms) (r = my_yyinput(b, ms))
  31. char* argbuf[200];
  32. int argcnt = 0;
  33. typedef int (*buildin_cmd_handle)(int, char**);
  34. typedef struct
  35. {
  36. const char* cmd;
  37. buildin_cmd_handle handle;
  38. } CMD_ENTRY;
  39. const CMD_ENTRY buildin_cmd_table[] = 
  40. {
  41. {"exit",  do_exit},
  42. {"cd",  do_cd},
  43. {"echo",  do_echo},
  44. {"export",  do_export},
  45. {"history", do_history},
  46. {0, 0}
  47. };
  48. %}
  49. %x QUOTE
  50. %x SINGQUOTE
  51. blank [ t]
  52. %%
  53. """ {BEGIN QUOTE;}
  54. <QUOTE>[^n"]+ {add_arg(yytext);}
  55. <QUOTE>""" {BEGIN 0;}
  56. <QUOTE>n {BEGIN 0; do_list_cmd(); reset_args();}
  57. ";" {add_simple_arg(yytext);}
  58. ">" {add_simple_arg(yytext);}
  59. "<" {add_simple_arg(yytext);}
  60. "|" {add_simple_arg(yytext);}
  61. [^ tn|<>;"]+ {add_arg(yytext);}
  62. n {do_list_cmd(); reset_args();}
  63. . ;
  64. %%
  65. static buildin_cmd_handle get_cmd_handle(const char* cmd)
  66. {
  67. int i = 0;
  68. while(buildin_cmd_table[i].cmd) {
  69. if(strcmp(buildin_cmd_table[i].cmd, cmd) == 0)
  70. return buildin_cmd_table[i].handle;
  71. i++;
  72. }
  73. return 0;
  74. }
  75. static void free_resource()
  76. {
  77. reset_args();
  78. }
  79. static int do_exit(int argc, char** argv)
  80. {
  81. int val = 0;
  82. if(argc > 1)
  83. val = atoi(argv[1]);
  84. free_resource();
  85. history_finish();
  86. exit(val);
  87. return 0;
  88. }
  89. static int do_cd(int argc, char** argv)
  90. {
  91. char* dir;
  92. char cwd[100];
  93. extern char lastdir[];
  94. if(argc == 1) {
  95. if(!(dir = getenv("HOME"))) {
  96. printf("cd: %sn", strerror(errno));
  97. return -1;
  98. }
  99. } else if(argc == 2) {
  100. if(strcmp(argv[1], "-") == 0) {
  101. dir = lastdir;
  102. } else if(strcmp(argv[1], "~") == 0) {
  103. if(!(dir = getenv("HOME"))) {
  104. printf("cd: %sn", strerror(errno));
  105. return -1;
  106. }
  107. } else
  108. dir = argv[1];
  109. } else {
  110. printf("Usage: cd [dir]n");
  111. return -1;
  112. }
  113. getcwd(cwd, 99); 
  114. if(chdir(dir) == -1) {
  115. printf("cd: %sn", strerror(errno));
  116. return -1;
  117. }
  118. strcpy(lastdir, cwd);
  119. return 0;
  120. }
  121. static int do_export(int argc, char** argv)
  122. {
  123. int i = 1;
  124. char* p;
  125. while(argv[i]) {
  126. if((p = strchr(argv[i], '='))) {
  127. *p = 0;
  128. if(strpbrk(argv[i], "~`!@#$%^&*()-_+=|\{}[];:'"<>,.?/")) {
  129. *p = '=';
  130. printf("export: %s: not a valid indentifiern", argv[i]);
  131. i++;
  132. continue;
  133. if(setenv(argv[i], p+1, 1) == -1) 
  134. printf("export: %sn", strerror(errno));
  135. *p = '=';
  136. }
  137. i++;
  138. }
  139. return 0;
  140. }
  141. static int do_echo(int argc, char** argv)
  142. {
  143. int i = 1;
  144. int j;
  145. int argn = 0;
  146. int arge = 0;
  147. if(argv[1]) {
  148. if(strcmp(argv[1], "-n") == 0) {
  149. argn = 1;
  150. i = 2;
  151. } else if(strcmp(argv[1], "-e") == 0) {
  152. arge = 1;
  153. i = 2;
  154. } else if((strcmp(argv[1], "-ne") == 0) || (strcmp(argv[1], "-en") == 0)) {
  155. argn = arge = 1;
  156. i = 2;
  157. }
  158. }
  159. j = i;
  160. while(argv[i]) {
  161. if(i > j)
  162. printf(" %s", argv[i]);
  163. else 
  164. printf("%s", argv[i]);
  165. i++;
  166. }
  167. if(argn == 0)
  168. printf("n");
  169. return 0;
  170. }
  171. int do_history(int argc, char** argv)
  172. {
  173. display_history_list();
  174. return 0;
  175. }
  176. static void add_simple_arg(const char* arg)
  177. {
  178. argbuf[argcnt] = (char*)malloc(strlen(arg)+1);
  179. strcpy(argbuf[argcnt], arg);
  180. argcnt++;
  181. argbuf[argcnt] = 0;
  182. }
  183. // $HOME
  184. // $$
  185. // $HOME$
  186. // $HOME$HOME
  187. static void add_arg(const char* xarg)
  188. {
  189. char* arg;
  190. char buf[200];
  191. char xbuf[200];
  192. int i,j,k;
  193. int len = strlen(xarg);
  194. k = 0;
  195. for(i = 0; i < len; i++) {
  196. if(xarg[i] == '$') {
  197. if(xarg[i+1] == '$') {//$$,get pid
  198. int pid = getpid();
  199. sprintf(buf+k, "%d", pid);
  200. k = strlen(buf);
  201. i++;
  202. } else if(xarg[i+1] == 0){//$ and end
  203. buf[k] = '$';
  204. k++;
  205. break;
  206. } else {//$HOME or $HOME$OTHER
  207. for(j = i+1; j < len; j++) {
  208. if(xarg[j] == '$') 
  209. break;
  210. xbuf[j-i-1] = xarg[j];
  211. }
  212. xbuf[j-i-1] = 0;
  213. i = j-1;
  214. if((arg = getenv(xbuf))) {
  215. strcpy(buf+k, arg);
  216. k += strlen(arg);
  217. }
  218. }
  219. } else {
  220. buf[k] = xarg[i];
  221. k++; 
  222. }
  223. }
  224. buf[k] = 0;
  225. if(k > 0)
  226. add_simple_arg(buf);
  227. }
  228. static int file_exist(const char* file, char* buffer)
  229. {
  230. int i = 0;
  231. const char* p;
  232. const char* path;
  233. path = getenv("PATH");
  234. p = path;
  235. while(*p != 0) {
  236. if(*p != ':')
  237. buffer[i++] = *p;
  238. else {
  239. buffer[i++] = '/';
  240. buffer[i] = 0;
  241. strcat(buffer, file);
  242. if(access(buffer, F_OK) == 0)
  243. return 1;
  244. i = 0;
  245. }
  246. p++;
  247. }
  248. return 0;
  249. }
  250. static void do_list_cmd()
  251. {
  252. int i = 0;
  253. int j = 0;
  254. char* p;
  255. while(argbuf[i]) {
  256. if(strcmp(argbuf[i], ";") == 0) {//  ;
  257. p = argbuf[i];
  258. argbuf[i] = 0;
  259. do_pipe_cmd(i-j, argbuf+j);
  260. argbuf[i] = p;
  261. j = ++i;
  262. } else
  263. i++;
  264. }
  265. do_pipe_cmd(i-j, argbuf+j);
  266. }
  267. static int do_pipe_cmd(int argc, char** argv)
  268. {
  269. int i = 0;
  270. int j = 0;
  271. int prepipe = 0;
  272. int prefd[2];
  273. int postfd[2];
  274. char* p;
  275. while(argv[i]) {
  276. if(strcmp(argv[i], "|") == 0) { // pipe
  277. p = argv[i];
  278. argv[i] = 0;
  279. pipe(postfd);  //create the post pipe
  280. //be sure not close pipe in, otherwise whenever father write to this pipe,
  281. //cause a Broken pipe.
  282. //close(postfd[0]); //father close pipe in
  283. if(prepipe)
  284. do_simple_cmd(i-j, argv+j, prefd, postfd);
  285. else
  286. do_simple_cmd(i-j, argv+j, 0, postfd);
  287. argv[i] = p;
  288. prepipe = 1;
  289. prefd[0] = postfd[0];
  290. prefd[1] = postfd[1];
  291. j = ++i;
  292. } else
  293. i++;
  294. }
  295. if(prepipe)
  296. do_simple_cmd(i-j, argv+j, prefd, 0);
  297. else 
  298. do_simple_cmd(i-j, argv+j, 0, 0);
  299. return 0;
  300. }
  301. static int predo_for_redirect(int argc, char** argv, int* re)
  302. {
  303. int i;
  304. int redirect = 0;
  305. for(i = 1; i < argc; i++) {
  306. if(strcmp(argv[i], "<") == 0) {
  307. redirect = 1;
  308. argv[i] = 0;
  309. break;
  310. } else if(strcmp(argv[i], ">") == 0) {
  311. redirect = 2;
  312. argv[i] = 0;
  313. break;
  314. }
  315. }
  316. if(redirect) {// need redirect stdin or stdout
  317. if(argv[i+1]) {
  318. int fd;
  319. if(redirect == 2) {
  320. if((fd = open(argv[i+1], O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR)) == -1) {
  321. fprintf(stderr, "Open out %s failedn", argv[i+1]);
  322. return 1;
  323. }
  324. dup2(fd, STDOUT_FILENO);
  325. } else {//redirect == 1
  326. if((fd = open(argv[i+1], O_RDONLY, S_IRUSR|S_IWUSR)) == -1) {
  327. fprintf(stderr, "Open in %s failedn", argv[i+1]);
  328. return 1;
  329. }
  330. dup2(fd, STDIN_FILENO);
  331. }
  332. } else {
  333. fprintf(stderr, "Bad redirect, need more argn");
  334. return 1;
  335. }
  336. }
  337. if(re)
  338. *re = redirect;
  339. return 0;
  340. }
  341. static int do_simple_cmd(int argc, char** argv, int prefd[], int postfd[])
  342. {
  343. int pid;
  344. int status;
  345. buildin_cmd_handle hd;
  346. if(argc == 0)
  347. return 0;
  348. if(prefd == 0 && postfd == 0) {
  349. // a very simple buitin command, not have pre and post pipe, father should do the
  350. // builtin command itself.
  351. if((hd = get_cmd_handle(argv[0]))) {
  352. if(predo_for_redirect(argc, argv, 0))
  353. return 1;
  354. (*hd)(argc, argv);
  355. return 0;
  356. }
  357. }
  358. if((pid = fork()) == 0) {//child
  359. // reset the signal INT handle to default
  360. int redirect = 0;
  361. signal(SIGINT, SIG_DFL);
  362. if(predo_for_redirect(argc, argv, &redirect))
  363. exit(1);
  364. if(redirect != 1 && prefd) {//has a pre pipe, redirect stdin
  365. close(prefd[1]);
  366. if(prefd[0] != STDIN_FILENO) {
  367. // fprintf(stderr, "redirect stdinn");
  368. dup2(prefd[0], STDIN_FILENO);
  369. close(prefd[0]);
  370. }
  371. }
  372. if(redirect != 2 && postfd) {//has a post pipe, redirect stdout
  373. close(postfd[0]);
  374. if(postfd[1] != STDOUT_FILENO) {
  375. // fprintf(stderr, "redirect stdoutn");
  376. dup2(postfd[1], STDOUT_FILENO);
  377. close(postfd[1]);
  378. }
  379. }
  380. if((hd = get_cmd_handle(argv[0]))) {
  381. (*hd)(argc, argv);
  382. exit(0);
  383. }
  384. char buffer[100];
  385. if(file_exist(argv[0], buffer)) {
  386. // fprintf(stderr, "exec command %sn", buffer);
  387. execv(buffer, argv);
  388. }
  389. else {
  390. fprintf(stderr, "-msh: %s: command not foundn", argv[0]);
  391. exit(0);
  392. }
  393. }
  394. waitpid(pid, &status, 0);
  395. if(postfd) { // no
  396. close(postfd[1]); // must close this fd here.
  397. }
  398. return 0;
  399. }
  400. static void reset_args()
  401. {
  402. int i;
  403. for(i = 0; i < argcnt; i++) {
  404. free(argbuf[i]);
  405. argbuf[i] = 0;
  406. }
  407. argcnt = 0;
  408. }
  409. static int my_yyinput(char* buf, int max)
  410. {
  411. int n;
  412. n = (max < (mylim-myptr)) ? max : (mylim-myptr);
  413. if(n > 0) {
  414. memcpy(buf, myptr, n);
  415. myptr += n;
  416. }
  417. return n;
  418. }