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