我有以下代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>
void passe(char *ligne, char **argv)
{
while (*ligne != '\0')
{
while (*ligne == ' ' || *ligne == '\t' || *ligne == '\n')
*ligne++ = '\0';
*argv++ = ligne;
while (*ligne != '\0' && *ligne != ' ' && *ligne != '\t' && *ligne != '\n')
ligne++;
}
*argv = '\0';
}
void executer(char **argv)
{
pid_t pid;
int status;
if ((pid=fork()) == 0)
{
if (execvp(*argv, argv) < 0)
{
printf("*** ERREUR: exec echoué\n");
exit(1);
}
}
wait(&status);
}
int main(void)
{
char ligne[1024];
char *argv[64];
while (1)
{
printf("Shell -> ");
scanf("%s",ligne);
printf("\n");
passe(ligne, argv);
if (strcmp(argv[0], "exit") == 0)
exit(0);
executer(argv);
}
return 0;
}
程序运行良好,但是当我解析类似“ps-f”的内容时,它会重新显示“execvp echoué”,因为代码删除了空格。我该怎么做才能让它接受带有ps-f等选项的Comands?
最佳答案
您应该使用fgets()而不是scanf()。因为fgets不会从输入中删除空格。scanf函数只消耗输入直到空格。例如,如果输入“ps-f”,scanf会将此输入用作“ps”。如果您直接将ps写入shell终端,您可能会面临相同的异常,这就是您的程序异常。您可以使用fgets作为流读取器,它可以是文件流或标准输入流(stdin)。我已经写了代码来解决你的问题。你可以检查一下如何使用。
/* ----------------------------------------------------------------- */
/* PROGRAM shell.c */
/* This program reads in an input line, parses the input line */
/* into tokens, and use execvp() to execute the command. */
/* ----------------------------------------------------------------- */
#include <stdio.h>
#include <sys/types.h>
/* ----------------------------------------------------------------- */
/* FUNCTION parse: */
/* This function takes an input line and parse it into tokens. */
/* It first replaces all white spaces with zeros until it hits a */
/* non-white space character which indicates the beginning of an */
/* argument. It saves the address to argv[], and then skips all */
/* non-white spaces which constitute the argument. */
/* ----------------------------------------------------------------- */
void parse(char *line, char **argv)
{
while (*line != '\0') { /* if not the end of line ....... */
while (*line == ' ' || *line == '\t' || *line == '\n')
*line++ = '\0'; /* replace white spaces with 0 */
*argv++ = line; /* save the argument position */
while (*line != '\0' && *line != ' ' &&
*line != '\t' && *line != '\n')
line++; /* skip the argument until ... */
}
*argv = '\0'; /* mark the end of argument list */
}
/* ----------------------------------------------------------------- */
/* FUNCTION execute: */
/* This function receives a commend line argument list with the */
/* first one being a file name followed by its arguments. Then, */
/* this function forks a child process to execute the command using */
/* system call execvp(). */
/* ----------------------------------------------------------------- */
void execute(char **argv)
{
pid_t pid;
int status;
if ((pid = fork()) < 0) { /* fork a child process */
printf("*** ERROR: forking child process failed\n");
exit(1);
}
else if (pid == 0) { /* for the child process: */
if (execvp(*argv, argv) < 0) { /* execute the command */
printf("*** ERROR: exec failed\n");
exit(1);
}
}
else { /* for the parent: */
while (wait(&status) != pid) /* wait for completion */
;
}
}
/* ----------------------------------------------------------------- */
/* The main program starts here */
/* ----------------------------------------------------------------- */
void main(void)
{
char line[1024]; /* the input line */
char *argv[64]; /* the command line argument */
while (1) { /* repeat until done .... */
printf("Shell -> "); /* display a prompt */
fgets(line,1024,stdin); /* read in the command line */
int i = strlen(line)-1;
if( line[ i ] == '\n')
line[i] = '\0';
parse(line, argv); /* parse the line */
if (strcmp(argv[0], "exit") == 0) /* is it an "exit"? */
exit(0); /* exit if it is */
execute(argv); /* otherwise, execute the command */
}
}
关于c - C Shell执行命令,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40272013/