Advertisement
Guest User

Untitled

a guest
Apr 29th, 2017
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.17 KB | None | 0 0
  1. #include <cstdlib>
  2. #include <cstring>
  3. #include <cerrno>
  4. #include <unistd.h>
  5. #include <fcntl.h>
  6. #include <string>
  7. #include <iostream>
  8. #include <sys/wait.h>
  9. #include <stdlib.h>
  10.  
  11. using namespace std;
  12.  
  13. extern char ** environ; //environmental variables
  14. char * result[100]; //used to store user input
  15. bool wasNotBuiltIn = true; //used to determine if you call execute or not
  16. int exitStatus = 0; //stores the last process's exit status
  17.  
  18. //converts the string the user inputs to an array of characters
  19. char ** convert(string s)
  20. {
  21.  
  22. char * cstr = new char [s.length()+1];
  23. strcpy (cstr, s.c_str());
  24.  
  25. // cstr now contains a c-string copy of str
  26.  
  27. int counter = 0;
  28. char * p = strtok (cstr," ");
  29. while (p!=0)
  30. {
  31. result[counter] = p;
  32. p = std::strtok(NULL," ");
  33. counter++;
  34. }
  35.  
  36. return result;
  37. }
  38.  
  39. //checks if there is at least one pipe
  40. bool checkPipes(char ** c)
  41. {
  42. int count = 0;
  43. while(result[count] != nullptr)
  44. {
  45. string pipe = "|";
  46. if((strcmp(result[count], pipe.c_str())) == 0)
  47. return true;
  48. count++;
  49. }
  50.  
  51. return false;
  52. }
  53.  
  54. //executes the user's input if it is not a builtin command
  55. void execute(char ** c)
  56. {
  57. pid_t pid;
  58. int status;
  59.  
  60. //make child process
  61. if ((pid = fork()) < 0)
  62. {
  63. printf("*** ERROR: forking child process failed\n");
  64. exit(1);
  65. }
  66. //only in child
  67. else if (pid == 0)
  68. {
  69. //executes the command or prints error
  70. if (execvp(*c, c) < 0)
  71. {
  72. printf("*** ERROR: exec failed\n");
  73. exit(1);
  74. }
  75. }
  76. //only in parent
  77. else
  78. {
  79. //waiting for child to finish
  80. while (wait(&status) != pid);
  81. }
  82.  
  83. //setting exitStatus to the exit status of last process
  84. exitStatus = status;
  85.  
  86. }
  87.  
  88. //deletes pipes
  89. void close_pipe(int pipefd [2]) {
  90. if (close(pipefd[0]) == -1) {
  91. perror("close");
  92. exit(EXIT_FAILURE);
  93. } // if
  94. if (close(pipefd[1]) == -1) {
  95. perror("close");
  96. exit(EXIT_FAILURE);
  97. } // if
  98. } // close_pipe
  99.  
  100. //execute logic if there are pipes
  101. void executePipes(char ** c)
  102. {
  103. int pipefd [2];
  104. int pid;
  105.  
  106. // create pipe
  107. if (pipe(pipefd) == -1)
  108. {
  109. perror("pipe");
  110. } // if
  111.  
  112. // create first child
  113. if ((pid = fork()) == -1) {
  114. perror("fork");
  115. } else if (pid == 0) {
  116.  
  117. if (dup2(pipefd[1], STDOUT_FILENO) == -1) {
  118. perror("dup2");
  119. } // if
  120.  
  121. close_pipe(pipefd);
  122.  
  123. char ** args = new char * [3];
  124. args[0] = strdup(c[0]);
  125. args[1] = strdup(c[1]);
  126. args[2] = nullptr;
  127.  
  128. execvp(args[0], args);
  129.  
  130. perror("execvp");
  131. for (int i = 0; i < 3; ++i) free(args[i]);
  132. delete[] args;
  133. exit(EXIT_FAILURE);
  134.  
  135. } // if
  136.  
  137. // create second child
  138. if ((pid = fork()) == -1) {
  139. perror("fork");
  140. } else if (pid == 0) {
  141.  
  142. if (dup2(pipefd[0], STDIN_FILENO) == -1) {
  143. perror("dup2");
  144. } // if
  145.  
  146. close_pipe(pipefd);
  147.  
  148. char ** args;
  149. if(c[4] == nullptr)
  150. {
  151. args = new char * [2];
  152. args[0] = strdup(c[3]);
  153. args[1] = nullptr;
  154. }
  155. else
  156. {
  157. args = new char * [3];
  158. args[0] = strdup(c[3]);
  159. args[1] = strdup(c[4]);
  160. args[2] = nullptr;
  161. }
  162.  
  163. execvp(args[0], args);
  164.  
  165. perror("execvp");
  166. for (int i = 0; i < 2; ++i) free(args[i]);
  167. delete[] args;
  168. exit(EXIT_FAILURE);
  169.  
  170. } // if
  171. close_pipe(pipefd);
  172.  
  173. // wait on last child
  174. waitpid(pid, nullptr, 0);
  175.  
  176. }
  177.  
  178. //creates the prompt, contains builtin logic, and calls the other two methods
  179. int main()
  180. {
  181. //user's input
  182. string line;
  183.  
  184. //prompt logic
  185. string homeDir = getenv("HOME");
  186. string presentDir = getenv("PWD");
  187. string toPrint;
  188. if(strcmp(homeDir.c_str(), presentDir.substr(0, homeDir.length()).c_str()) == 0)
  189. {
  190. toPrint = "~" + presentDir.substr(homeDir.length(), presentDir.length());
  191. }
  192. else
  193. {
  194. toPrint = presentDir;
  195. }
  196.  
  197. //looping prompt until user exits
  198. label:
  199. while(printf("1730sh:%s$ ", toPrint.c_str()) && getline(cin, line))
  200. {
  201. convert(line);
  202.  
  203.  
  204. //built in commands
  205.  
  206. if(result[0] == nullptr)
  207. {
  208. goto label;
  209. }
  210.  
  211. //exit
  212. string exit = "exit";
  213. if(strcmp(result[0],exit.c_str()) == 0)
  214. {
  215. //user just typed exit
  216. //return exit status of last executed process
  217. if(result[1] == nullptr)
  218. {
  219. return exitStatus;
  220. }
  221. //user typed exit and an exit status
  222. //return the exit status the user entered
  223. else
  224. {
  225. char * ep;
  226. return (int)strtol(result[1], &ep, 10);
  227. }
  228. }
  229.  
  230. //help
  231. string help = "help";
  232. string cd = "cd";
  233. if(strcmp(result[0],help.c_str()) == 0)
  234. {
  235. //user typed just help
  236. //print info about all the builtin commands
  237. if(result[1] == nullptr)
  238. {
  239. cout << "Built-In Commands" << endl;
  240. cout << "cd [PATH] - Change the current directory to PATH. The environmental variable HOME is the default PATH." << endl;
  241. cout << "exit [N] - Cause the shell to exit with a status of N. If N is omitted, the exit status is that of the last job executed." << endl;
  242. cout << "help - Display helpful information about builtin commands." << endl;
  243. }
  244. //user typed help and a specific command
  245. //give info about that command
  246. else
  247. {
  248. if(strcmp(result[1],cd.c_str()) == 0)
  249. {
  250. cout << "Built-In Command " << result[1] << endl;
  251. cout << "cd [PATH] - Change the current directory to PATH. The environmental variable HOME is the default PATH." << endl;
  252. }
  253. else if(strcmp(result[1],exit.c_str()) == 0)
  254. {
  255. cout << "Built-In Command " << result[1] << endl;
  256. cout << "exit [N] - Cause the shell to exit with a status of N. If N is omitted, the exit status is that of the last job executed." << endl;
  257. }
  258. else if(strcmp(result[1],help.c_str()) == 0)
  259. {
  260. cout << "Built-In Command " << result[1] << endl;
  261. cout << "help - Display helpful information about builtin commands." << endl;
  262. }
  263. else
  264. {
  265. cout << "That built-in command does not exist." << endl;
  266. }
  267. }
  268.  
  269. wasNotBuiltIn = false;
  270. }
  271.  
  272.  
  273. //cd
  274. if(strcmp(result[0],cd.c_str()) == 0)
  275. {
  276. //if just cd, return to home directory
  277. if(result[1] == nullptr)
  278. {
  279. chdir(getenv("HOME"));
  280. }
  281. //otherwise, change to target directory
  282. else
  283. {
  284. chdir(result[1]);
  285. }
  286.  
  287. //changing prompt logic
  288. homeDir = getenv("HOME");
  289. presentDir = get_current_dir_name();
  290. if(strcmp(homeDir.c_str(), presentDir.substr(0, homeDir.length()).c_str()) == 0)
  291. {
  292. toPrint = "~" + presentDir.substr(homeDir.length(), presentDir.length());
  293. }
  294. else
  295. {
  296. toPrint = presentDir;
  297. }
  298.  
  299. wasNotBuiltIn = false;
  300. }
  301.  
  302. //if it wasn't a built in command, execute
  303. if(checkPipes(result))
  304. {
  305. executePipes(result);
  306. }
  307. else if(wasNotBuiltIn)
  308. {
  309. execute(result);
  310. }
  311. wasNotBuiltIn = true;
  312.  
  313.  
  314. //resetting the char array
  315. for(int i = 0; i < 100; i++)
  316. {
  317. result[i] = nullptr;
  318. }
  319. }
  320.  
  321. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement