我正在尝试运行一个小型shell程序,确保我的代码正常运行的第一步是确保我获得正确的命令和参数:
//Split the command and store each string in parameter[]
cp = (strtok(command, hash)); //Get the initial string (the command)
parameter[0] = (char*) malloc(strlen(cp)+ 1); //Allocate some space to the first element in the array
strncpy(parameter[0], cp, strlen(cp)+ 1);
for(i = 1; i < MAX_ARG; i++)
{
cp = strtok(NULL, hash); //Check for each string in the array
parameter[i] = (char*) malloc(strlen(cp)+ 1);
strncpy(parameter[i], cp, strlen(cp)+ 1); //Store the result string in an indexed off array
if(parameter[i] == NULL)
{
break;
}
if(strcmp(parameter[i], "|") == 0)
{
cp = strtok(NULL, hash);
parameter2[0] = (char*) malloc(strlen(cp)+ 1);
strncpy(parameter2[0], cp, strlen(cp)+ 1);
//Find the second set of commands and parameters
for (j = 1; j < MAX_ARG; j++)
{
cp = strtok(NULL, hash);
if (strlen(cp) == NULL)
{
break;
}
parameter2[j] = (char*) malloc(strlen(cp)+ 1);
strncpy(parameter2[j], cp, strlen(cp)+ 1);
}
break;
}
当我比较cp和NULL时遇到问题,我的程序崩溃了。我想要的是在第二组或参数的条目完成后退出循环(这是我尝试用if(strlen(cp)== NULL)
答案 0 :(得分:1)
我可能误解了这个问题,但是你的程序不会看到管道符|
。
shell处理整个命令行,你的程序只会得到它在命令行中的份额,可以这么说。
示例:
cat file1 file2 | sed s/frog/bat/
在上面的示例中,仅使用两个参数cat
和file1
调用file2
。此外,仅使用一个参数调用sed
:s/frog/bat/
。
答案 1 :(得分:0)
让我们来看看你的代码:
parameter[0] = malloc(255);
由于strtok()
分割了原始command
数组,因此您无需使用malloc()
分配额外空间;你可以简单地将parameter[n]
指针指向原始命令字符串的相关部分。但是,一旦你超越空格分隔的命令(在一个真实的shell中,|
符号不必被空格包围,但它确实在你的空间中),那么你可能需要复制部分命令字符串,所以这不是完全错误的。
您应该检查内存分配是否成功。
cp = strtok(command, " "); //Get the initial string (the command)
strncpy(parameter[0], cp, 50);
您分配了255个字符;最多复制49.最好等到参数被隔离,然后复制它 - 只分配所需的空间。请注意,如果(通向路径)命令名称为50个字符或更多,则不会有以空字符结尾的字符串 - malloc()
分配的空间不会归零,strncpy()
不会写入超长字符串上的尾随零。
for (i = 1; i < MAX_ARG; i++)
目前尚不清楚您应该对参数的数量设置一个上限。有一个上限,但它通常是所有参数的总长度。
{
parameter[i] = malloc(255);
关于内存分配和检查的类似评论。
cp = strtok(NULL, " ");
parameter[i] = cp;
糟糕!有记忆。抱歉泄漏。
if (strcmp(parameter[i], "|") == 0)
我认为在复制之前进行这种比较可能会更好...而且,你不希望管道在任何一个命令的参数列表中;它是shell的表示法,不是命令参数列表的一部分。您还应确保第一个命令的参数列表以NULL指针终止,特别是因为i
设置在MAX_ARG
的下方,所以您不会知道指定了多少个参数。
{
i = MAX_ARG;
cp = strtok(NULL, " ");
parameter2[0] = malloc(255);
strncpy(parameter2[0], cp, 50);
这感觉奇怪;你隔离命令,然后分别处理它的参数。设置i = MAX_ARG
似乎很有趣,因为你的下一个动作是打破循环。
break;
}
if(parameter[i] == NULL)
{
break;
}
}
//Find the second set of commands and parameter
//strncpy(parameter2[0], cp, 50);
for (j = 1; j < MAX_ARG; j++)
{
parameter2[j] = malloc(255);
cp = strtok(NULL, " ");
parameter2[j] = cp;
}
如果找到管道,您应该只进入此循环。然后这个代码就像另一个代码一样泄漏内存(所以你是一致的 - 一致性很重要;但正确性也是如此)。
您需要检查您的代码以确保它正确处理'无管道符号'和'管道但没有后续命令'。在某些时候,您应该考虑多阶段管道(三,四,......命令)。推广您的代码以处理这种情况。
在为Bash或等效的shell编写代码时,我经常使用这个脚本之类的符号,我今天曾多次使用过这样的符号。
ct find /vobs/somevob \
-branch 'brtype(dev.branch)' \
-version 'created_since(2011-10-11T00:00-00:00)' \
-print |
grep -v '/0$' |
xargs ct des -fmt '%u %d %Vn %En\n' |
grep '^jleffler ' |
sort -k 4 |
awk '{ printf "%-8s %s %-25s %s\n", $1, $2, $3, $4; }'
它的作用并不重要(但是它找到了我自10月11日以来在ClearCase的一个特定分支上制作的所有签到);这是我使用的符号很重要。 (是的,它可能会被优化 - 这不值得这样做。)同样,这不一定是你现在需要处理的 - 但它确实能让你了解你需要去的地方。