~youscribe/parted/3.1

« back to all changes in this revision

Viewing changes to parted/ui.c

  • Committer: Guilhem Lettron
  • Date: 2012-10-22 14:37:59 UTC
  • Revision ID: guilhem+ubuntu@lettron.fr-20121022143759-m403kecgz13sknvp
3.1 from tarball

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    parted - a frontend to libparted
 
3
    Copyright (C) 1999-2002, 2006-2012 Free Software Foundation, Inc.
 
4
 
 
5
    This program is free software; you can redistribute it and/or modify
 
6
    it under the terms of the GNU General Public License as published by
 
7
    the Free Software Foundation; either version 3 of the License, or
 
8
    (at your option) any later version.
 
9
 
 
10
    This program is distributed in the hope that it will be useful,
 
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
    GNU General Public License for more details.
 
14
 
 
15
    You should have received a copy of the GNU General Public License
 
16
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
17
*/
 
18
#include <config.h>
 
19
 
 
20
#include <config.h>
 
21
 
 
22
#include <parted/parted.h>
 
23
#include <parted/debug.h>
 
24
 
 
25
#include <ctype.h>
 
26
#include <signal.h>
 
27
#include <stdlib.h>
 
28
#include <string.h>
 
29
#include <unistd.h>
 
30
#include <setjmp.h>
 
31
#include <assert.h>
 
32
 
 
33
#include "command.h"
 
34
#include "strlist.h"
 
35
#include "ui.h"
 
36
#include "error.h"
 
37
 
 
38
#define N_(String) String
 
39
#if ENABLE_NLS
 
40
#  include <libintl.h>
 
41
#  include <locale.h>
 
42
#  define _(String) dgettext (PACKAGE, String)
 
43
#else
 
44
#  define _(String) (String)
 
45
#endif /* ENABLE_NLS */
 
46
 
 
47
#ifdef HAVE_LIBREADLINE
 
48
 
 
49
#ifdef HAVE_TERMCAP_H
 
50
#include <termcap.h>
 
51
#else
 
52
extern int tgetnum (char* key);
 
53
#endif
 
54
 
 
55
#include <readline/readline.h>
 
56
#include <readline/history.h>
 
57
 
 
58
#ifndef HAVE_RL_COMPLETION_MATCHES
 
59
#define rl_completion_matches completion_matches
 
60
#endif
 
61
 
 
62
#ifndef rl_compentry_func_t
 
63
#define rl_compentry_func_t void
 
64
#endif
 
65
 
 
66
#endif /* HAVE_LIBREADLINE */
 
67
 
 
68
#ifndef SA_SIGINFO
 
69
#  ifndef HAVE_SIGACTION
 
70
 
 
71
struct sigaction {
 
72
};
 
73
 
 
74
static inline int
 
75
sigaction (int signum, const struct* sigaction, struct* sigaction)
 
76
{
 
77
}
 
78
 
 
79
#  endif /* HAVE_SIGACTON */
 
80
 
 
81
struct siginfo_t {
 
82
        int si_code;
 
83
};
 
84
 
 
85
#endif /* SA_SIGINFO */
 
86
 
 
87
#ifndef SEGV_MAPERR
 
88
#  define SEGV_MAPERR (INTMAX - 1)
 
89
#endif
 
90
 
 
91
#ifndef SEGV_ACCERR
 
92
#  define SEGV_ACCERR (INTMAX - 2)
 
93
#endif
 
94
 
 
95
#ifndef FPE_INTDIV
 
96
#  define FPE_INTDIV (INTMAX - 1)
 
97
#endif
 
98
 
 
99
#ifndef FPE_INTOVF
 
100
#  define FPE_INTOVF (INTMAX - 2)
 
101
#endif
 
102
 
 
103
#ifndef FPE_FLTDIV
 
104
#  define FPE_FLTDIV (INTMAX - 3)
 
105
#endif
 
106
 
 
107
#ifndef FPE_FLTOVF
 
108
#  define FPE_FLTOVF (INTMAX - 4)
 
109
#endif
 
110
 
 
111
#ifndef FPE_FLTUND
 
112
#  define FPE_FLTUND (INTMAX - 5)
 
113
#endif
 
114
 
 
115
#ifndef FPE_FLTRES
 
116
#  define FPE_FLTRES (INTMAX - 6)
 
117
#endif
 
118
 
 
119
#ifndef FPE_FLTINV
 
120
#  define FPE_FLTINV (INTMAX - 7)
 
121
#endif
 
122
 
 
123
#ifndef FPE_FLTSUB
 
124
#  define FPE_FLTSUB (INTMAX - 8)
 
125
#endif
 
126
 
 
127
#ifndef ILL_ILLOPC
 
128
#  define ILL_ILLOPC (INTMAX - 1)
 
129
#endif
 
130
 
 
131
#ifndef ILL_ILLOPN
 
132
#  define ILL_ILLOPN (INTMAX - 2)
 
133
#endif
 
134
 
 
135
#ifndef ILL_ILLADR
 
136
#  define ILL_ILLADR (INTMAX - 3)
 
137
#endif
 
138
 
 
139
#ifndef ILL_ILLTRP
 
140
#  define ILL_ILLTRP (INTMAX - 4)
 
141
#endif
 
142
 
 
143
#ifndef ILL_PRVOPC
 
144
#  define ILL_PRVOPC (INTMAX - 5)
 
145
#endif
 
146
 
 
147
#ifndef ILL_PRVREG
 
148
#  define ILL_PRVREG (INTMAX - 6)
 
149
#endif
 
150
 
 
151
#ifndef ILL_COPROC
 
152
#  define ILL_COPROC (INTMAX - 7)
 
153
#endif
 
154
 
 
155
#ifndef ILL_BADSTK
 
156
#  define ILL_BADSTK (INTMAX - 8)
 
157
#endif
 
158
 
 
159
const char* prog_name = "GNU Parted " VERSION "\n";
 
160
 
 
161
static const char* banner_msg = N_(
 
162
"Welcome to GNU Parted! Type 'help' to view a list of commands.\n");
 
163
 
 
164
static const char* usage_msg = N_(
 
165
"Usage: parted [OPTION]... [DEVICE [COMMAND [PARAMETERS]...]...]\n"
 
166
"Apply COMMANDs with PARAMETERS to DEVICE.  If no COMMAND(s) are given, "
 
167
"run in\ninteractive mode.\n");
 
168
 
 
169
static const char* bug_msg = N_(
 
170
"\n\nYou found a bug in GNU Parted! Here's what you have to do:\n\n"
 
171
"Don't panic! The bug has most likely not affected any of your data.\n"
 
172
"Help us to fix this bug by doing the following:\n\n"
 
173
"Check whether the bug has already been fixed by checking\n"
 
174
"the last version of GNU Parted that you can find at:\n\n"
 
175
"\thttp://ftp.gnu.org/gnu/parted/\n\n"
 
176
"Please check this version prior to bug reporting.\n\n"
 
177
"If this has not been fixed yet or if you don't know how to check,\n"
 
178
"please visit the GNU Parted website:\n\n"
 
179
"\thttp://www.gnu.org/software/parted\n\n"
 
180
"for further information.\n\n"
 
181
"Your report should contain the version of this release (%s)\n"
 
182
"along with the error message below, the output of\n\n"
 
183
"\tparted DEVICE unit co print unit s print\n\n"
 
184
"and the following history of commands you entered.\n"
 
185
"Also include any additional information about your setup you\n"
 
186
"consider important.\n");
 
187
 
 
188
#define MAX_WORDS    1024
 
189
 
 
190
static StrList*     command_line;
 
191
static Command**    commands;
 
192
static StrList*     ex_opt_str [64];
 
193
static StrList*     on_list;
 
194
static StrList*     off_list;
 
195
static StrList*     on_off_list;
 
196
 
 
197
static StrList*     align_opt_list;
 
198
static StrList*     align_min_list;
 
199
static StrList*     align_opt_min_list;
 
200
 
 
201
static StrList*     fs_type_list;
 
202
static StrList*     disk_type_list;
 
203
 
 
204
static struct {
 
205
        const StrList*    possibilities;
 
206
        const StrList*    cur_pos;
 
207
        int               in_readline;
 
208
        sigjmp_buf        jmp_state;
 
209
} readline_state;
 
210
 
 
211
static struct sigaction    sig_segv;
 
212
static struct sigaction    sig_int;
 
213
static struct sigaction    sig_fpe;
 
214
static struct sigaction    sig_ill;
 
215
 
 
216
volatile int got_ctrl_c = 0;    /* used in exception_handler */
 
217
 
 
218
int
 
219
screen_width ()
 
220
{
 
221
        int    width = 0;
 
222
 
 
223
        if (opt_script_mode || pretend_input_tty)
 
224
                return 32768;    /* no wrapping ;) */
 
225
 
 
226
/* HACK: don't specify termcap separately - it'll annoy the users. */
 
227
#ifdef HAVE_LIBREADLINE
 
228
        width = tgetnum ((char *) "co");
 
229
#endif
 
230
 
 
231
        if (width <= 0)
 
232
                width = 80;
 
233
 
 
234
        return width;
 
235
}
 
236
 
 
237
void
 
238
wipe_line ()
 
239
{
 
240
        if (opt_script_mode)
 
241
                return;
 
242
 
 
243
        /* yuck */
 
244
        fputs ("\r                                     "
 
245
               "                                     \r", stdout);
 
246
}
 
247
 
 
248
#ifdef HAVE_LIBREADLINE
 
249
/* returns matching commands for text */
 
250
static char*
 
251
command_generator (char* text, int state)
 
252
{
 
253
        if (!state)
 
254
                readline_state.cur_pos = readline_state.possibilities;
 
255
 
 
256
        while (readline_state.cur_pos) {
 
257
                const StrList*    cur = readline_state.cur_pos;
 
258
                readline_state.cur_pos = cur->next;
 
259
                if (str_list_match_node (cur, text))
 
260
                        return str_list_convert_node (cur);
 
261
        }
 
262
 
 
263
        return NULL;
 
264
}
 
265
 
 
266
/* completion function for readline() */
 
267
char**
 
268
complete_function (char* text, int start, int end)
 
269
{
 
270
        return rl_completion_matches (text,
 
271
                (rl_compentry_func_t*) command_generator);
 
272
}
 
273
 
 
274
static void
 
275
_add_history_unique (const char* line)
 
276
{
 
277
        HIST_ENTRY*    last_entry = current_history ();
 
278
        if (!strlen (line))
 
279
                return;
 
280
        if (!last_entry || strcmp (last_entry->line, line))
 
281
                add_history ((char*) line);
 
282
}
 
283
 
 
284
/* Prints command history, to be used before aborting */
 
285
static void
 
286
_dump_history ()
 
287
{
 
288
        int             i = 0;
 
289
        HIST_ENTRY**    all_entries = history_list ();
 
290
 
 
291
        fputs (_("\nCommand History:\n"), stdout);
 
292
        while (all_entries[i]) {
 
293
                puts(all_entries[i++]->line);
 
294
        }
 
295
}
 
296
 
 
297
#else
 
298
 
 
299
/* Print nothing because Readline is absent. */
 
300
static inline void
 
301
_dump_history (void)
 
302
{
 
303
}
 
304
 
 
305
#endif /* HAVE_LIBREADLINE */
 
306
 
 
307
/* Resets the environment by jumping to the initial state
 
308
 * saved during ui intitialisation.
 
309
 * Pass 1 as the parameter if you want to quit parted,
 
310
 * 0 if you just want to reset to the command prompt.
 
311
 */
 
312
static void
 
313
reset_env (int quit)
 
314
{
 
315
        int    in_readline = readline_state.in_readline;
 
316
 
 
317
        readline_state.in_readline = 0;
 
318
 
 
319
        if (in_readline) {
 
320
                putchar ('\n');
 
321
                if (quit)
 
322
                        exit (EXIT_SUCCESS);
 
323
 
 
324
                siglongjmp (readline_state.jmp_state, 1);
 
325
        }
 
326
}
 
327
 
 
328
/* Signal handler for SIGINT using 'sigaction'. */
 
329
static void
 
330
sa_sigint_handler (int signum, siginfo_t* info, void *ucontext)
 
331
{
 
332
        if (info)
 
333
                sigaction (SIGINT, &sig_int, NULL);
 
334
 
 
335
        got_ctrl_c = 1;
 
336
        reset_env (0);
 
337
}
 
338
 
 
339
/* Signal handler for SIGSEGV using 'sigaction'. */
 
340
static void
 
341
sa_sigsegv_handler (int signum, siginfo_t* info, void* ucontext)
 
342
{
 
343
        fprintf (stderr, bug_msg, VERSION);
 
344
        _dump_history ();
 
345
 
 
346
        if (!info)
 
347
                abort ();
 
348
 
 
349
        sigaction (SIGSEGV, &sig_segv, NULL);
 
350
 
 
351
        switch (info->si_code) {
 
352
 
 
353
                case SEGV_MAPERR:
 
354
                        fputs(_("\nError: SEGV_MAPERR (Address not mapped "
 
355
                                "to object)\n"), stdout);
 
356
                        PED_ASSERT(0); /* Force a backtrace */
 
357
                        break;
 
358
 
 
359
                case SEGV_ACCERR:
 
360
                        fputs(_("\nError: SEGV_ACCERR (Invalid permissions "
 
361
                                "for mapped object)\n"), stdout);
 
362
                        break;
 
363
 
 
364
                default:
 
365
                        fputs(_("\nError: A general SIGSEGV signal was "
 
366
                                "encountered.\n"), stdout);
 
367
                        PED_ASSERT(0); /* Force a backtrace */
 
368
                        break;
 
369
        }
 
370
 
 
371
        abort ();
 
372
}
 
373
 
 
374
/* Signal handler for SIGFPE using 'sigaction'. */
 
375
static void
 
376
sa_sigfpe_handler (int signum, siginfo_t* info, void* ucontext)
 
377
{
 
378
        fprintf (stderr, bug_msg, VERSION);
 
379
        _dump_history ();
 
380
 
 
381
        if (!info)
 
382
                abort ();
 
383
 
 
384
        sigaction (SIGFPE, &sig_fpe, NULL);
 
385
 
 
386
        switch (info->si_code) {
 
387
 
 
388
                case FPE_INTDIV:
 
389
                        fputs(_("\nError: FPE_INTDIV (Integer: "
 
390
                                "divide by zero)"), stdout);
 
391
                        break;
 
392
 
 
393
                case FPE_INTOVF:
 
394
                        fputs(_("\nError: FPE_INTOVF (Integer: "
 
395
                                "overflow)"), stdout);
 
396
                        break;
 
397
 
 
398
                case FPE_FLTDIV:
 
399
                        fputs(_("\nError: FPE_FLTDIV (Float: "
 
400
                                "divide by zero)"), stdout);
 
401
                        break;
 
402
 
 
403
                case FPE_FLTOVF:
 
404
                        fputs(_("\nError: FPE_FLTOVF (Float: "
 
405
                                "overflow)"), stdout);
 
406
                        break;
 
407
 
 
408
                case FPE_FLTUND:
 
409
                        fputs(_("\nError: FPE_FLTUND (Float: "
 
410
                                "underflow)"), stdout);
 
411
                        break;
 
412
 
 
413
                case FPE_FLTRES:
 
414
                        fputs(_("\nError: FPE_FLTRES (Float: "
 
415
                                "inexact result)"), stdout);
 
416
                        break;
 
417
 
 
418
                case FPE_FLTINV:
 
419
                        fputs(_("\nError: FPE_FLTINV (Float: "
 
420
                                "invalid operation)"), stdout);
 
421
                        break;
 
422
 
 
423
                case FPE_FLTSUB:
 
424
                        fputs(_("\nError: FPE_FLTSUB (Float: "
 
425
                                "subscript out of range)"), stdout);
 
426
                        break;
 
427
 
 
428
                default:
 
429
                        fputs(_("\nError: A general SIGFPE signal "
 
430
                                "was encountered."), stdout);
 
431
                        break;
 
432
 
 
433
        }
 
434
 
 
435
        abort ();
 
436
}
 
