ui.c revision 1
/*
parted - a frontend to libparted
Copyright (C) 1999-2002, 2006-2010 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 <config.h>
#include <ctype.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <setjmp.h>
#include <assert.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 const 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* align_opt_list;
static StrList* align_min_list;
static StrList* align_opt_min_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 */
/* 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 (EXIT_SUCCESS);
}
}
/* Signal handler for SIGINT using 'sigaction'. */
static void
{
if (info)
got_ctrl_c = 1;
reset_env (0);
}
/* 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 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 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 ();
}
#ifndef SA_SIGINFO
static void
{
sigfillset(&curr);
}
/* Signal handler for SIGINT using 'signal'. */
static void
s_sigint_handler (int signum)
{
mask_signal ();
}
/* Signal handler for SIGILL using 'signal'. */
static void
s_sigill_handler (int signum)
{
mask_signal ();
}
/* Signal handler for SIGSEGV using 'signal'. */
static void
s_sigsegv_handler (int signum)
{
mask_signal ();
}
/* Signal handler for SIGFPE using 'signal'. */
static void
s_sigfpe_handler (int signum)
{
mask_signal ();
}
#endif
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
/* kill trailing NL */
} 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) {
/* readline returns NULL to indicate EOF.
Treat that like an interrupt. */
got_ctrl_c = 1;
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
{
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* def_word;
char* input;
if (*align_type)
else
if (!input)
return 0;
: PA_MINIMUM);
return 1;
}
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
{
return 1;
}
static void
{
}
static int
{
fs_type_list = NULL;
{
if (!fs_type_list)
return 0;
}
{
alias_walk->alias);
if (!fs_type_list)
return 0;
}
return 1;
}
static int
{
{
if (!disk_type_list)
return 0;
}
return 1;
}
int
init_readline (void)
{
#ifdef HAVE_LIBREADLINE
if (!opt_script_mode) {
rl_initialize ();
}
#endif
return 0;
}
int
init_ui ()
{
if (!init_ex_opt_str ()
|| !init_state_str ()
|| !init_alignment_type_str ()
|| !init_fs_type_str ()
|| !init_disk_type_str ())
return 0;
#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 (EXIT_SUCCESS);
}
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);
goto error;
}
goto error;
}
return 1;
return 0;
}