ui.c revision 7e7bd3dccbfe8f79e25e5c1554b5bc3a9aaca321
/*
parted - a frontend to libparted
Copyright (C) 1999, 2000, 2001, 2002, 2006, 2007
Free Software Foundation, Inc.
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, see <http://www.gnu.org/licenses/>.
*/
#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"
#include "error.h"
#if ENABLE_NLS
# include <libintl.h>
# include <locale.h>
#else
#endif /* ENABLE_NLS */
#ifdef HAVE_LIBREADLINE
#ifdef HAVE_TERMCAP_H
#include <termcap.h>
#else
#endif
#include <readline/readline.h>
#ifndef HAVE_RL_COMPLETION_MATCHES
#endif
#ifndef rl_compentry_func_t
#define rl_compentry_func_t void
#endif
#endif /* HAVE_LIBREADLINE */
#ifndef SA_SIGINFO
# ifndef HAVE_SIGACTION
struct sigaction {
};
static inline int
{
}
# endif /* HAVE_SIGACTON */
struct siginfo_t {
int si_code;
};
#endif /* SA_SIGINFO */
#ifndef SEGV_MAPERR
#endif
#ifndef SEGV_ACCERR
#endif
#ifndef FPE_INTDIV
#endif
#ifndef FPE_INTOVF
#endif
#ifndef FPE_FLTDIV
#endif
#ifndef FPE_FLTOVF
#endif
#ifndef FPE_FLTUND
#endif
#ifndef FPE_FLTRES
#endif
#ifndef FPE_FLTINV
#endif
#ifndef FPE_FLTSUB
#endif
#ifndef ILL_ILLOPC
#endif
#ifndef ILL_ILLOPN
#endif
#ifndef ILL_ILLADR
#endif
#ifndef ILL_ILLTRP
#endif
#ifndef ILL_PRVOPC
#endif
#ifndef ILL_PRVREG
#endif
#ifndef ILL_COPROC
#endif
#ifndef ILL_BADSTK
#endif
static char* banner_msg = N_(
"Welcome to GNU Parted! Type 'help' to view a list of commands.\n");
"Usage: parted [OPTION]... [DEVICE [COMMAND [PARAMETERS]...]...]\n"
"Apply COMMANDs with PARAMETERS to DEVICE. If no COMMAND(s) are given, "
"run in\ninteractive mode.\n");
"\n\nYou found a bug in GNU Parted! Here's what you have to do:\n\n"
"Don't panic! The bug has most likely not affected any of your data.\n"
"Help us to fix this bug by doing the following:\n\n"
"Check whether the bug has already been fixed by checking\n"
"the last version of GNU Parted that you can find at:\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,\n"
"please visit the GNU Parted website:\n\n"
"for further information.\n\n"
"Your report should contain the version of this release (%s)\n"
"along with the error message below, the output of\n\n"
"\tparted DEVICE unit co print unit s print\n\n"
"and the following history of commands you entered.\n"
"Also include any additional information about your setup you\n"
"consider important.\n");
#define MAX_WORDS 1024
static StrList* command_line;
static StrList* on_off_list;
static StrList* fs_type_list;
static StrList* disk_type_list;
static struct {
const StrList* possibilities;
int in_readline;
volatile int got_ctrl_c = 0; /* used in exception_handler */
int
screen_width ()
{
int width = 0;
if (opt_script_mode || pretend_input_tty)
return 32768; /* no wrapping ;) */
/* HACK: don't specify termcap separately - it'll annoy the users. */
#ifdef HAVE_LIBREADLINE
#endif
if (width <= 0)
width = 80;
return width;
}
void
wipe_line ()
{
if (opt_script_mode)
return;
/* yuck */
fputs ("\r "
" \r", stdout);
}
#ifdef HAVE_LIBREADLINE
/* returns matching commands for text */
static char*
{
if (!state)
while (readline_state.cur_pos) {
return str_list_convert_node (cur);
}
return NULL;
}
/* completion function for readline() */
char**
{
return rl_completion_matches (text,
}
static void
_add_history_unique (const char* line)
{
return;
add_history ((char*) line);
}
/* Prints command history, to be used before aborting */
static void
{
int i = 0;
while (all_entries[i]) {
}
}
#else
/* Print nothing because Readline is absent. */
static inline void
_dump_history (void)
{
}
#endif /* HAVE_LIBREADLINE */
static void
{
sigfillset(&curr);
}
/* Resets the environment by jumping to the initial state
* saved during ui intitialisation.
* Pass 1 as the parameter if you want to quit parted,
* 0 if you just want to reset to the command prompt.
*/
static void
{
if (in_readline) {
putchar ('\n');
if (quit)
exit (0);
}
}
/* Signal handler for SIGINT using 'sigaction'. */
static void
{
if (info)
got_ctrl_c = 1;
reset_env (0);
}
/* Signal handler for SIGINT using 'signal'. */
static void
s_sigint_handler (int signum)
{
mask_signal ();
}
/* Signal handler for SIGSEGV using 'sigaction'. */
static void
{
_dump_history ();
if (!info)
abort ();
case SEGV_MAPERR:
fputs(_("\nError: SEGV_MAPERR (Address not mapped "
"to object)\n"), stdout);
PED_ASSERT(0, break); /* Force a backtrace */
break;
case SEGV_ACCERR:
fputs(_("\nError: SEGV_ACCERR (Invalid permissions "
"for mapped object)\n"), stdout);
break;
default:
fputs(_("\nError: A general SIGSEGV signal was "
"encountered.\n"), stdout);
PED_ASSERT(0, break); /* Force a backtrace */
break;
}
abort ();
}
/* Signal handler for SIGSEGV using 'signal'. */
static void
s_sigsegv_handler (int signum)
{
mask_signal ();
}
/* Signal handler for SIGFPE using 'sigaction'. */
static void
{
_dump_history ();
if (!info)
abort ();
case FPE_INTDIV:
fputs(_("\nError: FPE_INTDIV (Integer: "
"divide by zero)"), stdout);
break;
case FPE_INTOVF:
fputs(_("\nError: FPE_INTOVF (Integer: "
"overflow)"), stdout);
break;
case FPE_FLTDIV:
fputs(_("\nError: FPE_FLTDIV (Float: "
"divide by zero)"), stdout);
break;
case FPE_FLTOVF:
fputs(_("\nError: FPE_FLTOVF (Float: "
"overflow)"), stdout);
break;
case FPE_FLTUND:
fputs(_("\nError: FPE_FLTUND (Float: "
"underflow)"), stdout);
break;
case FPE_FLTRES:
fputs(_("\nError: FPE_FLTRES (Float: "
"inexact result)"), stdout);
break;
case FPE_FLTINV:
fputs(_("\nError: FPE_FLTINV (Float: "
"invalid operation)"), stdout);
break;
case FPE_FLTSUB:
fputs(_("\nError: FPE_FLTSUB (Float: "
"subscript out of range)"), stdout);
break;
default:
fputs(_("\nError: A general SIGFPE signal "
"was encountered."), stdout);
break;
}
abort ();
}
/* Signal handler for SIGFPE using 'signal'. */
static void
s_sigfpe_handler (int signum)
{
mask_signal ();
}
/* Signal handler for SIGILL using 'sigaction'. */
static void
{
_dump_history ();
if (!info)
abort();
case ILL_ILLOPC:
fputs(_("\nError: ILL_ILLOPC "
"(Illegal Opcode)"), stdout);
break;
case ILL_ILLOPN:
fputs(_("\nError: ILL_ILLOPN "
"(Illegal Operand)"), stdout);
break;
case ILL_ILLADR:
fputs(_("\nError: ILL_ILLADR "
"(Illegal addressing mode)"), stdout);
break;
case ILL_ILLTRP:
fputs(_("\nError: ILL_ILLTRP "
"(Illegal Trap)"), stdout);
break;
case ILL_PRVOPC:
fputs(_("\nError: ILL_PRVOPC "
"(Privileged Opcode)"), stdout);
break;
case ILL_PRVREG:
fputs(_("\nError: ILL_PRVREG "
"(Privileged Register)"), stdout);
break;
case ILL_COPROC:
fputs(_("\nError: ILL_COPROC "
"(Coprocessor Error)"), stdout);
break;
case ILL_BADSTK:
fputs(_("\nError: ILL_BADSTK "
"(Internal Stack Error)"), stdout);
break;
default:
fputs(_("\nError: A general SIGILL "
"signal was encountered."), stdout);
break;
}
abort ();
}
/* Signal handler for SIGILL using 'signal'. */
static void
s_sigill_handler (int signum)
{
mask_signal ();
}
static char*
{
char* line;
return NULL;
wipe_line ();
#ifdef HAVE_LIBREADLINE
if (!opt_script_mode) {
/* XXX: why isn't prompt const? */
if (line)
} else
#endif
{
#ifndef HAVE_LIBREADLINE
/* Echo the input line, to be consistent with
how readline-5.2 works. */
#endif
} else {
}
}
return line;
}
static PedExceptionOption
{
if (current == 0)
else
i = current * 2;
for (; i <= options; i *= 2) {
if (options & i)
return i;
}
return 0;
}
static void
{
wipe_line ();
} else {
text = str_list_create (
}
}
static PedExceptionOption
{
/* only one choice? Take it ;-) */
return opt;
/* script-mode: don't handle the exception */
return PED_EXCEPTION_UNHANDLED;
got_ctrl_c = 0;
do {
} while (opt == PED_EXCEPTION_UNHANDLED
if (got_ctrl_c) {
got_ctrl_c = 0;
}
return opt;
}
void
command_line_push_word (const char* word)
{
}
char*
{
char* result;
command_line = next;
return result;
}
void
{
command_line = NULL;
}
char*
{
if (command_line)
return str_list_convert_node (command_line);
else
return NULL;
}
int
{
return str_list_length (command_line);
}
static int
_str_is_spaces (const char* str)
{
str++;
return *str == 0;
}
/* "multi_word mode" is the "normal" mode... many words can be typed,
* delimited by spaces, etc.
* In single-word mode, only one word is parsed per line.
* Leading and trailing spaces are removed. For example: " a b c "
* is a single word "a b c". The motivation for this mode is partition
* names, etc. In single-word mode, the empty string is a word.
* (but not in multi-word mode).
*/
void
{
int quoted = 0;
char quote_char = 0;
char this_word [256];
int i;
do {
while (*line == ' ')
line++;
i = 0;
if (multi_word)
break;
/* single word: check for trailing spaces + eol */
if (_str_is_spaces (line))
break;
}
quoted = 1;
quote_char = *line;
continue;
}
quoted = 0;
continue;
}
/* hack: escape characters */
line++;
}
if (i || !multi_word) {
this_word [i] = 0;
}
} while (*line && multi_word);
}
static char*
{
return new_str;
}
static char*
const StrList* possibilities)
{
if (def && possibilities)
return NULL);
if (walk != possibilities)
} else {
}
}
} else if (def) {
} else {
}
return prompt;
}
void
{
char* line;
char* real_prompt;
int _def_needs_free = 0;
_def_needs_free = 1;
}
if (opt_script_mode) {
if (_def)
command_line_push_line (_def, 0);
return;
}
do {
free (real_prompt);
if (!line)
break;
if (_def)
command_line_push_line (_def, 0);
} else {
}
} while (!command_line_get_word_count () && !_def);
if (_def_needs_free)
}
/**
* Get a word from command line.
*
* \param possibilities a StrList of valid strings, NULL if all are valid.
* \param multi_word whether multiple words are allowed.
*
* \return The word(s), or NULL if empty.
*/
char*
{
do {
if (command_line_get_word_count ()) {
char* result = command_line_pop_word ();
if (!possibilities)
return result;
if (result_node == NULL)
if (result_node)
return str_list_convert_node (result_node);
if (opt_script_mode)
return NULL;
}
} while (command_line_get_word_count ());
return NULL;
}
int
{
char def_str [10];
char* input;
int valid;
NULL, 1);
if (!input)
return 0;
return valid;
}
int
PedGeometry** range)
{
char* def_str;
char* input;
int valid;
NULL, 1);
/* def_str might have rounded *value a little bit. If the user picked
* the default, make sure the selected sector is identical to the
* default.
*/
if (range) {
}
return 1;
}
if (!input) {
*value = 0;
if (range)
return 0;
}
return valid;
}
int
{
char* def_word;
char* input;
if (*value)
else
if (!input)
return 0;
*value = 1;
else
*value = 0;
return 1;
}
int
{
char* dev_name;
if (!dev_name)
return 0;
if (!dev)
return 0;
return 1;
}
int
{
return 0;
if (!new_disk)
return 0;
}
return 1;
}
int
{
/* Flawed logic, doesn't seem to work?!
check = ped_disk_next_partition (disk, part);
part = ped_disk_next_partition (disk, check);
if (part == NULL) {
*value = check;
printf (_("The (only) primary partition has "
"been automatically selected\n"));
return 1;
} else {
*/
_("Expecting a partition number."));
return 0;
}
if (!part) {
_("Partition doesn't exist."));
return 0;
}
return 1;
//}
}
int
{
char* fs_type_name;
fs_type_list, 1);
if (!fs_type_name) {
_("Expecting a file system type."));
return 0;
}
if (!fs_type) {
_("Unknown file system type \"%s\"."),
return 0;
}
free (fs_type_name);
return 1;
}
int
{
char* disk_type_name;
disk_type_list, 1);
if (!disk_type_name) {
_("Expecting a disk label type."));
return 0;
}
return 1;
}
int
{
PedPartitionFlag walk = 0;
char* flag_name;
const char* walk_name;
}
}
if (flag_name) {
return 1;
} else
return 0;
}
static int
{
int i;
if (!ped_disk_get_partition (disk, i))
return 1;
}
return 0;
}
static int
{
if (!_can_create_primary (disk))
return 0;
return 0;
if (ped_disk_extended_partition (disk))
return 0;
return 1;
}
static int
{
return 0;
return ped_disk_extended_partition (disk) != 0;
}
int
{
char* type_name;
if (_can_create_primary (disk)) {
}
if (_can_create_extended (disk)) {
}
if (_can_create_logical (disk)) {
}
if (!opts) {
_("Can't create any more partitions."));
return 0;
}
if (!type_name) {
_("Expecting a partition type."));
return 0;
}
*type = 0;
}
}
}
return 1;
}
{
char* opt_name;
}
if (!opt_name)
return PED_EXCEPTION_UNHANDLED;
while (1) {
ped_exception_get_option_string (opt)) == 0)
break;
_(ped_exception_get_option_string (opt))) == 0)
break;
}
return opt;
}
int
{
char* unit_name;
const char* default_unit_name;
if (unit_name) {
return 1;
} else
return 0;
}
int
{
char* word;
int is_integer;
int scratch;
word = command_line_peek_word ();
if (!word)
return 0;
return is_integer;
}
static int
{
int i;
for (i = 0; (1 << i) <= PED_EXCEPTION_OPTION_LAST; i++) {
opt = (1 << i);
ex_opt_str [i]
= str_list_create (
NULL);
if (!ex_opt_str [i])
return 0;
}
ex_opt_str [i] = NULL;
return 1;
}
static void
{
int i;
for (i=0; ex_opt_str [i]; i++)
str_list_destroy (ex_opt_str [i]);
}
static int
{
return 1;
}
static void
{
}
static int
{
fs_type_list = NULL;
{
if (!fs_type_list)
return 0;
}
return 1;
}
static int
{
{
if (!disk_type_list)
return 0;
}
return 1;
}
int
init_ui ()
{
if (!init_ex_opt_str ()
|| !init_state_str ()
|| !init_fs_type_str ()
|| !init_disk_type_str ())
return 0;
#ifdef HAVE_LIBREADLINE
rl_initialize ();
#endif
#ifdef SA_SIGINFO
sigfillset (&curr);
#else
#endif /* SA_SIGINFO */
return 1;
}
void
done_ui ()
{
done_ex_opt_str ();
done_state_str ();
}
void
help_msg ()
{
putchar ('\n');
putchar ('\n');
putchar ('\n');
putchar ('\n');
exit (0);
}
void
{
}
int
{
print_using_dev (*dev);
while (1) {
char* word;
while (!command_line_get_word_count ()) {
putchar ('\n');
return 1;
}
command_names, 1);
}
word = command_line_pop_word ();
if (word) {
if (cmd) {
} else
}
}
return 1;
}
int
{
int i;
for (i = 0; i < argc; i++)
while (command_line_get_word_count ()) {
char* word;
word = command_line_pop_word ();
if (!word)
break;
if (!cmd) {
help_msg ();
goto error;
}
if (!(cmd->non_interactive)) {
fputs(_("This command does not make sense in "
"non-interactive mode.\n"), stdout);
exit(1);
goto error;
}
goto error;
}
return 1;
return 0;
}