我现在拥有的代码将提示发送到标准输出,然后从标准输入读取一行。在任何时候接收SIGINT
都会中断执行并退出程序。我不确定我应该在哪里捕获SIGINT
,并且我知道当我当前的代码收到信号时我无法启动新的提示。是否有适当的方法来实现这一点(最终目标是让它像大多数 shell 一样工作(SIGINT 取消当前提示并开始一个新提示))?
此代码将在 Linux 上运行,但平台独立性越低越好。
get_line
从标准输入读取一行到缓冲区并生成一个 char[],分配给 line。
split_args
取一行并将其转换为 char[] 数组,在空白处拆分。
is_command_valid
确定用户是否键入了已知的内部命令。无法执行外部程序。
static int run_interactive(char *user)
{
int done = 0;
do
{
char *line, **args;
int (*fn)(char *, char **);
fprintf(stderr, "gitorium (%s)> ", user);
get_line(&line);
if (line[0] == '\0')
{
free(line);
break;
}
split_args(&args, line);
if (!strcmp(args[0], "quit") || !strcmp(args[0], "exit") ||
!strcmp(args[0], "logout") || !strcmp(args[0], "bye"))
done = 1;
else if (NULL == args[0] ||
(!strcmp("help", args[0]) && NULL == args[1]))
interactive_help();
else if ((fn = is_command_valid(args)) != NULL)
(*fn)(user, args);
else
error("The command does not exist.");
free(line);
free(args);
}
while (!done);
return 0;
}
这是两个最重要的辅助函数
static int split_args(char ***args, char *str)
{
char **res = NULL, *p = strtok(str, " ");
int n_spaces = 0, i = 0;
while (p)
{
res = realloc(res, sizeof (char*) * ++n_spaces);
if (res == NULL)
return GITORIUM_MEM_ALLOC;
res[n_spaces-1] = p;
i++;
p = strtok(NULL, " ");
}
res = realloc(res, sizeof(char*) * (n_spaces+1));
if (res == NULL)
return GITORIUM_MEM_ALLOC;
res[n_spaces] = 0;
*args = res;
return i;
}
static int get_line(char **linep)
{
char *line = malloc(LINE_BUFFER_SIZE);
int len = LINE_BUFFER_SIZE, c;
*linep = line;
if(line == NULL)
return GITORIUM_MEM_ALLOC;
for(;;)
{
c = fgetc(stdin);
if(c == EOF || c == '\n')
break;
if(--len == 0)
{
char *linen = realloc(*linep, sizeof *linep + LINE_BUFFER_SIZE);
if(linen == NULL)
return GITORIUM_MEM_ALLOC;
len = LINE_BUFFER_SIZE;
line = linen + (line - *linep);
*linep = linen;
}
*line++ = c;
}
*line = 0;
return 0;
}