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