437
 
 
438
/* Signal handler for SIGILL using 'sigaction'. */
 
439
static void
 
440
sa_sigill_handler (int signum, siginfo_t* info, void* ucontext)
 
441
{
 
442
        fprintf (stderr, bug_msg, VERSION);
 
443
        _dump_history ();
 
444
 
 
445
        if (!info)
 
446
                abort();
 
447
 
 
448
        sigaction (SIGILL, &sig_ill, NULL);
 
449
 
 
450
        switch (info->si_code) {
 
451
 
 
452
                case ILL_ILLOPC:
 
453
                        fputs(_("\nError: ILL_ILLOPC "
 
454
                                "(Illegal Opcode)"), stdout);
 
455
                        break;
 
456
 
 
457
                case ILL_ILLOPN:
 
458
                        fputs(_("\nError: ILL_ILLOPN "
 
459
                                "(Illegal Operand)"), stdout);
 
460
                        break;
 
461
 
 
462
                case ILL_ILLADR:
 
463
                        fputs(_("\nError: ILL_ILLADR "
 
464
                                "(Illegal addressing mode)"), stdout);
 
465
                        break;
 
466
 
 
467
                case ILL_ILLTRP:
 
468
                        fputs(_("\nError: ILL_ILLTRP "
 
469
                                "(Illegal Trap)"), stdout);
 
470
                        break;
 
471
 
 
472
                case ILL_PRVOPC:
 
473
                        fputs(_("\nError: ILL_PRVOPC "
 
474
                                "(Privileged Opcode)"), stdout);
 
475
                        break;
 
476
 
 
477
                case ILL_PRVREG:
 
478
                        fputs(_("\nError: ILL_PRVREG "
 
479
                                "(Privileged Register)"), stdout);
 
480
                        break;
 
481
 
 
482
                case ILL_COPROC:
 
483
                        fputs(_("\nError: ILL_COPROC "
 
484
                                "(Coprocessor Error)"), stdout);
 
485
                        break;
 
486
 
 
487
                case ILL_BADSTK:
 
488
                        fputs(_("\nError: ILL_BADSTK "
 
489
                                "(Internal Stack Error)"), stdout);
 
490
                        break;
 
491
 
 
492
                default:
 
493
                        fputs(_("\nError: A general SIGILL "
 
494
                                "signal was encountered."), stdout);
 
495
                        break;
 
496
        }
 
497
 
 
498
        abort ();
 
499
}
 
500
 
 
501
#ifndef SA_SIGINFO
 
502
 
 
503
static void
 
504
mask_signal()
 
505
{
 
506
        sigset_t    curr;
 
507
        sigset_t    prev;
 
508
 
 
509
        sigfillset(&curr);
 
510
        sigprocmask(SIG_SETMASK, &curr, &prev);
 
511
}
 
512
 
 
513
/* Signal handler for SIGINT using 'signal'. */
 
514
static void
 
515
s_sigint_handler (int signum)
 
516
{
 
517
        signal (SIGINT, &s_sigint_handler);
 
518
        mask_signal ();
 
519
        sa_sigint_handler (signum, NULL, NULL);
 
520
}
 
521
 
 
522
/* Signal handler for SIGILL using 'signal'. */
 
523
static void
 
524
s_sigill_handler (int signum)
 
525
{
 
526
        signal (SIGILL, &s_sigill_handler);
 
527
        mask_signal ();
 
528
        sa_sigill_handler (signum, NULL, NULL);
 
529
}
 
530
 
 
531
/* Signal handler for SIGSEGV using 'signal'. */
 
532
static void
 
533
s_sigsegv_handler (int signum)
 
534
{
 
535
        signal (SIGSEGV, &s_sigsegv_handler);
 
536
        mask_signal ();
 
537
        sa_sigsegv_handler (signum, NULL, NULL);
 
538
}
 
539
 
 
540
/* Signal handler for SIGFPE using 'signal'. */
 
541
static void
 
542
s_sigfpe_handler (int signum)
 
543
{
 
544
        signal (SIGFPE, &s_sigfpe_handler);
 
545
        mask_signal ();
 
546
        sa_sigfpe_handler (signum, NULL, NULL);
 
547
}
 
548
#endif
 
549
 
 
550
static char*
 
551
_readline (const char* prompt, const StrList* possibilities)
 
552
{
 
553
        char*    line;
 
554
 
 
555
        readline_state.possibilities = possibilities;
 
556
        readline_state.cur_pos = NULL;
 
557
        readline_state.in_readline = 1;
 
558
 
 
559
        if (sigsetjmp (readline_state.jmp_state,1))
 
560
                return NULL;
 
561
 
 
562
        wipe_line ();
 
563
#ifdef HAVE_LIBREADLINE
 
564
        if (!opt_script_mode) {
 
565
                /* XXX: why isn't prompt const? */
 
566
                line = readline ((char*) prompt);
 
567
                if (line)
 
568
                        _add_history_unique (line);
 
569
        } else
 
570
#endif
 
571
        {
 
572
                fputs (prompt, stdout);
 
573
                fflush (stdout);
 
574
                line = (char*) malloc (256);
 
575
                if (fgets (line, 256, stdin) && strcmp (line, "") != 0) {
 
576
#ifndef HAVE_LIBREADLINE
 
577
                        /* Echo the input line, to be consistent with
 
578
                           how readline-5.2 works.  */
 
579
                        fputs (line, stdout);
 
580
                        fflush (stdout);
 
581
#endif
 
582
                        /* kill trailing NL */
 
583
                        if (strlen (line))
 
584
                                line [strlen (line) - 1] = 0;
 
585
                } else {
 
586
                        free (line);
 
587
                        line = NULL;
 
588
                }
 
589
        }
 
590
 
 
591
        readline_state.in_readline = 0;
 
592
        return line;
 
593
}
 
594
 
 
595
static PedExceptionOption _GL_ATTRIBUTE_PURE
 
596
option_get_next (PedExceptionOption options, PedExceptionOption current)
 
597
{
 
598
        PedExceptionOption    i;
 
599
 
 
600
        if (current == 0)
 
601
                i = PED_EXCEPTION_OPTION_FIRST;
 
602
        else
 
603
                i = current * 2;
 
604
 
 
605
        for (; i <= options; i *= 2) {
 
606
                if (options & i)
 
607
                        return i;
 
608
        }
 
609
        return 0;
 
610
}
 
611
 
 
612
static void
 
613
_print_exception_text (PedException* ex)
 
614
{
 
615
        StrList*    text;
 
616
 
 
617
        wipe_line ();
 
618
 
 
619
        if (ex->type == PED_EXCEPTION_BUG) {
 
620
                fprintf (stderr, bug_msg, VERSION);
 
621
                text = str_list_create ("\n", ex->message, "\n\n", NULL);
 
622
        } else {
 
623
                text = str_list_create (
 
624
                           _(ped_exception_get_type_string (ex->type)),
 
625
                           ": ", ex->message, "\n", NULL);
 
626
        }
 
627
 
 
628
        str_list_print_wrap (text, screen_width (), 0, 0, stderr);
 
629
        str_list_destroy (text);
 
630
}
 
631
 
 
632
static PedExceptionOption
 
633
exception_handler (PedException* ex)
 
634
{
 
635
        PedExceptionOption    opt;
 
636
 
 
637
        _print_exception_text (ex);
 
638
 
 
639
        /* only one choice?  Take it ;-) */
 
640
        opt = option_get_next (ex->options, 0);
 
641
        if (!option_get_next (ex->options, opt))
 
642
                return opt;
 
643
 
 
644
        /* script-mode: don't handle the exception */
 
645
        if (opt_script_mode || (!isatty (0) && !pretend_input_tty))
 
646
                return PED_EXCEPTION_UNHANDLED;
 
647
 
 
648
        got_ctrl_c = 0;
 
649
 
 
650
        do {
 
651
                opt = command_line_get_ex_opt ("", ex->options);
 
652
        } while (opt == PED_EXCEPTION_UNHANDLED
 
653
                 && (isatty (0) || pretend_input_tty) && !got_ctrl_c);
 
654
 
 
655
        if (got_ctrl_c) {
 
656
                got_ctrl_c = 0;
 
657
                opt = PED_EXCEPTION_UNHANDLED;
 
658
        }
 
659
 
 
660
        return opt;
 
661
}
 
662
 
 
663
void
 
664
command_line_push_word (const char* word)
 
665
{
 
666
        command_line = str_list_append (command_line, word);
 
667
}
 
668
 
 
669
char*
 
670
command_line_pop_word ()
 
671
{
 
672
        char*       result;
 
673
        StrList*    next;
 
674
 
 
675
        PED_ASSERT (command_line != NULL);
 
676
 
 
677
        result = str_list_convert_node (command_line);
 
678
        next = command_line->next;
 
679
 
 
680
        str_list_destroy_node (command_line);
 
681
        command_line = next;
 
682
        return result;
 
683
}
 
684
 
 
685
void
 
686
command_line_flush ()
 
687
{
 
688
        str_list_destroy (command_line);
 
689
        command_line = NULL;
 
690
}
 
691
 
 
692
char*
 
693
command_line_peek_word ()
 
694
{
 
695
        if (command_line)
 
696
                return str_list_convert_node (command_line);
 
697
        else
 
698
                return NULL;
 
699
}
 
700
 
 
701
int
 
702
command_line_get_word_count ()
 
703
{
 
704
        return str_list_length (command_line);
 
705
}
 
706
 
 
707
static int _GL_ATTRIBUTE_PURE
 
708
_str_is_spaces (const char* str)
 
709
{
 
710
        while (isspace (*str))
 
711
                str++;
 
712
 
 
713
        return *str == 0;
 
714
}
 
715
 
 
716
/* "multi_word mode" is the "normal" mode... many words can be typed,
 
717
 * delimited by spaces, etc.
 
718
 *         In single-word mode, only one word is parsed per line.
 
719
 * Leading and trailing spaces are removed.  For example: " a b c "
 
720
 * is a single word "a b c".  The motivation for this mode is partition
 
721
 * names, etc.  In single-word mode, the empty string is a word.
 
722
 * (but not in multi-word mode).
 
723
 */
 
724
void
 
725
command_line_push_line (const char* line, int multi_word)
 
726
{
 
727
        int     quoted = 0;
 
728
        char    quote_char = 0;
 
729
        char    this_word [256];
 
730
        int     i;
 
731
 
 
732
        do {
 
733
                while (*line == ' ')
 
734
                        line++;
 
735
 
 
736
                i = 0;
 
737
                for (; *line; line++) {
 
738
                        if (*line == ' ' && !quoted) {
 
739
                                if (multi_word)
 
740
                                        break;
 
741
 
 
742
                        /* single word: check for trailing spaces + eol */
 
743
                                if (_str_is_spaces (line))
 
744
                                        break;
 
745
                        }
 
746
 
 
747
                        if (!quoted && strchr ("'\"", *line)) {
 
748
                                quoted = 1;
 
749
                                quote_char = *line;
 
750
                                continue;
 
751
                        }
 
752
 
 
753
                        if (quoted && *line == quote_char) {
 
754
                                quoted = 0;
 
755
                                continue;
 
756
                        }
 
757
 
 
758
                        /* hack: escape characters */
 
759
                        if (quoted && line[0] == '\\' && line[1])
 
760
                                line++;
 
761
 
 
762
                        this_word [i++] = *line;
 
763
                }
 
764
                if (i || !multi_word) {
 
765
                        this_word [i] = 0;
 
766
                        command_line_push_word (this_word);
 
767
                }
 
768
        } while (*line && multi_word);
 
769
}
 
770
 
 
771
static char*
 
772
realloc_and_cat (char* str, const char* append)
 
773
{
 
774
        int      length = strlen (str) + strlen (append) + 1;
 
775
        char*    new_str = realloc (str, length);
 
776
 
 
777
        strcat (new_str, append);
 
778
        return new_str;
 
779
}
 
780
 
 
781
static char*
 
782
_construct_prompt (const char* head, const char* def,
 
783
                   const StrList* possibilities)
 
784
{
 
785
        char*    prompt = strdup (head);
 
786
 
 
787
        if (def && possibilities)
 
788
                PED_ASSERT (str_list_match_any (possibilities, def));
 
789
 
 
790
        if (possibilities && str_list_length (possibilities) < 8) {
 
791
                const StrList*    walk;
 
792
 
 
793
                if (strlen (prompt))
 
794
                        prompt = realloc_and_cat (prompt, "  ");
 
795
 
 
796
                for (walk = possibilities; walk; walk = walk->next) {
 
797
                        if (walk != possibilities)
 
798
                                prompt = realloc_and_cat (prompt, "/");
 
799
 
 
800
                        if (def && str_list_match_node (walk, def) == 2) {
 
801
                                prompt = realloc_and_cat (prompt, "[");
 
802
                                prompt = realloc_and_cat (prompt, def);
 
803
                                prompt = realloc_and_cat (prompt, "]");
 
804
                        } else {
 
805
                                char*    text = str_list_convert_node (walk);
 
806
                                prompt = realloc_and_cat (prompt, text);
 
807
                                free (text);
 
808
                        }
 
809
                }
 
810
                prompt = realloc_and_cat (prompt, "? ");
 
811
        } else if (def) {
 
812
                if (strlen (prompt))
 
813
                        prompt = realloc_and_cat (prompt, "  ");
 
814
                prompt = realloc_and_cat (prompt, "[");
 
815
                prompt = realloc_and_cat (prompt, def);
 
816
                prompt = realloc_and_cat (prompt, "]? ");
 
817
        } else {
 
818
                if (strlen (prompt))
 
819
                        prompt = realloc_and_cat (prompt, " ");
 
820
        }
 
821
 
 
822
        return prompt;
 
823
}
 
824
 
 
825
void
 
826
command_line_prompt_words (const char* prompt, const char* def,
 
827
                           const StrList* possibilities, int multi_word)
 
828
{
 
829
        char*    line;
 
830
        char*    real_prompt;
 
831
        char*    _def = (char*) def;
 
832
        int      _def_needs_free = 0;
 
833
 
 
834
        if (!def && str_list_length (possibilities) == 1) {
 
835
                _def = str_list_convert_node (possibilities);
 
836
                _def_needs_free = 1;
 
837
        }
 
838
 
 
839
        if (opt_script_mode) {
 
840
                if (_def)
 
841
                        command_line_push_line (_def, 0);
 
842
                return;
 
843
        }
 
844
 
 
845
        do {
 
846
                real_prompt = _construct_prompt (prompt, _def, possibilities);
 
847
                line = _readline (real_prompt, possibilities);
 
848
                free (real_prompt);
 
849
                if (!line) {
 
850
                        /* readline returns NULL to indicate EOF.
 
851
                           Treat that like an interrupt.  */
 
852
                        got_ctrl_c = 1;
 
853
                        break;
 
854
                }
 
855
 
 
856
                if (!strlen (line)) {
 
857
                        if (_def)
 
858
                                command_line_push_line (_def, 0);
 
859
                } else {
 
860
                        command_line_push_line (line, multi_word);
 
861
                }
 
862
                free (line);
 
863
        } while (!command_line_get_word_count () && !_def);
 
864
 
 
865
        if (_def_needs_free)
 
866
                free (_def);
 
867
}
 
868
 
 
869
/**
 
870
 * Get a word from command line.
 
871
 *
 
872
 * \param possibilities a StrList of valid strings, NULL if all are valid.
 
873
 * \param multi_word whether multiple words are allowed.
 
874
 *
 
875
 * \return The word(s), or NULL if empty.
 
876
 */
 
877
char*
 
878
command_line_get_word (const char* prompt, const char* def,
 
879
                       const StrList* possibilities, int multi_word)
 
880
{
 
881
        do {
 
882
                if (command_line_get_word_count ()) {
 
883
                        char*       result = command_line_pop_word ();
 
884
                        StrList*    result_node;
 
885
 
 
886
                        if (!possibilities)
 
887
                                return result;
 
888
 
 
889
                        result_node = str_list_match (possibilities, result);
 
890
                        if (result_node == NULL)
 
891
                                error (0, 0, _("invalid token: %s"), result);
 
892
                        free (result);
 
893
                        if (result_node)
 
894
                                return str_list_convert_node (result_node);
 
895
 
 
896
                        command_line_flush ();
 
897
                        if (opt_script_mode)
 
898
                                return NULL;
 
899
                }
 
900
 
 
901
                command_line_prompt_words (prompt, def, possibilities,
 
902
                                           multi_word);
 
903
        } while (command_line_get_word_count ());
 
904
 
 
905
        return NULL;
 
906
}
 
907
 
 
908
int
 
909
command_line_get_integer (const char* prompt, int* value)
 
910
{
 
911
        char     def_str [10];
 
912
        char*    input;
 
913
        int      valid;
 
914
 
 
915
        snprintf (def_str, 10, "%d", *value);
 
916
        input = command_line_get_word (prompt, *value ? def_str : NULL,
 
917
                                       NULL, 1);
 
918
        if (!input)
 
919
                return 0;
 
920
        valid = sscanf (input, "%d", value);
 
921
        free (input);
 
922
        return valid;
 
923
}
 
924
 
 
925
int
 
926
command_line_get_sector (const char* prompt, PedDevice* dev, PedSector* value,
 
927
                         PedGeometry** range, char** raw_input)
 
928
{
 
929
        char*    def_str;
 
930
        char*    input;
 
931
        int      valid;
 
932
 
 
933
        def_str = ped_unit_format (dev, *value);
 
934
        input = command_line_get_word (prompt, *value ? def_str : NULL,
 
935
                                       NULL, 1);
 
936
 
 
937
        /* def_str might have rounded *value a little bit.  If the user picked
 
938
         * the default, make sure the selected sector is identical to the
 
939
         * default.
 
940
         */
 
941
        if (input && *value && !strcmp (input, def_str)) {
 
942
                if (range) {
 
943
                        *range = ped_geometry_new (dev, *value, 1);
 
944
                        free (def_str);
 
945
                        return *range != NULL;
 
946
                }
 
947
 
 
948
                free (def_str);
 
949
                free (input);
 
950
                return 1;
 
951
        }
 
952
 
 
953
        free (def_str);
 
954
        if (!input) {
 
955
                *value = 0;
 
956
                if (range)
 
957
                        *range = NULL;
 
958
                return 0;
 
959
        }
 
960
 
 
961
        valid = ped_unit_parse (input, dev, value, range);
 
962
 
 
963
        if (raw_input)
 
964
            *raw_input = input;
 
965
        else
 
966
            free (input);
 
967
        return valid;
 
968
}
 
969
 
 
970
int
 
971
command_line_get_state (const char* prompt, int* value)
 
972
{
 
973
        char*    def_word;
 
974
        char*    input;
 
975
 
 
976
        if (*value)
 
977
                def_word = str_list_convert_node (on_list);
 
978
        else
 
979
                def_word = str_list_convert_node (off_list);
 
980
        input = command_line_get_word (prompt, def_word, on_off_list, 1);
 
981
        free (def_word);
 
982
        if (!input)
 
983
                return 0;
 
984
        if (str_list_match_any (on_list, input))
 
985
                *value = 1;
 
986
        else
 
987
                *value = 0;
 
988
        free (input);
 
989
        return 1;
 
990
}
 
991
 
 
992
int
 
993
command_line_get_device (const char* prompt, PedDevice** value)
 
994
{
 
995
        char *def_dev_name = *value ? (*value)->path : NULL;
 
996
        char *dev_name = command_line_get_word (prompt, def_dev_name, NULL, 1);
 
997
        if (!dev_name)
 
998
                return 0;
 
999
 
 
1000
        PedDevice *dev = ped_device_get (dev_name);
 
1001
        free (dev_name);
 
1002
        if (!dev)
 
1003
                return 0;
 
1004
 
 
1005
        *value = dev;
 
1006
        return 1;
 
1007
}
 
1008
 
 
1009
int
 
1010
command_line_get_disk (const char* prompt, PedDisk** value)
 
1011
{
 
1012
        PedDevice*    dev = *value ? (*value)->dev : NULL;
 
1013
 
 
1014
        if (!command_line_get_device (prompt, &dev))
 
1015
                return 0;
 
1016
 
 
1017
        assert (*value);
 
1018
        if (dev != (*value)->dev) {
 
1019
                PedDisk*    new_disk = ped_disk_new (dev);
 
1020
                if (!new_disk)
 
1021
                        return 0;
 
1022
                *value = new_disk;
 
1023
        }
 
1024
        return 1;
 
1025
}
 
1026
 
 
1027
int
 
1028
command_line_get_partition (const char* prompt, PedDisk* disk,
 
1029
                            PedPartition** value)
 
1030
{
 
1031
        PedPartition*    part;
 
1032
 
 
1033
        /* Flawed logic, doesn't seem to work?!
 
1034
        check = ped_disk_next_partition (disk, part);
 
1035
        part  = ped_disk_next_partition (disk, check);
 
1036
 
 
1037
        if (part == NULL) {
 
1038
 
 
1039
        *value = check;
 
1040
        printf (_("The (only) primary partition has "
 
1041
                  "been automatically selected\n"));
 
1042
        return 1;
 
1043
 
 
1044
        } else {
 
1045
        */
 
1046
        int num = (*value) ? (*value)->num : 0;
 
1047
 
 
1048
        if (!command_line_get_integer (prompt, &num)) {
 
1049
                ped_exception_throw (PED_EXCEPTION_ERROR,
 
1050
                                     PED_EXCEPTION_CANCEL,
 
1051
                                     _("Expecting a partition number."));
 
1052
                return 0;
 
1053
        }
 
1054
 
 
1055
        part = ped_disk_get_partition (disk, num);
 
1056
 
 
1057
        if (!part) {
 
1058
                ped_exception_throw (PED_EXCEPTION_ERROR,
 
1059
                                     PED_EXCEPTION_CANCEL,
 
1060
                                     _("Partition doesn't exist."));
 
1061
            return 0;
 
1062
        }
 
1063
 
 
1064
        *value = part;
 
1065
        return 1;
 
1066
        //}
 
1067
}
 
1068
 
 
1069
int
 
1070
command_line_get_fs_type (const char* prompt, const PedFileSystemType*(* value))
 
1071
{
 
1072
        char*                 fs_type_name;
 
1073
        PedFileSystemType*    fs_type;
 
1074
 
 
1075
        fs_type_name = command_line_get_word (prompt,
 
1076
                                              *value ? (*value)->name : NULL,
 
1077
                                                     fs_type_list, 1);
 
1078
        if (!fs_type_name) {
 
1079
                ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
 
1080
                                     _("Expecting a file system type."));
 
1081
                return 0;
 
1082
        }
 
1083
 
 
1084
        fs_type = ped_file_system_type_get (fs_type_name);
 
1085
        if (!fs_type) {
 
1086
                ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
 
1087
                                     _("Unknown file system type \"%s\"."),
 
1088
                                     fs_type_name);
 
1089
                free (fs_type_name);
 
1090
                return 0;
 
1091
        }
 
1092
 
 
1093
        free (fs_type_name);
 
1094
        *value = fs_type;
 
1095
        return 1;
 
1096
}
 
1097
 
 
1098
int
 
1099
command_line_get_disk_type (const char* prompt, const PedDiskType*(* value))
 
1100
{
 
1101
        char*    disk_type_name;
 
1102
 
 
1103
        disk_type_name = command_line_get_word (prompt,
 
1104
                                                *value ? (*value)->name : NULL,
 
1105
                                                disk_type_list, 1);
 
1106
        if (!disk_type_name) {
 
1107
                ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
 
1108
                                     _("Expecting a disk label type."));
 
1109
                return 0;
 
1110
        }
 
1111
 
 
1112
        *value = ped_disk_type_get (disk_type_name);
 
1113
        free (disk_type_name);
 
1114
        PED_ASSERT (*value != NULL);
 
1115
        return 1;
 
1116
}
 
1117
 
 
1118
int
 
1119
command_line_get_disk_flag (const char* prompt, const PedDisk* disk,
 
1120
                            PedDiskFlag* flag)
 
1121
{
 
1122
        StrList*            opts = NULL;
 
1123
        PedPartitionFlag    walk = 0;
 
1124
        char*               flag_name;
 
1125
 
 
1126
        while ( (walk = ped_disk_flag_next (walk)) ) {
 
1127
                if (ped_disk_is_flag_available (disk, walk)) {
 
1128
                        const char*        walk_name;
 
1129
 
 
1130
                        walk_name = ped_disk_flag_get_name (walk);
 
1131
                        opts = str_list_append (opts, walk_name);
 
1132
                        opts = str_list_append_unique (opts, _(walk_name));
 
1133
                }
 
1134
        }
 
1135
 
 
1136
        flag_name = command_line_get_word (prompt, NULL, opts, 1);
 
1137
        str_list_destroy (opts);
 
1138
 
 
1139
        if (flag_name) {
 
1140
                *flag = ped_disk_flag_get_by_name (flag_name);
 
1141
                free (flag_name);
 
1142
                return 1;
 
1143
        } else
 
1144
                return 0;
 
1145
}
 
1146
 
 
1147
int
 
1148
command_line_get_part_flag (const char* prompt, const PedPartition* part,
 
1149
                            PedPartitionFlag* flag)
 
1150
{
 
1151
        StrList*            opts = NULL;
 
1152
        PedPartitionFlag    walk = 0;
 
1153
        char*               flag_name;
 
1154
 
 
1155
        while ( (walk = ped_partition_flag_next (walk)) ) {
 
1156
                if (ped_partition_is_flag_available (part, walk)) {
 
1157
                        const char*        walk_name;
 
1158
 
 
1159
                        walk_name = ped_partition_flag_get_name (walk);
 
1160
                        opts = str_list_append (opts, walk_name);
 
1161
                        opts = str_list_append_unique (opts, _(walk_name));
 
1162
                }
 
1163
        }
 
1164
 
 
1165
        flag_name = command_line_get_word (prompt, NULL, opts, 1);
 
1166
        str_list_destroy (opts);
 
1167
 
 
1168
        if (flag_name) {
 
1169
                *flag = ped_partition_flag_get_by_name (flag_name);
 
1170
                free (flag_name);
 
1171
                return 1;
 
1172
        } else
 
1173
                return 0;
 
1174
}
 
1175
 
 
1176
static int
 
1177
_can_create_primary (const PedDisk* disk)
 
1178
{
 
1179
        int    i;
 
1180
 
 
1181
        for (i = 1; i <= ped_disk_get_max_primary_partition_count (disk); i++) {
 
1182
                if (!ped_disk_get_partition (disk, i))
 
1183
                        return 1;
 
1184
        }
 
1185
 
 
1186
        return 0;
 
1187
}
 
1188
 
 
1189
static int
 
1190
_can_create_extended (const PedDisk* disk)
 
1191
{
 
1192
        if (!_can_create_primary (disk))
 
1193
                return 0;
 
1194
 
 
1195
        if (!ped_disk_type_check_feature (disk->type, PED_DISK_TYPE_EXTENDED))
 
1196
                return 0;
 
1197
 
 
1198
        if (ped_disk_extended_partition (disk))
 
1199
                return 0;
 
1200
 
 
1201
        return 1;
 
1202
}
 
1203
 
 
1204
static int
 
1205
_can_create_logical (const PedDisk* disk)
 
1206
{
 
1207
        if (!ped_disk_type_check_feature (disk->type, PED_DISK_TYPE_EXTENDED))
 
1208
                return 0;
 
1209
 
 
1210
        return ped_disk_extended_partition (disk) != 0;
 
1211
}
 
1212
 
 
1213
int
 
1214
command_line_get_part_type (const char* prompt, const PedDisk* disk,
 
1215
                                   PedPartitionType* type)
 
1216
{
 
1217
        StrList*    opts = NULL;
 
1218
        char*       type_name;
 
1219
 
 
1220
        if (_can_create_primary (disk)) {
 
1221
                opts = str_list_append_unique (opts, "primary");
 
1222
                opts = str_list_append_unique (opts, _("primary"));
 
1223
        }
 
1224
        if (_can_create_extended (disk)) {
 
1225
                opts = str_list_append_unique (opts, "extended");
 
1226
                opts = str_list_append_unique (opts, _("extended"));
 
1227
        }
 
1228
        if (_can_create_logical (disk)) {
 
1229
                opts = str_list_append_unique (opts, "logical");
 
1230
                opts = str_list_append_unique (opts, _("logical"));
 
1231
        }
 
1232
        if (!opts) {
 
1233
                ped_exception_throw (
 
1234
                        PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
 
1235
                        _("Can't create any more partitions."));
 
1236
                return 0;
 
1237
        }
 
1238
 
 
1239
        type_name = command_line_get_word (prompt, NULL, opts, 1);
 
1240
        str_list_destroy (opts);
 
1241
 
 
1242
        if (!type_name) {
 
1243
                ped_exception_throw (
 
1244
                        PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
 
1245
                        _("Expecting a partition type."));
 
1246
                return 0;
 
1247
        }
 
1248
 
 
1249
        if (!strcmp (type_name, "primary")
 
1250
                        || !strcmp (type_name, _("primary"))) {
 
1251
                *type = 0;
 
1252
        }
 
1253
        if (!strcmp (type_name, "extended")
 
1254
                        || !strcmp (type_name, _("extended"))) {
 
1255
                *type = PED_PARTITION_EXTENDED;
 
1256
        }
 
1257
        if (!strcmp (type_name, "logical")
 
1258
                        || !strcmp (type_name, _("logical"))) {
 
1259
                *type = PED_PARTITION_LOGICAL;
 
1260
        }
 
1261
 
 
1262
        free (type_name);
 
1263
        return 1;
 
1264
}
 
1265
 
 
1266
PedExceptionOption
 
1267
command_line_get_ex_opt (const char* prompt, PedExceptionOption options)
 
1268
{
 
1269
        StrList*              options_strlist = NULL;
 
1270
        PedExceptionOption    opt;
 
1271
        char*                 opt_name;
 
1272
 
 
1273
        for (opt = option_get_next (options, 0); opt;
 
1274
             opt = option_get_next (options, opt)) {
 
1275
                options_strlist = str_list_append_unique (options_strlist,
 
1276
                                     _(ped_exception_get_option_string (opt)));
 
1277
                options_strlist = str_list_append_unique (options_strlist,
 
1278
                                     ped_exception_get_option_string (opt));
 
1279
        }
 
1280
 
 
1281
        opt_name = command_line_get_word (prompt, NULL, options_strlist, 1);
 
1282
        if (!opt_name)
 
1283
                return PED_EXCEPTION_UNHANDLED;
 
1284
        str_list_destroy (options_strlist);
 
1285
 
 
1286
        opt = PED_EXCEPTION_OPTION_FIRST;
 
1287
        while (1) {
 
1288
                if (strcmp (opt_name,
 
1289
                            ped_exception_get_option_string (opt)) == 0)
 
1290
                        break;
 
1291
                if (strcmp (opt_name,
 
1292
                            _(ped_exception_get_option_string (opt))) == 0)
 
1293
                        break;
 
1294
                opt = option_get_next (options, opt);
 
1295
        }
 
1296
        free (opt_name);
 
1297
        return opt;
 
1298
}
 
1299
 
 
1300
int
 
1301
command_line_get_align_type (const char *prompt, enum AlignmentType *align_type)
 
1302
{
 
1303
  char*    def_word;
 
1304
  char*    input;
 
1305
 
 
1306
  if (*align_type)
 
1307
    def_word = str_list_convert_node (align_opt_list);
 
1308
  else
 
1309
    def_word = str_list_convert_node (align_min_list);
 
1310
  input = command_line_get_word (prompt, def_word, align_opt_min_list, 1);
 
1311
  free (def_word);
 
1312
  if (!input)
 
1313
    return 0;
 
1314
  *align_type = (str_list_match_any (align_opt_list, input)
 
1315
             ? PA_OPTIMUM
 
1316
             : PA_MINIMUM);
 
1317
  free (input);
 
1318
  return 1;
 
1319
}
 
1320
 
 
1321
int
 
1322
command_line_get_unit (const char* prompt, PedUnit* unit)
 
1323
{
 
1324
        StrList*       opts = NULL;
 
1325
        PedUnit        walk;
 
1326
        char*          unit_name;
 
1327
        const char*    default_unit_name;
 
1328
 
 
1329
        for (walk = PED_UNIT_FIRST; walk <= PED_UNIT_LAST; walk++)
 
1330
                opts = str_list_append (opts, ped_unit_get_name (walk));
 
1331
 
 
1332
        default_unit_name = ped_unit_get_name (ped_unit_get_default ());
 
1333
        unit_name = command_line_get_word (prompt, default_unit_name, opts, 1);
 
1334
        str_list_destroy (opts);
 
1335
 
 
1336
        if (unit_name) {
 
1337
                *unit = ped_unit_get_by_name (unit_name);
 
1338
                free (unit_name);
 
1339
                return 1;
 
1340
        } else
 
1341
                return 0;
 
1342
}
 
1343
 
 
1344
int
 
1345
command_line_is_integer ()
 
1346
{
 
1347
        char*    word;
 
1348
        int      is_integer;
 
1349
        int      scratch;
 
1350
 
 
1351
        word = command_line_peek_word ();
 
1352
        if (!word)
 
1353
                return 0;
 
1354
 
 
1355
        is_integer = sscanf (word, "%d", &scratch);
 
1356
        free (word);
 
1357
        return is_integer;
 
1358
}
 
1359
 
 
1360
static int
 
1361
init_ex_opt_str ()
 
1362
{
 
1363
        int                   i;
 
1364
        PedExceptionOption    opt;
 
1365
 
 
1366
        for (i = 0; (1 << i) <= PED_EXCEPTION_OPTION_LAST; i++) {
 
1367
                opt = (1 << i);
 
1368
                ex_opt_str [i]
 
1369
                        = str_list_create (
 
1370
                                ped_exception_get_option_string (opt),
 
1371
                                _(ped_exception_get_option_string (opt)),
 
1372
                                NULL);
 
1373
                if (!ex_opt_str [i])
 
1374
                        return 0;
 
1375
        }
 
1376
 
 
1377
        ex_opt_str [i] = NULL;
 
1378
        return 1;
 
1379
}
 
1380
 
 
1381
static void
 
1382
done_ex_opt_str ()
 
1383
{
 
1384
        int    i;
 
1385
 
 
1386
        for (i=0; ex_opt_str [i]; i++)
 
1387
                str_list_destroy (ex_opt_str [i]);
 
1388
}
 
1389
 
 
1390
static int
 
1391
init_state_str ()
 
1392
{
 
1393
        on_list = str_list_create_unique (_("on"), "on", NULL);
 
1394
        off_list = str_list_create_unique (_("off"), "off", NULL);
 
1395
        on_off_list = str_list_join (str_list_duplicate (on_list),
 
1396
                                     str_list_duplicate (off_list));
 
1397
        return 1;
 
1398
}
 
1399
 
 
1400
static void
 
1401
done_state_str ()
 
1402
{
 
1403
        str_list_destroy (on_list);
 
1404
        str_list_destroy (off_list);
 
1405
        str_list_destroy (on_off_list);
 
1406
}
 
1407
 
 
1408
static int
 
1409
init_alignment_type_str ()
 
1410
{
 
1411
        align_opt_list = str_list_create_unique (_("optimal"), "optimal", NULL);
 
1412
        align_min_list = str_list_create_unique (_("minimal"), "minimal", NULL);
 
1413
        align_opt_min_list = str_list_join (str_list_duplicate (align_opt_list),
 
1414
                                            str_list_duplicate (align_min_list));
 
1415
        return 1;
 
1416
}
 
1417
 
 
1418
static void
 
1419
done_alignment_type_str ()
 
1420
{
 
1421
        str_list_destroy (align_opt_list);
 
1422
        str_list_destroy (align_min_list);
 
1423
        str_list_destroy (align_opt_min_list);
 
1424
}
 
1425
 
 
1426
static int
 
1427
init_fs_type_str ()
 
1428
{
 
1429
        PedFileSystemType*    walk;
 
1430
        PedFileSystemAlias*   alias_walk;
 
1431
 
 
1432
        fs_type_list = NULL;
 
1433
 
 
1434
        for (walk = ped_file_system_type_get_next (NULL); walk;
 
1435
             walk = ped_file_system_type_get_next (walk))
 
1436
        {
 
1437
                fs_type_list = str_list_insert (fs_type_list, walk->name);
 
1438
                if (!fs_type_list)
 
1439
                        return 0;
 
1440
        }
 
1441
        for (alias_walk = ped_file_system_alias_get_next (NULL); alias_walk;
 
1442
             alias_walk = ped_file_system_alias_get_next (alias_walk))
 
1443
        {
 
1444
                fs_type_list = str_list_insert (fs_type_list,
 
1445
                                                alias_walk->alias);
 
1446
                if (!fs_type_list)
 
1447
                        return 0;
 
1448
        }
 
1449
 
 
1450
        return 1;
 
1451
}
 
1452
 
 
1453
static int
 
1454
init_disk_type_str ()
 
1455
{
 
1456
        PedDiskType*    walk;
 
1457
 
 
1458
        disk_type_list = NULL;
 
1459
 
 
1460
        for (walk = ped_disk_type_get_next (NULL); walk;
 
1461
             walk = ped_disk_type_get_next (walk))
 
1462
        {
 
1463
                disk_type_list = str_list_insert (disk_type_list, walk->name);
 
1464
                if (!disk_type_list)
 
1465
                        return 0;
 
1466
        }
 
1467
 
 
1468
        return 1;
 
1469
}
 
1470
 
 
1471
int
 
1472
init_readline (void)
 
1473
{
 
1474
#ifdef HAVE_LIBREADLINE
 
1475
  if (!opt_script_mode) {
 
1476
    rl_initialize ();
 
1477
    rl_attempted_completion_function = (CPPFunction*) complete_function;
 
1478
    readline_state.in_readline = 0;
 
1479
  }
 
1480
#endif
 
1481
  return 0;
 
1482
}
 
1483
 
 
1484
int
 
1485
init_ui ()
 
1486
{
 
1487
        if (!init_ex_opt_str ()
 
1488
            || !init_state_str ()
 
1489
            || !init_alignment_type_str ()
 
1490
            || !init_fs_type_str ()
 
1491
            || !init_disk_type_str ())
 
1492
                return 0;
 
1493
        ped_exception_set_handler (exception_handler);
 
1494
 
 
1495
#ifdef SA_SIGINFO
 
1496
        sigset_t curr;
 
1497
        sigfillset (&curr);
 
1498
 
 
1499
        sig_segv.sa_sigaction = &sa_sigsegv_handler;
 
1500
        sig_int.sa_sigaction = &sa_sigint_handler;
 
1501
        sig_fpe.sa_sigaction = &sa_sigfpe_handler;
 
1502
        sig_ill.sa_sigaction = &sa_sigill_handler;
 
1503
 
 
1504
        sig_segv.sa_mask =
 
1505
                sig_int.sa_mask =
 
1506
                        sig_fpe.sa_mask =
 
1507
                                sig_ill.sa_mask = curr;
 
1508
 
 
1509
        sig_segv.sa_flags =
 
1510
                sig_int.sa_flags =
 
1511
                        sig_fpe.sa_flags =
 
1512
                                sig_ill.sa_flags = SA_SIGINFO;
 
1513
 
 
1514
        sigaction (SIGSEGV, &sig_segv, NULL);
 
1515
        sigaction (SIGINT, &sig_int, NULL);
 
1516
        sigaction (SIGFPE, &sig_fpe, NULL);
 
1517
        sigaction (SIGILL, &sig_ill, NULL);
 
1518
#else
 
1519
        signal (SIGSEGV, s_sigsegv_handler);
 
1520
        signal (SIGINT, s_sigint_handler);
 
1521
        signal (SIGFPE, s_sigfpe_handler);
 
1522
        signal (SIGILL, s_sigill_handler);
 
1523
#endif /* SA_SIGINFO */
 
1524
 
 
1525
        return 1;
 
1526
}
 
1527
 
 
1528
void
 
1529
done_ui ()
 
1530
{
 
1531
        ped_exception_set_handler (NULL);
 
1532
        done_ex_opt_str ();
 
1533
        done_state_str ();
 
1534
        done_alignment_type_str ();
 
1535
        str_list_destroy (fs_type_list);
 
1536
        str_list_destroy (disk_type_list);
 
1537
}
 
1538
 
 
1539
void
 
1540
help_msg ()
 
1541
{
 
1542
        fputs (_(usage_msg), stdout);
 
1543
 
 
1544
        putchar ('\n');
 
1545
        fputs (_("OPTIONs:"), stdout);
 
1546
        putchar ('\n');
 
1547
        print_options_help ();
 
1548
 
 
1549
        putchar ('\n');
 
1550
        fputs (_("COMMANDs:"), stdout);
 
1551
        putchar ('\n');
 
1552
        print_commands_help ();
 
1553
        printf (_("\nReport bugs to %s\n"), PACKAGE_BUGREPORT);
 
1554
        exit (EXIT_SUCCESS);
 
1555
}
 
1556
 
 
1557
void
 
1558
print_using_dev (PedDevice* dev)
 
1559
{
 
1560
        printf (_("Using %s\n"), dev->path);
 
1561
}
 
1562
 
 
1563
int
 
1564
interactive_mode (PedDevice** dev, Command* cmd_list[])
 
1565
{
 
1566
        StrList*    list;
 
1567
        StrList*    command_names = command_get_names (cmd_list);
 
1568
 
 
1569
        commands = cmd_list;    /* FIXME yucky, nasty, evil hack */
 
1570
 
 
1571
        fputs (prog_name, stdout);
 
1572
 
 
1573
        print_using_dev (*dev);
 
1574
 
 
1575
        list = str_list_create (_(banner_msg), NULL);
 
1576
        str_list_print_wrap (list, screen_width (), 0, 0, stdout);
 
1577
        str_list_destroy (list);
 
1578
 
 
1579
        while (1) {
 
1580
                char*       word;
 
1581
                Command*    cmd;
 
1582
 
 
1583
                while (!command_line_get_word_count ()) {
 
1584
                        if (feof (stdin)) {
 
1585
                                putchar ('\n');
 
1586
                                return 1;
 
1587
                        }
 
1588
                        command_line_prompt_words ("(parted)", NULL,
 
1589
                                                   command_names, 1);
 
1590
                }
 
1591
 
 
1592
                word = command_line_pop_word ();
 
1593
                if (word) {
 
1594
                        cmd = command_get (commands, word);
 
1595
                        free (word);
 
1596
                        if (cmd) {
 
1597
                                if (!command_run (cmd, dev))
 
1598
                                        command_line_flush ();
 
1599
                        } else
 
1600
                                print_commands_help ();
 
1601
                }
 
1602
        }
 
1603
 
 
1604
        return 1;
 
1605
}
 
1606
 
 
1607
 
 
1608
int
 
1609
non_interactive_mode (PedDevice** dev, Command* cmd_list[],
 
1610
                      int argc, char* argv[])
 
1611
{
 
1612
        int         i;
 
1613
        Command*    cmd;
 
1614
 
 
1615
        commands = cmd_list;    /* FIXME yucky, nasty, evil hack */
 
1616
 
 
1617
        for (i = 0; i < argc; i++)
 
1618
                command_line_push_line (argv [i], 1);
 
1619
 
 
1620
        while (command_line_get_word_count ()) {
 
1621
                char*    word;
 
1622
 
 
1623
                word = command_line_pop_word ();
 
1624
                if (!word)
 
1625
                        break;
 
1626
 
 
1627
                cmd = command_get (commands, word);
 
1628
                free (word);
 
1629
                if (!cmd) {
 
1630
                        help_msg ();
 
1631
                        goto error;
 
1632
                }
 
1633
                if (!(cmd->non_interactive)) {
 
1634
                        fputs(_("This command does not make sense in "
 
1635
                                "non-interactive mode.\n"), stdout);
 
1636
                        exit(EXIT_FAILURE);
 
1637
                        goto error;
 
1638
                }
 
1639
 
 
1640
                if (!command_run (cmd, dev))
 
1641
                        goto error;
 
1642
        }
 
1643
        return 1;
 
1644
 
 
1645
error:
 
1646
        return 0;
 
1647
}