Advertisement
Guest User

Untitled

a guest
Sep 18th, 2019
147
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.07 KB | None | 0 0
  1. #include <cstdlib>
  2. #include <iostream>
  3. #include <string>
  4. #include <vector>
  5. #include <sstream>
  6. #include <cstring>
  7. #include <unistd.h>
  8. #include <sys/wait.h>
  9. #include <sys/types.h>
  10. #include <fcntl.h>
  11. #include <stdio.h>
  12. using namespace std;
  13.  
  14. class Cmd
  15. {
  16. public:
  17. vector<string> args;
  18. string input_rd_str;
  19. string output_rd_str;
  20. int input_rd;
  21. int output_rd;
  22. int input_fd;
  23. int output_fd;
  24. };
  25. void parse_and_run_command(const string &command) {
  26. /* TODO: Implement this. */
  27. /* Note that this is not the correct way to test for the exit command.
  28. For example the command " exit " should also exit your shell.
  29. */
  30.  
  31. /* check for input length */
  32. if(command.length() > 100){
  33. cerr << "Input statement too long." << endl;
  34. return;
  35. }
  36. vector<string> tokens;
  37. string token;
  38. istringstream s(command);
  39.  
  40. int num_commands = 1;
  41. while(s >> token){
  42. if(token == "|"){
  43. num_commands++;
  44. }
  45. tokens.push_back(token);
  46. }
  47. if(tokens[0] == "exit"){
  48. exit(0);
  49. }
  50. //string first_command = "";
  51. //vector <char *> argv;
  52. //int k = 0;
  53. /*if(tokens[0] != ">" && tokens[0] != "<"){
  54. //first_command = tokens[0];
  55. argv.push_back(&tokens[0][0]);
  56. k = 1;
  57. }
  58. else{
  59. //first_command = tokens[2];
  60. argv.push_back(&tokens[2][0]);
  61. * redirection code
  62. k = 3;
  63. }
  64. */
  65. vector<Cmd*> cmds;
  66. for(int a=0; a < num_commands; a++){
  67. cmds.push_back(new Cmd());
  68. }
  69. string input_redirection = "<DEF>";
  70. string output_redirection = "<DEF>";
  71. int num_input_rd = 0;
  72. int num_output_rd = 0;
  73.  
  74. bool invalid = false;
  75. int cur_cmd = 0;
  76.  
  77. vector<char *> all_args;
  78. for(size_t i=0; i < tokens.size(); i++){
  79. if(tokens[i] == "<"){
  80. /* do this */
  81. if(i == tokens.size()-1 || num_input_rd == 1){
  82. invalid = true;
  83. break;
  84. }
  85. else{
  86. string tkn = tokens[i+1];
  87. if(tkn == "<" || tkn == ">" || tkn == "|"){
  88. invalid = true;
  89. break;
  90. }
  91.  
  92. input_redirection = tkn;
  93. num_input_rd++;
  94. i++;
  95. }
  96. }
  97. /* Check for output redirection */
  98. else if(tokens[i] == ">"){
  99. /* do this */
  100. if(i == tokens.size()-1 || num_output_rd == 1){
  101. invalid = true;
  102. break;
  103. }
  104. else{
  105. string tkn = tokens[i+1];
  106. if(tkn == "<" || tkn == ">" || tkn == "|"){
  107. invalid = true;
  108. break;
  109. }
  110. output_redirection = tkn;
  111. num_output_rd++;
  112. i++;
  113. }
  114. }
  115. else if(tokens[i] == "|"){
  116. if(i == tokens.size()-1){
  117. invalid = true;
  118. break;
  119. }
  120. if(cmds[cur_cmd]->args.size() == 0){
  121. invalid = true;
  122. break;
  123. }
  124. Cmd* cmd1 = cmds[cur_cmd];
  125.  
  126. if(num_input_rd){
  127. cmd1->input_rd_str = input_redirection;
  128. }
  129. if(num_output_rd){
  130. cmd1->output_rd_str = output_redirection;
  131. }
  132. cmd1->input_rd = num_input_rd;
  133. cmd1->output_rd = num_output_rd;
  134.  
  135. num_input_rd = 0;
  136. num_output_rd = 0;
  137.  
  138. input_redirection = "<DEF>";
  139. output_redirection = "<DEF>";
  140.  
  141. //if(cmds[cur_cmd]->args.size() == 0)
  142. cur_cmd++;
  143. }
  144. else{
  145. //argv.push_back(&tokens[i][0]);
  146. Cmd* cmd1 = cmds[cur_cmd];
  147. //cmd1->args.push_back(&tokens[i][0]);
  148. cmd1->args.push_back(tokens[i]);
  149. //cout << "PUSHED" << cmd1->args[cmd1->args.size()-1] << endl;
  150. all_args.push_back(&tokens[i][0]);
  151. }
  152. }
  153. Cmd* cmd_last = cmds[cur_cmd];
  154. if(num_input_rd){
  155. cmd_last->input_rd_str = input_redirection;
  156. }
  157. if(num_output_rd){
  158. cmd_last->output_rd_str = output_redirection;
  159. }
  160. cmd_last->input_rd = num_input_rd;
  161. cmd_last->output_rd = num_output_rd;
  162. if(cmd_last->args.size() == 0){
  163. invalid = true;
  164.  
  165. }
  166.  
  167. if(invalid){
  168. cerr << "Invalid command." << endl;
  169. return;
  170. }
  171.  
  172. //cout << first_command << endl;
  173. //cout << arguments << endl;
  174.  
  175. vector<int> pids;
  176.  
  177. //int current_cmd = 0;
  178. //int pipefd[2] = {-1, -1};
  179. //int last_read = -1;
  180. //int output = -1;
  181. int last_read = -1;
  182. for(int i=0; i < num_commands; i++){
  183. int pipefd[2] = {-1, -1};
  184. //int last_read = -1;
  185. int input = -1;
  186. int output = -1;
  187.  
  188. //int output = -1;
  189. //int pipefd[2];
  190. Cmd* cmd2 = cmds[i];
  191. /*if(cmd2->args[0] == "exit"){
  192. exit(0);
  193. }*/
  194. //int pipefd[2];i
  195. //if(pipe(pipefd) == -1){
  196. // cerr << "Out of file descriptors" << endl;
  197. //}
  198. if(i != 0){
  199. if(last_read < 0){
  200. cout << "ERROR" << endl;
  201. break;
  202. }
  203. else{
  204. input = last_read;
  205. last_read = -1;
  206. }
  207. }
  208. if(i < num_commands-1){
  209. if(pipe(pipefd) == -1){
  210. cerr << "Out of file descriptors" << endl;
  211. }
  212. //last_read = pipefd[0];
  213. //output = pipefd[1];
  214. output = pipefd[1];
  215. last_read = pipefd[0];
  216. //cout << "Create pipes i = " << i << " " << pipefd[0] << pipefd[1] << endl;
  217. }
  218. int pid = fork();
  219. if(pid < 0){
  220. cerr << strerror(errno) << endl;
  221. break;
  222. }
  223. if(pid == 0){
  224. if(last_read != -1){
  225. close(last_read);
  226. }
  227. //cout << "i" << i << endl;
  228. //cout << "ncmds" << num_commands << endl;
  229. //cout << "Close pipes child i = " << i << " " << pipefd[0] << endl;
  230. //close(pipefd[0]);
  231. if(i < num_commands-1){
  232. //cout << "Close pipes child i = " << i << " " << pipefd[1] << endl;
  233. dup2(pipefd[1], 1);
  234. close(pipefd[1]);
  235. }
  236. if(i != 0){
  237. //cout << "Close pipes child i = " << i << " " << last_read << endl;
  238. dup2(last_read, 0);
  239. close(last_read);
  240. }
  241.  
  242. if(input >= 0){
  243. dup2(input, 0);
  244. close(input);
  245. }
  246. if(output >= 0){
  247. dup2(output, 1);
  248. close(output);
  249. }
  250. //cout << "Close pipes child i = " << i << " " << pipefd[1] << endl;
  251. //close(pipefd[1]);
  252. //cmd2->input_fd = 0;
  253. //cmd2->output_fd = 1;
  254. vector<string> args = cmd2->args;
  255. if(cmd2->input_rd == 1){
  256. int newfd = open(&cmd2->input_rd_str[0], O_RDONLY);
  257. dup2(newfd, 0);
  258. close(newfd);
  259. }
  260. if(cmd2->output_rd == 1){
  261. int newfd = open(&cmd2->output_rd_str[0], O_WRONLY | O_TRUNC | O_CREAT, 0777);
  262. dup2(newfd, 1);
  263. close(newfd);
  264. }
  265. //cout << cmd2->args[0] << endl;
  266. //cout << "output_rd: " << cmd2->output_rd << endl;
  267. //cout << "output_rd_str: " << cmd2->output_rd_str << endl;
  268. //cout << "input_rd: " << cmd2->input_rd << endl;
  269. //cout << "input_rd_str: " << cmd2->input_rd_str << endl;
  270. //cout << "CHECK" << endl;
  271. vector<char *> argv;
  272. for(size_t k = 0; k < args.size(); k++){
  273. //cout << args[k] << endl;
  274. string arg = args[k];
  275. char* copy_arg = new char[arg.size()+1];
  276. strcpy(copy_arg, arg.c_str());
  277. argv.push_back(copy_arg);
  278. //argv.push_back(&args[k][0]);
  279. }
  280. argv.push_back(NULL);
  281. execv(argv[0], &argv[0]);
  282. cerr << strerror(errno) << endl;
  283. cout << "Exec failed. Exiting..." << endl;
  284. exit(0);
  285. }
  286. else{
  287. //dup2(cmd2
  288. //cout << "Close pipes parent i = " << i << " " << pipefd[1] << endl;
  289. //cout << "Close pipes parent i = " << i << " " << last_read << endl;
  290. if(input >= 0){
  291. close(input);
  292. }
  293. if(output >=0){
  294. close(output);
  295. }
  296. //close(pipefd[1]);
  297. //cout << last_read << endl;
  298. //close(last_read);
  299. //last_read = pipefd[0];
  300.  
  301. //int status;
  302. //waitpid(pid, &status, 0);
  303. //if(WIFSIGNALED(status)){
  304. // cout << cmds[i]->args[0] << " ended due to a signal." << endl;
  305. //}
  306. //else{
  307. // cout << cmds[i]->args[0] << " exit status: " << WEXITSTATUS(status) << endl;
  308. //}
  309. pids.push_back(pid);
  310. }
  311. }
  312. for(size_t j = 0; j < pids.size(); j++){
  313. int status;
  314. waitpid(pids[j], &status, 0);
  315. //if(WIFSIGNALED(status)){
  316. // cout << cmds[j]->args[0] << " ended due to a signal." << endl;
  317. //}
  318. //else{
  319. cout << cmds[j]->args[0] << " exit status: " << WEXITSTATUS(status) << endl;
  320. //}
  321.  
  322. //delete cmds[j];
  323. }
  324.  
  325. for(int b = 0; b < num_commands; b++){
  326. delete cmds[b];
  327. }
  328. }
  329.  
  330. int main(void) {
  331. string command;
  332. cout << "> ";
  333. while (getline(cin, command)) {
  334. parse_and_run_command(command);
  335. std::cout << "> ";
  336. }
  337. return 0;
  338. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement