|
|
|
@ -3,166 +3,185 @@
|
|
|
|
|
* Released under the terms of the GNU GPL v2.0.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <locale.h>
|
|
|
|
|
#include <ctype.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <time.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <getopt.h>
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
#include <sys/time.h>
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
|
|
#include "lkc.h"
|
|
|
|
|
|
|
|
|
|
static void conf(struct menu *menu);
|
|
|
|
|
static void check_conf(struct menu *menu);
|
|
|
|
|
static void xfgets(char *str, int size, FILE *in);
|
|
|
|
|
|
|
|
|
|
#include <locale.h> // 引入本地化相关功能的头文件
|
|
|
|
|
#include <ctype.h> // 引入字符处理函数的头文件,例如 isspace、isdigit 等
|
|
|
|
|
#include <stdio.h> // 引入标准输入输出库
|
|
|
|
|
#include <stdlib.h> // 引入标准库,提供内存管理、程序退出等功能
|
|
|
|
|
#include <string.h> // 引入字符串处理函数库
|
|
|
|
|
#include <time.h> // 引入时间日期相关函数
|
|
|
|
|
#include <unistd.h> // 引入 Unix 系统 API,提供与系统交互的功能
|
|
|
|
|
#include <getopt.h> // 引入命令行参数解析函数
|
|
|
|
|
#include <sys/stat.h> // 引入文件状态函数
|
|
|
|
|
#include <sys/time.h> // 引入时间管理函数
|
|
|
|
|
#include <errno.h> // 引入错误码定义
|
|
|
|
|
#include "lkc.h" // 引入项目自定义的头文件
|
|
|
|
|
|
|
|
|
|
// 函数声明
|
|
|
|
|
static void conf(struct menu *menu); // 配置函数
|
|
|
|
|
static void check_conf(struct menu *menu); // 检查配置函数
|
|
|
|
|
static void xfgets(char *str, int size, FILE *in); // 自定义的 fgets 函数
|
|
|
|
|
|
|
|
|
|
// 定义输入模式枚举类型
|
|
|
|
|
enum input_mode {
|
|
|
|
|
oldaskconfig,
|
|
|
|
|
silentoldconfig,
|
|
|
|
|
oldconfig,
|
|
|
|
|
allnoconfig,
|
|
|
|
|
allyesconfig,
|
|
|
|
|
allmodconfig,
|
|
|
|
|
alldefconfig,
|
|
|
|
|
randconfig,
|
|
|
|
|
defconfig,
|
|
|
|
|
savedefconfig,
|
|
|
|
|
listnewconfig,
|
|
|
|
|
olddefconfig,
|
|
|
|
|
} input_mode = oldaskconfig;
|
|
|
|
|
|
|
|
|
|
static int indent = 1;
|
|
|
|
|
static int tty_stdio;
|
|
|
|
|
static int valid_stdin = 1;
|
|
|
|
|
static int sync_kconfig;
|
|
|
|
|
static int conf_cnt;
|
|
|
|
|
static char line[128];
|
|
|
|
|
static struct menu *rootEntry;
|
|
|
|
|
|
|
|
|
|
oldaskconfig, // 用户交互模式
|
|
|
|
|
silentoldconfig, // 无用户交互模式,使用默认值
|
|
|
|
|
oldconfig, // 使用旧的配置
|
|
|
|
|
allnoconfig, // 所有选项都为 no
|
|
|
|
|
allyesconfig, // 所有选项都为 yes
|
|
|
|
|
allmodconfig, // 所有选项都为模块
|
|
|
|
|
alldefconfig, // 所有选项都为默认值
|
|
|
|
|
randconfig, // 随机配置
|
|
|
|
|
defconfig, // 使用默认配置
|
|
|
|
|
savedefconfig, // 保存默认配置
|
|
|
|
|
listnewconfig, // 列出新的配置项
|
|
|
|
|
olddefconfig, // 使用旧的默认配置
|
|
|
|
|
} input_mode = oldaskconfig; // 设置默认输入模式为 oldaskconfig
|
|
|
|
|
|
|
|
|
|
// 静态变量声明
|
|
|
|
|
static int indent = 1; // 配置输出时的缩进级别
|
|
|
|
|
static int tty_stdio; // 标识标准输入输出是否是终端设备
|
|
|
|
|
static int valid_stdin = 1; // 标识标准输入是否有效
|
|
|
|
|
static int sync_kconfig; // 同步配置标志
|
|
|
|
|
static int conf_cnt; // 配置项计数器
|
|
|
|
|
static char line[128]; // 用于存储输入行的缓冲区
|
|
|
|
|
static struct menu *rootEntry; // 配置菜单的根节点指针
|
|
|
|
|
|
|
|
|
|
// 打印帮助信息
|
|
|
|
|
static void print_help(struct menu *menu)
|
|
|
|
|
{
|
|
|
|
|
struct gstr help = str_new();
|
|
|
|
|
struct gstr help = str_new(); // 创建一个新的字符串对象
|
|
|
|
|
|
|
|
|
|
menu_get_ext_help(menu, &help);
|
|
|
|
|
menu_get_ext_help(menu, &help); // 获取菜单项的扩展帮助信息
|
|
|
|
|
|
|
|
|
|
printf("\n%s\n", str_get(&help));
|
|
|
|
|
str_free(&help);
|
|
|
|
|
printf("\n%s\n", str_get(&help)); // 打印帮助信息
|
|
|
|
|
str_free(&help); // 释放帮助字符串资源
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 去除字符串两端的空白字符
|
|
|
|
|
static void strip(char *str)
|
|
|
|
|
{
|
|
|
|
|
char *p = str;
|
|
|
|
|
int l;
|
|
|
|
|
|
|
|
|
|
while ((isspace(*p)))
|
|
|
|
|
p++;
|
|
|
|
|
l = strlen(p);
|
|
|
|
|
if (p != str)
|
|
|
|
|
memmove(str, p, l + 1);
|
|
|
|
|
if (!l)
|
|
|
|
|
return;
|
|
|
|
|
p = str + l - 1;
|
|
|
|
|
while ((isspace(*p)))
|
|
|
|
|
*p-- = 0;
|
|
|
|
|
char *p = str;
|
|
|
|
|
int l;
|
|
|
|
|
|
|
|
|
|
// 跳过前导空格
|
|
|
|
|
while ((isspace(*p)))
|
|
|
|
|
p++;
|
|
|
|
|
|
|
|
|
|
l = strlen(p); // 获取字符串的长度
|
|
|
|
|
if (p != str) // 如果有前导空格,移动字符串内容
|
|
|
|
|
memmove(str, p, l + 1);
|
|
|
|
|
|
|
|
|
|
if (!l) // 如果字符串为空,返回
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// 去除尾部空格
|
|
|
|
|
p = str + l - 1;
|
|
|
|
|
while ((isspace(*p))) // 从字符串末尾向前查找空格并去除
|
|
|
|
|
*p-- = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 检查标准输入是否有效
|
|
|
|
|
static void check_stdin(void)
|
|
|
|
|
{
|
|
|
|
|
if (!valid_stdin) {
|
|
|
|
|
printf(_("aborted!\n\n"));
|
|
|
|
|
printf(_("Console input/output is redirected. "));
|
|
|
|
|
printf(_("Run 'make oldconfig' to update configuration.\n\n"));
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
if (!valid_stdin) { // 如果标准输入无效
|
|
|
|
|
printf(_("aborted!\n\n"));
|
|
|
|
|
printf(_("Console input/output is redirected. "));
|
|
|
|
|
printf(_("Run 'make oldconfig' to update configuration.\n\n"));
|
|
|
|
|
exit(1); // 退出程序
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 配置选项的处理函数
|
|
|
|
|
static int conf_askvalue(struct symbol *sym, const char *def)
|
|
|
|
|
{
|
|
|
|
|
enum symbol_type type = sym_get_type(sym);
|
|
|
|
|
|
|
|
|
|
if (!sym_has_value(sym))
|
|
|
|
|
printf(_("(NEW) "));
|
|
|
|
|
|
|
|
|
|
line[0] = '\n';
|
|
|
|
|
line[1] = 0;
|
|
|
|
|
|
|
|
|
|
if (!sym_is_changable(sym)) {
|
|
|
|
|
printf("%s\n", def);
|
|
|
|
|
line[0] = '\n';
|
|
|
|
|
line[1] = 0;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (input_mode) {
|
|
|
|
|
case oldconfig:
|
|
|
|
|
case silentoldconfig:
|
|
|
|
|
if (sym_has_value(sym)) {
|
|
|
|
|
printf("%s\n", def);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
check_stdin();
|
|
|
|
|
/* fall through */
|
|
|
|
|
case oldaskconfig:
|
|
|
|
|
fflush(stdout);
|
|
|
|
|
xfgets(line, 128, stdin);
|
|
|
|
|
if (!tty_stdio)
|
|
|
|
|
printf("\n");
|
|
|
|
|
return 1;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
|
case S_INT:
|
|
|
|
|
case S_HEX:
|
|
|
|
|
case S_STRING:
|
|
|
|
|
printf("%s\n", def);
|
|
|
|
|
return 1;
|
|
|
|
|
default:
|
|
|
|
|
;
|
|
|
|
|
}
|
|
|
|
|
printf("%s", line);
|
|
|
|
|
return 1;
|
|
|
|
|
enum symbol_type type = sym_get_type(sym); // 获取符号的类型
|
|
|
|
|
|
|
|
|
|
if (!sym_has_value(sym)) // 如果没有值,标记为新选项
|
|
|
|
|
printf(_("(NEW) "));
|
|
|
|
|
|
|
|
|
|
line[0] = '\n';
|
|
|
|
|
line[1] = 0;
|
|
|
|
|
|
|
|
|
|
if (!sym_is_changable(sym)) { // 如果符号不可修改,直接输出默认值
|
|
|
|
|
printf("%s\n", def);
|
|
|
|
|
line[0] = '\n';
|
|
|
|
|
line[1] = 0;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 根据输入模式不同执行不同的操作
|
|
|
|
|
switch (input_mode) {
|
|
|
|
|
case oldconfig:
|
|
|
|
|
case silentoldconfig:
|
|
|
|
|
if (sym_has_value(sym)) { // 如果已有值,直接输出默认值
|
|
|
|
|
printf("%s\n", def);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
check_stdin(); // 检查标准输入有效性
|
|
|
|
|
/* fall through */
|
|
|
|
|
case oldaskconfig:
|
|
|
|
|
fflush(stdout); // 刷新标准输出缓冲区
|
|
|
|
|
xfgets(line, 128, stdin); // 获取用户输入
|
|
|
|
|
if (!tty_stdio) // 如果标准输入不是终端,换行
|
|
|
|
|
printf("\n");
|
|
|
|
|
return 1;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 根据符号类型进行处理
|
|
|
|
|
switch (type) {
|
|
|
|
|
case S_INT:
|
|
|
|
|
case S_HEX:
|
|
|
|
|
case S_STRING:
|
|
|
|
|
printf("%s\n", def);
|
|
|
|
|
return 1;
|
|
|
|
|
default:
|
|
|
|
|
;
|
|
|
|
|
}
|
|
|
|
|
printf("%s", line); // 输出用户输入的内容
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 配置字符串类型的处理函数
|
|
|
|
|
static int conf_string(struct menu *menu)
|
|
|
|
|
{
|
|
|
|
|
struct symbol *sym = menu->sym;
|
|
|
|
|
const char *def;
|
|
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
|
printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
|
|
|
|
|
printf("(%s) ", sym->name);
|
|
|
|
|
def = sym_get_string_value(sym);
|
|
|
|
|
if (sym_get_string_value(sym))
|
|
|
|
|
printf("[%s] ", def);
|
|
|
|
|
if (!conf_askvalue(sym, def))
|
|
|
|
|
return 0;
|
|
|
|
|
switch (line[0]) {
|
|
|
|
|
case '\n':
|
|
|
|
|
break;
|
|
|
|
|
case '?':
|
|
|
|
|
/* print help */
|
|
|
|
|
if (line[1] == '\n') {
|
|
|
|
|
print_help(menu);
|
|
|
|
|
def = NULL;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
/* fall through */
|
|
|
|
|
default:
|
|
|
|
|
line[strlen(line)-1] = 0;
|
|
|
|
|
def = line;
|
|
|
|
|
}
|
|
|
|
|
if (def && sym_set_string_value(sym, def))
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
struct symbol *sym = menu->sym;
|
|
|
|
|
const char *def;
|
|
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
|
printf("%*s%s ", indent - 1, "", _(menu->prompt->text)); // 打印菜单提示
|
|
|
|
|
printf("(%s) ", sym->name); // 打印符号名称
|
|
|
|
|
def = sym_get_string_value(sym); // 获取符号的默认字符串值
|
|
|
|
|
if (def) // 如果有默认值,打印出来
|
|
|
|
|
printf("[%s] ", def);
|
|
|
|
|
if (!conf_askvalue(sym, def)) // 获取用户输入并处理
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
// 根据用户输入的内容进行处理
|
|
|
|
|
switch (line[0]) {
|
|
|
|
|
case '\n':
|
|
|
|
|
break; // 如果用户没有输入内容,继续
|
|
|
|
|
case '?':
|
|
|
|
|
// 打印帮助信息
|
|
|
|
|
if (line[1] == '\n') {
|
|
|
|
|
print_help(menu); // 打印帮助
|
|
|
|
|
def = NULL;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
/* fall through */
|
|
|
|
|
default:
|
|
|
|
|
line[strlen(line) - 1] = 0; // 去掉换行符
|
|
|
|
|
def = line; // 将用户输入的内容赋给 def
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置符号的字符串值
|
|
|
|
|
if (def && sym_set_string_value(sym, def))
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int conf_sym(struct menu *menu)
|
|
|
|
|
{
|
|
|
|
|
struct symbol *sym = menu->sym;
|
|
|
|
|