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