我试图创建一个简单的shell程序,并使用fgets()从用户那里获取输入。我将用户输入存储在char []中,然后尝试使用我编写的getword()方法进行解析。但是,我不知道如何获取getword()方法来解析字符串。我可以打印出commandLine char []并确切地看到在提示符下键入的内容,但是没有得到解析。 getword()返回未解析的相同字符串,并尝试将整个内容存储在argv [0]中。我已经单独测试了getword()方法,它返回了我想要的结果。这是我目前的尝试:
主要的shell程序:
int main() {
pid_t pid, first, second;
mode_t fileBits;
size_t ln;
int argc, inputRedirect, firstStatus, i, execvpReturnVal;
int childOutput_fd;
long octalPermissionString;
char *home = getenv("HOME");
char *argv[MAXITEM];
char devNull[10] = "/dev/null";
char commandLine[STORAGE];
struct stat fileStats;
signal(SIGTERM, myhandler);
for (;;) {
background = 0;
printf("p2: ");
fflush(stdout);
/*---------FGETS PROMPT----------*/
fgets(commandLine, STORAGE, stdin);
commandLine[strlen(commandLine) - 1] = '\0';
printf("commandLine = [%s]\n", commandLine);
/*==============OTHER SHELL METHODS=============*/
调用getword()的parse()方法:
int parse(char *commandLine, char *argv[]) {
int argc = 0;
char *commandPointer;
argv[argc++] = commandLine;
printf("argv[%d] = [%s]\n", argc-1, commandLine);
do{
commandPointer = (char*)malloc(sizeof(char) * STORAGE);
argv[argc++] = commandPointer;
printf("argv[%d] = [%s]\n", argc-1, commandPointer);
getword(commandPointer);
}while(*commandPointer != '\0');
argc--;
argv[argc] = '\0';
return argc;
}
getword()解析方法:
/*Function Prototypes*/
int tilde(char *p, int i);
int isMeta(int thisChar);
int getword(char *w) {
int currChar, nextChar, offset;
int index = 0;
int *tildeHelper;
currChar = getchar();
while(currChar == ' ' || currChar == '\t') {
currChar = getchar();
}
if(currChar == EOF)
return -1;
switch(currChar) {
case '\0':
w[index] = '\0';
return index;
case '\n':
w[index] = '\0';
return index;
case ';':
w[index] = '\0';
return index;
case '<':
w[index++] = currChar;
w[index] = '\0';
return index;
case '>':
w[index++] = currChar;
if((nextChar = getchar()) == '>')
w[index++] = currChar;
else {
ungetc(nextChar, stdin);
}
w[index] = '\0';
return index;
case '|':
w[index++] = currChar;
w[index] = '\0';
return index;
case '&':
w[index++] = currChar;
w[index] = '\0';
return index;
case '~':
tildeHelper = &index;
index = tilde(&w[index], *tildeHelper);
default:
w[index++] = currChar;
while((currChar = getchar()) != ' ' && currChar != '<' && currChar != '>' && currChar != '|' && currChar != ';' && currChar != '&' && currChar != '\t' && currChar != '\n' && currChar != '\0' && currChar != EOF && index <= STORAGE - 1) {
switch(currChar) {
case '~':
tildeHelper = &index;
index = tilde(&w[index], *tildeHelper);
break;
case '\\':
nextChar = getchar();
if(metaCharacter(nextChar))
w[index++] = nextChar;
else {
ungetc(nextChar, stdin);
w[index++] = currChar;
}
break;
default:
w[index++] = currChar;
}
}
ungetc(currChar, stdin);
w[index] = '\0';
return index;
}
}
int tilde(char *cp, int i) {
int *ip = &i;
char *p = cp;
char *o;
o = (strcpy(p, getenv("HOME")));
int offset = strlen(o);
*ip = *ip + offset;
return i;
}
int metaCharacter(int thisChar) {
int isMeta = 0;
switch(thisChar) {
case '~':
isMeta = 1;
break;
case '<':
isMeta = 1;
break;
case '>':
isMeta = 1;
break;
case '|':
isMeta = 1;
break;
case ';':
isMeta = 1;
break;
case '&':
isMeta = 1;
break;
case '\\':
isMeta = 1;
break;
}
return isMeta;
}
最佳答案
您试图从stdin
读取命令行两次。首先,用fgets()
读整行,然后在getword
中尝试用getchar()
获取下一个字符。实际上,这试图读取第二行。您应该改为读取包含该行的char缓冲区。
更新您的getword
函数以使用第二个参数src
,即要读取的行。然后将所有对getline
的调用替换为*src++
:
int getword(char *w, const char *src) {
int currChar, nextChar, offset;
int index = 0;
int *tildeHelper;
currChar = *src++;
while(currChar == ' ' || currChar == '\t') currChar = *src++;
/* ... */
}
然后,您的
parse
函数必须将命令行传递给getword
并使用getword
的返回值来更新字符串位置:int parse(char *commandLine, char *argv[])
{
int argc = 0;
int index = 0;
while (1) {
char *commandPointer = malloc(sizeof(char) * STORAGE);
index += getword(commandPointer, commandLine + index);
if (*commandPointer == '\0') break;
argv[argc++] = commandPointer;
}
return argc;
}
这样,您仍然在代码中遇到问题,例如,未正确获得
getword
的返回值以及未释放参数字符串。另外,要实现外壳程序,请查看
getline
,它是比普通的旧版“ fgets”更好的命令行输入界面。