[英]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.