繁体   English   中英

用C编写Shell,不返回任何内容

[英]Writing a shell in C, doesn't return anything

我运行外壳程序,并提示:“ 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 The sizeof operator声明:

当将其应用于具有char,unsigned char或signed char类型(或其限定版本)的操作数时,结果为1。

在C11中不变。

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


其次,一条语句序列如下:

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数组的规则。 该数组中的最后一个元素应为NULL指针,如ls x.txt命令将生成:

  • "ls"
  • "x.txt"
  • NULL

现在,解决您的特定问题。 您应该检查execv调用的返回值,因为不能保证可执行文件会运行(例如,如果ls不在/bin目录中)。 我会改变:

int rv = execv(prog, array_of_strings);

变成:

printf ("DEBUG: [%s]\n", prog);
int rv = execv(prog, array_of_strings);
printf ("DEBUG: execv returned %d/%d\n", rv, errno); // need errno.h

用于调试目的,并查看输出结果。

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

DEBUG: [/bin/ls
]
DEBUG: execv returned -1/2

换句话说,您要运行的可执行文件名称是/bin/lsX ,其中X是换行符。 没有这样的可执行文件,因此execv的错误2( ENOENT = No such file or directory )-您需要修复解析代码,以免遗漏换行符。

作为快速调试修复,我更改了这一行:

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

变成:

prog = strcat(strcpy(prog, path),array_of_strings[0]);
if (prog[strlen(prog)-1] == '\n') prog[strlen(prog)-1] = '\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(array_of_strings[0]+strlen(path)) (您保留的字节数)与array_of_strings[0]的长度和path(您要连接的字符串)的总和具有不可预测的关系。 这可能导致段错误。

execv之后,当前工作目录也发生了一些奇怪的事情。 尝试“ Shell> pwd”,甚至“ Shell> ls / home /”。

无论如何,我认为我可以通过在fget之后紧接着删除“ buffer”字符串末尾的'\\ n'字符来解决此问题。 看看是否适合您:

 fgets(buffer, 512, stdin);
 int j = strlen(buffer) - 1;
 if (buffer[j] == '\n')
     buffer[j] = 0;

对于我为什么还发生奇怪的CWD行为,我仍然是个谜。

希望这可以帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM