first commit
This commit is contained in:
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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user