Проблема здесь в том, что вы записываете пользовательские данные в буфер, который недостаточно велик для хранения чего-либо, кроме нулевого терминатора.
char user_in[] = "";
В приведенной выше строке сообщается компилятору C, чтовам нужно достаточно места для хранения [ '\0' ]
, то есть одного байта.Компилятор C не знает, что вы можете позже написать 100-байтовую строку в этот буфер.
Когда вы записываете в буфер, пользовательский ввод переполняется и перезаписывает другие значения в вашем стеке.Поскольку другие значения в вашем стеке являются указателями, то произойдет то, что вы столкнетесь с ошибками сегмента, поскольку вы записываете символьные значения в эти байты, но интерпретируете их как указатели на символы.
правильно ограничив размер разрешенного ввода от пользователя до 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] = "exit\n";
builtins[1] = "pid\n";
builtins[2] = "ppid\n";
builtins[3] = "cd\n";
builtins[4] = "pwd\n";
builtins[5] = "set\n";
builtins[6] = "get\n";
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 command\n");
}
}
return 0;
}
Кроме того, относительно вашей функции init_shell
: вы проверяете, является ли argc больше 1, но это только гарантирует, что определено argv[1]
;это не гарантирует, что argv[2]
определен.(Помните, argc - это размер массива argv, где первый элемент - это имя выполняемой программы).Вы должны убедиться, что argc равен по крайней мере 3, прежде чем проверять наличие флага подсказки в том виде, в каком вы находитесь.
Это может быть излишним для вашего варианта использования, но рассмотрите возможность использования функции getopt
для полученияПользовательское значение подсказки от пользователя.См. http://man7.org/linux/man-pages/man3/getopt.3.html для документации относительно этого метода.