用C编写shell,不需要';我什么也不退

用C编写shell,不需要';我什么也不退,c,shell,fork,execv,C,Shell,Fork,Execv,我运行shell,它会提示:“shell>”。我键入一个命令,比如ls,它只会生成一个新行,再次显示“Shell>” 你知道为什么它似乎没有击中execv吗 int no_of_args = count(buffer); // plus one to make it NULL char** array_of_strings = malloc((sizeof(char*)*(no_of_args+1)));

我运行shell,它会提示:“
shell>
”。我键入一个命令,比如
ls
,它只会生成一个新行,再次显示“
Shell>

你知道为什么它似乎没有击中execv吗

            int no_of_args = count(buffer);
            // plus one to make it NULL
            char** array_of_strings = malloc((sizeof(char*)*(no_of_args+1)));

            //  break the string up and create an array of pointers that
            // point to each of the arguments.
            int count=0;
            char* pch2;
            pch2 = strtok (buffer," ");
            while (pch2 != NULL)
            {
                array_of_strings[count]=(char*)malloc((sizeof(char)*strlen(pch2)));
                strcpy(array_of_strings[count], pch2);

                pch2 = strtok (NULL, " ");
                count++;
            }

            //format for command is eg. ls -a -l
            //therefore the first element in the array will be the program name
            //add the path so it'll be /bin/command eg. /bin/ls
            char* prog = malloc(sizeof(char)*(strlen(array_of_strings[0]+strlen(path))));
            prog = strcat(strcpy(prog, path),array_of_strings[0]);


}
首先,您永远不需要使用
sizeof(char)
,因为它总是1

ISO C99对字节的定义如下:

可寻址的数据存储单元,大到足以容纳基本字符的任何成员 执行环境的集合

随后在
6.5.3.4中说明了运算符的大小:

应用于具有char、unsigned char或signed char类型的操作数时, (或其合格版本)结果为1

这在C11中是不变的

因此,基本上,一个字节就是
char
的大小。ISO通常将术语“八位字节”保留为8位值


第二,语句序列如下:

array_of_strings[count]=(char*)malloc((sizeof(char)*strlen(pch2)));
strcpy(array_of_strings[count], pch2);
是未定义的行为,因为
strlen(pch2)
距离存储由
pch2
指向的字符串副本的空间仅差一个。您应该使用以下内容:

array_of_strings[count] = malloc (strlen (pch2) + 1);
你也会注意到我删除了演员阵容。永远不要在C中强制转换内存分配函数的返回值,因为在某些情况下它可能隐藏问题

第三,您似乎没有遵守
argv
数组的规则。此数组中的最后一个元素应为空指针,因为在命令
ls x.txt
中将生成:

  • “ls”
  • “x.txt”
  • NULL

现在,谈谈你的具体问题。您应该检查
execv
调用的返回值,因为无法保证可执行文件将运行(例如,如果
ls
不在
/bin
目录中)。我会改变:

int rv = execv(prog, array_of_strings);
进入:

用于调试目的,并查看其输出

如果
execv
有效,您将永远看不到最后一条消息。如果出现,它将告诉您为什么
execv
无法工作。当我这样做时,我看到:

DEBUG: [/bin/ls
]
DEBUG: execv returned -1/2
换句话说,您试图运行的可执行文件名是
/bin/lsX
,其中
X
是换行符。没有这样的可执行文件,因此出现了
execv
中的错误2(
enoint=no-this-file或directory
)-您需要修复解析代码,以便新行不会保留在中

作为快速调试修复,我更改了以下行:

prog = strcat(strcpy(prog, path),array_of_strings[0]);
进入:

要删除尾随的换行符(如果有),并成功列出文件,请执行以下操作:

Shell>ls
DEBUG: [/bin/ls]
accounts2011.ods  birthdays    shares    workspace_android
accounts2012.ods  development  wildlife
Shell>_
这只是一个用于验证的调试工作,不适用于实际代码,所以您仍然必须去修复您的解析


您可能想看一看,因为它显示了一种使用缓冲区溢出保护从用户处获取输入的好方法,如果输入行太长,则清除其余的输入行,并提示和(在本例中最重要的)删除换行符。

首先,您永远不需要使用
sizeof(char)
,因为它总是1

ISO C99对字节的定义如下:

可寻址的数据存储单元,大到足以容纳基本字符的任何成员 执行环境的集合

随后在
6.5.3.4中说明了运算符的大小:

应用于具有char、unsigned char或signed char类型的操作数时, (或其合格版本)结果为1

这在C11中是不变的

因此,基本上,一个字节就是
char
的大小。ISO通常将术语“八位字节”保留为8位值


第二,语句序列如下:

array_of_strings[count]=(char*)malloc((sizeof(char)*strlen(pch2)));
strcpy(array_of_strings[count], pch2);
是未定义的行为,因为
strlen(pch2)
距离存储由
pch2
指向的字符串副本的空间仅差一个。您应该使用以下内容:

array_of_strings[count] = malloc (strlen (pch2) + 1);
你也会注意到我删除了演员阵容。永远不要在C中强制转换内存分配函数的返回值,因为在某些情况下它可能隐藏问题

第三,您似乎没有遵守
argv
数组的规则。此数组中的最后一个元素应为空指针,因为在命令
ls x.txt
中将生成:

  • “ls”
  • “x.txt”
  • NULL

现在,谈谈你的具体问题。您应该检查
execv
调用的返回值,因为无法保证可执行文件将运行(例如,如果
ls
不在
/bin
目录中)。我会改变:

int rv = execv(prog, array_of_strings);
进入:

用于调试目的,并查看其输出

如果
execv
有效,您将永远看不到最后一条消息。如果出现,它将告诉您为什么
execv
无法工作。当我这样做时,我看到:

DEBUG: [/bin/ls
]
DEBUG: execv returned -1/2
换句话说,您试图运行的可执行文件名是
/bin/lsX
,其中
X
是换行符。没有这样的可执行文件,因此出现了
execv
中的错误2(
enoint=no-this-file或directory
)-您需要修复解析代码,以便新行不会保留在中

作为快速调试修复,我更改了以下行:

prog = strcat(strcpy(prog, path),array_of_strings[0]);
进入:

要删除尾随的换行符(如果有),并成功列出文件,请执行以下操作:

Shell>ls
DEBUG: [/bin/ls]
accounts2011.ods  birthdays    shares    workspace_android
accounts2012.ods  development  wildlife
Shell>_
这只是一个用于验证的调试工作,不适用于实际代码,所以您仍然必须去修复您的解析


您可能想看一看,因为它显示了一种使用缓冲区溢出保护从用户处获取输入的好方法,如果输入行太长,请清理输入行的其余部分,并提示(在本例中最重要的)删除换行符。

换行符

char* prog = malloc(sizeof(char)*(strlen(array_of_strings[0]+strlen(path))));
这似乎是错误的。你确定你不是故意的吗

char* prog = malloc(sizeof(char)*(strlen(array_of_strings[0])+strlen(path)));
(注:括号已移动)
strlen(字符串数组[0]+strlen(路径))
(保留的字节数)将承载不可预测的