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