projet-systeme-exploitation.../readcmd.c

298 lines
4.9 KiB
C
Raw Normal View History

2021-04-20 16:12:44 +00:00
/*
* 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;
}