mysh.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /*
  2. * File: mysh.c
  3. * Author: Arthur Brandao
  4. *
  5. * Created on 31 octobre 2018, 12:43
  6. */
  7. #define _POSIX_C_SOURCE 2
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <unistd.h>
  11. #include <fcntl.h>
  12. #include <sys/stat.h>
  13. #include <wait.h>
  14. #include "error.h"
  15. #include "str.h"
  16. #include "parser.h"
  17. #include "command.h"
  18. #include "execute.h"
  19. #include "mysh.h"
  20. /* --- Extern --- */
  21. extern Error error;
  22. /* --- Global --- */
  23. pid_list pidlist;
  24. pid_node* active = NULL;
  25. /* --- Fonctions privées --- */
  26. void test_write() {
  27. char* a = "azerty\n";
  28. int tmp = write(1, a, strlen(a));
  29. printf("%d\n", tmp);
  30. }
  31. void test_tmp_file(){
  32. int a;
  33. FILE* f = tmpfile();
  34. printf("F : %d\n", f == NULL);
  35. int fd = fileno(f);
  36. printf("%d : %ld\n", fd, write(fd, "bonjour", 8));
  37. a = lseek(fd, 0L, SEEK_SET);
  38. sleep(2);
  39. char buf[10];
  40. memset(buf, 0 , 10);
  41. a = read(fd, buf, 10);
  42. printf("%d : %s\n", a, buf);
  43. close(fd);
  44. }
  45. /* --- Fonctions utilitaires --- */
  46. void show_current_dir(const char* before, const char* after) {
  47. char buffer[BUFFER_SIZE];
  48. if (getcwd(buffer, sizeof (buffer)) == NULL) {
  49. addperror("Erreur getcwd()");
  50. } else {
  51. if(before == NULL && after == NULL){
  52. printf("%s", buffer);
  53. } else if(before == NULL){
  54. printf("%s%s", buffer, after);
  55. } else if(after == NULL){
  56. printf("%s%s", before, buffer);
  57. } else {
  58. printf("%s%s%s", before, buffer, after);
  59. }
  60. }
  61. }
  62. int get_tmp_file(){
  63. FILE* f = tmpfile();
  64. if(f == NULL){
  65. adderror("Impossible de créer un fichier temporaire");
  66. return SHELL_ERR;
  67. }
  68. return fileno(f);
  69. }
  70. /* --- Main --- */
  71. int main(int argc, char* argv[]) {
  72. CommandTab ct;
  73. char str[BUFFER_SIZE];
  74. int a;
  75. //Initialisation structures
  76. error_finit("mysh.log");
  77. ini_pid_list(&pidlist);
  78. error.exit();
  79. //Recup ligne
  80. //printf("%s\n", fgets(str, 500, stdin));&
  81. memset(str, 0, 500);
  82. a = read(STDIN, str, 500);
  83. printf("%s\n", str);
  84. //Separe les commandes
  85. a = parse_line(&ct, str);
  86. if(a == SHELL_ERR){
  87. addserror("Erreur lors du parse de la ligne");
  88. error.exit_err();
  89. }
  90. //Parse les commandes
  91. a = parse_all_command(&ct);
  92. if(a == SHELL_FAIL){
  93. addserror("Erreur lors du parse des commandes");
  94. error.exit_err();
  95. }
  96. //Affiche resultat
  97. for (int i = 0; i < ct.length; i++) {
  98. Command* c = ct.cmd[i];
  99. printf("Commande %d (%s) : \n", i, c->name);
  100. for (int j = 0; j < c->argc; j++) {
  101. printf(" Argument %d : %s\n", j, c->argv[j]);
  102. }
  103. printf("Commande en fond : %d\n\n", ct.bck);
  104. //Si c'est une commande interne on l'execute
  105. if(is_internal_cmd(ct.cmd[i]->name)){
  106. show_current_dir(NULL, "\n");
  107. printf("Result : %d\n", launch_internal_command(ct.cmd[i]));
  108. show_current_dir(NULL, "\n");
  109. }
  110. }
  111. //Nettoyage structures
  112. clean_command(&ct);
  113. clean_pid(&pidlist);
  114. error.exit();
  115. }
  116. int run(CommandTab ct){
  117. pid_t pid;
  118. int result;
  119. pid_node* pnode;
  120. //Fork pour executer la commande
  121. pid = fork();
  122. if(pid == ERR){
  123. addperror("Erreur lors du fork pour l'execution des commandes");
  124. error.print("Erreur systeme, impossible de continuer\n");
  125. return SHELL_ERR;
  126. }
  127. // --- Pere ---
  128. else if(pid != 0){
  129. //Ajoute du pid dans la liste des pid actifs
  130. pnode = add_pid(&pidlist, pid);
  131. //Si on attend le retour de la commande
  132. if(!ct.bck){
  133. //Ajout du pid comme étant le pid actif et attente
  134. active = pnode;
  135. wait(&result);
  136. //Le processus n'est plus actif et analyse retour
  137. active = NULL;
  138. remove_pid(&pidlist, pnode);
  139. if(WIFEXITED(result)){
  140. return WEXITSTATUS(result);
  141. } else {
  142. return SHELL_FAIL;
  143. }
  144. }
  145. //Sinon ok
  146. return SHELL_OK;
  147. }
  148. // --- Fils ---
  149. //Reset sortie erreur
  150. error.end();
  151. //Execute chaque commande
  152. Command* c;
  153. int tmpfd;
  154. for(int i = 0; i < ct.length; i++){
  155. c = ct.cmd[i];
  156. //Si il y a un pipe creation d'un fichier temporaire à la place de la sortie standard
  157. if(c->next == SHELL_PIPE){
  158. tmpfd = get_tmp_file();
  159. if(tmpfd == SHELL_ERR){
  160. exit(EXIT_FAILURE);
  161. }
  162. tmpfd = redirect_fd(STDOUT, tmpfd);
  163. }
  164. //Effectue les redirections IO
  165. /*ToDo*/
  166. //Execute la commande
  167. if(is_internal_cmd(c->name)){
  168. result = launch_internal_command(c);
  169. } else if(is_executable_file(c->name)){
  170. } else {
  171. }
  172. //Reset IO
  173. /*ToDo*/
  174. //Agit en fonction de la jointure avec la prochaine commande
  175. /*ToDo*/
  176. }
  177. return SHELL_OK;
  178. }