first commit

This commit is contained in:
2021-01-09 17:11:34 +01:00
parent 44efd17d51
commit c369c77685
6 changed files with 578 additions and 0 deletions

139
main.c Normal file
View File

@@ -0,0 +1,139 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include "readcmd.h"
#include "processlist.h"
#define BUFFERSIZE 255
process * list;
int sortie = 0;
int errno;
int cpt = 0;
void suivi_fils (int sig) {
int etat_fils, pid_fils;
do {
pid_fils = waitpid(-1, &etat_fils, WNOHANG | WUNTRACED | WCONTINUED);
if ((pid_fils == -1) && (errno != ECHILD)) {
perror("waitpid");
exit(EXIT_FAILURE);
} else if (pid_fils > 0) {
if (WIFSTOPPED(etat_fils)) {
list = setStatus(list,pid_fils,0);
} else if (WIFCONTINUED(etat_fils)) {
list = setStatus(list,pid_fils,1);
} else if (WIFEXITED(etat_fils)) {
list = supprimer(list, pid_fils);
printf("suppression");
} else if (WIFSIGNALED(etat_fils)) {
//if(WSTOPSIG(etat_fils) == )
}
}
} while (pid_fils > 0);
}
char * copyCommandText(char ** cmd){
char * cmdtxt = malloc(BUFFERSIZE * sizeof(char));
int x=0;
while( cmd[x]!= NULL){
strcat(cmdtxt, cmd[x]);
x++;
}
return cmdtxt;
}
void executerCommande(char ** commande, int backgrounded){
if(strcmp(commande[0], "cd") == 0){
char *s = malloc(sizeof(char)*250);
getcwd(s, 255);
// cas de la commande cd sans argument
if(commande[1] == NULL){
chdir(getenv("HOME"));
}
// cas de cd avec chemin relatif ou absolu
else if(chdir(commande[1]) == 0 || chdir(strcat(s, commande[1])) == 0){}
// cas ou le repertoire renseigné n'existe pas
else{
printf("Repertoire non accessible %s", s);
}
free(s);
}
else if(strcmp(commande[0], "list") == 0){
printf("%-12s%-12s%-12s%s\n", "ID", "PID", "STATUS", "COMMANDE");
afficherProcess(list);
}
else if(strcmp(commande[0], "stop") == 0){
if(commande[1] == NULL)
printf("Utilisation : stop id\n");
else{
int pid = getPID(list, atoi(commande[1]));
//printf("%d", pid);
kill(pid , SIGSTOP);
setStatus(list, pid, 0);
}
}
else if(strcmp(commande[0], "exit") == 0){
sortie = 1;
}
else{
int status;
int pid = fork();
list = inserer(list, cpt, pid, 1, copyCommandText(commande));
cpt++;
if(pid == 0) {
//sigset_t ens_signaux;
//sigemptyset(&ens_signaux);
//sigaddset(&ens_signaux, SIGINT);
//sigaddset(&ens_signaux, SIGUSR1);
//printf("Masquage de SIGINT et SIGUSR1\n\n");
//sigprocmask(SIG_SETMASK, &ens_signaux, NULL);
execvp(commande[0],commande);
printf("Erreur sur la commande\n");
exit(3);
}
else if (pid == -1) {
printf("Une erreur est sur venu au niveau du fork\n");
exit(2);
}
if(backgrounded < 1){
int ret = waitpid(pid, &status, 0);
list = supprimer(list, pid);
if(ret == -1){
perror("Erreur sur le wait\n");
exit(3);
}
}
}
}
int main()
{
//signal(SIGINT, handler_SIG);
//signal(20, handler_SIG);
struct cmdline *cmd;
int i;
while(sortie != 1){
printf("minishell$ ");
cmd = readcmd();
i = 0;
while(cmd->seq[i] != NULL){
if(cmd->backgrounded == NULL)
executerCommande(cmd->seq[i], 0);
else
executerCommande(cmd->seq[i], 1);
i++;
}
}
}

80
processlist.c Normal file
View File

@@ -0,0 +1,80 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "processlist.h"
process * setStatus(process * pr ,int pid_proc, int status){
if(pr == NULL){}
else if(pr->pid == pid_proc){
pr->status = status;
}
else{
setStatus(pr->procSuivant, pid_proc, status);
}
return pr;
}
process * supprimer(process* pr ,int pid_proc){
process * toDel;
if(pr == NULL){}
else{
if(pr->pid == pid_proc){
toDel = pr;
pr = pr->procSuivant;
}
else{
process * tmp = pr;
while(tmp->procSuivant->pid != pid_proc){
tmp = tmp->procSuivant;
}
toDel = tmp ->procSuivant;
tmp->procSuivant = tmp->procSuivant->procSuivant;
}
free(toDel->commande);
free(toDel);
}
return pr;
}
process * inserer(process * pr , int id, int pid, int status, char * commande){
process * toAdd = malloc(sizeof(process));
toAdd->id = id;
toAdd->pid = pid;
toAdd->status = status;
toAdd->commande = commande;
toAdd->procSuivant = pr;
pr = toAdd;
return pr;
}
int taille(process * pr){
if(pr == NULL)
return 0;
else
return 1 + taille(pr->procSuivant);
}
int getPID(const process * pr, int idMinishell){
if(pr == NULL)
return -1;
if(pr->id == idMinishell){
return pr->pid;
}
else return getPID(pr->procSuivant, idMinishell);
}
void afficherProcess(process * pr){
if(pr != NULL){
printf("%-12d%-12d", pr->id, pr->pid);
if(pr->status>0)
printf("%-12s", "actif");
else
printf("%-12s", "suspendu");
printf("%s", pr->commande);
printf("\n");
afficherProcess(pr->procSuivant);
}
}

20
processlist.h Normal file
View File

@@ -0,0 +1,20 @@
#ifndef PROCESSLIST_H_INCLUDED
#define PROCESSLIST_H_INCLUDED
typedef struct process process;
struct process {
int id;
int pid;
int status;
char * commande;
process * procSuivant;
};
process * inserer(process *pr , int id, int pid, int status, char * commande);
process * setStatus(process* pr ,int pid_proc, int status);
process * supprimer(process* pr ,int pid_proc);
int getPID(const process * pr, int idMinishell);
void afficherProcess(process *pr);
int taille(process * pr);
#endif // PROCESSLIST_H_INCLUDED

298
readcmd.c Normal file
View File

@@ -0,0 +1,298 @@
/*
* Copyright (C) 2002, Simon Nieuviarts
*/
/*
* Backgrounding added. [PM] Ajout d'une rustine nécessaire : lignes 153 et 293 commentées
*/
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
#include <string.h>
#include "readcmd.h"
static void memory_error(void)
{
errno = ENOMEM;
perror(0);
exit(1);
}
static void *xmalloc(size_t size)
{
void *p = malloc(size);
if (!p) memory_error();
return p;
}
static void *xrealloc(void *ptr, size_t size)
{
void *p = realloc(ptr, size);
if (!p) memory_error();
return p;
}
/* Read a line from standard input and put it in a char[] */
static char *readline(void)
{
size_t buf_len = 16;
char *buf = xmalloc(buf_len * sizeof(char));
if (fgets(buf, buf_len, stdin) == NULL) {
free(buf);
return NULL;
}
do {
size_t l = strlen(buf);
if ((l > 0) && (buf[l-1] == '\n')) {
l--;
buf[l] = 0;
return buf;
}
if (buf_len >= (INT_MAX / 2)) memory_error();
buf_len *= 2;
buf = xrealloc(buf, buf_len * sizeof(char));
if (fgets(buf + l, buf_len - l, stdin) == NULL) return buf;
} while (1);
}
/* Split the string in words, according to the simple shell grammar. */
static char **split_in_words(char *line)
{
char *cur = line;
char **tab = 0;
size_t l = 0;
char c;
while ((c = *cur) != 0) {
char *w = 0;
char *start;
switch (c) {
case ' ':
case '\t':
/* Ignore any whitespace */
cur++;
break;
case '<':
w = "<";
cur++;
break;
case '>':
w = ">";
cur++;
break;
case '|':
w = "|";
cur++;
break;
case '&':
w = "&";
cur++;
break;
default:
/* Another word */
start = cur;
while (c) {
c = *++cur;
switch (c) {
case 0:
case ' ':
case '\t':
case '<':
case '>':
case '|':
case '&':
c = 0;
break;
default: ;
}
}
w = xmalloc((cur - start + 1) * sizeof(char));
strncpy(w, start, cur - start);
w[cur - start] = 0;
}
if (w) {
tab = xrealloc(tab, (l + 1) * sizeof(char *));
tab[l++] = w;
}
}
tab = xrealloc(tab, (l + 1) * sizeof(char *));
tab[l++] = 0;
return tab;
}
static void freeseq(char ***seq)
{
int i, j;
for (i=0; seq[i]!=0; i++) {
char **cmd = seq[i];
for (j=0; cmd[j]!=0; j++) free(cmd[j]);
free(cmd);
}
free(seq);
}
/* Free the fields of the structure but not the structure itself */
static void freecmd(struct cmdline *s)
{
if (s->in) free(s->in);
if (s->out) free(s->out);
// if (s->backgrounded) free(s->backgrounded);
if (s->seq) freeseq(s->seq);
}
struct cmdline *readcmd(void)
{
static struct cmdline *static_cmdline = 0;
struct cmdline *s = static_cmdline;
char *line;
char **words;
int i;
char *w;
char **cmd;
char ***seq;
size_t cmd_len, seq_len;
line = readline();
if (line == NULL) {
if (s) {
freecmd(s);
free(s);
}
return static_cmdline = 0;
}
cmd = xmalloc(sizeof(char *));
cmd[0] = 0;
cmd_len = 0;
seq = xmalloc(sizeof(char **));
seq[0] = 0;
seq_len = 0;
words = split_in_words(line);
free(line);
if (!s)
static_cmdline = s = xmalloc(sizeof(struct cmdline));
else
freecmd(s);
s->err = 0;
s->in = 0;
s->out = 0;
s->backgrounded = 0;
s->seq = 0;
i = 0;
while ((w = words[i++]) != 0) {
switch (w[0]) {
case '&':
if(s->backgrounded){
s->err = "error on &";
goto error;
}
s->backgrounded = &w[0];
break;
case '<':
/* Tricky : the word can only be "<" */
if (s->in) {
s->err = "only one input file supported";
goto error;
}
if (words[i] == 0) {
s->err = "filename missing for input redirection";
goto error;
}
s->in = words[i++];
break;
case '>':
/* Tricky : the word can only be ">" */
if (s->out) {
s->err = "only one output file supported";
goto error;
}
if (words[i] == 0) {
s->err = "filename missing for output redirection";
goto error;
}
s->out = words[i++];
break;
case '|':
/* Tricky : the word can only be "|" */
if (cmd_len == 0) {
s->err = "misplaced pipe";
goto error;
}
seq = xrealloc(seq, (seq_len + 2) * sizeof(char **));
seq[seq_len++] = cmd;
seq[seq_len] = 0;
cmd = xmalloc(sizeof(char *));
cmd[0] = 0;
cmd_len = 0;
break;
default:
cmd = xrealloc(cmd, (cmd_len + 2) * sizeof(char *));
cmd[cmd_len++] = w;
cmd[cmd_len] = 0;
}
}
if (cmd_len != 0) {
seq = xrealloc(seq, (seq_len + 2) * sizeof(char **));
seq[seq_len++] = cmd;
seq[seq_len] = 0;
} else if (seq_len != 0) {
s->err = "misplaced pipe";
i--;
goto error;
} else
free(cmd);
free(words);
s->seq = seq;
return s;
error:
while ((w = words[i++]) != 0) {
switch (w[0]) {
case '<':
case '>':
case '|':
case '&':
break;
default:
free(w);
}
}
free(words);
freeseq(seq);
for (i=0; cmd[i]!=0; i++) free(cmd[i]);
free(cmd);
if (s->in) {
free(s->in);
s->in = 0;
}
if (s->out) {
free(s->out);
s->out = 0;
}
if (s->backgrounded) {
// free(s->backgrounded);
s->out = 0;
}
return s;
}

41
readcmd.h Normal file
View File

@@ -0,0 +1,41 @@
#ifndef __READCMD_H
#define __READCMD_H
/* Lit une ligne de commande depuis l'entrée standard.
* Remarque :
* Dans le cas où suffisamment de mémoire ne peut être allouée pour le résultat,
* affiche un message d'erreur et appelle exit().
*/
struct cmdline *readcmd(void);
/* Structure retournée par readcmd()
* Remarques utiles :
* - readcmd() peut retourner null, dans le cas où le processus en attente sur readcmd reçoit un signal
* - en cas d'appels successifs,
* readcmd() réutilise la mémoire allouée à la structure cmdline qu'elle retourne
*/
struct cmdline {
char *err; /* Si non null : message d'erreur à afficher.
* Dans ce cas, les autres champs sont nuls. */
char *in; /* Si non null : nom du fichier vers lequel l'entrée doit être redirigée. */
char *out; /* Si non null : nom du fichier vers lequel la sortie doit être redirigée. */
char *backgrounded; /* Si non null : commande en tâche de fond */
char ***seq; /* Une ligne de commande est une suite de commandes liées par des tubes
* Ainsi,
* - une commande est un tableau de chaînes de caractères (char **).
* Chaque élément de ce tableau est en effet une chaîne (char *)
* correspondant à un argument de la commande.
* Le dernier pointeur du tableau est suivi d'un pointeur null, qui
* marque la fin du tableau.
* - seq est un tableau de commandes (char ***), chaque commande de ce
* tableau correspondant à une commande élémentaire du pipeline.
* Le dernier élément (char **) du tableau est ici aussi suivi d'un pointeur null.
* - Dans le cas particulier où une ligne vide est saisie, le pointeur référencé par
* seq vaut directement NULL : puisque le tableau n'a aucun élément, le marqueur
* de fin de tableau se trouve référencé par seq, ce que l'on peut écrire
* (*seq == NULL)
* (ou (seq[0] == NULL), mais cela peut prêter à confusion, seq[0] n'existant pas)
*/
};
#endif

BIN
schema pipe.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB