抱歉标题,我想不出更好的方式来表达它。
所以我的C作业与fork
和exec
一起使用。
我有三个名为ps
,echo
和history
的程序,所有程序都采用不同的参数。最终的程序称为shell
,它接收来自stdin
的命令,并在采取适当的命令后调用exec
。
示例:
ps -a
echo Hello World
history 1.txt
一旦它读取一行并发现它是一个有效的命令,就会生成子进程并调用exec
。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
const int MAX_LINE = 100;
const char *HISTORY = "./history";
const char *PS = "./ps";
const char *ECHO = "./echo";
void call_cmd(int cmd, char *const argv[]);
/* main function */
int main(int argc, char** argv)
{
FILE * out;
char line[MAX_LINE], line_print[MAX_LINE], seps[] = " \n", rm[80];
char *first, *tmp, ** params;
pid_t pid;
int cmd = -1, i = 0,j= 0;
if (argc != 2)
{
printf("Invalid arguments");
return EXIT_FAILURE;
}
out = fopen(argv[1],"w");
if (out == NULL)
{
perror("Couldn't open file to write");
return EXIT_FAILURE;
}
while(fgets(line,sizeof(line),stdin) != NULL)
{
strcpy(line_print,line);
params = (char**) malloc(sizeof(char*));
tmp = strtok(line,seps);
while (tmp != NULL)
{
if(i != 0)
params = (char**) realloc(params,sizeof(char*) * (i + 1));
params[i] = tmp;
j++;
tmp = strtok(NULL,seps);
i++;
}
first = params[0];
if (strcmp("exit",first) == 0)
{
sprintf(rm,"rm %s",argv[1]);
system(rm);
exit(0);
}
if(strcmp("echo",first) == 0)
cmd = 0;
if(strcmp("history",first) == 0)
cmd = 1;
if(strcmp("ps",first) == 0)
cmd = 2;
if(cmd == -1){
perror("\nInvalid Command\n");
}
if(cmd >= 0)
{
fprintf(out,"%s",line_print);
pid = fork();
if (pid == -1)
{
perror("Error Creating Child");
return EXIT_FAILURE;
}
if(pid == 0)
{
call_cmd(cmd,params);
exit(0);
}
}
for (i = 0; i < j ; i++)
free(params[i]);
free(params);
i = j = 0;
cmd = -1;
}
fclose(out);
return EXIT_SUCCESS;
}
void call_cmd(int cmd, char *const argv[])
{
switch(cmd)
{
case 0:
execv(ECHO, argv);
break;
case 1:
execv(HISTORY, argv);
break;
default:
execv(PS, argv);
break;
}
}
这是我的代码到目前为止,它表现得很奇怪,导致分段错误, 我很确定这是因为我分割参数并释放它们的方式。
示例输出:
*** Error in `./shell': double free or corruption (out): 0x00007ffe58f1a630 ***
Parent Id: 1928
Aborted (core dumped)
所以我一直在编辑for循环
for (i = 0; i < j ; i++)
free(params[i]);
所有这一切只是从双重自由跳转到分段错误,或者我写了一个像ps或历史这样的命令而它什么都没做,所以我必须做一些事情,但我真的迷失了,试图修复它两天,如果你看到我做错了,请指出。
谢谢。
答案 0 :(得分:4)
strtok
解析字符串就地,因此您不应释放单个结果。它们是原始字符串的一部分。您可以使用POSIX函数strdup
制作可以免费复制的副本,并且会在原始缓冲区内容的生命周期内保留。
答案 1 :(得分:2)
你应该添加
params[0] = NULL;
在初始malloc之后(或使用calloc),否则如果该行为空,您将使用单位指针。然后在最后
free(params);
你不需要释放任何params [i],因为它们是指向本地行[]缓冲区的指针。