我被要求为操作系统类实现我自己的 shell。
我的 shell 可以正常运行所有命令,除了ls不会在execve上返回,这很奇怪,因为 cd、cp、mv 和所有其他主要命令都可以正常返回。
ls仍在显示正确的输出(文件夹中的文件列表),但只是继续运行(execve 挂起并需要回车完成)。
-l、-a 等所有选项也都可以正常工作,但存在同样的问题。
编辑:我修改了我的代码以完全避免任何内存泄漏(我使用 valgrind 来跟踪它们),添加了一些注释,以便您可以看到发生了什么,但 ls 仍然没有返回。这是更新的版本:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/wait.h>
#define MAXPATHLEN 40
#define MAXSIZE 100
#define MAXARGS 10
static char cwd[MAXPATHLEN];
typedef void (*sighandler_t)(int);
void handle_signal(int signo);
void parse_command(char *command, char **arguments);
int main(int argc, char *argv[], char *envp[])
{
int status;
char *command;
char **arguments;
signal(SIGINT, SIG_IGN);
signal(SIGINT, handle_signal);
while(1) {
//Allocating memory
command = calloc(MAXSIZE, sizeof(char));
arguments = calloc(MAXARGS, sizeof(char *));
//Print shell name and cwd
getcwd(cwd,MAXPATHLEN);
printf("[MY_SHELL]:%s$ ", cwd);
parse_command(command, arguments);
//Displays command and arguments
printf("Command is %s\n", command);
int i;
for(i=0; arguments[i] != NULL; ++i){
printf("Argument %d is %s\n", i, arguments[i]);
}
//Fork exec code
if (fork() != 0){
waitpid(1, &status, 0);
} else{
execve(command, arguments, 0);
}
free(command);
for (i=0; arguments[i] != NULL; ++i) {
free(arguments[i]);
}
free(arguments);
}
return 0;
}
void handle_signal(int signo)
{
getcwd(cwd,MAXPATHLEN);
printf("\n[MY_SHELL]:%s$ ", cwd);
fflush(stdout);
}
void parse_command(char *command, char **arguments){
char buf[MAXSIZE];
char env[MAXPATHLEN];
char *tmp;
//Initiate array values to avoid buffer overflows
memset(buf, 0, sizeof(buf));
memset(env, 0, sizeof(env));
//Read command and put it in a buffer
char c = '\0';
int N = 0; //Number of chars in input - shouldn't be more than MAXSIZE
while(1) {
c = getchar();
if (c == '\n')
break;
else{
if (N == MAXSIZE)
break;
buf[N] = c;
}
++N;
}
//Extract command name (e.g "ls"), fetch path to command, append it to command name
tmp = strtok(buf, " ");
strcpy(env, "/bin/");
size_t len1 = strlen(env);
size_t len2 = strlen(tmp);
memcpy(command, env, len1);
memcpy(command + len1, tmp, len2);
//Extracts arguments array: arguments[0] is path+command name
arguments[0] = calloc(strlen(command) + 1, sizeof(char));
strcpy(arguments[0], command);
int i = 1;
while(1){
tmp = strtok(NULL, " ");
if (tmp == NULL)
break;
else{
arguments[i] = calloc(strlen(tmp) + 1, sizeof(char));
strcpy(arguments[i],tmp);
++i;
}
}
}
编辑 2:这似乎与 STDIN(或 STDOUT)有关:与ls类似,cat在执行后使 execve 挂起,我需要回车以使我的 shell 行[MY_SHELL]current_working_directory$:回行。关于为什么会这样的任何想法?