我正在创建一个shell,我已经有一段时间没有使用C了。我已经正确初始化了shell,但当我试图将用户输入与字符串数组进行比较时,我会遇到分段错误。我计划在for循环中添加casce语句,以便在用户调用每个进程时启动它们。自从我试图弄清楚如何让用户输入与字符串数组中的值匹配以来,我还没有包括这些。在调试过程中,我只收到了内置[j]值的第一个字符,这是因为它是一个指针。然而,我被卡住了,可以用一些想法来解释为什么当我输入"退出"时没有返回0。感谢
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
//This code is for creating a basic shell
void init_shell(int num, char *prompt[]){
char s1[] = "-p";
int result;
if(num>1){
result = strcmp(s1, prompt[1]);
if(result==0){
printf("%s>$", prompt[2]);
}else{
printf("308sh>$");
}
}
//printf("%sn %sn %sn %dn", prompt[0], prompt[1], prompt[2], result);
else{
printf("308sh>$");
}
}
//接受用户输入直到关闭的无限循环
int main(int argc, char *argv[]){
const char *builtins[7];
builtins[0] = "exitn";
builtins[1] = "pidn";
builtins[2] = "ppidn";
builtins[3] = "cdn";
builtins[4] = "pwdn";
builtins[5] = "setn";
builtins[6] = "getn";
char usr_in[]="";
char cmp[]="";
while(1==1){
init_shell(argc, argv);//intial prompt for the shell
fgets(usr_in,100,stdin);
//Check for builtin Commands
int cmds_size = 7;
int j=0;
int res;
for(j; j<cmds_size; j++){
res=strcmp(usr_in, hold);
if(res==0){
printf("Execuctingn");
}
else{
printf("no commandn");
}
}
}
return(0);
}
这里的问题是,您将用户的输入写入的缓冲区不够大,无法容纳除null终止符之外的任何内容。
char user_in[] = "";
上面的行告诉C编译器,您只需要足够的空间来存储[ ' ' ]
,这是一个单字节。C编译器不知道您以后可能会向该缓冲区写入一个100字节的字符串。
当您向缓冲区写入时,用户的输入溢出,并将覆盖堆栈中的其他值。由于堆栈中的其他值都是指针,因此会遇到seg错误,因为您将字符值写入这些字节,但将其解释为字符指针。
您正确地将允许用户输入的大小限制为100个字符,但您应该确保您的缓冲区足够大,可以容纳您正在读取的值:
char user_in[101];
for(int i = 0; i < sizeof(user_in) / sizeof(user_in[0]); i++) {
user_in[i] = 0; // Since this is allocated on the stack *in main*, this
// shouldn't be necessary
}
下面是一个如何重写主要方法的例子:
#include <stdio.h>
#include <string.h>
typedef enum { false, true } bool; // If you don't have this
// defined already
int main(int argc, char *argv[]) {
const char *builtins[7];
builtins[0] = "exitn";
builtins[1] = "pidn";
builtins[2] = "ppidn";
builtins[3] = "cdn";
builtins[4] = "pwdn";
builtins[5] = "setn";
builtins[6] = "getn";
char user_in[101];
for(int i = 0; i < sizeof(user_in) / sizeof(user_in[0]); i++) {
user_in[i] = 0;
}
while(1) {
printf("Enter a command: ");
fgets(user_in, 100, stdin);
bool found = false;
for(int i = 0; i < sizeof(builtins) / sizeof(builtins[0]); i++) {
if (!strcmp(user_in, builtins[i])) {
printf("Found command %s", builtins[i]);
found = true;
break;
}
}
if (!found) {
printf("Didn't find commandn");
}
}
return 0;
}
此外,关于函数init_shell
:您正在检查argc是否大于1,但这只能保证定义了argv[1]
;不能保证定义了CCD_ 4。(记住,argc是argv数组的大小,其中第一个元素是正在执行的程序的名称)。在检查提示标志之前,您需要确保argc至少为3。
对于您的用例来说,这可能有些过头了,但可以考虑使用getopt
函数从用户那里获取自定义提示值。看见http://man7.org/linux/man-pages/man3/getopt.3.html有关该方法的文档。