first commit
This commit is contained in:
139
main.c
Normal file
139
main.c
Normal 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
80
processlist.c
Normal 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
20
processlist.h
Normal 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
298
readcmd.c
Normal 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
41
readcmd.h
Normal 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
BIN
schema pipe.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 89 KiB |
Reference in New Issue
Block a user