Check error returns from posix_fallocate (RHBZ#579664).
[libguestfs.git] / fish / fish.c
1 /* guestfish - the filesystem interactive shell
2  * Copyright (C) 2009 Red Hat Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18
19 #include <config.h>
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <fcntl.h>
26 #include <getopt.h>
27 #include <signal.h>
28 #include <assert.h>
29 #include <sys/types.h>
30 #include <sys/wait.h>
31 #include <locale.h>
32
33 #ifdef HAVE_LIBREADLINE
34 #include <readline/readline.h>
35 #include <readline/history.h>
36 #endif
37
38 #include <guestfs.h>
39
40 #include "fish.h"
41 #include "c-ctype.h"
42 #include "closeout.h"
43 #include "progname.h"
44
45 struct mp {
46   struct mp *next;
47   char *device;
48   char *mountpoint;
49 };
50
51 struct drv {
52   struct drv *next;
53   char *filename;
54 };
55
56 static void add_drives (struct drv *drv);
57 static void mount_mps (struct mp *mp);
58 static void interactive (void);
59 static void shell_script (void);
60 static void script (int prompt);
61 static void cmdline (char *argv[], int optind, int argc);
62 static void initialize_readline (void);
63 static void cleanup_readline (void);
64 static void add_history_line (const char *);
65
66 /* Currently open libguestfs handle. */
67 guestfs_h *g;
68
69 int read_only = 0;
70 int quit = 0;
71 int verbose = 0;
72 int echo_commands = 0;
73 int remote_control_listen = 0;
74 int remote_control = 0;
75 int exit_on_error = 1;
76
77 int
78 launch (guestfs_h *_g)
79 {
80   assert (_g == g);
81
82   if (guestfs_is_config (g)) {
83     if (guestfs_launch (g) == -1)
84       return -1;
85   }
86   return 0;
87 }
88
89 static void __attribute__((noreturn))
90 usage (int status)
91 {
92   if (status != EXIT_SUCCESS)
93     fprintf (stderr, _("Try `%s --help' for more information.\n"),
94              program_name);
95   else {
96     fprintf (stdout,
97            _("%s: guest filesystem shell\n"
98              "%s lets you edit virtual machine filesystems\n"
99              "Copyright (C) 2009 Red Hat Inc.\n"
100              "Usage:\n"
101              "  %s [--options] cmd [: cmd : cmd ...]\n"
102              "  %s -i libvirt-domain\n"
103              "  %s -i disk-image(s)\n"
104              "or for interactive use:\n"
105              "  %s\n"
106              "or from a shell script:\n"
107              "  %s <<EOF\n"
108              "  cmd\n"
109              "  ...\n"
110              "  EOF\n"
111              "Options:\n"
112              "  -h|--cmd-help        List available commands\n"
113              "  -h|--cmd-help cmd    Display detailed help on 'cmd'\n"
114              "  -a|--add image       Add image\n"
115              "  -D|--no-dest-paths   Don't tab-complete paths from guest fs\n"
116              "  -f|--file file       Read commands from file\n"
117              "  -i|--inspector       Run virt-inspector to get disk mountpoints\n"
118              "  --listen             Listen for remote commands\n"
119              "  -m|--mount dev[:mnt] Mount dev on mnt (if omitted, /)\n"
120              "  -n|--no-sync         Don't autosync\n"
121              "  --remote[=pid]       Send commands to remote %s\n"
122              "  -r|--ro              Mount read-only\n"
123              "  --selinux            Enable SELinux support\n"
124              "  -v|--verbose         Verbose messages\n"
125              "  -x                   Echo each command before executing it\n"
126              "  -V|--version         Display version and exit\n"
127              "For more information,  see the manpage %s(1).\n"),
128              program_name, program_name, program_name,
129              program_name, program_name, program_name,
130              program_name, program_name, program_name);
131   }
132   exit (status);
133 }
134
135 int
136 main (int argc, char *argv[])
137 {
138   /* Set global program name that is not polluted with libtool artifacts.  */
139   set_program_name (argv[0]);
140
141   atexit (close_stdout);
142
143   setlocale (LC_ALL, "");
144   bindtextdomain (PACKAGE, LOCALEBASEDIR);
145   textdomain (PACKAGE);
146
147   enum { HELP_OPTION = CHAR_MAX + 1 };
148
149   static const char *options = "a:Df:h::im:nrv?Vx";
150   static const struct option long_options[] = {
151     { "add", 1, 0, 'a' },
152     { "cmd-help", 2, 0, 'h' },
153     { "file", 1, 0, 'f' },
154     { "help", 0, 0, HELP_OPTION },
155     { "inspector", 0, 0, 'i' },
156     { "listen", 0, 0, 0 },
157     { "mount", 1, 0, 'm' },
158     { "no-dest-paths", 0, 0, 'D' },
159     { "no-sync", 0, 0, 'n' },
160     { "remote", 2, 0, 0 },
161     { "ro", 0, 0, 'r' },
162     { "selinux", 0, 0, 0 },
163     { "verbose", 0, 0, 'v' },
164     { "version", 0, 0, 'V' },
165     { 0, 0, 0, 0 }
166   };
167   struct drv *drvs = NULL;
168   struct drv *drv;
169   struct mp *mps = NULL;
170   struct mp *mp;
171   char *p, *file = NULL;
172   int c;
173   int inspector = 0;
174   int option_index;
175   struct sigaction sa;
176
177   initialize_readline ();
178
179   memset (&sa, 0, sizeof sa);
180   sa.sa_handler = SIG_IGN;
181   sa.sa_flags = SA_RESTART;
182   sigaction (SIGPIPE, &sa, NULL);
183
184   /* guestfs_create is meant to be a lightweight operation, so
185    * it's OK to do it early here.
186    */
187   g = guestfs_create ();
188   if (g == NULL) {
189     fprintf (stderr, _("guestfs_create: failed to create handle\n"));
190     exit (EXIT_FAILURE);
191   }
192
193   guestfs_set_autosync (g, 1);
194
195   /* If developing, add ./appliance to the path.  Note that libtools
196    * interferes with this because uninstalled guestfish is a shell
197    * script that runs the real program with an absolute path.  Detect
198    * that too.
199    *
200    * BUT if LIBGUESTFS_PATH environment variable is already set by
201    * the user, then don't override it.
202    */
203   if (getenv ("LIBGUESTFS_PATH") == NULL &&
204       argv[0] &&
205       (argv[0][0] != '/' || strstr (argv[0], "/.libs/lt-") != NULL))
206     guestfs_set_path (g, "appliance:" GUESTFS_DEFAULT_PATH);
207
208   /* CAUTION: we are careful to modify argv[0] here, only after
209    * using it just above.
210    *
211    * getopt_long uses argv[0], so give it the sanitized name.  Save a copy
212    * of the original, in case it's needed in virt-inspector mode, below.
213    */
214   char *real_argv0 = argv[0];
215   argv[0] = bad_cast (program_name);
216
217   for (;;) {
218     c = getopt_long (argc, argv, options, long_options, &option_index);
219     if (c == -1) break;
220
221     switch (c) {
222     case 0:                     /* options which are long only */
223       if (STREQ (long_options[option_index].name, "listen"))
224         remote_control_listen = 1;
225       else if (STREQ (long_options[option_index].name, "remote")) {
226         if (optarg) {
227           if (sscanf (optarg, "%d", &remote_control) != 1) {
228             fprintf (stderr, _("%s: --listen=PID: PID was not a number: %s\n"),
229                      program_name, optarg);
230             exit (EXIT_FAILURE);
231           }
232         } else {
233           p = getenv ("GUESTFISH_PID");
234           if (!p || sscanf (p, "%d", &remote_control) != 1) {
235             fprintf (stderr, _("%s: remote: $GUESTFISH_PID must be set"
236                                " to the PID of the remote process\n"),
237                      program_name);
238             exit (EXIT_FAILURE);
239           }
240         }
241       } else if (STREQ (long_options[option_index].name, "selinux")) {
242         guestfs_set_selinux (g, 1);
243       } else {
244         fprintf (stderr, _("%s: unknown long option: %s (%d)\n"),
245                  program_name, long_options[option_index].name, option_index);
246         exit (EXIT_FAILURE);
247       }
248       break;
249
250     case 'a':
251       if (access (optarg, R_OK) != 0) {
252         perror (optarg);
253         exit (EXIT_FAILURE);
254       }
255       drv = malloc (sizeof (struct drv));
256       if (!drv) {
257         perror ("malloc");
258         exit (EXIT_FAILURE);
259       }
260       drv->filename = optarg;
261       drv->next = drvs;
262       drvs = drv;
263       break;
264
265     case 'D':
266       complete_dest_paths = 0;
267       break;
268
269     case 'f':
270       if (file) {
271         fprintf (stderr, _("%s: only one -f parameter can be given\n"),
272                  program_name);
273         exit (EXIT_FAILURE);
274       }
275       file = optarg;
276       break;
277
278     case 'h':
279       if (optarg)
280         display_command (optarg);
281       else if (argv[optind] && argv[optind][0] != '-')
282         display_command (argv[optind++]);
283       else
284         list_commands ();
285       exit (EXIT_SUCCESS);
286
287     case 'i':
288       inspector = 1;
289       break;
290
291     case 'm':
292       mp = malloc (sizeof (struct mp));
293       if (!mp) {
294         perror ("malloc");
295         exit (EXIT_FAILURE);
296       }
297       p = strchr (optarg, ':');
298       if (p) {
299         *p = '\0';
300         mp->mountpoint = p+1;
301       } else
302         mp->mountpoint = bad_cast ("/");
303       mp->device = optarg;
304       mp->next = mps;
305       mps = mp;
306       break;
307
308     case 'n':
309       guestfs_set_autosync (g, 0);
310       break;
311
312     case 'r':
313       read_only = 1;
314       break;
315
316     case 'v':
317       verbose++;
318       guestfs_set_verbose (g, verbose);
319       break;
320
321     case 'V':
322       printf ("%s %s\n", program_name, PACKAGE_VERSION);
323       exit (EXIT_SUCCESS);
324
325     case 'x':
326       echo_commands = 1;
327       break;
328
329     case HELP_OPTION:
330       usage (EXIT_SUCCESS);
331
332     default:
333       usage (EXIT_FAILURE);
334     }
335   }
336
337   /* Inspector mode invalidates most of the other arguments. */
338   if (inspector) {
339     char cmd[1024];
340     int r;
341
342     if (drvs || mps || remote_control_listen || remote_control ||
343         guestfs_get_selinux (g)) {
344       fprintf (stderr, _("%s: cannot use -i option with -a, -m,"
345                          " --listen, --remote or --selinux\n"),
346                program_name);
347       exit (EXIT_FAILURE);
348     }
349     if (optind >= argc) {
350       fprintf (stderr,
351            _("%s: -i requires a libvirt domain or path(s) to disk image(s)\n"),
352                program_name);
353       exit (EXIT_FAILURE);
354     }
355
356     strcpy (cmd, "a=`virt-inspector");
357     while (optind < argc) {
358       if (strlen (cmd) + strlen (argv[optind]) + strlen (real_argv0) + 60
359           >= sizeof cmd) {
360         fprintf (stderr,
361                  _("%s: virt-inspector command too long for fixed-size buffer\n"),
362                  program_name);
363         exit (EXIT_FAILURE);
364       }
365       strcat (cmd, " '");
366       strcat (cmd, argv[optind]);
367       strcat (cmd, "'");
368       optind++;
369     }
370
371     if (read_only)
372       strcat (cmd, " --ro-fish");
373     else
374       strcat (cmd, " --fish");
375
376     sprintf (&cmd[strlen(cmd)], "` && %s $a", real_argv0);
377
378     if (guestfs_get_verbose (g))
379       strcat (cmd, " -v");
380     if (!guestfs_get_autosync (g))
381       strcat (cmd, " -n");
382
383     if (verbose)
384       fprintf (stderr,
385                "%s -i: running virt-inspector command:\n%s\n", program_name, cmd);
386
387     r = system (cmd);
388     if (r == -1) {
389       perror ("system");
390       exit (EXIT_FAILURE);
391     }
392     exit (WEXITSTATUS (r));
393   }
394
395   /* If we've got drives to add, add them now. */
396   add_drives (drvs);
397
398   /* If we've got mountpoints, we must launch the guest and mount them. */
399   if (mps != NULL) {
400     if (launch (g) == -1) exit (EXIT_FAILURE);
401     mount_mps (mps);
402   }
403
404   /* Remote control? */
405   if (remote_control_listen && remote_control) {
406     fprintf (stderr,
407              _("%s: cannot use --listen and --remote options at the same time\n"),
408              program_name);
409     exit (EXIT_FAILURE);
410   }
411
412   if (remote_control_listen) {
413     if (optind < argc) {
414       fprintf (stderr,
415                _("%s: extra parameters on the command line with --listen flag\n"),
416                program_name);
417       exit (EXIT_FAILURE);
418     }
419     if (file) {
420       fprintf (stderr,
421                _("%s: cannot use --listen and --file options at the same time\n"),
422                program_name);
423       exit (EXIT_FAILURE);
424     }
425     rc_listen ();
426   }
427
428   /* -f (file) parameter? */
429   if (file) {
430     close (0);
431     if (open (file, O_RDONLY) == -1) {
432       perror (file);
433       exit (EXIT_FAILURE);
434     }
435   }
436
437   /* Interactive, shell script, or command(s) on the command line? */
438   if (optind >= argc) {
439     if (isatty (0))
440       interactive ();
441     else
442       shell_script ();
443   }
444   else
445     cmdline (argv, optind, argc);
446
447   cleanup_readline ();
448
449   exit (EXIT_SUCCESS);
450 }
451
452 void
453 pod2text (const char *name, const char *shortdesc, const char *str)
454 {
455   FILE *fp;
456
457   fp = popen ("pod2text", "w");
458   if (fp == NULL) {
459     /* pod2text failed, maybe not found, so let's just print the
460      * source instead, since that's better than doing nothing.
461      */
462     printf ("%s - %s\n\n%s\n", name, shortdesc, str);
463     return;
464   }
465   fprintf (fp, "=head1 NAME\n\n%s - %s\n\n", name, shortdesc);
466   fputs (str, fp);
467   pclose (fp);
468 }
469
470 /* List is built in reverse order, so mount them in reverse order. */
471 static void
472 mount_mps (struct mp *mp)
473 {
474   int r;
475
476   if (mp) {
477     mount_mps (mp->next);
478
479     /* Don't use guestfs_mount here because that will default to mount
480      * options -o sync,noatime.  For more information, see guestfs(3)
481      * section "LIBGUESTFS GOTCHAS".
482      */
483     const char *options = read_only ? "ro" : "";
484     r = guestfs_mount_options (g, options, mp->device, mp->mountpoint);
485     if (r == -1)
486       exit (EXIT_FAILURE);
487   }
488 }
489
490 static void
491 add_drives (struct drv *drv)
492 {
493   int r;
494
495   if (drv) {
496     add_drives (drv->next);
497     if (!read_only)
498       r = guestfs_add_drive (g, drv->filename);
499     else
500       r = guestfs_add_drive_ro (g, drv->filename);
501     if (r == -1)
502       exit (EXIT_FAILURE);
503   }
504 }
505
506 static void
507 interactive (void)
508 {
509   script (1);
510 }
511
512 static void
513 shell_script (void)
514 {
515   script (0);
516 }
517
518 #define FISH "><fs> "
519
520 static char *line_read = NULL;
521
522 static char *
523 rl_gets (int prompt)
524 {
525 #ifdef HAVE_LIBREADLINE
526
527   if (prompt) {
528     if (line_read) {
529       free (line_read);
530       line_read = NULL;
531     }
532
533     line_read = readline (prompt ? FISH : "");
534
535     if (line_read && *line_read)
536       add_history_line (line_read);
537
538     return line_read;
539   }
540
541 #endif /* HAVE_LIBREADLINE */
542
543   static char buf[8192];
544   int len;
545
546   if (prompt) printf (FISH);
547   line_read = fgets (buf, sizeof buf, stdin);
548
549   if (line_read) {
550     len = strlen (line_read);
551     if (len > 0 && buf[len-1] == '\n') buf[len-1] = '\0';
552   }
553
554   return line_read;
555 }
556
557 static void
558 script (int prompt)
559 {
560   char *buf;
561   char *cmd;
562   char *p, *pend;
563   char *argv[64];
564   int len;
565   int global_exit_on_error = !prompt;
566   int tilde_candidate;
567
568   if (prompt)
569     printf (_("\n"
570               "Welcome to guestfish, the libguestfs filesystem interactive shell for\n"
571               "editing virtual machine filesystems.\n"
572               "\n"
573               "Type: 'help' for help with commands\n"
574               "      'quit' to quit the shell\n"
575               "\n"));
576
577   while (!quit) {
578     char *pipe = NULL;
579
580     exit_on_error = global_exit_on_error;
581
582     buf = rl_gets (prompt);
583     if (!buf) {
584       quit = 1;
585       break;
586     }
587
588     /* Skip any initial whitespace before the command. */
589   again:
590     while (*buf && c_isspace (*buf))
591       buf++;
592
593     if (!*buf) continue;
594
595     /* If the next character is '#' then this is a comment. */
596     if (*buf == '#') continue;
597
598     /* If the next character is '!' then pass the whole lot to system(3). */
599     if (*buf == '!') {
600       int r;
601
602       r = system (buf+1);
603       if (exit_on_error) {
604         if (r == -1 ||
605             (WIFSIGNALED (r) &&
606              (WTERMSIG (r) == SIGINT || WTERMSIG (r) == SIGQUIT)) ||
607             WEXITSTATUS (r) != 0)
608           exit (EXIT_FAILURE);
609       }
610       continue;
611     }
612
613     /* If the next character is '-' allow the command to fail without
614      * exiting on error (just for this one command though).
615      */
616     if (*buf == '-') {
617       exit_on_error = 0;
618       buf++;
619       goto again;
620     }
621
622     /* Get the command (cannot be quoted). */
623     len = strcspn (buf, " \t");
624
625     if (len == 0) continue;
626
627     cmd = buf;
628     unsigned int i = 0;
629     if (buf[len] == '\0') {
630       argv[0] = NULL;
631       goto got_command;
632     }
633
634     buf[len] = '\0';
635     p = &buf[len+1];
636     p += strspn (p, " \t");
637
638     /* Get the parameters. */
639     while (*p && i < sizeof argv / sizeof argv[0]) {
640       tilde_candidate = 0;
641
642       /* Parameters which start with quotes or pipes are treated
643        * specially.  Bare parameters are delimited by whitespace.
644        */
645       if (*p == '"') {
646         p++;
647         len = strcspn (p, "\"");
648         if (p[len] == '\0') {
649           fprintf (stderr, _("%s: unterminated double quote\n"), program_name);
650           if (exit_on_error) exit (EXIT_FAILURE);
651           goto next_command;
652         }
653         if (p[len+1] && (p[len+1] != ' ' && p[len+1] != '\t')) {
654           fprintf (stderr,
655                    _("%s: command arguments not separated by whitespace\n"),
656                    program_name);
657           if (exit_on_error) exit (EXIT_FAILURE);
658           goto next_command;
659         }
660         p[len] = '\0';
661         pend = p[len+1] ? &p[len+2] : &p[len+1];
662       } else if (*p == '\'') {
663         p++;
664         len = strcspn (p, "'");
665         if (p[len] == '\0') {
666           fprintf (stderr, _("%s: unterminated single quote\n"), program_name);
667           if (exit_on_error) exit (EXIT_FAILURE);
668           goto next_command;
669         }
670         if (p[len+1] && (p[len+1] != ' ' && p[len+1] != '\t')) {
671           fprintf (stderr,
672                    _("%s: command arguments not separated by whitespace\n"),
673                    program_name);
674           if (exit_on_error) exit (EXIT_FAILURE);
675           goto next_command;
676         }
677         p[len] = '\0';
678         pend = p[len+1] ? &p[len+2] : &p[len+1];
679       } else if (*p == '|') {
680         *p = '\0';
681         pipe = p+1;
682         continue;
683         /*
684       } else if (*p == '[') {
685         int c = 1;
686         p++;
687         pend = p;
688         while (*pend && c != 0) {
689           if (*pend == '[') c++;
690           else if (*pend == ']') c--;
691           pend++;
692         }
693         if (c != 0) {
694           fprintf (stderr,
695                    _("%s: unterminated \"[...]\" sequence\n"), program_name);
696           if (exit_on_error) exit (EXIT_FAILURE);
697           goto next_command;
698         }
699         if (*pend && (*pend != ' ' && *pend != '\t')) {
700           fprintf (stderr,
701                    _("%s: command arguments not separated by whitespace\n"),
702                    program_name);
703           if (exit_on_error) exit (EXIT_FAILURE);
704           goto next_command;
705         }
706         *(pend-1) = '\0';
707         */
708       } else if (*p != ' ' && *p != '\t') {
709         /* If the first character is a ~ then note that this parameter
710          * is a candidate for ~username expansion.  NB this does not
711          * apply to quoted parameters.
712          */
713         tilde_candidate = *p == '~';
714         len = strcspn (p, " \t");
715         if (p[len]) {
716           p[len] = '\0';
717           pend = &p[len+1];
718         } else
719           pend = &p[len];
720       } else {
721         fprintf (stderr, _("%s: internal error parsing string at '%s'\n"),
722                  program_name, p);
723         abort ();
724       }
725
726       if (!tilde_candidate)
727         argv[i] = p;
728       else
729         argv[i] = try_tilde_expansion (p);
730       i++;
731       p = pend;
732
733       if (*p)
734         p += strspn (p, " \t");
735     }
736
737     if (i == sizeof argv / sizeof argv[0]) {
738       fprintf (stderr, _("%s: too many arguments\n"), program_name);
739       if (exit_on_error) exit (EXIT_FAILURE);
740       goto next_command;
741     }
742
743     argv[i] = NULL;
744
745   got_command:
746     if (issue_command (cmd, argv, pipe) == -1) {
747       if (exit_on_error) exit (EXIT_FAILURE);
748     }
749
750   next_command:;
751   }
752   if (prompt) printf ("\n");
753 }
754
755 static void
756 cmdline (char *argv[], int optind, int argc)
757 {
758   const char *cmd;
759   char **params;
760
761   exit_on_error = 1;
762
763   if (optind >= argc) return;
764
765   cmd = argv[optind++];
766   if (STREQ (cmd, ":")) {
767     fprintf (stderr, _("%s: empty command on command line\n"), program_name);
768     exit (EXIT_FAILURE);
769   }
770   params = &argv[optind];
771
772   /* Search for end of command list or ":" ... */
773   while (optind < argc && STRNEQ (argv[optind], ":"))
774     optind++;
775
776   if (optind == argc) {
777     if (issue_command (cmd, params, NULL) == -1) exit (EXIT_FAILURE);
778   } else {
779     argv[optind] = NULL;
780     if (issue_command (cmd, params, NULL) == -1) exit (EXIT_FAILURE);
781     cmdline (argv, optind+1, argc);
782   }
783 }
784
785 int
786 issue_command (const char *cmd, char *argv[], const char *pipecmd)
787 {
788   int argc;
789   int stdout_saved_fd = -1;
790   int pid = 0;
791   int i, r;
792
793   if (echo_commands) {
794     printf ("%s", cmd);
795     for (i = 0; argv[i] != NULL; ++i)
796       printf (" %s", argv[i]);
797     printf ("\n");
798   }
799
800   /* For | ... commands.  Annoyingly we can't use popen(3) here. */
801   if (pipecmd) {
802     int fd[2];
803
804     if (fflush (stdout) == EOF) {
805       perror ("failed to flush standard output");
806       return -1;
807     }
808     if (pipe (fd) < 0) {
809       perror ("pipe failed");
810       return -1;
811     }
812     pid = fork ();
813     if (pid == -1) {
814       perror ("fork");
815       return -1;
816     }
817
818     if (pid == 0) {             /* Child process. */
819       close (fd[1]);
820       if (dup2 (fd[0], 0) < 0) {
821         perror ("dup2 of stdin failed");
822         _exit (1);
823       }
824
825       r = system (pipecmd);
826       if (r == -1) {
827         perror (pipecmd);
828         _exit (1);
829       }
830       _exit (WEXITSTATUS (r));
831     }
832
833     if ((stdout_saved_fd = dup (1)) < 0) {
834       perror ("failed to dup stdout");
835       return -1;
836     }
837     close (fd[0]);
838     if (dup2 (fd[1], 1) < 0) {
839       perror ("failed to dup stdout");
840       close (stdout_saved_fd);
841       return -1;
842     }
843     close (fd[1]);
844   }
845
846   for (argc = 0; argv[argc] != NULL; ++argc)
847     ;
848
849   /* If --remote was set, then send this command to a remote process. */
850   if (remote_control)
851     r = rc_remote (remote_control, cmd, argc, argv, exit_on_error);
852
853   /* Otherwise execute it locally. */
854   else if (STRCASEEQ (cmd, "help")) {
855     if (argc == 0)
856       list_commands ();
857     else
858       display_command (argv[0]);
859     r = 0;
860   }
861   else if (STRCASEEQ (cmd, "quit") ||
862            STRCASEEQ (cmd, "exit") ||
863            STRCASEEQ (cmd, "q")) {
864     quit = 1;
865     r = 0;
866   }
867   else if (STRCASEEQ (cmd, "alloc") ||
868            STRCASEEQ (cmd, "allocate"))
869     r = do_alloc (cmd, argc, argv);
870   else if (STRCASEEQ (cmd, "echo"))
871     r = do_echo (cmd, argc, argv);
872   else if (STRCASEEQ (cmd, "edit") ||
873            STRCASEEQ (cmd, "vi") ||
874            STRCASEEQ (cmd, "emacs"))
875     r = do_edit (cmd, argc, argv);
876   else if (STRCASEEQ (cmd, "lcd"))
877     r = do_lcd (cmd, argc, argv);
878   else if (STRCASEEQ (cmd, "glob"))
879     r = do_glob (cmd, argc, argv);
880   else if (STRCASEEQ (cmd, "more") ||
881            STRCASEEQ (cmd, "less"))
882     r = do_more (cmd, argc, argv);
883   else if (STRCASEEQ (cmd, "reopen"))
884     r = do_reopen (cmd, argc, argv);
885   else if (STRCASEEQ (cmd, "sparse"))
886     r = do_sparse (cmd, argc, argv);
887   else if (STRCASEEQ (cmd, "time"))
888     r = do_time (cmd, argc, argv);
889   else
890     r = run_action (cmd, argc, argv);
891
892   /* Always flush stdout after every command, so that messages, results
893    * etc appear immediately.
894    */
895   if (fflush (stdout) == EOF) {
896     perror ("failed to flush standard output");
897     return -1;
898   }
899
900   if (pipecmd) {
901     close (1);
902     if (dup2 (stdout_saved_fd, 1) < 0) {
903       perror ("failed to dup2 standard output");
904       r = -1;
905     }
906     close (stdout_saved_fd);
907     if (waitpid (pid, NULL, 0) < 0) {
908       perror ("waiting for command to complete");
909       r = -1;
910     }
911   }
912
913   return r;
914 }
915
916 void
917 list_builtin_commands (void)
918 {
919   /* help and quit should appear at the top */
920   printf ("%-20s %s\n",
921           "help", _("display a list of commands or help on a command"));
922   printf ("%-20s %s\n",
923           "quit", _("quit guestfish"));
924
925   printf ("%-20s %s\n",
926           "alloc", _("allocate an image"));
927   printf ("%-20s %s\n",
928           "echo", _("display a line of text"));
929   printf ("%-20s %s\n",
930           "edit", _("edit a file in the image"));
931   printf ("%-20s %s\n",
932           "lcd", _("local change directory"));
933   printf ("%-20s %s\n",
934           "glob", _("expand wildcards in command"));
935   printf ("%-20s %s\n",
936           "more", _("view a file in the pager"));
937   printf ("%-20s %s\n",
938           "reopen", _("close and reopen libguestfs handle"));
939   printf ("%-20s %s\n",
940           "sparse", _("allocate a sparse image file"));
941   printf ("%-20s %s\n",
942           "time", _("measure time taken to run command"));
943
944   /* actions are printed after this (see list_commands) */
945 }
946
947 void
948 display_builtin_command (const char *cmd)
949 {
950   /* help for actions is auto-generated, see display_command */
951
952   if (STRCASEEQ (cmd, "alloc") ||
953       STRCASEEQ (cmd, "allocate"))
954     printf (_("alloc - allocate an image\n"
955               "     alloc <filename> <size>\n"
956               "\n"
957               "    This creates an empty (zeroed) file of the given size,\n"
958               "    and then adds so it can be further examined.\n"
959               "\n"
960               "    For more advanced image creation, see qemu-img utility.\n"
961               "\n"
962               "    Size can be specified (where <nn> means a number):\n"
963               "    <nn>             number of kilobytes\n"
964               "      eg: 1440       standard 3.5\" floppy\n"
965               "    <nn>K or <nn>KB  number of kilobytes\n"
966               "    <nn>M or <nn>MB  number of megabytes\n"
967               "    <nn>G or <nn>GB  number of gigabytes\n"
968               "    <nn>T or <nn>TB  number of terabytes\n"
969               "    <nn>P or <nn>PB  number of petabytes\n"
970               "    <nn>E or <nn>EB  number of exabytes\n"
971               "    <nn>sects        number of 512 byte sectors\n"));
972   else if (STRCASEEQ (cmd, "echo"))
973     printf (_("echo - display a line of text\n"
974               "     echo [<params> ...]\n"
975               "\n"
976               "    This echos the parameters to the terminal.\n"));
977   else if (STRCASEEQ (cmd, "edit") ||
978            STRCASEEQ (cmd, "vi") ||
979            STRCASEEQ (cmd, "emacs"))
980     printf (_("edit - edit a file in the image\n"
981               "     edit <filename>\n"
982               "\n"
983               "    This is used to edit a file.\n"
984               "\n"
985               "    It is the equivalent of (and is implemented by)\n"
986               "    running \"cat\", editing locally, and then \"write-file\".\n"
987               "\n"
988               "    Normally it uses $EDITOR, but if you use the aliases\n"
989               "    \"vi\" or \"emacs\" you will get those editors.\n"
990               "\n"
991               "    NOTE: This will not work reliably for large files\n"
992               "    (> 2 MB) or binary files containing \\0 bytes.\n"));
993   else if (STRCASEEQ (cmd, "lcd"))
994     printf (_("lcd - local change directory\n"
995               "    lcd <directory>\n"
996               "\n"
997               "    Change guestfish's current directory. This command is\n"
998               "    useful if you want to download files to a particular\n"
999               "    place.\n"));
1000   else if (STRCASEEQ (cmd, "glob"))
1001     printf (_("glob - expand wildcards in command\n"
1002               "    glob <command> [<args> ...]\n"
1003               "\n"
1004               "    Glob runs <command> with wildcards expanded in any\n"
1005               "    command args.  Note that the command is run repeatedly\n"
1006               "    once for each expanded argument.\n"));
1007   else if (STRCASEEQ (cmd, "help"))
1008     printf (_("help - display a list of commands or help on a command\n"
1009               "     help cmd\n"
1010               "     help\n"));
1011   else if (STRCASEEQ (cmd, "more") ||
1012            STRCASEEQ (cmd, "less"))
1013     printf (_("more - view a file in the pager\n"
1014               "     more <filename>\n"
1015               "\n"
1016               "    This is used to view a file in the pager.\n"
1017               "\n"
1018               "    It is the equivalent of (and is implemented by)\n"
1019               "    running \"cat\" and using the pager.\n"
1020               "\n"
1021               "    Normally it uses $PAGER, but if you use the alias\n"
1022               "    \"less\" then it always uses \"less\".\n"
1023               "\n"
1024               "    NOTE: This will not work reliably for large files\n"
1025               "    (> 2 MB) or binary files containing \\0 bytes.\n"));
1026   else if (STRCASEEQ (cmd, "quit") ||
1027            STRCASEEQ (cmd, "exit") ||
1028            STRCASEEQ (cmd, "q"))
1029     printf (_("quit - quit guestfish\n"
1030               "     quit\n"));
1031   else if (STRCASEEQ (cmd, "reopen"))
1032     printf (_("reopen - close and reopen the libguestfs handle\n"
1033               "     reopen\n"
1034               "\n"
1035               "Close and reopen the libguestfs handle.  It is not necessary to use\n"
1036               "this normally, because the handle is closed properly when guestfish\n"
1037               "exits.  However this is occasionally useful for testing.\n"));
1038   else if (STRCASEEQ (cmd, "sparse"))
1039     printf (_("sparse - allocate a sparse image file\n"
1040               "     sparse <filename> <size>\n"
1041               "\n"
1042               "    This creates an empty sparse file of the given size,\n"
1043               "    and then adds so it can be further examined.\n"
1044               "\n"
1045               "    In all respects it works the same as the 'alloc'\n"
1046               "    command, except that the image file is allocated\n"
1047               "    sparsely, which means that disk blocks are not assigned\n"
1048               "    to the file until they are needed.  Sparse disk files\n"
1049               "    only use space when written to, but they are slower\n"
1050               "    and there is a danger you could run out of real disk\n"
1051               "    space during a write operation.\n"
1052               "\n"
1053               "    For more advanced image creation, see qemu-img utility.\n"
1054               "\n"
1055               "    Size can be specified (where <nn> means a number):\n"
1056               "    <nn>             number of kilobytes\n"
1057               "      eg: 1440       standard 3.5\" floppy\n"
1058               "    <nn>K or <nn>KB  number of kilobytes\n"
1059               "    <nn>M or <nn>MB  number of megabytes\n"
1060               "    <nn>G or <nn>GB  number of gigabytes\n"
1061               "    <nn>T or <nn>TB  number of terabytes\n"
1062               "    <nn>P or <nn>PB  number of petabytes\n"
1063               "    <nn>E or <nn>EB  number of exabytes\n"
1064               "    <nn>sects        number of 512 byte sectors\n"));
1065   else if (STRCASEEQ (cmd, "time"))
1066     printf (_("time - measure time taken to run command\n"
1067               "    time <command> [<args> ...]\n"
1068               "\n"
1069               "    This runs <command> as usual, and prints the elapsed\n"
1070               "    time afterwards.\n"));
1071   else
1072     fprintf (stderr, _("%s: command not known, use -h to list all commands\n"),
1073              cmd);
1074 }
1075
1076 void
1077 free_strings (char **argv)
1078 {
1079   int argc;
1080
1081   for (argc = 0; argv[argc] != NULL; ++argc)
1082     free (argv[argc]);
1083   free (argv);
1084 }
1085
1086 int
1087 count_strings (char *const *argv)
1088 {
1089   int c;
1090
1091   for (c = 0; argv[c]; ++c)
1092     ;
1093   return c;
1094 }
1095
1096 void
1097 print_strings (char *const *argv)
1098 {
1099   int argc;
1100
1101   for (argc = 0; argv[argc] != NULL; ++argc)
1102     printf ("%s\n", argv[argc]);
1103 }
1104
1105 void
1106 print_table (char *const *argv)
1107 {
1108   int i;
1109
1110   for (i = 0; argv[i] != NULL; i += 2)
1111     printf ("%s: %s\n", argv[i], argv[i+1]);
1112 }
1113
1114 int
1115 is_true (const char *str)
1116 {
1117   return
1118     STRCASENEQ (str, "0") &&
1119     STRCASENEQ (str, "f") &&
1120     STRCASENEQ (str, "false") &&
1121     STRCASENEQ (str, "n") &&
1122     STRCASENEQ (str, "no");
1123 }
1124
1125 /* Free strings from a non-NULL terminated char** */
1126 static void
1127 free_n_strings (char **str, size_t len)
1128 {
1129   size_t i;
1130
1131   for (i = 0; i < len; i++) {
1132     free (str[i]);
1133   }
1134   free (str);
1135 }
1136
1137 char **
1138 parse_string_list (const char *str)
1139 {
1140   char **argv = NULL;
1141   size_t argv_len = 0;
1142
1143   /* Current position pointer */
1144   const char *p = str;
1145
1146   /* Token might be simple:
1147    *  Token
1148    * or be quoted:
1149    *  'This is a single token'
1150    * or contain embedded single-quoted sections:
1151    *  This' is a sing'l'e to'ken
1152    *
1153    * The latter may seem over-complicated, but it's what a normal shell does.
1154    * Not doing it risks surprising somebody.
1155    *
1156    * This outer loop is over complete tokens.
1157    */
1158   while (*p) {
1159     char *tok = NULL;
1160     size_t tok_len = 0;
1161
1162     /* Skip leading whitespace */
1163     p += strspn (p, " \t");
1164
1165     char in_quote = 0;
1166
1167     /* This loop is over token 'fragments'. A token can be in multiple bits if
1168      * it contains single quotes. We also treat both sides of an escaped quote
1169      * as separate fragments because we can't just copy it: we have to remove
1170      * the \.
1171      */
1172     while (*p && (!c_isblank (*p) || in_quote)) {
1173       const char *end = p;
1174
1175       /* Check if the fragment starts with a quote */
1176       if ('\'' == *p) {
1177         /* Toggle in_quote */
1178         in_quote = !in_quote;
1179
1180         /* Skip the quote */
1181         p++; end++;
1182       }
1183
1184       /* If we're in a quote, look for an end quote */
1185       if (in_quote) {
1186         end += strcspn (end, "'");
1187       }
1188
1189       /* Otherwise, look for whitespace or a quote */
1190       else {
1191         end += strcspn (end, " \t'");
1192       }
1193
1194       /* Grow the token to accommodate the fragment */
1195       size_t tok_end = tok_len;
1196       tok_len += end - p;
1197       char *tok_new = realloc (tok, tok_len + 1);
1198       if (NULL == tok_new) {
1199         perror ("realloc");
1200         free_n_strings (argv, argv_len);
1201         free (tok);
1202         exit (EXIT_FAILURE);
1203       }
1204       tok = tok_new;
1205
1206       /* Check if we stopped on an escaped quote */
1207       if ('\'' == *end && end != p && *(end-1) == '\\') {
1208         /* Add everything before \' to the token */
1209         memcpy (&tok[tok_end], p, end - p - 1);
1210
1211         /* Add the quote */
1212         tok[tok_len-1] = '\'';
1213
1214         /* Already processed the quote */
1215         p = end + 1;
1216       }
1217
1218       else {
1219         /* Add the whole fragment */
1220         memcpy (&tok[tok_end], p, end - p);
1221
1222         p = end;
1223       }
1224     }
1225
1226     /* We've reached the end of a token. We shouldn't still be in quotes. */
1227     if (in_quote) {
1228       fprintf (stderr, _("Runaway quote in string \"%s\"\n"), str);
1229
1230       free_n_strings (argv, argv_len);
1231
1232       return NULL;
1233     }
1234
1235     /* Add this token if there is one. There might not be if there was
1236      * whitespace at the end of the input string */
1237     if (tok) {
1238       /* Add the NULL terminator */
1239       tok[tok_len] = '\0';
1240
1241       /* Add the argument to the argument list */
1242       argv_len++;
1243       char **argv_new = realloc (argv, sizeof (*argv) * argv_len);
1244       if (NULL == argv_new) {
1245         perror ("realloc");
1246         free_n_strings (argv, argv_len-1);
1247         free (tok);
1248         exit (EXIT_FAILURE);
1249       }
1250       argv = argv_new;
1251
1252       argv[argv_len-1] = tok;
1253     }
1254   }
1255
1256   /* NULL terminate the argument list */
1257   argv_len++;
1258   char **argv_new = realloc (argv, sizeof (*argv) * argv_len);
1259   if (NULL == argv_new) {
1260     perror ("realloc");
1261     free_n_strings (argv, argv_len-1);
1262     exit (EXIT_FAILURE);
1263   }
1264   argv = argv_new;
1265
1266   argv[argv_len-1] = NULL;
1267
1268   return argv;
1269 }
1270
1271 #ifdef HAVE_LIBREADLINE
1272 static char histfile[1024];
1273 static int nr_history_lines = 0;
1274 #endif
1275
1276 static void
1277 initialize_readline (void)
1278 {
1279 #ifdef HAVE_LIBREADLINE
1280   const char *home;
1281
1282   home = getenv ("HOME");
1283   if (home) {
1284     snprintf (histfile, sizeof histfile, "%s/.guestfish", home);
1285     using_history ();
1286     (void) read_history (histfile);
1287   }
1288
1289   rl_readline_name = "guestfish";
1290   rl_attempted_completion_function = do_completion;
1291 #endif
1292 }
1293
1294 static void
1295 cleanup_readline (void)
1296 {
1297 #ifdef HAVE_LIBREADLINE
1298   int fd;
1299
1300   if (histfile[0] != '\0') {
1301     fd = open (histfile, O_WRONLY|O_CREAT, 0644);
1302     if (fd == -1) {
1303       perror (histfile);
1304       return;
1305     }
1306     close (fd);
1307
1308 #ifdef HAVE_APPEND_HISTORY
1309     (void) append_history (nr_history_lines, histfile);
1310 #else
1311     (void) write_history (histfile);
1312 #endif
1313   }
1314 #endif
1315 }
1316
1317 static void
1318 add_history_line (const char *line)
1319 {
1320 #ifdef HAVE_LIBREADLINE
1321   add_history (line);
1322   nr_history_lines++;
1323 #endif
1324 }
1325
1326 int
1327 xwrite (int fd, const void *v_buf, size_t len)
1328 {
1329   int r;
1330   const char *buf = v_buf;
1331
1332   while (len > 0) {
1333     r = write (fd, buf, len);
1334     if (r == -1) {
1335       perror ("write");
1336       return -1;
1337     }
1338     buf += r;
1339     len -= r;
1340   }
1341
1342   return 0;
1343 }
1344
1345 /* Resolve the special "win:..." form for Windows-specific paths.
1346  * This always returns a newly allocated string which is freed by the
1347  * caller function in "cmds.c".
1348  */
1349 char *
1350 resolve_win_path (const char *path)
1351 {
1352   char *ret;
1353   size_t i;
1354
1355   if (STRCASENEQLEN (path, "win:", 4)) {
1356     ret = strdup (path);
1357     if (ret == NULL)
1358       perror ("strdup");
1359     return ret;
1360   }
1361
1362   path += 4;
1363
1364   /* Drop drive letter, if it's "C:". */
1365   if (STRCASEEQLEN (path, "c:", 2))
1366     path += 2;
1367
1368   if (!*path) {
1369     ret = strdup ("/");
1370     if (ret == NULL)
1371       perror ("strdup");
1372     return ret;
1373   }
1374
1375   ret = strdup (path);
1376   if (ret == NULL) {
1377     perror ("strdup");
1378     return NULL;
1379   }
1380
1381   /* Blindly convert any backslashes into forward slashes.  Is this good? */
1382   for (i = 0; i < strlen (ret); ++i)
1383     if (ret[i] == '\\')
1384       ret[i] = '/';
1385
1386   char *t = guestfs_case_sensitive_path (g, ret);
1387   free (ret);
1388   ret = t;
1389
1390   return ret;
1391 }