我想运行一个小的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)来退出循环)
我可能误解了这个问题,但是你的程序不会看到管道字符|
。
shell处理整个命令行,你的程序只会被分配给命令行,可以这么说。
例:
cat file1 file2 | sed s/frog/bat/
在上面的例子中,只用两个参数file1
和file2
来调用cat
。 另外, sed
只用一个参数调用: s/frog/bat/
。
让我们看看你的代码:
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的一个特定分支上所做的所有检查)。 这是我使用的符号很重要。 (是的,它可能会被优化 – 这是不值得这样做的。)同样,这不一定是你现在需要处理的 – 但它确实给你一个你需要去的地方。