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