📄 ui.c
字号:
/* fdisk - Linux fdisk clone This file originally from GNU Parted. Copyright (C) 1999, 2000, 2001, 2002, 2006 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA*/#include <parted/parted.h>#include <parted/debug.h>#include <ctype.h>#include <signal.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <setjmp.h>#include "config.h"#include "command.h"#include "strlist.h"#include "ui.h"#define N_(String) String#if ENABLE_NLS# include <libintl.h># include <locale.h># define _(String) dgettext (PACKAGE, String)#else# define _(String) (String)#endif /* ENABLE_NLS */#ifdef HAVE_LIBREADLINE#ifdef HAVE_TERMCAP_H#include <termcap.h>#elseextern int tgetnum (char* key);#endif#include <readline/readline.h>#include <readline/history.h>#ifndef HAVE_RL_COMPLETION_MATCHES#define rl_completion_matches completion_matches#endif#ifndef rl_compentry_func_t#define rl_compentry_func_t void#endif#endif /* HAVE_LIBREADLINE */char* interface_name = "GNU Fdisk " VERSION;static char* banner_msg = N_("Copyright (C) 1998 - 2006 Free Software Foundation, Inc.\n""This program is free software, covered by the GNU General Public License.\n""\n""This program is distributed in the hope that it will be useful, ""but WITHOUT ANY WARRANTY; without even the implied warranty of ""MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ""GNU General Public License for more details.\n\n");static char* usage_msg = N_("Usage: fdisk [OPTION]... [DEVICE]\n"); static char* bug_msg = N_("You found a bug in GNU Fdisk.\n""This may have been fixed in the last version of GNU Parted that you can find at:\n""\thttp://ftp.gnu.org/gnu/parted/\n\n""Please check this version prior to bug reporting.\n\n""If this has not been fixed yet or if you don't know how to check, please email:\n""\tbug-parted@gnu.org\n""or (preferably) file a bug report at:\n""\thttp://parted.alioth.debian.org/bugs/\n\n""Your report should contain the version of this release (%s) along with the\n""error message below, the output of\n""\tparted DEVICE unit co print unit s print\n""and additional information about your setup you consider important.\n");#define MAX_WORDS 1024static StrList* command_line;static FdiskCommand** commands;static StrList* ex_opt_str [64];static StrList* on_list;static StrList* off_list;static StrList* on_off_list;static StrList* fs_type_list;static StrList* disk_type_list;static struct { const StrList* possibilities; const StrList* cur_pos; int in_readline; sigjmp_buf jmp_state;} readline_state;static PedExceptionOption current_exception_opt = 0;/* If we don't want the possibilities to appear on the prompt, this should be set to 0. TODO: Making this without a global variable might be a good idea */static prompt_possibilities = 1;#ifdef HAVE_LIBREADLINE/* returns matching commands for text */static char*command_generator (char* text, int state){ if (!state) readline_state.cur_pos = readline_state.possibilities; while (readline_state.cur_pos) { const StrList* cur = readline_state.cur_pos; readline_state.cur_pos = cur->next; if (str_list_match_node (cur, text)) return str_list_convert_node (cur); } return NULL;}/* completion function for readline() */char**fdisk_complete_function (char* text, int start, int end){ return rl_completion_matches (text, (rl_compentry_func_t*) command_generator);}static void_add_history_unique (const char* line){ HIST_ENTRY* last_entry = current_history (); if (!strlen (line)) return; if (!last_entry || strcmp (last_entry->line, line)) add_history ((char*) line);}#endif /* HAVE_LIBREADLINE */static voidinterrupt_handler (int signum){ int in_readline = readline_state.in_readline; readline_state.in_readline = 0; signal (signum, &interrupt_handler); if (in_readline) { printf ("\n"); siglongjmp (readline_state.jmp_state, 1); }}static char*_readline (const char* prompt, const StrList* possibilities){ char* line; readline_state.possibilities = possibilities; readline_state.cur_pos = NULL; readline_state.in_readline = 1; if (sigsetjmp (readline_state.jmp_state, 1)) return NULL; fdisk_wipe_line ();#ifdef HAVE_LIBREADLINE if (!fdisk_opt_script_mode) { /* XXX: why isn't prompt const? */ line = readline ((char*) prompt); if (line) _add_history_unique (line); } else#endif { printf ("%s", prompt); fflush (stdout); line = (char*) malloc (256); if (fgets (line, 256, stdin) && strcmp (line, "") != 0) { line [strlen (line) - 1] = 0; /* kill trailing CR */ } else { free (line); line = NULL; } } readline_state.in_readline = 0; return line;}static PedExceptionOptionoption_get_next (PedExceptionOption options, PedExceptionOption current){ PedExceptionOption i; if (current == 0) i = PED_EXCEPTION_OPTION_FIRST; else i = current * 2; for (; i <= options; i *= 2) { if (options & i) return i; } return 0;}static void_print_exception_text (PedException* ex){ StrList* text; fdisk_wipe_line (); if (ex->type == PED_EXCEPTION_BUG) { printf (bug_msg, VERSION); text = str_list_create ("\n", ex->message, "\n", NULL); } else { text = str_list_create ( _(ped_exception_get_type_string (ex->type)), ": ", ex->message, "\n", NULL); } str_list_print_wrap (text, fdisk_screen_width (), 0, 0); str_list_destroy (text);}static PedExceptionOptionexception_handler (PedException* ex){ PedExceptionOption opt; _print_exception_text (ex); /* only one choice? Take it ;-) */ opt = option_get_next (ex->options, 0); if (!option_get_next (ex->options, opt)) return opt; /* script-mode: don't handle the exception */ if (fdisk_opt_script_mode) return PED_EXCEPTION_UNHANDLED; do { opt = fdisk_command_line_get_ex_opt ("", ex->options); } while (opt == PED_EXCEPTION_UNHANDLED && isatty (0)); return opt;}static int_str_is_spaces (const char* str){ while (isspace (*str)) str++; return *str == 0;}static char*realloc_and_cat (char* str, const char* append){ int length = strlen (str) + strlen (append) + 1; char* new_str = realloc (str, length); strcat (new_str, append); return new_str;}static char*_construct_prompt (const char* head, const char* def, const StrList* possibilities){ char* prompt = strdup (head); if (def && possibilities) PED_ASSERT (str_list_match_any (possibilities, def), return NULL); if (possibilities && prompt_possibilities && str_list_length (possibilities) < 8) { const StrList* walk; if (strlen (prompt)) prompt = realloc_and_cat (prompt, " "); for (walk = possibilities; walk; walk = walk->next) { if (walk != possibilities) prompt = realloc_and_cat (prompt, "/"); if (def && str_list_match_node (walk, def) == 2) { prompt = realloc_and_cat (prompt, "["); prompt = realloc_and_cat (prompt, def); prompt = realloc_and_cat (prompt, "]"); } else { char* text = str_list_convert_node (walk); prompt = realloc_and_cat (prompt, text); free (text); } } prompt = realloc_and_cat (prompt, ": "); } else if (def) { size_t len = strlen (prompt); if (len && prompt[len-1] != '\n') prompt = realloc_and_cat (prompt, " "); prompt = realloc_and_cat (prompt, "(default "); prompt = realloc_and_cat (prompt, def); prompt = realloc_and_cat (prompt, "): "); } else { size_t len = strlen (prompt); if (len && prompt[--len] != '\n') { if (prompt[len] == ':' || prompt[len] == '?') prompt = realloc_and_cat (prompt, " "); else prompt = realloc_and_cat (prompt, ": "); } } return prompt;}static int_can_create_primary (const PedDisk* disk){ int i; for (i = 1; i <= ped_disk_get_max_primary_partition_count (disk); i++) { if (!ped_disk_get_partition (disk, i)) return 1; } return 0;}static int_can_create_extended (const PedDisk* disk){ if (!_can_create_primary (disk)) return 0; if (!ped_disk_type_check_feature (disk->type, PED_DISK_TYPE_EXTENDED)) return 0; if (ped_disk_extended_partition (disk)) return 0; return 1;}static int_can_create_logical (const PedDisk* disk){ if (!ped_disk_type_check_feature (disk->type, PED_DISK_TYPE_EXTENDED)) return 0; return ped_disk_extended_partition (disk) != 0;}static intinit_ex_opt_str (){ int i; PedExceptionOption opt; for (i = 0; (1 << i) <= PED_EXCEPTION_OPTION_LAST; i++) { opt = (1 << i); ex_opt_str [i] = str_list_create ( ped_exception_get_option_string (opt), _(ped_exception_get_option_string (opt)), NULL); if (!ex_opt_str [i]) return 0; } ex_opt_str [i] = NULL; return 1;}static voiddone_ex_opt_str (){ int i; for (i=0; ex_opt_str [i]; i++) str_list_destroy (ex_opt_str [i]);}static intinit_state_str (){ on_list = str_list_create_unique (_("on"), "on", NULL); off_list = str_list_create_unique (_("off"), "off", NULL); on_off_list = str_list_join (str_list_duplicate (on_list), str_list_duplicate (off_list)); return 1;}static voiddone_state_str (){ str_list_destroy (on_list); str_list_destroy (off_list); str_list_destroy (on_off_list);}static intinit_fs_type_str (){ PedFileSystemType* walk; fs_type_list = NULL; for (walk = ped_file_system_type_get_next (NULL); walk; walk = ped_file_system_type_get_next (walk)) { fs_type_list = str_list_insert (fs_type_list, walk->name); if (!fs_type_list) return 0; } return 1;}static intinit_disk_type_str (){ PedDiskType* walk; disk_type_list = NULL; for (walk = ped_disk_type_get_next (NULL); walk; walk = ped_disk_type_get_next (walk)) { disk_type_list = str_list_insert (disk_type_list, walk->name); if (!disk_type_list) return 0; } return 1;}void fdisk_usage_msg() { printf (_(usage_msg));}voidfdisk_help_msg (){ fdisk_usage_msg(); printf ("\n%s\n", _("OPTIONs:")); fdisk_print_options_help ();/* printf ("\n%s\n", _("COMMANDs:")); fdisk_print_commands_help ((FdiskCommand**)NULL);*/ exit (0);}intfdisk_interactive_mode (PedDisk** disk, FdiskCommand* cmd_list[]){ char* line; StrList* list; StrList* command_names = fdisk_command_get_names (cmd_list); printf ("%s\n", interface_name); list = str_list_create (_(banner_msg), NULL); str_list_print_wrap (list, fdisk_screen_width (), 0, 0); str_list_destroy (list); fdisk_print_using_dev ((*disk)->dev); while (1) { char* word; FdiskCommand* cmd; commands = cmd_list; /* FIXME yucky, nasty, evil hack */ while (!fdisk_command_line_get_word_count ()) { if (feof (stdin)) { printf ("\n"); return 1; } prompt_possibilities = 0; fdisk_command_line_prompt_words ("Command (m for help):", NULL, command_names, 1); prompt_possibilities = 1; } word = fdisk_command_line_pop_word (); if (word) { cmd = fdisk_command_get (commands, word); free (word); if (cmd) { if (!fdisk_command_run (cmd, disk)) fdisk_command_line_flush (); } else { fdisk_print_commands_help (commands); } } } return 1;}/* If menu equals: * 0 - expert menu. * 1 - filesystem menu. * 2 - bsd menu */intfdisk_interactive_menu (PedDisk** disk, FdiskCommand* cmd_list[], int menu){ char* line; StrList* list; StrList* command_names = fdisk_command_get_names (cmd_list); /* FIXME yucky, nasty, evil hack */ FdiskCommand **saved_commands = commands; commands = cmd_list; while (1) { char* word; FdiskCommand* cmd; while (!fdisk_command_line_get_word_count ()) { if (feof (stdin)) { printf ("\n"); commands = saved_commands; return 1; } prompt_possibilities = 0; if (!menu) fdisk_command_line_prompt_words ("Expert command (m for help)", NULL, command_names, 1); else if (menu == 1) fdisk_command_line_prompt_words ("Filesystem (m for help)", NULL, command_names, 1); else if (menu == 2) fdisk_command_line_prompt_words ("BSD disklabel command (m for help)", NULL, command_names, 1); prompt_possibilities = 1; } word = fdisk_command_line_pop_word (); if (word) { cmd = fdisk_command_get (commands, word); free (word); if (cmd) { if (strcmp ((char *)cmd->names->str, "r")) { if (!fdisk_command_run (cmd, disk)) fdisk_command_line_flush (); } else { commands = saved_commands; return 1; } } else { fdisk_print_commands_help ((FdiskCommand **)NULL); } } } commands = saved_commands; return 1;}/* Prompt the user to answer a yes or no question. */intcommand_line_prompt_boolean_question (const char* prompt) { char *user_ans; StrList *possibilities = str_list_create (_("yes"), _("no"), NULL); user_ans = fdisk_command_line_get_word (_(prompt), _("no"), possibilities, 0); if (strcmp (user_ans, _("yes")) == 0) return 1; /* user answered no */ return 0;}intfdisk_screen_width (){ int width = 0; if (fdisk_opt_script_mode) return 32768; /* no wrapping ;) *//* HACK: don't specify termcap separately - it'll annoy the users. */#ifdef HAVE_LIBREADLINE width = tgetnum ("co");#endif if (width <= 0) width = 80; return width;}voidfdisk_wipe_line (){ if (fdisk_opt_script_mode) return; /* yuck */ printf ("\r \r" );}PedExceptionOptionfdisk_command_line_get_ex_opt (const char* prompt, PedExceptionOption options){ Option optlist[10]; PedExceptionOption opt; const char* opt_name; int i = 0, result; for (opt = option_get_next (options, 0); opt && i < sizeof(optlist) - 1; opt = option_get_next (options, opt), i++) { opt_name = ped_exception_get_option_string (opt); optlist[i].option = tolower(opt_name[0]); /* FIXME: Localization here won't work this way */ optlist[i].description = _(ped_exception_get_option_string (opt)); } optlist[i].option = 0; result = fdisk_command_line_get_option (prompt, optlist); if (!result) return PED_EXCEPTION_UNHANDLED; for (opt = option_get_next (options, 0); opt; opt = option_get_next (options, opt)) { opt_name = ped_exception_get_option_string (opt); if (result == tolower(opt_name[0])) break; } return opt;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -