Advertisement
Guest User

Untitled

a guest
May 22nd, 2019
100
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.22 KB | None | 0 0
  1. #include <sys/wait.h>
  2. #include <sys/stat.h>
  3. #include <unistd.h>
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <fcntl.h>
  8. #include <signal.h>
  9.  
  10. #define LSH_TOK_BUFSIZE 64
  11. #define LSH_TOK_DELIM " \t\r\n\a"
  12. #define MAX_COMMAND_HISTORY 20
  13.  
  14. int lsh_cd(char **args);
  15. int lsh_help(char **args);
  16. int lsh_exit(char **args);
  17.  
  18. char *builtin_str[] = {
  19. "cd",
  20. "help",
  21. "exit" };
  22.  
  23. int(*builtin_func[])(char **) = {
  24. &lsh_cd,
  25. &lsh_help,
  26. &lsh_exit,
  27. };
  28.  
  29. int lsh_num_builtins() /*Funkcja zwraca ilość wbudowanych poleceń.*/
  30. {
  31. return sizeof(builtin_str) / sizeof(char *);
  32. }
  33.  
  34. char *lsh_get_history_dir(void) /*Zwraca ścieżkę do pliku z historią poleceń*/
  35. {
  36. char filepath[] = "bash_history.txt";
  37. char *homedir = getenv("HOME");
  38. char *path = malloc((strlen(filepath) + strlen(homedir) + 1) * sizeof(char));
  39. strcpy(path, homedir);
  40. strcat(path, "/");
  41. strcat(path, filepath);
  42. return path;
  43. }
  44.  
  45. int lsh_cd(char **args) /*Obsługa polecenia cd.*/
  46. {
  47. if (args[1] == NULL)
  48. fprintf(stderr, "lsh: expected argument to \"cd\"\n");
  49. else if (chdir(args[1]) != 0)
  50. perror("lsh");
  51. return 1;
  52. }
  53.  
  54. int lsh_help(char **args) /*Obsługa polecenia help.*/
  55. {
  56. puts("Dostepne komendy: \n");
  57. for (int i = 0; i < lsh_num_builtins(); i++)
  58. printf(" %s\n", builtin_str[i]);
  59. printf(" history\n");
  60. puts("Program przygotowany na zajecia z Systemow Operacyjnych przez:");
  61. puts("Emilie Jutkiewicz\nDawida Rydzewskiego\nRadoslawa Skiepko");
  62. return 1;
  63. }
  64.  
  65. void lsh_history(int sig) /*Obsługa polecenia history.*/
  66. {
  67. if (sig == SIGUSR1) //Funkcję wywołuje sygnał SIGUSR1, funkcja jest 'handlerem' tego sygnału.
  68. {
  69. puts("");
  70. int f = open(lsh_get_history_dir(), O_RDONLY);
  71. if (f != -1)
  72. {
  73. char buf[100];
  74. while (read(f, buf, 100))
  75. write(1, buf, strlen(buf));
  76. puts("");
  77. close(f);
  78. }
  79. }
  80. }
  81.  
  82. int lsh_exit(char **args) /*Obsługa polecenia exit.*/
  83. {
  84. return 0;
  85. }
  86.  
  87. int lsh_launch(char **args, int flag) /*Funkcja uruchamiająca polecenia.*/
  88. {
  89. pid_t pid, wpid;
  90. int status, background_flag = 0, position = 0, position2 = 0;
  91. pid = fork();
  92. while (args[position] != NULL)
  93. position++;
  94. /* Pętla sprawdza czy wystąpiło żadąnie działania w tle.*/
  95. while (args[position - 1][position2] != '\0')
  96. position2++;
  97. if (args[position - 1][position2 - 1] == '&')
  98. {
  99. background_flag = 1; /*Jeśli wytąpiło zmienia flagę działania w tle.*/
  100. args[position - 1][position2 - 1] = '\0';
  101. }
  102. if (pid == 0)
  103. {
  104. if (flag != -1) /*Jeśli w poleceniu wystąpiło przekierowanie ">>", zmienna*/
  105. { /*flag przyjmuje wartość w którym nastąpiło.*/
  106. int fd1;
  107. if ((fd1 = open(args[flag + 1], O_WRONLY | O_CREAT | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1)
  108. {
  109. perror(args[flag + 1]);
  110. exit(EXIT_FAILURE);
  111. }
  112. dup2(fd1, 1); /*Zmiana standardowego wyjścia na przekazane po znakach ">>".*/
  113. close(fd1);
  114. args[flag] = args[flag + 1] = NULL; /*Usunięcie z tablicy poleceń przekierowania.*/
  115. }
  116. if (execvp(args[0], args) == -1) /*Uruchamianie poleceń, w przypadku błędu wyświetla error.*/
  117. perror("lsh");
  118. exit(EXIT_FAILURE);
  119. }
  120. else if (pid < 0)
  121. perror("lsh");
  122. else if (background_flag == 0) /*Gdy wystąpiło żądanie działania w tle program nie wchodzi*/
  123. do /*w pętle i nie czeka na zakończenie uruchomionego procesu.*/
  124. {
  125. wpid = waitpid(pid, &status, WUNTRACED);
  126. } while (!WIFEXITED(status) && !WIFSIGNALED(status));
  127. return 1;
  128. }
  129.  
  130. int lsh_loop_pipe(char ***cmd) /*Pętla wykonująca nielimitowane potoki*/
  131. {
  132. int p[2];
  133. pid_t pid, wpid;
  134. int status;
  135. int fd_in = 0;
  136. while (*cmd != NULL)
  137. {
  138. pipe(p);
  139. pid = fork();
  140. if (pid == 0)
  141. {
  142. dup2(fd_in, 0); /*Zmiana wejścia zgodnie z starszym*/
  143. if (*(cmd + 1) != NULL)
  144. dup2(p[1], 1);
  145. close(p[0]);
  146. execvp((*cmd)[0], *cmd); /*Wykonanie polecenia*/
  147. exit(EXIT_FAILURE);
  148. }
  149. else if (pid < 0)
  150. {
  151. perror("lsh");
  152. }
  153. else
  154. {
  155. do
  156. {
  157. wpid = waitpid(pid, &status, WUNTRACED);
  158. } while (!WIFEXITED(status) && !WIFSIGNALED(status));
  159.  
  160. close(p[1]);
  161. fd_in = p[0]; /*Zapisanie wejścia dla następnej komendy*/
  162. cmd++;
  163. }
  164. }
  165. }
  166.  
  167. int lsh_execute(char **args) /*Funkcja sprawdza czy wystąpiły predefiniowane polecenia,*/
  168. { /*przekierowania lub potoki.*/
  169. int second_position, history_flag, output_flag;
  170. char tmp_history[] = "history";
  171. for (int first_position = 0; args[first_position] != NULL; first_position++)
  172. { /*Pętla przechodząca po wszystkich argumentach.*/
  173. history_flag = 1;
  174. output_flag = 0;
  175. for (second_position = 0; second_position < 7; second_position++)
  176. if (args[first_position][second_position] != tmp_history[second_position])
  177. { /*Sprawdza czy wystąpiło polecenie history.*/
  178. history_flag = 0;
  179. break;
  180. }
  181. if (history_flag == 1)
  182. {
  183. if (signal(SIGUSR1, lsh_history) == SIG_ERR) /*Definiowanie obsługi sygnału.*/
  184. printf("Nie udalo sie obsluzyc sygnalu");
  185. raise(SIGUSR1); /*Wywołanie wyświetlenia historii poleceń.*/
  186. if (args[first_position + 1] == NULL)
  187. args[first_position] = NULL;
  188. else
  189. for (int i = first_position; args[i + 1] != NULL; i++)
  190. {
  191. args[i] = args[i + 1];
  192. args[i + 1] = NULL;
  193. }
  194. continue;
  195. }
  196. for (int i = 0; i < lsh_num_builtins(); i++)
  197. if (strcmp(args[0], builtin_str[i]) == 0)
  198. return (*builtin_func[i])(args);
  199. if (args[first_position][0] == '>' && args[first_position][1] == '>')
  200. return lsh_launch(args, first_position); /*Wykryte przekierowanie.*/
  201. else if (args[first_position][0] == '|')
  202. { /*Wykryte potoki.*/
  203. char ***cmd;
  204. int counter, potoki_count = 0, cmd_position1 = 0, count_arguments = 0;
  205. for (counter = 0; args[counter] != NULL; counter++)
  206. if (args[counter][0] == '|')
  207. potoki_count++;
  208. cmd = (char ***)malloc((potoki_count + 1) * sizeof(char **));
  209. for (counter = 0; args[counter] != NULL; counter++)
  210. { /*Przygotowanie poleceń do przekazania.*/
  211. if (args[counter][0] == '|')
  212. {
  213. cmd[cmd_position1] = (char **)malloc((count_arguments + 1) * sizeof(char *));
  214. for (int i = 0; i < count_arguments; i++)
  215. cmd[cmd_position1][i] = args[counter - count_arguments + i];
  216. cmd[cmd_position1][count_arguments] = NULL;
  217. cmd_position1++;
  218. count_arguments = 0;
  219. }
  220. else if (args[counter + 1] == NULL)
  221. {
  222. cmd[cmd_position1] = (char **)malloc((count_arguments + 2) * sizeof(char *));
  223. for (int i = 0; i <= count_arguments + 1; i++)
  224. cmd[cmd_position1][i] = args[counter - count_arguments + i];
  225. cmd[cmd_position1][count_arguments + 1] = NULL;
  226. cmd_position1++;
  227.  
  228. count_arguments = 0;
  229. }
  230. else
  231. count_arguments++;
  232. }
  233. cmd[cmd_position1] = NULL;
  234. lsh_loop_pipe(cmd);
  235. for (int i = 1; i < cmd_position1; i++)
  236. free(cmd[i]);
  237. free(cmd);
  238. return 1;
  239. }
  240. }
  241. if (args[0] != NULL)
  242. return lsh_launch(args, -1);
  243. else
  244. return 1;
  245. }
  246.  
  247. void lsh_save_line(char *line) /*Funkcja zapisująca podane polecenie do pliku historii.*/
  248. {
  249. char *path = lsh_get_history_dir();
  250. FILE *fp;
  251. char commands[20][254];
  252. int i = 0;
  253. size_t len = 0;
  254. ssize_t read;
  255. if ((fp = fopen(path, "r")) != NULL)
  256. {
  257. while (fgets(commands[i], sizeof(commands[i]), fp)) /*zczytujemy zawartość do tablicy.*/
  258. i++;
  259. fclose(fp);
  260. }
  261. else
  262. puts("Nie udalo sie otworzyc pliku.\nPowstanie nowy plik historii.");
  263.  
  264. if (i < MAX_COMMAND_HISTORY - 1) /*Jeśli ilość poleceń nie przekracza*/
  265. { /*20 dodajemy na koniec pliku.*/
  266. if ((fp = fopen(path, "a")) != NULL)
  267. {
  268. fputs(line, fp);
  269. fclose(fp);
  270. }
  271. }
  272. else
  273. {
  274. if ((fp = fopen(path, "w")) != NULL) /*W przeciwnym wypadku pomijamy najstarszą*/
  275. { /*komendę i dodajemy na koneic nowa.*/
  276. for (int j = 1; j < i; j++)
  277. fputs(commands[j], fp);
  278. fputs(line, fp);
  279. fclose(fp);
  280. }
  281. }
  282. }
  283.  
  284. char *lsh_read_line(void) /*Zczytuje wpisane polecenie do tablicy charów.*/
  285. {
  286. char *line = NULL;
  287. ssize_t bufsize = 0;
  288. getline(&line, &bufsize, stdin);
  289. return line;
  290. }
  291.  
  292. char **lsh_split_line(char *line) /*Funkcja rozdzielająca ciąg poleceń do tablicy.*/
  293. {
  294. int bufsize = LSH_TOK_BUFSIZE, position = 0;
  295. char **args = malloc(bufsize * sizeof(char *)), *arg;
  296. if (!args)
  297. {
  298. fprintf(stderr, "lsh: allocation error\n");
  299. exit(EXIT_FAILURE);
  300. }
  301. lsh_save_line(line); /*Wywołanie funkcji zapisującej polecenia w historii.*/
  302. arg = strtok(line, LSH_TOK_DELIM);
  303. while (arg != NULL)
  304. {
  305. args[position] = arg;
  306. position++;
  307. if (position >= bufsize)
  308. {
  309. bufsize += LSH_TOK_BUFSIZE;
  310. args = realloc(args, bufsize * sizeof(char *));
  311. if (!args)
  312. {
  313. fprintf(stderr, "lsh: allocation error\n");
  314. exit(EXIT_FAILURE);
  315. }
  316. }
  317. arg = strtok(NULL, LSH_TOK_DELIM);
  318. }
  319. args[position] = NULL;
  320. return args;
  321. }
  322.  
  323. void lsh_loop() /*Głowna pętla shella.*/
  324. {
  325. char *line;
  326. char **args;
  327. int status;
  328. do
  329. {
  330. printf("> ");
  331. line = lsh_read_line();
  332. args = lsh_split_line(line);
  333. if (args[0] == NULL)
  334. continue;
  335. status = lsh_execute(args);
  336. free(line);
  337. free(args);
  338. } while (status);
  339. }
  340.  
  341. int main(int argc, char **argv)
  342. {
  343. lsh_loop();
  344. return EXIT_SUCCESS;
  345. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement