图一结果展示
图二问题部分代码
经过测试 在这个//fill the command structrue部分之后,这里的token[2]就消失了,我测试的用例是“abc;”, 测试结果为图1
command.c
#include <string.h>
#include "command.h"
#include <stdio.h>
#include <stdlib.h>
// whether is separator
int separator(char *token)
{
int i = 0;
char *commandSeparators[] = {pipeSep, conSep, seqSep, NULL};
while(commandSeparators[i] != NULL) {
if(strcmp(token, commandSeparators[i]) == 0)
{
return 1;
}
++i;
}
printf("\nin separator\ntoken: %s\n", token);
return 0;
}
// fill one command structure with details
void fillCommandStructure(Command *cp, int first, int last, char *sep)
{
cp->first = first;
cp->last = last - 1;
cp->sep = sep;
}
// process standard in/out redirections in a command
void searchRedirection(int tknum, char (*token)[MAX_NUM_COMMANDS], Command *cp)
{
int i;
for( i = cp->first; i <= cp->last; ++i)
{
if(strcmp(token[i], "<") == 0)
{
// convert from char array to char
int k = 0;
char t[cp->last-i];
for(int j = i + 1; j <= cp->last; j++)
{
t[k] = token[j][0];
++k;
}
// dynamic allocate memory
cp->stdin_file = (char*)malloc(cp->last-i);
for(int l = 0; l < cp->last -i; l++)
{
cp->stdin_file[l] = t[l];
}
cp->stdin_file[cp->last-i] = '\0';
++i;
} else if (strcmp(token[i], ">") == 0)
{
int k = 0;
char t[cp->last-i];
for(int j = i + 1; j <= cp->last; j++)
{
t[k] = token[j][0];
++k;
}
cp->stdout_file = (char*)malloc(cp->last-i);
for(int l = 0; l < cp->last - i; l++)
{
cp->stdout_file[l] = t[l];
}
cp->stdout_file[cp->last-i] = '\0';
++i;
}
}
}
// build command line argument vector for execvp function
void buildCommandArgumentArray(char (*token)[MAX_NUM_COMMANDS], Command *cp)
{
int n = cp->last - cp->first + 1;
printf("n: %d\n", n);
// re-allocate memoery for argument vector
cp->argv = (char**) realloc(cp->argv, sizeof(char*)*n );
if(cp->argv == NULL)
{
perror("realloc");
exit(1);
}
// build the argument vector
int i;
int k = 0;
printf("first: %d\n last: %d\n", cp->first, cp->last);
for(i = cp->first; i <= cp->last; ++i)
{
if(strcmp(token[i], ">") == 0 || strcmp(token[i], "<") == 0)
++i;
else
{
cp->argv[k] = token[i];
printf("k %d\nargvk %s\ntoken %s\n", k, cp->argv[k], token[i]);
++k;
}
}
cp->argv[k] == NULL;
}
int separateCommands(char (*token)[MAX_NUM_COMMANDS], Command command[], int nTokens)
{
for(int i = 0; i < nTokens;++i)
{
printf("token: %s\n", token[i]);
}
// if line is empty
if (nTokens == 0)
return 0;
// check the first token
if (separator(token[0]))
return -3;
// check the last token, add ";" if necessary
if (!separator(token[nTokens-1]))
{
strcpy(token[nTokens], seqSep);
++nTokens;
}
//fill the command structure
int first = 0;
int last = 0;
char *sep;
int c = 0;
for(int i = 0; i < nTokens; ++i)
{
last = i;
if (separator(token[i]))
{
sep = token[i];
if(first == last)
return -2;
fillCommandStructure(&(command[c]), first, last, sep);
++c;
first = i + 1;
}
}
printf("\nafter fill\n");
for(int i = 0; i < nTokens;++i)
{
printf("token: %s\n", token[i]);
}
// check the last token of the last command
if (strcmp(token[last], pipeSep) == 0)
return -4;
int nCommands = c;
// handle standard in/out redirection and build command line argument vector
for (int i=0; i < nCommands; ++i)
{
searchRedirection(nTokens, token, &(command[i]));
buildCommandArgumentArray(token, &(command[i]));
}
return nCommands;
command.h
#define MAX_NUM_COMMANDS 1000
#define pipeSep "|"
#define conSep "&"
#define seqSep ";"
struct CommandStruct {
int first;
int last;
char *sep;
// new fields
char ** argv;
char *stdin_file;
char *stdout_file;
};
typedef struct CommandStruct Command;
int separateCommands(char (*token)[MAX_NUM_COMMANDS], Command command[], int cmd_num);
main.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "command.h"
char* s_gets(char* st, int n)
{
char* ret_val;
int i = 0;
ret_val = fgets(st, n, stdin);
if(ret_val)
{
while (st[i] != '\n' && st[i] != '\0')
i++;
if (st[i] == '\n')
{
st[i] = '\0';
}
else
{
while (getchar() != '\n')
{
continue;
}
}
}
return ret_val;
}
char* tostring(char des[], char src)
{
des[0] = src;
des[1] = '\0';
return des;
}
int main()
{
while(1)
{
char str[MAX_NUM_COMMANDS];
char tokens[2][MAX_NUM_COMMANDS];
int cmd_num = 0;
printf("$\n");
s_gets(str, MAX_NUM_COMMANDS);
cmd_num = strlen(str);
for(int i = 0; i < cmd_num; ++i)
{
tostring(tokens[i], str[i]);
}
Command cmdlst[MAX_NUM_COMMANDS];
cmd_num = separateCommands(tokens, cmdlst, cmd_num);
puts("");
printf("return value is: %d\n",cmd_num);
puts("");
for(int i = 0; i < cmd_num; ++i)
{
printf("fst %d\n", cmdlst[i].first);
printf("lst %d\n", cmdlst[i].last);
printf("sep %s\n", cmdlst[i].sep);
if(cmdlst[i].stdin_file != NULL)
printf("stdin file: %s\n", cmdlst[i].stdin_file);
if(cmdlst[i].stdout_file != NULL)
printf("stdout file: %s\n", cmdlst[i].stdout_file);
puts("");
}
// clean pointer
for(int i = 0; i < cmd_num; ++i)
{
if(cmdlst[i].stdin_file != NULL)
free(cmdlst[i].stdin_file);
if(cmdlst[i].stdout_file != NULL)
free(cmdlst[i].stdout_file);
}
puts("");
}
return 0;
}