c4ade8c26af7be6ae7338edd95b54e8dce4de918
[libguestfs.git] / fish / fish.c
1 /* guestfish - the filesystem interactive shell
2  * Copyright (C) 2009-2010 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 #include <langinfo.h>
34 #include <termios.h>
35
36 #ifdef HAVE_LIBREADLINE
37 #include <readline/readline.h>
38 #include <readline/history.h>
39 #endif
40
41 #include <guestfs.h>
42
43 #include "fish.h"
44 #include "c-ctype.h"
45 #include "closeout.h"
46 #include "progname.h"
47
48 /* List of drives added via -a, -d or -N options. */
49 struct drv {
50   struct drv *next;
51   enum { drv_a, drv_d, drv_N } type;
52   union {
53     struct {
54       char *filename;       /* disk filename */
55     } a;
56     struct {
57       char *guest;          /* guest name */
58     } d;
59     struct {
60       char *filename;       /* disk filename (testX.img) */
61       prep_data *data;      /* prepared type */
62       char *device;         /* device inside the appliance */
63     } N;
64   };
65 };
66
67 struct mp {
68   struct mp *next;
69   char *device;
70   char *mountpoint;
71 };
72
73 static void set_up_terminal (void);
74 static char add_drives (struct drv *drv, char next_drive);
75 static void prepare_drives (struct drv *drv);
76 static void mount_mps (struct mp *mp);
77 static int launch (void);
78 static void interactive (void);
79 static void shell_script (void);
80 static void script (int prompt);
81 static void cmdline (char *argv[], int optind, int argc);
82 static void initialize_readline (void);
83 static void cleanup_readline (void);
84 #ifdef HAVE_LIBREADLINE
85 static void add_history_line (const char *);
86 #endif
87
88 /* Currently open libguestfs handle. */
89 guestfs_h *g;
90
91 int read_only = 0;
92 int quit = 0;
93 int verbose = 0;
94 int remote_control_listen = 0;
95 int remote_control = 0;
96 int exit_on_error = 1;
97 int command_num = 0;
98 int keys_from_stdin = 0;
99 const char *libvirt_uri = NULL;
100 int inspector = 0;
101 int utf8_mode = 0;
102 int have_terminfo = 0;
103
104 static void __attribute__((noreturn))
105 usage (int status)
106 {
107   if (status != EXIT_SUCCESS)
108     fprintf (stderr, _("Try `%s --help' for more information.\n"),
109              program_name);
110   else {
111     fprintf (stdout,
112            _("%s: guest filesystem shell\n"
113              "%s lets you edit virtual machine filesystems\n"
114              "Copyright (C) 2009 Red Hat Inc.\n"
115              "Usage:\n"
116              "  %s [--options] cmd [: cmd : cmd ...]\n"
117              "  %s -i libvirt-domain\n"
118              "  %s -i disk-image(s)\n"
119              "or for interactive use:\n"
120              "  %s\n"
121              "or from a shell script:\n"
122              "  %s <<EOF\n"
123              "  cmd\n"
124              "  ...\n"
125              "  EOF\n"
126              "Options:\n"
127              "  -h|--cmd-help        List available commands\n"
128              "  -h|--cmd-help cmd    Display detailed help on 'cmd'\n"
129              "  -a|--add image       Add image\n"
130              "  -c|--connect uri     Specify libvirt URI for -d option\n"
131              "  -d|--domain guest    Add disks from libvirt guest\n"
132              "  -D|--no-dest-paths   Don't tab-complete paths from guest fs\n"
133              "  -f|--file file       Read commands from file\n"
134              "  -i|--inspector       Automatically mount filesystems\n"
135              "  --keys-from-stdin    Read passphrases from stdin\n"
136              "  --listen             Listen for remote commands\n"
137              "  -m|--mount dev[:mnt] Mount dev on mnt (if omitted, /)\n"
138              "  -n|--no-sync         Don't autosync\n"
139              "  -N|--new type        Create prepared disk (test1.img, ...)\n"
140              "  --remote[=pid]       Send commands to remote %s\n"
141              "  -r|--ro              Mount read-only\n"
142              "  --selinux            Enable SELinux support\n"
143              "  -v|--verbose         Verbose messages\n"
144              "  -x                   Echo each command before executing it\n"
145              "  -V|--version         Display version and exit\n"
146              "For more information,  see the manpage %s(1).\n"),
147              program_name, program_name, program_name,
148              program_name, program_name, program_name,
149              program_name, program_name, program_name);
150   }
151   exit (status);
152 }
153
154 int
155 main (int argc, char *argv[])
156 {
157   /* Set global program name that is not polluted with libtool artifacts.  */
158   set_program_name (argv[0]);
159
160   atexit (close_stdout);
161
162   setlocale (LC_ALL, "");
163   bindtextdomain (PACKAGE, LOCALEBASEDIR);
164   textdomain (PACKAGE);
165
166   set_up_terminal ();
167
168   enum { HELP_OPTION = CHAR_MAX + 1 };
169
170   static const char *options = "a:c:d:Df:h::im:nN:rv?Vx";
171   static const struct option long_options[] = {
172     { "add", 1, 0, 'a' },
173     { "cmd-help", 2, 0, 'h' },
174     { "connect", 1, 0, 'c' },
175     { "domain", 1, 0, 'd' },
176     { "file", 1, 0, 'f' },
177     { "help", 0, 0, HELP_OPTION },
178     { "inspector", 0, 0, 'i' },
179     { "keys-from-stdin", 0, 0, 0 },
180     { "listen", 0, 0, 0 },
181     { "mount", 1, 0, 'm' },
182     { "new", 1, 0, 'N' },
183     { "no-dest-paths", 0, 0, 'D' },
184     { "no-sync", 0, 0, 'n' },
185     { "remote", 2, 0, 0 },
186     { "ro", 0, 0, 'r' },
187     { "selinux", 0, 0, 0 },
188     { "verbose", 0, 0, 'v' },
189     { "version", 0, 0, 'V' },
190     { 0, 0, 0, 0 }
191   };
192   struct drv *drvs = NULL;
193   struct drv *drv;
194   struct mp *mps = NULL;
195   struct mp *mp;
196   char *p, *file = NULL;
197   int c;
198   int option_index;
199   struct sigaction sa;
200   int next_prepared_drive = 1;
201
202   initialize_readline ();
203
204   memset (&sa, 0, sizeof sa);
205   sa.sa_handler = SIG_IGN;
206   sa.sa_flags = SA_RESTART;
207   sigaction (SIGPIPE, &sa, NULL);
208
209   /* guestfs_create is meant to be a lightweight operation, so
210    * it's OK to do it early here.
211    */
212   g = guestfs_create ();
213   if (g == NULL) {
214     fprintf (stderr, _("guestfs_create: failed to create handle\n"));
215     exit (EXIT_FAILURE);
216   }
217
218   guestfs_set_autosync (g, 1);
219
220   /* If developing, add ./appliance to the path.  Note that libtools
221    * interferes with this because uninstalled guestfish is a shell
222    * script that runs the real program with an absolute path.  Detect
223    * that too.
224    *
225    * BUT if LIBGUESTFS_PATH environment variable is already set by
226    * the user, then don't override it.
227    */
228   if (getenv ("LIBGUESTFS_PATH") == NULL &&
229       argv[0] &&
230       (argv[0][0] != '/' || strstr (argv[0], "/.libs/lt-") != NULL))
231     guestfs_set_path (g, "appliance:" GUESTFS_DEFAULT_PATH);
232
233   /* CAUTION: we are careful to modify argv[0] here, only after
234    * using it just above.
235    *
236    * getopt_long uses argv[0], so give it the sanitized name.  Save a copy
237    * of the original, in case it's needed below.
238    */
239   char *real_argv0 = argv[0];
240   argv[0] = bad_cast (program_name);
241
242   for (;;) {
243     c = getopt_long (argc, argv, options, long_options, &option_index);
244     if (c == -1) break;
245
246     switch (c) {
247     case 0:                     /* options which are long only */
248       if (STREQ (long_options[option_index].name, "listen"))
249         remote_control_listen = 1;
250       else if (STREQ (long_options[option_index].name, "remote")) {
251         if (optarg) {
252           if (sscanf (optarg, "%d", &remote_control) != 1) {
253             fprintf (stderr, _("%s: --listen=PID: PID was not a number: %s\n"),
254                      program_name, optarg);
255             exit (EXIT_FAILURE);
256           }
257         } else {
258           p = getenv ("GUESTFISH_PID");
259           if (!p || sscanf (p, "%d", &remote_control) != 1) {
260             fprintf (stderr, _("%s: remote: $GUESTFISH_PID must be set"
261                                " to the PID of the remote process\n"),
262                      program_name);
263             exit (EXIT_FAILURE);
264           }
265         }
266       } else if (STREQ (long_options[option_index].name, "selinux")) {
267         guestfs_set_selinux (g, 1);
268       } else if (STREQ (long_options[option_index].name, "keys-from-stdin")) {
269         keys_from_stdin = 1;
270       } else {
271         fprintf (stderr, _("%s: unknown long option: %s (%d)\n"),
272                  program_name, long_options[option_index].name, option_index);
273         exit (EXIT_FAILURE);
274       }
275       break;
276
277     case 'a':
278       if (access (optarg, R_OK) != 0) {
279         perror (optarg);
280         exit (EXIT_FAILURE);
281       }
282       drv = malloc (sizeof (struct drv));
283       if (!drv) {
284         perror ("malloc");
285         exit (EXIT_FAILURE);
286       }
287       drv->type = drv_a;
288       drv->a.filename = optarg;
289       drv->next = drvs;
290       drvs = drv;
291       break;
292
293     case 'c':
294       libvirt_uri = optarg;
295       break;
296
297     case 'd':
298       drv = malloc (sizeof (struct drv));
299       if (!drv) {
300         perror ("malloc");
301         exit (EXIT_FAILURE);
302       }
303       drv->type = drv_d;
304       drv->d.guest = optarg;
305       drv->next = drvs;
306       drvs = drv;
307       break;
308
309     case 'N':
310       if (STRCASEEQ (optarg, "list")) {
311         list_prepared_drives ();
312         exit (EXIT_SUCCESS);
313       }
314       drv = malloc (sizeof (struct drv));
315       if (!drv) {
316         perror ("malloc");
317         exit (EXIT_FAILURE);
318       }
319       drv->type = drv_N;
320       if (asprintf (&drv->N.filename, "test%d.img",
321                     next_prepared_drive++) == -1) {
322         perror ("asprintf");
323         exit (EXIT_FAILURE);
324       }
325       drv->N.data = create_prepared_file (optarg, drv->N.filename);
326       drv->N.device = NULL;     /* filled in by add_drives */
327       drv->next = drvs;
328       drvs = drv;
329       break;
330
331     case 'D':
332       complete_dest_paths = 0;
333       break;
334
335     case 'f':
336       if (file) {
337         fprintf (stderr, _("%s: only one -f parameter can be given\n"),
338                  program_name);
339         exit (EXIT_FAILURE);
340       }
341       file = optarg;
342       break;
343
344     case 'h': {
345       int r = 0;
346
347       if (optarg)
348         r = display_command (optarg);
349       else if (argv[optind] && argv[optind][0] != '-')
350         r = display_command (argv[optind++]);
351       else
352         list_commands ();
353
354       exit (r == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
355     }
356
357     case 'i':
358       inspector = 1;
359       break;
360
361     case 'm':
362       mp = malloc (sizeof (struct mp));
363       if (!mp) {
364         perror ("malloc");
365         exit (EXIT_FAILURE);
366       }
367       p = strchr (optarg, ':');
368       if (p) {
369         *p = '\0';
370         mp->mountpoint = p+1;
371       } else
372         mp->mountpoint = bad_cast ("/");
373       mp->device = optarg;
374       mp->next = mps;
375       mps = mp;
376       break;
377
378     case 'n':
379       guestfs_set_autosync (g, 0);
380       break;
381
382     case 'r':
383       read_only = 1;
384       break;
385
386     case 'v':
387       verbose++;
388       guestfs_set_verbose (g, verbose);
389       break;
390
391     case 'V': {
392       struct guestfs_version *v = guestfs_version (g);
393       printf ("%s %"PRIi64".%"PRIi64".%"PRIi64"%s\n", program_name,
394               v->major, v->minor, v->release, v->extra);
395       exit (EXIT_SUCCESS);
396     }
397
398     case 'x':
399       guestfs_set_trace (g, 1);
400       break;
401
402     case HELP_OPTION:
403       usage (EXIT_SUCCESS);
404
405     default:
406       usage (EXIT_FAILURE);
407     }
408   }
409
410   /* Old-style -i syntax?  Since -a/-d/-N and -i was disallowed
411    * previously, if we have -i without any drives but with something
412    * on the command line, it must be old-style syntax.
413    */
414   if (inspector && drvs == NULL && optind < argc) {
415     while (optind < argc) {
416       if (strchr (argv[optind], '/') ||
417           access (argv[optind], F_OK) == 0) { /* simulate -a option */
418         drv = malloc (sizeof (struct drv));
419         if (!drv) {
420           perror ("malloc");
421           exit (EXIT_FAILURE);
422         }
423         drv->type = drv_a;
424         drv->a.filename = argv[optind];
425         drv->next = drvs;
426         drvs = drv;
427       } else {                  /* simulate -d option */
428         drv = malloc (sizeof (struct drv));
429         if (!drv) {
430           perror ("malloc");
431           exit (EXIT_FAILURE);
432         }
433         drv->type = drv_d;
434         drv->d.guest = argv[optind];
435         drv->next = drvs;
436         drvs = drv;
437       }
438
439       optind++;
440     }
441   }
442
443   /* If we've got drives to add, add them now. */
444   add_drives (drvs, 'a');
445
446   /* If we've got mountpoints or prepared drives or -i option, we must
447    * launch the guest and mount them.
448    */
449   if (next_prepared_drive > 1 || mps != NULL || inspector) {
450     /* RHBZ#612178: If --listen flag is given, then we will fork into
451      * the background in rc_listen().  However you can't do this while
452      * holding a libguestfs handle open because the recovery process
453      * will think the main program has died and kill qemu.  Therefore
454      * don't use the recovery process for this case.  (A better
455      * solution would be to call launch () etc after the fork, but
456      * that greatly complicates the code here).
457      */
458     if (remote_control_listen)
459       guestfs_set_recovery_proc (g, 0);
460
461     if (launch () == -1) exit (EXIT_FAILURE);
462
463     if (inspector)
464       inspect_mount ();
465
466     prepare_drives (drvs);
467     mount_mps (mps);
468   }
469
470   /* Remote control? */
471   if (remote_control_listen && remote_control) {
472     fprintf (stderr,
473              _("%s: cannot use --listen and --remote options at the same time\n"),
474              program_name);
475     exit (EXIT_FAILURE);
476   }
477
478   if (remote_control_listen) {
479     if (optind < argc) {
480       fprintf (stderr,
481                _("%s: extra parameters on the command line with --listen flag\n"),
482                program_name);
483       exit (EXIT_FAILURE);
484     }
485     if (file) {
486       fprintf (stderr,
487                _("%s: cannot use --listen and --file options at the same time\n"),
488                program_name);
489       exit (EXIT_FAILURE);
490     }
491     rc_listen ();
492   }
493
494   /* -f (file) parameter? */
495   if (file) {
496     close (0);
497     if (open (file, O_RDONLY) == -1) {
498       perror (file);
499       exit (EXIT_FAILURE);
500     }
501   }
502
503   /* Interactive, shell script, or command(s) on the command line? */
504   if (optind >= argc) {
505     if (isatty (0))
506       interactive ();
507     else
508       shell_script ();
509   }
510   else
511     cmdline (argv, optind, argc);
512
513   cleanup_readline ();
514
515   exit (EXIT_SUCCESS);
516 }
517
518 /* The <term.h> header file which defines this has "issues". */
519 extern int tgetent (char *, const char *);
520
521 static void
522 set_up_terminal (void)
523 {
524   /* http://www.cl.cam.ac.uk/~mgk25/unicode.html#activate */
525   utf8_mode = STREQ (nl_langinfo (CODESET), "UTF-8");
526
527   char *term = getenv ("TERM");
528   if (term == NULL) {
529     //fprintf (stderr, _("guestfish: TERM (terminal type) not defined.\n"));
530     return;
531   }
532
533   int r = tgetent (NULL, term);
534   if (r == -1) {
535     fprintf (stderr, _("guestfish: could not access termcap or terminfo database.\n"));
536     return;
537   }
538   if (r == 0) {
539     fprintf (stderr, _("guestfish: terminal type \"%s\" not defined.\n"),
540              term);
541     return;
542   }
543
544   have_terminfo = 1;
545 }
546
547 void
548 pod2text (const char *name, const char *shortdesc, const char *str)
549 {
550   FILE *fp;
551
552   fp = popen ("pod2text", "w");
553   if (fp == NULL) {
554     /* pod2text failed, maybe not found, so let's just print the
555      * source instead, since that's better than doing nothing.
556      */
557     printf ("%s - %s\n\n%s\n", name, shortdesc, str);
558     return;
559   }
560   fprintf (fp, "=head1 NAME\n\n%s - %s\n\n", name, shortdesc);
561   fputs (str, fp);
562   pclose (fp);
563 }
564
565 /* List is built in reverse order, so mount them in reverse order. */
566 static void
567 mount_mps (struct mp *mp)
568 {
569   int r;
570
571   if (mp) {
572     mount_mps (mp->next);
573
574     /* Don't use guestfs_mount here because that will default to mount
575      * options -o sync,noatime.  For more information, see guestfs(3)
576      * section "LIBGUESTFS GOTCHAS".
577      */
578     const char *options = read_only ? "ro" : "";
579     r = guestfs_mount_options (g, options, mp->device, mp->mountpoint);
580     if (r == -1)
581       exit (EXIT_FAILURE);
582   }
583 }
584
585 static char
586 add_drives (struct drv *drv, char next_drive)
587 {
588   int r;
589
590   if (next_drive > 'z') {
591     fprintf (stderr,
592              _("guestfish: too many drives added on the command line\n"));
593     exit (EXIT_FAILURE);
594   }
595
596   if (drv) {
597     next_drive = add_drives (drv->next, next_drive);
598
599     switch (drv->type) {
600     case drv_a:
601       if (!read_only)
602         r = guestfs_add_drive (g, drv->a.filename);
603       else
604         r = guestfs_add_drive_ro (g, drv->a.filename);
605       if (r == -1)
606         exit (EXIT_FAILURE);
607
608       next_drive++;
609       break;
610
611     case drv_d:
612       r = add_libvirt_drives (drv->d.guest);
613       if (r == -1)
614         exit (EXIT_FAILURE);
615
616       next_drive += r;
617       break;
618
619     case drv_N:
620       /* -N option is not affected by --ro */
621       r = guestfs_add_drive (g, drv->N.filename);
622       if (r == -1)
623         exit (EXIT_FAILURE);
624
625       if (asprintf (&drv->N.device, "/dev/sd%c", next_drive) == -1) {
626         perror ("asprintf");
627         exit (EXIT_FAILURE);
628       }
629
630       next_drive++;
631       break;
632
633     default: /* keep GCC happy */
634       abort ();
635     }
636   }
637
638   return next_drive;
639 }
640
641 static void
642 prepare_drives (struct drv *drv)
643 {
644   if (drv) {
645     prepare_drives (drv->next);
646     if (drv->type == drv_N)
647       prepare_drive (drv->N.filename, drv->N.data, drv->N.device);
648   }
649 }
650
651 static int
652 launch (void)
653 {
654   if (guestfs_is_config (g)) {
655     if (guestfs_launch (g) == -1)
656       return -1;
657   }
658   return 0;
659 }
660
661 static void
662 interactive (void)
663 {
664   script (1);
665 }
666
667 static void
668 shell_script (void)
669 {
670   script (0);
671 }
672
673 #define FISH "><fs> "
674
675 static char *line_read = NULL;
676
677 static char *
678 rl_gets (int prompt)
679 {
680 #ifdef HAVE_LIBREADLINE
681
682   if (prompt) {
683     if (line_read) {
684       free (line_read);
685       line_read = NULL;
686     }
687
688     line_read = readline (prompt ? FISH : "");
689
690     if (line_read && *line_read)
691       add_history_line (line_read);
692
693     return line_read;
694   }
695
696 #endif /* HAVE_LIBREADLINE */
697
698   static char buf[8192];
699   int len;
700
701   if (prompt) printf (FISH);
702   line_read = fgets (buf, sizeof buf, stdin);
703
704   if (line_read) {
705     len = strlen (line_read);
706     if (len > 0 && buf[len-1] == '\n') buf[len-1] = '\0';
707   }
708
709   return line_read;
710 }
711
712 static void
713 script (int prompt)
714 {
715   char *buf;
716   char *cmd;
717   char *p, *pend;
718   char *argv[64];
719   int len;
720   int global_exit_on_error = !prompt;
721   int tilde_candidate;
722
723   if (prompt) {
724     printf (_("\n"
725               "Welcome to guestfish, the libguestfs filesystem interactive shell for\n"
726               "editing virtual machine filesystems.\n"
727               "\n"
728               "Type: 'help' for a list of commands\n"
729               "      'man' to read the manual\n"
730               "      'quit' to quit the shell\n"
731               "\n"));
732
733     if (inspector) {
734       print_inspect_prompt ();
735       printf ("\n");
736     }
737   }
738
739   while (!quit) {
740     char *pipe = NULL;
741
742     exit_on_error = global_exit_on_error;
743
744     buf = rl_gets (prompt);
745     if (!buf) {
746       quit = 1;
747       break;
748     }
749
750     /* Skip any initial whitespace before the command. */
751   again:
752     while (*buf && c_isspace (*buf))
753       buf++;
754
755     if (!*buf) continue;
756
757     /* If the next character is '#' then this is a comment. */
758     if (*buf == '#') continue;
759
760     /* If the next character is '!' then pass the whole lot to system(3). */
761     if (*buf == '!') {
762       int r;
763
764       r = system (buf+1);
765       if (exit_on_error) {
766         if (r == -1 ||
767             (WIFSIGNALED (r) &&
768              (WTERMSIG (r) == SIGINT || WTERMSIG (r) == SIGQUIT)) ||
769             WEXITSTATUS (r) != 0)
770           exit (EXIT_FAILURE);
771       }
772       continue;
773     }
774
775     /* If the next character is '-' allow the command to fail without
776      * exiting on error (just for this one command though).
777      */
778     if (*buf == '-') {
779       exit_on_error = 0;
780       buf++;
781       goto again;
782     }
783
784     /* Get the command (cannot be quoted). */
785     len = strcspn (buf, " \t");
786
787     if (len == 0) continue;
788
789     cmd = buf;
790     unsigned int i = 0;
791     if (buf[len] == '\0') {
792       argv[0] = NULL;
793       goto got_command;
794     }
795
796     buf[len] = '\0';
797     p = &buf[len+1];
798     p += strspn (p, " \t");
799
800     /* Get the parameters. */
801     while (*p && i < sizeof argv / sizeof argv[0]) {
802       tilde_candidate = 0;
803
804       /* Parameters which start with quotes or pipes are treated
805        * specially.  Bare parameters are delimited by whitespace.
806        */
807       if (*p == '"') {
808         p++;
809         len = strcspn (p, "\"");
810         if (p[len] == '\0') {
811           fprintf (stderr, _("%s: unterminated double quote\n"), program_name);
812           if (exit_on_error) exit (EXIT_FAILURE);
813           goto next_command;
814         }
815         if (p[len+1] && (p[len+1] != ' ' && p[len+1] != '\t')) {
816           fprintf (stderr,
817                    _("%s: command arguments not separated by whitespace\n"),
818                    program_name);
819           if (exit_on_error) exit (EXIT_FAILURE);
820           goto next_command;
821         }
822         p[len] = '\0';
823         pend = p[len+1] ? &p[len+2] : &p[len+1];
824       } else if (*p == '\'') {
825         p++;
826         len = strcspn (p, "'");
827         if (p[len] == '\0') {
828           fprintf (stderr, _("%s: unterminated single quote\n"), program_name);
829           if (exit_on_error) exit (EXIT_FAILURE);
830           goto next_command;
831         }
832         if (p[len+1] && (p[len+1] != ' ' && p[len+1] != '\t')) {
833           fprintf (stderr,
834                    _("%s: command arguments not separated by whitespace\n"),
835                    program_name);
836           if (exit_on_error) exit (EXIT_FAILURE);
837           goto next_command;
838         }
839         p[len] = '\0';
840         pend = p[len+1] ? &p[len+2] : &p[len+1];
841       } else if (*p == '|') {
842         *p = '\0';
843         pipe = p+1;
844         continue;
845         /*
846       } else if (*p == '[') {
847         int c = 1;
848         p++;
849         pend = p;
850         while (*pend && c != 0) {
851           if (*pend == '[') c++;
852           else if (*pend == ']') c--;
853           pend++;
854         }
855         if (c != 0) {
856           fprintf (stderr,
857                    _("%s: unterminated \"[...]\" sequence\n"), program_name);
858           if (exit_on_error) exit (EXIT_FAILURE);
859           goto next_command;
860         }
861         if (*pend && (*pend != ' ' && *pend != '\t')) {
862           fprintf (stderr,
863                    _("%s: command arguments not separated by whitespace\n"),
864                    program_name);
865           if (exit_on_error) exit (EXIT_FAILURE);
866           goto next_command;
867         }
868         *(pend-1) = '\0';
869         */
870       } else if (*p != ' ' && *p != '\t') {
871         /* If the first character is a ~ then note that this parameter
872          * is a candidate for ~username expansion.  NB this does not
873          * apply to quoted parameters.
874          */
875         tilde_candidate = *p == '~';
876         len = strcspn (p, " \t");
877         if (p[len]) {
878           p[len] = '\0';
879           pend = &p[len+1];
880         } else
881           pend = &p[len];
882       } else {
883         fprintf (stderr, _("%s: internal error parsing string at '%s'\n"),
884                  program_name, p);
885         abort ();
886       }
887
888       if (!tilde_candidate)
889         argv[i] = p;
890       else
891         argv[i] = try_tilde_expansion (p);
892       i++;
893       p = pend;
894
895       if (*p)
896         p += strspn (p, " \t");
897     }
898
899     if (i == sizeof argv / sizeof argv[0]) {
900       fprintf (stderr, _("%s: too many arguments\n"), program_name);
901       if (exit_on_error) exit (EXIT_FAILURE);
902       goto next_command;
903     }
904
905     argv[i] = NULL;
906
907   got_command:
908     if (issue_command (cmd, argv, pipe) == -1) {
909       if (exit_on_error) exit (EXIT_FAILURE);
910     }
911
912   next_command:;
913   }
914   if (prompt) printf ("\n");
915 }
916
917 static void
918 cmdline (char *argv[], int optind, int argc)
919 {
920   const char *cmd;
921   char **params;
922
923   exit_on_error = 1;
924
925   if (optind >= argc) return;
926
927   cmd = argv[optind++];
928   if (STREQ (cmd, ":")) {
929     fprintf (stderr, _("%s: empty command on command line\n"), program_name);
930     exit (EXIT_FAILURE);
931   }
932
933   /* Allow -cmd on the command line to mean (temporarily) override
934    * the normal exit on error (RHBZ#578407).
935    */
936   if (cmd[0] == '-') {
937     exit_on_error = 0;
938     cmd++;
939   }
940
941   params = &argv[optind];
942
943   /* Search for end of command list or ":" ... */
944   while (optind < argc && STRNEQ (argv[optind], ":"))
945     optind++;
946
947   if (optind == argc) {
948     if (issue_command (cmd, params, NULL) == -1 && exit_on_error)
949         exit (EXIT_FAILURE);
950   } else {
951     argv[optind] = NULL;
952     if (issue_command (cmd, params, NULL) == -1 && exit_on_error)
953       exit (EXIT_FAILURE);
954     cmdline (argv, optind+1, argc);
955   }
956 }
957
958 int
959 issue_command (const char *cmd, char *argv[], const char *pipecmd)
960 {
961   int argc;
962   int stdout_saved_fd = -1;
963   int pid = 0;
964   int i, r;
965
966   /* This counts the commands issued, starting at 1. */
967   command_num++;
968
969   /* For | ... commands.  Annoyingly we can't use popen(3) here. */
970   if (pipecmd) {
971     int fd[2];
972
973     if (fflush (stdout) == EOF) {
974       perror ("failed to flush standard output");
975       return -1;
976     }
977     if (pipe (fd) < 0) {
978       perror ("pipe failed");
979       return -1;
980     }
981     pid = fork ();
982     if (pid == -1) {
983       perror ("fork");
984       return -1;
985     }
986
987     if (pid == 0) {             /* Child process. */
988       close (fd[1]);
989       if (dup2 (fd[0], 0) < 0) {
990         perror ("dup2 of stdin failed");
991         _exit (1);
992       }
993
994       r = system (pipecmd);
995       if (r == -1) {
996         perror (pipecmd);
997         _exit (1);
998       }
999       _exit (WEXITSTATUS (r));
1000     }
1001
1002     if ((stdout_saved_fd = dup (1)) < 0) {
1003       perror ("failed to dup stdout");
1004       return -1;
1005     }
1006     close (fd[0]);
1007     if (dup2 (fd[1], 1) < 0) {
1008       perror ("failed to dup stdout");
1009       close (stdout_saved_fd);
1010       return -1;
1011     }
1012     close (fd[1]);
1013   }
1014
1015   for (argc = 0; argv[argc] != NULL; ++argc)
1016     ;
1017
1018   /* If --remote was set, then send this command to a remote process. */
1019   if (remote_control)
1020     r = rc_remote (remote_control, cmd, argc, argv, exit_on_error);
1021
1022   /* Otherwise execute it locally. */
1023   else if (STRCASEEQ (cmd, "help")) {
1024     if (argc == 0) {
1025       list_commands ();
1026       r = 0;
1027     } else
1028       r = display_command (argv[0]);
1029   }
1030   else if (STRCASEEQ (cmd, "quit") ||
1031            STRCASEEQ (cmd, "exit") ||
1032            STRCASEEQ (cmd, "q")) {
1033     quit = 1;
1034     r = 0;
1035   }
1036   else if (STRCASEEQ (cmd, "alloc") ||
1037            STRCASEEQ (cmd, "allocate"))
1038     r = do_alloc (cmd, argc, argv);
1039   else if (STRCASEEQ (cmd, "echo"))
1040     r = do_echo (cmd, argc, argv);
1041   else if (STRCASEEQ (cmd, "edit") ||
1042            STRCASEEQ (cmd, "vi") ||
1043            STRCASEEQ (cmd, "emacs"))
1044     r = do_edit (cmd, argc, argv);
1045   else if (STRCASEEQ (cmd, "lcd"))
1046     r = do_lcd (cmd, argc, argv);
1047   else if (STRCASEEQ (cmd, "glob"))
1048     r = do_glob (cmd, argc, argv);
1049   else if (STRCASEEQ (cmd, "man") ||
1050            STRCASEEQ (cmd, "manual"))
1051     r = do_man (cmd, argc, argv);
1052   else if (STRCASEEQ (cmd, "more") ||
1053            STRCASEEQ (cmd, "less"))
1054     r = do_more (cmd, argc, argv);
1055   else if (STRCASEEQ (cmd, "reopen"))
1056     r = do_reopen (cmd, argc, argv);
1057   else if (STRCASEEQ (cmd, "sparse"))
1058     r = do_sparse (cmd, argc, argv);
1059   else if (STRCASEEQ (cmd, "supported"))
1060     r = do_supported (cmd, argc, argv);
1061   else if (STRCASEEQ (cmd, "time"))
1062     r = do_time (cmd, argc, argv);
1063   else
1064     r = run_action (cmd, argc, argv);
1065
1066   /* Always flush stdout after every command, so that messages, results
1067    * etc appear immediately.
1068    */
1069   if (fflush (stdout) == EOF) {
1070     perror ("failed to flush standard output");
1071     return -1;
1072   }
1073
1074   if (pipecmd) {
1075     close (1);
1076     if (dup2 (stdout_saved_fd, 1) < 0) {
1077       perror ("failed to dup2 standard output");
1078       r = -1;
1079     }
1080     close (stdout_saved_fd);
1081     if (waitpid (pid, NULL, 0) < 0) {
1082       perror ("waiting for command to complete");
1083       r = -1;
1084     }
1085   }
1086
1087   return r;
1088 }
1089
1090 void
1091 list_builtin_commands (void)
1092 {
1093   /* help, man and quit should appear at the top */
1094   printf ("%-20s %s\n",
1095           "help", _("display a list of commands or help on a command"));
1096   printf ("%-20s %s\n",
1097           "man", _("read the manual"));
1098   printf ("%-20s %s\n",
1099           "quit", _("quit guestfish"));
1100
1101   printf ("%-20s %s\n",
1102           "alloc", _("allocate an image"));
1103   printf ("%-20s %s\n",
1104           "echo", _("display a line of text"));
1105   printf ("%-20s %s\n",
1106           "edit", _("edit a file in the image"));
1107   printf ("%-20s %s\n",
1108           "lcd", _("local change directory"));
1109   printf ("%-20s %s\n",
1110           "glob", _("expand wildcards in command"));
1111   printf ("%-20s %s\n",
1112           "more", _("view a file in the pager"));
1113   printf ("%-20s %s\n",
1114           "reopen", _("close and reopen libguestfs handle"));
1115   printf ("%-20s %s\n",
1116           "sparse", _("allocate a sparse image file"));
1117   printf ("%-20s %s\n",
1118           "supported", _("list supported groups of commands"));
1119   printf ("%-20s %s\n",
1120           "time", _("measure time taken to run command"));
1121
1122   /* actions are printed after this (see list_commands) */
1123 }
1124
1125 int
1126 display_builtin_command (const char *cmd)
1127 {
1128   /* help for actions is auto-generated, see display_command */
1129
1130   if (STRCASEEQ (cmd, "alloc") ||
1131       STRCASEEQ (cmd, "allocate")) {
1132     printf (_("alloc - allocate an image\n"
1133               "     alloc <filename> <size>\n"
1134               "\n"
1135               "    This creates an empty (zeroed) file of the given size,\n"
1136               "    and then adds so it can be further examined.\n"
1137               "\n"
1138               "    For more advanced image creation, see qemu-img utility.\n"
1139               "\n"
1140               "    Size can be specified using standard suffixes, eg. '1M'.\n"
1141               ));
1142     return 0;
1143   }
1144   else if (STRCASEEQ (cmd, "echo")) {
1145     printf (_("echo - display a line of text\n"
1146               "     echo [<params> ...]\n"
1147               "\n"
1148               "    This echos the parameters to the terminal.\n"));
1149     return 0;
1150   }
1151   else if (STRCASEEQ (cmd, "edit") ||
1152            STRCASEEQ (cmd, "vi") ||
1153            STRCASEEQ (cmd, "emacs")) {
1154     printf (_("edit - edit a file in the image\n"
1155               "     edit <filename>\n"
1156               "\n"
1157               "    This is used to edit a file.\n"
1158               "\n"
1159               "    It is the equivalent of (and is implemented by)\n"
1160               "    running \"cat\", editing locally, and then \"write\".\n"
1161               "\n"
1162               "    Normally it uses $EDITOR, but if you use the aliases\n"
1163               "    \"vi\" or \"emacs\" you will get those editors.\n"
1164               "\n"
1165               "    NOTE: This will not work reliably for large files\n"
1166               "    (> 2 MB) or binary files containing \\0 bytes.\n"));
1167     return 0;
1168   }
1169   else if (STRCASEEQ (cmd, "lcd")) {
1170     printf (_("lcd - local change directory\n"
1171               "    lcd <directory>\n"
1172               "\n"
1173               "    Change guestfish's current directory. This command is\n"
1174               "    useful if you want to download files to a particular\n"
1175               "    place.\n"));
1176     return 0;
1177   }
1178   else if (STRCASEEQ (cmd, "glob")) {
1179     printf (_("glob - expand wildcards in command\n"
1180               "    glob <command> [<args> ...]\n"
1181               "\n"
1182               "    Glob runs <command> with wildcards expanded in any\n"
1183               "    command args.  Note that the command is run repeatedly\n"
1184               "    once for each expanded argument.\n"));
1185     return 0;
1186   }
1187   else if (STRCASEEQ (cmd, "man") ||
1188            STRCASEEQ (cmd, "manual")) {
1189     printf (_("man - read the manual\n"
1190               "    man\n"
1191               "\n"
1192               "    Opens the manual page for guestfish.\n"));
1193     return 0;
1194   }
1195   else if (STRCASEEQ (cmd, "help")) {
1196     printf (_("help - display a list of commands or help on a command\n"
1197               "     help cmd\n"
1198               "     help\n"));
1199     return 0;
1200   }
1201   else if (STRCASEEQ (cmd, "more") ||
1202            STRCASEEQ (cmd, "less")) {
1203     printf (_("more - view a file in the pager\n"
1204               "     more <filename>\n"
1205               "\n"
1206               "    This is used to view a file in the pager.\n"
1207               "\n"
1208               "    It is the equivalent of (and is implemented by)\n"
1209               "    running \"cat\" and using the pager.\n"
1210               "\n"
1211               "    Normally it uses $PAGER, but if you use the alias\n"
1212               "    \"less\" then it always uses \"less\".\n"
1213               "\n"
1214               "    NOTE: This will not work reliably for large files\n"
1215               "    (> 2 MB) or binary files containing \\0 bytes.\n"));
1216     return 0;
1217   }
1218   else if (STRCASEEQ (cmd, "quit") ||
1219            STRCASEEQ (cmd, "exit") ||
1220            STRCASEEQ (cmd, "q")) {
1221     printf (_("quit - quit guestfish\n"
1222               "     quit\n"));
1223     return 0;
1224   }
1225   else if (STRCASEEQ (cmd, "reopen")) {
1226     printf (_("reopen - close and reopen the libguestfs handle\n"
1227               "     reopen\n"
1228               "\n"
1229               "Close and reopen the libguestfs handle.  It is not necessary to use\n"
1230               "this normally, because the handle is closed properly when guestfish\n"
1231               "exits.  However this is occasionally useful for testing.\n"));
1232     return 0;
1233   }
1234   else if (STRCASEEQ (cmd, "sparse")) {
1235     printf (_("sparse - allocate a sparse image file\n"
1236               "     sparse <filename> <size>\n"
1237               "\n"
1238               "    This creates an empty sparse file of the given size,\n"
1239               "    and then adds so it can be further examined.\n"
1240               "\n"
1241               "    In all respects it works the same as the 'alloc'\n"
1242               "    command, except that the image file is allocated\n"
1243               "    sparsely, which means that disk blocks are not assigned\n"
1244               "    to the file until they are needed.  Sparse disk files\n"
1245               "    only use space when written to, but they are slower\n"
1246               "    and there is a danger you could run out of real disk\n"
1247               "    space during a write operation.\n"
1248               "\n"
1249               "    For more advanced image creation, see qemu-img utility.\n"
1250               "\n"
1251               "    Size can be specified using standard suffixes, eg. '1M'.\n"
1252               ));
1253     return 0;
1254   }
1255   else if (STRCASEEQ (cmd, "supported")) {
1256     printf (_("supported - list supported groups of commands\n"
1257               "     supported\n"
1258               "\n"
1259               "    This command returns a list of the optional groups\n"
1260               "    known to the daemon, and indicates which ones are\n"
1261               "    supported by this build of the libguestfs appliance.\n"
1262               "\n"
1263               "    See also guestfs(3) section AVAILABILITY.\n"
1264               ));
1265     return 0;
1266   }
1267   else if (STRCASEEQ (cmd, "time")) {
1268     printf (_("time - measure time taken to run command\n"
1269               "    time <command> [<args> ...]\n"
1270               "\n"
1271               "    This runs <command> as usual, and prints the elapsed\n"
1272               "    time afterwards.\n"));
1273     return 0;
1274   }
1275   else {
1276     fprintf (stderr, _("%s: command not known, use -h to list all commands\n"),
1277              cmd);
1278     return -1;
1279   }
1280 }
1281
1282 /* This is printed when the user types in an unknown command for the
1283  * first command issued.  A common case is the user doing:
1284  *   guestfish disk.img
1285  * expecting guestfish to open 'disk.img' (in fact, this tried to
1286  * run a command 'disk.img').
1287  */
1288 void
1289 extended_help_message (void)
1290 {
1291   fprintf (stderr,
1292            _("Did you mean to open a disk image?  guestfish -a disk.img\n"
1293              "For a list of commands:             guestfish -h\n"
1294              "For complete documentation:         man guestfish\n"));
1295 }
1296
1297 void
1298 free_strings (char **argv)
1299 {
1300   int argc;
1301
1302   for (argc = 0; argv[argc] != NULL; ++argc)
1303     free (argv[argc]);
1304   free (argv);
1305 }
1306
1307 int
1308 count_strings (char *const *argv)
1309 {
1310   int c;
1311
1312   for (c = 0; argv[c]; ++c)
1313     ;
1314   return c;
1315 }
1316
1317 void
1318 print_strings (char *const *argv)
1319 {
1320   int argc;
1321
1322   for (argc = 0; argv[argc] != NULL; ++argc)
1323     printf ("%s\n", argv[argc]);
1324 }
1325
1326 void
1327 print_table (char *const *argv)
1328 {
1329   int i;
1330
1331   for (i = 0; argv[i] != NULL; i += 2)
1332     printf ("%s: %s\n", argv[i], argv[i+1]);
1333 }
1334
1335 int
1336 is_true (const char *str)
1337 {
1338   return
1339     STRCASENEQ (str, "0") &&
1340     STRCASENEQ (str, "f") &&
1341     STRCASENEQ (str, "false") &&
1342     STRCASENEQ (str, "n") &&
1343     STRCASENEQ (str, "no");
1344 }
1345
1346 /* Free strings from a non-NULL terminated char** */
1347 static void
1348 free_n_strings (char **str, size_t len)
1349 {
1350   size_t i;
1351
1352   for (i = 0; i < len; i++) {
1353     free (str[i]);
1354   }
1355   free (str);
1356 }
1357
1358 char **
1359 parse_string_list (const char *str)
1360 {
1361   char **argv = NULL;
1362   size_t argv_len = 0;
1363
1364   /* Current position pointer */
1365   const char *p = str;
1366
1367   /* Token might be simple:
1368    *  Token
1369    * or be quoted:
1370    *  'This is a single token'
1371    * or contain embedded single-quoted sections:
1372    *  This' is a sing'l'e to'ken
1373    *
1374    * The latter may seem over-complicated, but it's what a normal shell does.
1375    * Not doing it risks surprising somebody.
1376    *
1377    * This outer loop is over complete tokens.
1378    */
1379   while (*p) {
1380     char *tok = NULL;
1381     size_t tok_len = 0;
1382
1383     /* Skip leading whitespace */
1384     p += strspn (p, " \t");
1385
1386     char in_quote = 0;
1387
1388     /* This loop is over token 'fragments'. A token can be in multiple bits if
1389      * it contains single quotes. We also treat both sides of an escaped quote
1390      * as separate fragments because we can't just copy it: we have to remove
1391      * the \.
1392      */
1393     while (*p && (!c_isblank (*p) || in_quote)) {
1394       const char *end = p;
1395
1396       /* Check if the fragment starts with a quote */
1397       if ('\'' == *p) {
1398         /* Toggle in_quote */
1399         in_quote = !in_quote;
1400
1401         /* Skip the quote */
1402         p++; end++;
1403       }
1404
1405       /* If we're in a quote, look for an end quote */
1406       if (in_quote) {
1407         end += strcspn (end, "'");
1408       }
1409
1410       /* Otherwise, look for whitespace or a quote */
1411       else {
1412         end += strcspn (end, " \t'");
1413       }
1414
1415       /* Grow the token to accommodate the fragment */
1416       size_t tok_end = tok_len;
1417       tok_len += end - p;
1418       char *tok_new = realloc (tok, tok_len + 1);
1419       if (NULL == tok_new) {
1420         perror ("realloc");
1421         free_n_strings (argv, argv_len);
1422         free (tok);
1423         exit (EXIT_FAILURE);
1424       }
1425       tok = tok_new;
1426
1427       /* Check if we stopped on an escaped quote */
1428       if ('\'' == *end && end != p && *(end-1) == '\\') {
1429         /* Add everything before \' to the token */
1430         memcpy (&tok[tok_end], p, end - p - 1);
1431
1432         /* Add the quote */
1433         tok[tok_len-1] = '\'';
1434
1435         /* Already processed the quote */
1436         p = end + 1;
1437       }
1438
1439       else {
1440         /* Add the whole fragment */
1441         memcpy (&tok[tok_end], p, end - p);
1442
1443         p = end;
1444       }
1445     }
1446
1447     /* We've reached the end of a token. We shouldn't still be in quotes. */
1448     if (in_quote) {
1449       fprintf (stderr, _("Runaway quote in string \"%s\"\n"), str);
1450
1451       free_n_strings (argv, argv_len);
1452
1453       return NULL;
1454     }
1455
1456     /* Add this token if there is one. There might not be if there was
1457      * whitespace at the end of the input string */
1458     if (tok) {
1459       /* Add the NULL terminator */
1460       tok[tok_len] = '\0';
1461
1462       /* Add the argument to the argument list */
1463       argv_len++;
1464       char **argv_new = realloc (argv, sizeof (*argv) * argv_len);
1465       if (NULL == argv_new) {
1466         perror ("realloc");
1467         free_n_strings (argv, argv_len-1);
1468         free (tok);
1469         exit (EXIT_FAILURE);
1470       }
1471       argv = argv_new;
1472
1473       argv[argv_len-1] = tok;
1474     }
1475   }
1476
1477   /* NULL terminate the argument list */
1478   argv_len++;
1479   char **argv_new = realloc (argv, sizeof (*argv) * argv_len);
1480   if (NULL == argv_new) {
1481     perror ("realloc");
1482     free_n_strings (argv, argv_len-1);
1483     exit (EXIT_FAILURE);
1484   }
1485   argv = argv_new;
1486
1487   argv[argv_len-1] = NULL;
1488
1489   return argv;
1490 }
1491
1492 #ifdef HAVE_LIBREADLINE
1493 static char histfile[1024];
1494 static int nr_history_lines = 0;
1495 #endif
1496
1497 static void
1498 initialize_readline (void)
1499 {
1500 #ifdef HAVE_LIBREADLINE
1501   const char *home;
1502
1503   home = getenv ("HOME");
1504   if (home) {
1505     snprintf (histfile, sizeof histfile, "%s/.guestfish", home);
1506     using_history ();
1507     (void) read_history (histfile);
1508   }
1509
1510   rl_readline_name = "guestfish";
1511   rl_attempted_completion_function = do_completion;
1512
1513   /* Note that .inputrc (or /etc/inputrc) is not read until the first
1514    * call the readline(), which happens later.  Therefore, these
1515    * provide default values which can be overridden by the user if
1516    * they wish.
1517    */
1518   (void) rl_variable_bind ("completion-ignore-case", "on");
1519 #endif
1520 }
1521
1522 static void
1523 cleanup_readline (void)
1524 {
1525 #ifdef HAVE_LIBREADLINE
1526   int fd;
1527
1528   if (histfile[0] != '\0') {
1529     fd = open (histfile, O_WRONLY|O_CREAT, 0644);
1530     if (fd == -1) {
1531       perror (histfile);
1532       return;
1533     }
1534     close (fd);
1535
1536 #ifdef HAVE_APPEND_HISTORY
1537     (void) append_history (nr_history_lines, histfile);
1538 #else
1539     (void) write_history (histfile);
1540 #endif
1541   }
1542 #endif
1543 }
1544
1545 #ifdef HAVE_LIBREADLINE
1546 static void
1547 add_history_line (const char *line)
1548 {
1549   add_history (line);
1550   nr_history_lines++;
1551 }
1552 #endif
1553
1554 int
1555 xwrite (int fd, const void *v_buf, size_t len)
1556 {
1557   int r;
1558   const char *buf = v_buf;
1559
1560   while (len > 0) {
1561     r = write (fd, buf, len);
1562     if (r == -1) {
1563       perror ("write");
1564       return -1;
1565     }
1566     buf += r;
1567     len -= r;
1568   }
1569
1570   return 0;
1571 }
1572
1573 /* Resolve the special "win:..." form for Windows-specific paths.
1574  * This always returns a newly allocated string which is freed by the
1575  * caller function in "cmds.c".
1576  */
1577 char *
1578 resolve_win_path (const char *path)
1579 {
1580   char *ret;
1581   size_t i;
1582
1583   if (STRCASENEQLEN (path, "win:", 4)) {
1584     ret = strdup (path);
1585     if (ret == NULL)
1586       perror ("strdup");
1587     return ret;
1588   }
1589
1590   path += 4;
1591
1592   /* Drop drive letter, if it's "C:". */
1593   if (STRCASEEQLEN (path, "c:", 2))
1594     path += 2;
1595
1596   if (!*path) {
1597     ret = strdup ("/");
1598     if (ret == NULL)
1599       perror ("strdup");
1600     return ret;
1601   }
1602
1603   ret = strdup (path);
1604   if (ret == NULL) {
1605     perror ("strdup");
1606     return NULL;
1607   }
1608
1609   /* Blindly convert any backslashes into forward slashes.  Is this good? */
1610   for (i = 0; i < strlen (ret); ++i)
1611     if (ret[i] == '\\')
1612       ret[i] = '/';
1613
1614   char *t = guestfs_case_sensitive_path (g, ret);
1615   free (ret);
1616   ret = t;
1617
1618   return ret;
1619 }
1620
1621 /* Resolve the special FileIn paths ("-" or "-<<END" or filename).
1622  * The caller (cmds.c) will call free_file_in after the command has
1623  * run which should clean up resources.
1624  */
1625 static char *file_in_heredoc (const char *endmarker);
1626 static char *file_in_tmpfile = NULL;
1627
1628 char *
1629 file_in (const char *arg)
1630 {
1631   char *ret;
1632
1633   if (STREQ (arg, "-")) {
1634     ret = strdup ("/dev/stdin");
1635     if (!ret) {
1636       perror ("strdup");
1637       return NULL;
1638     }
1639   }
1640   else if (STRPREFIX (arg, "-<<")) {
1641     const char *endmarker = &arg[3];
1642     if (*endmarker == '\0') {
1643       fprintf (stderr, "%s: missing end marker in -<< expression\n",
1644                program_name);
1645       return NULL;
1646     }
1647     ret = file_in_heredoc (endmarker);
1648     if (ret == NULL)
1649       return NULL;
1650   }
1651   else {
1652     ret = strdup (arg);
1653     if (!ret) {
1654       perror ("strdup");
1655       return NULL;
1656     }
1657   }
1658
1659   return ret;
1660 }
1661
1662 static char *
1663 file_in_heredoc (const char *endmarker)
1664 {
1665   static const char template[] = "/tmp/heredocXXXXXX";
1666   file_in_tmpfile = strdup (template);
1667   if (file_in_tmpfile == NULL) {
1668     perror ("strdup");
1669     return NULL;
1670   }
1671
1672   int fd = mkstemp (file_in_tmpfile);
1673   if (fd == -1) {
1674     perror ("mkstemp");
1675     goto error1;
1676   }
1677
1678   size_t markerlen = strlen (endmarker);
1679
1680   char buffer[BUFSIZ];
1681   int write_error = 0;
1682   while (fgets (buffer, sizeof buffer, stdin) != NULL) {
1683     /* Look for "END"<EOF> or "END\n" in input. */
1684     size_t blen = strlen (buffer);
1685     if (STREQLEN (buffer, endmarker, markerlen) &&
1686         (blen == markerlen ||
1687          (blen == markerlen+1 && buffer[markerlen] == '\n')))
1688       goto found_end;
1689
1690     if (xwrite (fd, buffer, blen) == -1) {
1691       if (!write_error) perror ("write");
1692       write_error = 1;
1693       /* continue reading up to the end marker */
1694     }
1695   }
1696
1697   /* Reached EOF of stdin without finding the end marker, which
1698    * is likely to be an error.
1699    */
1700   fprintf (stderr, "%s: end of input reached without finding '%s'\n",
1701            program_name, endmarker);
1702   goto error2;
1703
1704  found_end:
1705   if (write_error) {
1706     close (fd);
1707     goto error2;
1708   }
1709
1710   if (close (fd) == -1) {
1711     perror ("close");
1712     goto error2;
1713   }
1714
1715   return file_in_tmpfile;
1716
1717  error2:
1718   unlink (file_in_tmpfile);
1719
1720  error1:
1721   free (file_in_tmpfile);
1722   file_in_tmpfile = NULL;
1723   return NULL;
1724 }
1725
1726 void
1727 free_file_in (char *s)
1728 {
1729   if (file_in_tmpfile) {
1730     if (unlink (file_in_tmpfile) == -1)
1731       perror (file_in_tmpfile);
1732     file_in_tmpfile = NULL;
1733   }
1734
1735   /* Free the device or file name which was strdup'd in file_in().
1736    * Note it's not immediately clear, but for -<< heredocs,
1737    * s == file_in_tmpfile, so this frees up that buffer.
1738    */
1739   free (s);
1740 }
1741
1742 /* Resolve the special FileOut paths ("-" or filename).
1743  * The caller (cmds.c) will call free (str) after the command has run.
1744  */
1745 char *
1746 file_out (const char *arg)
1747 {
1748   char *ret;
1749
1750   if (STREQ (arg, "-"))
1751     ret = strdup ("/dev/stdout");
1752   else
1753     ret = strdup (arg);
1754
1755   if (!ret) {
1756     perror ("strdup");
1757     return NULL;
1758   }
1759   return ret;
1760 }
1761
1762 /* Read a passphrase ('Key') from /dev/tty with echo off.
1763  * The caller (cmds.c) will call free on the string afterwards.
1764  * Based on the code in cryptsetup file lib/utils.c.
1765  */
1766 char *
1767 read_key (const char *param)
1768 {
1769   FILE *infp, *outfp;
1770   struct termios orig, temp;
1771   char *ret = NULL;
1772
1773   /* Read and write to /dev/tty if available. */
1774   if (keys_from_stdin ||
1775       (infp = outfp = fopen ("/dev/tty", "w+")) == NULL) {
1776     infp = stdin;
1777     outfp = stdout;
1778   }
1779
1780   /* Print the prompt and set no echo. */
1781   int tty = isatty (fileno (infp));
1782   int tcset = 0;
1783   if (tty) {
1784     fprintf (outfp, _("Enter key or passphrase (\"%s\"): "), param);
1785
1786     if (tcgetattr (fileno (infp), &orig) == -1) {
1787       perror ("tcgetattr");
1788       goto error;
1789     }
1790     memcpy (&temp, &orig, sizeof temp);
1791     temp.c_lflag &= ~ECHO;
1792
1793     tcsetattr (fileno (infp), TCSAFLUSH, &temp);
1794     tcset = 1;
1795   }
1796
1797   size_t n = 0;
1798   ssize_t len;
1799   len = getline (&ret, &n, infp);
1800   if (len == -1) {
1801     perror ("getline");
1802     ret = NULL;
1803     goto error;
1804   }
1805
1806   /* Remove the terminating \n if there is one. */
1807   if (len > 0 && ret[len-1] == '\n')
1808     ret[len-1] = '\0';
1809
1810  error:
1811   /* Restore echo, close file descriptor. */
1812   if (tty && tcset) {
1813     printf ("\n");
1814     tcsetattr (fileno (infp), TCSAFLUSH, &orig);
1815   }
1816
1817   if (infp != stdin)
1818     fclose (infp); /* outfp == infp, so this is closed also */
1819
1820   return ret;
1821 }