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