fish: Add 'please wait' message when launching (and interactive).
[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 (isatty (0))
551       printf (_("guestfish: wait a moment while we launch libguestfs ...\n"));
552     if (guestfs_launch (g) == -1)
553       return -1;
554   }
555   return 0;
556 }
557
558 static void
559 interactive (void)
560 {
561   script (1);
562 }
563
564 static void
565 shell_script (void)
566 {
567   script (0);
568 }
569
570 #define FISH "><fs> "
571
572 static char *line_read = NULL;
573
574 static char *
575 rl_gets (int prompt)
576 {
577 #ifdef HAVE_LIBREADLINE
578
579   if (prompt) {
580     if (line_read) {
581       free (line_read);
582       line_read = NULL;
583     }
584
585     line_read = readline (prompt ? FISH : "");
586
587     if (line_read && *line_read)
588       add_history_line (line_read);
589
590     return line_read;
591   }
592
593 #endif /* HAVE_LIBREADLINE */
594
595   static char buf[8192];
596   int len;
597
598   if (prompt) printf (FISH);
599   line_read = fgets (buf, sizeof buf, stdin);
600
601   if (line_read) {
602     len = strlen (line_read);
603     if (len > 0 && buf[len-1] == '\n') buf[len-1] = '\0';
604   }
605
606   return line_read;
607 }
608
609 static void
610 script (int prompt)
611 {
612   char *buf;
613   char *cmd;
614   char *p, *pend;
615   char *argv[64];
616   int len;
617   int global_exit_on_error = !prompt;
618   int tilde_candidate;
619
620   if (prompt)
621     printf (_("\n"
622               "Welcome to guestfish, the libguestfs filesystem interactive shell for\n"
623               "editing virtual machine filesystems.\n"
624               "\n"
625               "Type: 'help' for a list of commands\n"
626               "      'man' to read the manual\n"
627               "      'quit' to quit the shell\n"
628               "\n"));
629
630   while (!quit) {
631     char *pipe = NULL;
632
633     exit_on_error = global_exit_on_error;
634
635     buf = rl_gets (prompt);
636     if (!buf) {
637       quit = 1;
638       break;
639     }
640
641     /* Skip any initial whitespace before the command. */
642   again:
643     while (*buf && c_isspace (*buf))
644       buf++;
645
646     if (!*buf) continue;
647
648     /* If the next character is '#' then this is a comment. */
649     if (*buf == '#') continue;
650
651     /* If the next character is '!' then pass the whole lot to system(3). */
652     if (*buf == '!') {
653       int r;
654
655       r = system (buf+1);
656       if (exit_on_error) {
657         if (r == -1 ||
658             (WIFSIGNALED (r) &&
659              (WTERMSIG (r) == SIGINT || WTERMSIG (r) == SIGQUIT)) ||
660             WEXITSTATUS (r) != 0)
661           exit (EXIT_FAILURE);
662       }
663       continue;
664     }
665
666     /* If the next character is '-' allow the command to fail without
667      * exiting on error (just for this one command though).
668      */
669     if (*buf == '-') {
670       exit_on_error = 0;
671       buf++;
672       goto again;
673     }
674
675     /* Get the command (cannot be quoted). */
676     len = strcspn (buf, " \t");
677
678     if (len == 0) continue;
679
680     cmd = buf;
681     unsigned int i = 0;
682     if (buf[len] == '\0') {
683       argv[0] = NULL;
684       goto got_command;
685     }
686
687     buf[len] = '\0';
688     p = &buf[len+1];
689     p += strspn (p, " \t");
690
691     /* Get the parameters. */
692     while (*p && i < sizeof argv / sizeof argv[0]) {
693       tilde_candidate = 0;
694
695       /* Parameters which start with quotes or pipes are treated
696        * specially.  Bare parameters are delimited by whitespace.
697        */
698       if (*p == '"') {
699         p++;
700         len = strcspn (p, "\"");
701         if (p[len] == '\0') {
702           fprintf (stderr, _("%s: unterminated double quote\n"), program_name);
703           if (exit_on_error) exit (EXIT_FAILURE);
704           goto next_command;
705         }
706         if (p[len+1] && (p[len+1] != ' ' && p[len+1] != '\t')) {
707           fprintf (stderr,
708                    _("%s: command arguments not separated by whitespace\n"),
709                    program_name);
710           if (exit_on_error) exit (EXIT_FAILURE);
711           goto next_command;
712         }
713         p[len] = '\0';
714         pend = p[len+1] ? &p[len+2] : &p[len+1];
715       } else if (*p == '\'') {
716         p++;
717         len = strcspn (p, "'");
718         if (p[len] == '\0') {
719           fprintf (stderr, _("%s: unterminated single quote\n"), program_name);
720           if (exit_on_error) exit (EXIT_FAILURE);
721           goto next_command;
722         }
723         if (p[len+1] && (p[len+1] != ' ' && p[len+1] != '\t')) {
724           fprintf (stderr,
725                    _("%s: command arguments not separated by whitespace\n"),
726                    program_name);
727           if (exit_on_error) exit (EXIT_FAILURE);
728           goto next_command;
729         }
730         p[len] = '\0';
731         pend = p[len+1] ? &p[len+2] : &p[len+1];
732       } else if (*p == '|') {
733         *p = '\0';
734         pipe = p+1;
735         continue;
736         /*
737       } else if (*p == '[') {
738         int c = 1;
739         p++;
740         pend = p;
741         while (*pend && c != 0) {
742           if (*pend == '[') c++;
743           else if (*pend == ']') c--;
744           pend++;
745         }
746         if (c != 0) {
747           fprintf (stderr,
748                    _("%s: unterminated \"[...]\" sequence\n"), program_name);
749           if (exit_on_error) exit (EXIT_FAILURE);
750           goto next_command;
751         }
752         if (*pend && (*pend != ' ' && *pend != '\t')) {
753           fprintf (stderr,
754                    _("%s: command arguments not separated by whitespace\n"),
755                    program_name);
756           if (exit_on_error) exit (EXIT_FAILURE);
757           goto next_command;
758         }
759         *(pend-1) = '\0';
760         */
761       } else if (*p != ' ' && *p != '\t') {
762         /* If the first character is a ~ then note that this parameter
763          * is a candidate for ~username expansion.  NB this does not
764          * apply to quoted parameters.
765          */
766         tilde_candidate = *p == '~';
767         len = strcspn (p, " \t");
768         if (p[len]) {
769           p[len] = '\0';
770           pend = &p[len+1];
771         } else
772           pend = &p[len];
773       } else {
774         fprintf (stderr, _("%s: internal error parsing string at '%s'\n"),
775                  program_name, p);
776         abort ();
777       }
778
779       if (!tilde_candidate)
780         argv[i] = p;
781       else
782         argv[i] = try_tilde_expansion (p);
783       i++;
784       p = pend;
785
786       if (*p)
787         p += strspn (p, " \t");
788     }
789
790     if (i == sizeof argv / sizeof argv[0]) {
791       fprintf (stderr, _("%s: too many arguments\n"), program_name);
792       if (exit_on_error) exit (EXIT_FAILURE);
793       goto next_command;
794     }
795
796     argv[i] = NULL;
797
798   got_command:
799     if (issue_command (cmd, argv, pipe) == -1) {
800       if (exit_on_error) exit (EXIT_FAILURE);
801     }
802
803   next_command:;
804   }
805   if (prompt) printf ("\n");
806 }
807
808 static void
809 cmdline (char *argv[], int optind, int argc)
810 {
811   const char *cmd;
812   char **params;
813
814   exit_on_error = 1;
815
816   if (optind >= argc) return;
817
818   cmd = argv[optind++];
819   if (STREQ (cmd, ":")) {
820     fprintf (stderr, _("%s: empty command on command line\n"), program_name);
821     exit (EXIT_FAILURE);
822   }
823
824   /* Allow -cmd on the command line to mean (temporarily) override
825    * the normal exit on error (RHBZ#578407).
826    */
827   if (cmd[0] == '-') {
828     exit_on_error = 0;
829     cmd++;
830   }
831
832   params = &argv[optind];
833
834   /* Search for end of command list or ":" ... */
835   while (optind < argc && STRNEQ (argv[optind], ":"))
836     optind++;
837
838   if (optind == argc) {
839     if (issue_command (cmd, params, NULL) == -1 && exit_on_error)
840         exit (EXIT_FAILURE);
841   } else {
842     argv[optind] = NULL;
843     if (issue_command (cmd, params, NULL) == -1 && exit_on_error)
844       exit (EXIT_FAILURE);
845     cmdline (argv, optind+1, argc);
846   }
847 }
848
849 int
850 issue_command (const char *cmd, char *argv[], const char *pipecmd)
851 {
852   int argc;
853   int stdout_saved_fd = -1;
854   int pid = 0;
855   int i, r;
856
857   /* This counts the commands issued, starting at 1. */
858   command_num++;
859
860   /* For | ... commands.  Annoyingly we can't use popen(3) here. */
861   if (pipecmd) {
862     int fd[2];
863
864     if (fflush (stdout) == EOF) {
865       perror ("failed to flush standard output");
866       return -1;
867     }
868     if (pipe (fd) < 0) {
869       perror ("pipe failed");
870       return -1;
871     }
872     pid = fork ();
873     if (pid == -1) {
874       perror ("fork");
875       return -1;
876     }
877
878     if (pid == 0) {             /* Child process. */
879       close (fd[1]);
880       if (dup2 (fd[0], 0) < 0) {
881         perror ("dup2 of stdin failed");
882         _exit (1);
883       }
884
885       r = system (pipecmd);
886       if (r == -1) {
887         perror (pipecmd);
888         _exit (1);
889       }
890       _exit (WEXITSTATUS (r));
891     }
892
893     if ((stdout_saved_fd = dup (1)) < 0) {
894       perror ("failed to dup stdout");
895       return -1;
896     }
897     close (fd[0]);
898     if (dup2 (fd[1], 1) < 0) {
899       perror ("failed to dup stdout");
900       close (stdout_saved_fd);
901       return -1;
902     }
903     close (fd[1]);
904   }
905
906   for (argc = 0; argv[argc] != NULL; ++argc)
907     ;
908
909   /* If --remote was set, then send this command to a remote process. */
910   if (remote_control)
911     r = rc_remote (remote_control, cmd, argc, argv, exit_on_error);
912
913   /* Otherwise execute it locally. */
914   else if (STRCASEEQ (cmd, "help")) {
915     if (argc == 0)
916       list_commands ();
917     else
918       display_command (argv[0]);
919     r = 0;
920   }
921   else if (STRCASEEQ (cmd, "quit") ||
922            STRCASEEQ (cmd, "exit") ||
923            STRCASEEQ (cmd, "q")) {
924     quit = 1;
925     r = 0;
926   }
927   else if (STRCASEEQ (cmd, "alloc") ||
928            STRCASEEQ (cmd, "allocate"))
929     r = do_alloc (cmd, argc, argv);
930   else if (STRCASEEQ (cmd, "echo"))
931     r = do_echo (cmd, argc, argv);
932   else if (STRCASEEQ (cmd, "edit") ||
933            STRCASEEQ (cmd, "vi") ||
934            STRCASEEQ (cmd, "emacs"))
935     r = do_edit (cmd, argc, argv);
936   else if (STRCASEEQ (cmd, "lcd"))
937     r = do_lcd (cmd, argc, argv);
938   else if (STRCASEEQ (cmd, "glob"))
939     r = do_glob (cmd, argc, argv);
940   else if (STRCASEEQ (cmd, "man") ||
941            STRCASEEQ (cmd, "manual"))
942     r = do_man (cmd, argc, argv);
943   else if (STRCASEEQ (cmd, "more") ||
944            STRCASEEQ (cmd, "less"))
945     r = do_more (cmd, argc, argv);
946   else if (STRCASEEQ (cmd, "reopen"))
947     r = do_reopen (cmd, argc, argv);
948   else if (STRCASEEQ (cmd, "sparse"))
949     r = do_sparse (cmd, argc, argv);
950   else if (STRCASEEQ (cmd, "time"))
951     r = do_time (cmd, argc, argv);
952   else
953     r = run_action (cmd, argc, argv);
954
955   /* Always flush stdout after every command, so that messages, results
956    * etc appear immediately.
957    */
958   if (fflush (stdout) == EOF) {
959     perror ("failed to flush standard output");
960     return -1;
961   }
962
963   if (pipecmd) {
964     close (1);
965     if (dup2 (stdout_saved_fd, 1) < 0) {
966       perror ("failed to dup2 standard output");
967       r = -1;
968     }
969     close (stdout_saved_fd);
970     if (waitpid (pid, NULL, 0) < 0) {
971       perror ("waiting for command to complete");
972       r = -1;
973     }
974   }
975
976   return r;
977 }
978
979 void
980 list_builtin_commands (void)
981 {
982   /* help, man and quit should appear at the top */
983   printf ("%-20s %s\n",
984           "help", _("display a list of commands or help on a command"));
985   printf ("%-20s %s\n",
986           "man", _("read the manual"));
987   printf ("%-20s %s\n",
988           "quit", _("quit guestfish"));
989
990   printf ("%-20s %s\n",
991           "alloc", _("allocate an image"));
992   printf ("%-20s %s\n",
993           "echo", _("display a line of text"));
994   printf ("%-20s %s\n",
995           "edit", _("edit a file in the image"));
996   printf ("%-20s %s\n",
997           "lcd", _("local change directory"));
998   printf ("%-20s %s\n",
999           "glob", _("expand wildcards in command"));
1000   printf ("%-20s %s\n",
1001           "more", _("view a file in the pager"));
1002   printf ("%-20s %s\n",
1003           "reopen", _("close and reopen libguestfs handle"));
1004   printf ("%-20s %s\n",
1005           "sparse", _("allocate a sparse image file"));
1006   printf ("%-20s %s\n",
1007           "time", _("measure time taken to run command"));
1008
1009   /* actions are printed after this (see list_commands) */
1010 }
1011
1012 void
1013 display_builtin_command (const char *cmd)
1014 {
1015   /* help for actions is auto-generated, see display_command */
1016
1017   if (STRCASEEQ (cmd, "alloc") ||
1018       STRCASEEQ (cmd, "allocate"))
1019     printf (_("alloc - allocate an image\n"
1020               "     alloc <filename> <size>\n"
1021               "\n"
1022               "    This creates an empty (zeroed) file of the given size,\n"
1023               "    and then adds so it can be further examined.\n"
1024               "\n"
1025               "    For more advanced image creation, see qemu-img utility.\n"
1026               "\n"
1027               "    Size can be specified (where <nn> means a number):\n"
1028               "    <nn>             number of kilobytes\n"
1029               "      eg: 1440       standard 3.5\" floppy\n"
1030               "    <nn>K or <nn>KB  number of kilobytes\n"
1031               "    <nn>M or <nn>MB  number of megabytes\n"
1032               "    <nn>G or <nn>GB  number of gigabytes\n"
1033               "    <nn>T or <nn>TB  number of terabytes\n"
1034               "    <nn>P or <nn>PB  number of petabytes\n"
1035               "    <nn>E or <nn>EB  number of exabytes\n"
1036               "    <nn>sects        number of 512 byte sectors\n"));
1037   else if (STRCASEEQ (cmd, "echo"))
1038     printf (_("echo - display a line of text\n"
1039               "     echo [<params> ...]\n"
1040               "\n"
1041               "    This echos the parameters to the terminal.\n"));
1042   else if (STRCASEEQ (cmd, "edit") ||
1043            STRCASEEQ (cmd, "vi") ||
1044            STRCASEEQ (cmd, "emacs"))
1045     printf (_("edit - edit a file in the image\n"
1046               "     edit <filename>\n"
1047               "\n"
1048               "    This is used to edit a file.\n"
1049               "\n"
1050               "    It is the equivalent of (and is implemented by)\n"
1051               "    running \"cat\", editing locally, and then \"write-file\".\n"
1052               "\n"
1053               "    Normally it uses $EDITOR, but if you use the aliases\n"
1054               "    \"vi\" or \"emacs\" you will get those editors.\n"
1055               "\n"
1056               "    NOTE: This will not work reliably for large files\n"
1057               "    (> 2 MB) or binary files containing \\0 bytes.\n"));
1058   else if (STRCASEEQ (cmd, "lcd"))
1059     printf (_("lcd - local change directory\n"
1060               "    lcd <directory>\n"
1061               "\n"
1062               "    Change guestfish's current directory. This command is\n"
1063               "    useful if you want to download files to a particular\n"
1064               "    place.\n"));
1065   else if (STRCASEEQ (cmd, "glob"))
1066     printf (_("glob - expand wildcards in command\n"
1067               "    glob <command> [<args> ...]\n"
1068               "\n"
1069               "    Glob runs <command> with wildcards expanded in any\n"
1070               "    command args.  Note that the command is run repeatedly\n"
1071               "    once for each expanded argument.\n"));
1072   else if (STRCASEEQ (cmd, "man") ||
1073            STRCASEEQ (cmd, "manual"))
1074     printf (_("man - read the manual\n"
1075               "    man\n"
1076               "\n"
1077               "    Opens the manual page for guestfish.\n"));
1078   else if (STRCASEEQ (cmd, "help"))
1079     printf (_("help - display a list of commands or help on a command\n"
1080               "     help cmd\n"
1081               "     help\n"));
1082   else if (STRCASEEQ (cmd, "more") ||
1083            STRCASEEQ (cmd, "less"))
1084     printf (_("more - view a file in the pager\n"
1085               "     more <filename>\n"
1086               "\n"
1087               "    This is used to view a file in the pager.\n"
1088               "\n"
1089               "    It is the equivalent of (and is implemented by)\n"
1090               "    running \"cat\" and using the pager.\n"
1091               "\n"
1092               "    Normally it uses $PAGER, but if you use the alias\n"
1093               "    \"less\" then it always uses \"less\".\n"
1094               "\n"
1095               "    NOTE: This will not work reliably for large files\n"
1096               "    (> 2 MB) or binary files containing \\0 bytes.\n"));
1097   else if (STRCASEEQ (cmd, "quit") ||
1098            STRCASEEQ (cmd, "exit") ||
1099            STRCASEEQ (cmd, "q"))
1100     printf (_("quit - quit guestfish\n"
1101               "     quit\n"));
1102   else if (STRCASEEQ (cmd, "reopen"))
1103     printf (_("reopen - close and reopen the libguestfs handle\n"
1104               "     reopen\n"
1105               "\n"
1106               "Close and reopen the libguestfs handle.  It is not necessary to use\n"
1107               "this normally, because the handle is closed properly when guestfish\n"
1108               "exits.  However this is occasionally useful for testing.\n"));
1109   else if (STRCASEEQ (cmd, "sparse"))
1110     printf (_("sparse - allocate a sparse image file\n"
1111               "     sparse <filename> <size>\n"
1112               "\n"
1113               "    This creates an empty sparse file of the given size,\n"
1114               "    and then adds so it can be further examined.\n"
1115               "\n"
1116               "    In all respects it works the same as the 'alloc'\n"
1117               "    command, except that the image file is allocated\n"
1118               "    sparsely, which means that disk blocks are not assigned\n"
1119               "    to the file until they are needed.  Sparse disk files\n"
1120               "    only use space when written to, but they are slower\n"
1121               "    and there is a danger you could run out of real disk\n"
1122               "    space during a write operation.\n"
1123               "\n"
1124               "    For more advanced image creation, see qemu-img utility.\n"
1125               "\n"
1126               "    Size can be specified (where <nn> means a number):\n"
1127               "    <nn>             number of kilobytes\n"
1128               "      eg: 1440       standard 3.5\" floppy\n"
1129               "    <nn>K or <nn>KB  number of kilobytes\n"
1130               "    <nn>M or <nn>MB  number of megabytes\n"
1131               "    <nn>G or <nn>GB  number of gigabytes\n"
1132               "    <nn>T or <nn>TB  number of terabytes\n"
1133               "    <nn>P or <nn>PB  number of petabytes\n"
1134               "    <nn>E or <nn>EB  number of exabytes\n"
1135               "    <nn>sects        number of 512 byte sectors\n"));
1136   else if (STRCASEEQ (cmd, "time"))
1137     printf (_("time - measure time taken to run command\n"
1138               "    time <command> [<args> ...]\n"
1139               "\n"
1140               "    This runs <command> as usual, and prints the elapsed\n"
1141               "    time afterwards.\n"));
1142   else
1143     fprintf (stderr, _("%s: command not known, use -h to list all commands\n"),
1144              cmd);
1145 }
1146
1147 /* This is printed when the user types in an unknown command for the
1148  * first command issued.  A common case is the user doing:
1149  *   guestfish disk.img
1150  * expecting guestfish to open 'disk.img' (in fact, this tried to
1151  * run a command 'disk.img').
1152  */
1153 void
1154 extended_help_message (void)
1155 {
1156   fprintf (stderr,
1157            _("Did you mean to open a disk image?  guestfish -a disk.img\n"
1158              "For a list of commands:             guestfish -h\n"
1159              "For complete documentation:         man guestfish\n"));
1160 }
1161
1162 void
1163 free_strings (char **argv)
1164 {
1165   int argc;
1166
1167   for (argc = 0; argv[argc] != NULL; ++argc)
1168     free (argv[argc]);
1169   free (argv);
1170 }
1171
1172 int
1173 count_strings (char *const *argv)
1174 {
1175   int c;
1176
1177   for (c = 0; argv[c]; ++c)
1178     ;
1179   return c;
1180 }
1181
1182 void
1183 print_strings (char *const *argv)
1184 {
1185   int argc;
1186
1187   for (argc = 0; argv[argc] != NULL; ++argc)
1188     printf ("%s\n", argv[argc]);
1189 }
1190
1191 void
1192 print_table (char *const *argv)
1193 {
1194   int i;
1195
1196   for (i = 0; argv[i] != NULL; i += 2)
1197     printf ("%s: %s\n", argv[i], argv[i+1]);
1198 }
1199
1200 int
1201 is_true (const char *str)
1202 {
1203   return
1204     STRCASENEQ (str, "0") &&
1205     STRCASENEQ (str, "f") &&
1206     STRCASENEQ (str, "false") &&
1207     STRCASENEQ (str, "n") &&
1208     STRCASENEQ (str, "no");
1209 }
1210
1211 /* Free strings from a non-NULL terminated char** */
1212 static void
1213 free_n_strings (char **str, size_t len)
1214 {
1215   size_t i;
1216
1217   for (i = 0; i < len; i++) {
1218     free (str[i]);
1219   }
1220   free (str);
1221 }
1222
1223 char **
1224 parse_string_list (const char *str)
1225 {
1226   char **argv = NULL;
1227   size_t argv_len = 0;
1228
1229   /* Current position pointer */
1230   const char *p = str;
1231
1232   /* Token might be simple:
1233    *  Token
1234    * or be quoted:
1235    *  'This is a single token'
1236    * or contain embedded single-quoted sections:
1237    *  This' is a sing'l'e to'ken
1238    *
1239    * The latter may seem over-complicated, but it's what a normal shell does.
1240    * Not doing it risks surprising somebody.
1241    *
1242    * This outer loop is over complete tokens.
1243    */
1244   while (*p) {
1245     char *tok = NULL;
1246     size_t tok_len = 0;
1247
1248     /* Skip leading whitespace */
1249     p += strspn (p, " \t");
1250
1251     char in_quote = 0;
1252
1253     /* This loop is over token 'fragments'. A token can be in multiple bits if
1254      * it contains single quotes. We also treat both sides of an escaped quote
1255      * as separate fragments because we can't just copy it: we have to remove
1256      * the \.
1257      */
1258     while (*p && (!c_isblank (*p) || in_quote)) {
1259       const char *end = p;
1260
1261       /* Check if the fragment starts with a quote */
1262       if ('\'' == *p) {
1263         /* Toggle in_quote */
1264         in_quote = !in_quote;
1265
1266         /* Skip the quote */
1267         p++; end++;
1268       }
1269
1270       /* If we're in a quote, look for an end quote */
1271       if (in_quote) {
1272         end += strcspn (end, "'");
1273       }
1274
1275       /* Otherwise, look for whitespace or a quote */
1276       else {
1277         end += strcspn (end, " \t'");
1278       }
1279
1280       /* Grow the token to accommodate the fragment */
1281       size_t tok_end = tok_len;
1282       tok_len += end - p;
1283       char *tok_new = realloc (tok, tok_len + 1);
1284       if (NULL == tok_new) {
1285         perror ("realloc");
1286         free_n_strings (argv, argv_len);
1287         free (tok);
1288         exit (EXIT_FAILURE);
1289       }
1290       tok = tok_new;
1291
1292       /* Check if we stopped on an escaped quote */
1293       if ('\'' == *end && end != p && *(end-1) == '\\') {
1294         /* Add everything before \' to the token */
1295         memcpy (&tok[tok_end], p, end - p - 1);
1296
1297         /* Add the quote */
1298         tok[tok_len-1] = '\'';
1299
1300         /* Already processed the quote */
1301         p = end + 1;
1302       }
1303
1304       else {
1305         /* Add the whole fragment */
1306         memcpy (&tok[tok_end], p, end - p);
1307
1308         p = end;
1309       }
1310     }
1311
1312     /* We've reached the end of a token. We shouldn't still be in quotes. */
1313     if (in_quote) {
1314       fprintf (stderr, _("Runaway quote in string \"%s\"\n"), str);
1315
1316       free_n_strings (argv, argv_len);
1317
1318       return NULL;
1319     }
1320
1321     /* Add this token if there is one. There might not be if there was
1322      * whitespace at the end of the input string */
1323     if (tok) {
1324       /* Add the NULL terminator */
1325       tok[tok_len] = '\0';
1326
1327       /* Add the argument to the argument list */
1328       argv_len++;
1329       char **argv_new = realloc (argv, sizeof (*argv) * argv_len);
1330       if (NULL == argv_new) {
1331         perror ("realloc");
1332         free_n_strings (argv, argv_len-1);
1333         free (tok);
1334         exit (EXIT_FAILURE);
1335       }
1336       argv = argv_new;
1337
1338       argv[argv_len-1] = tok;
1339     }
1340   }
1341
1342   /* NULL terminate the argument list */
1343   argv_len++;
1344   char **argv_new = realloc (argv, sizeof (*argv) * argv_len);
1345   if (NULL == argv_new) {
1346     perror ("realloc");
1347     free_n_strings (argv, argv_len-1);
1348     exit (EXIT_FAILURE);
1349   }
1350   argv = argv_new;
1351
1352   argv[argv_len-1] = NULL;
1353
1354   return argv;
1355 }
1356
1357 #ifdef HAVE_LIBREADLINE
1358 static char histfile[1024];
1359 static int nr_history_lines = 0;
1360 #endif
1361
1362 static void
1363 initialize_readline (void)
1364 {
1365 #ifdef HAVE_LIBREADLINE
1366   const char *home;
1367
1368   home = getenv ("HOME");
1369   if (home) {
1370     snprintf (histfile, sizeof histfile, "%s/.guestfish", home);
1371     using_history ();
1372     (void) read_history (histfile);
1373   }
1374
1375   rl_readline_name = "guestfish";
1376   rl_attempted_completion_function = do_completion;
1377 #endif
1378 }
1379
1380 static void
1381 cleanup_readline (void)
1382 {
1383 #ifdef HAVE_LIBREADLINE
1384   int fd;
1385
1386   if (histfile[0] != '\0') {
1387     fd = open (histfile, O_WRONLY|O_CREAT, 0644);
1388     if (fd == -1) {
1389       perror (histfile);
1390       return;
1391     }
1392     close (fd);
1393
1394 #ifdef HAVE_APPEND_HISTORY
1395     (void) append_history (nr_history_lines, histfile);
1396 #else
1397     (void) write_history (histfile);
1398 #endif
1399   }
1400 #endif
1401 }
1402
1403 static void
1404 add_history_line (const char *line)
1405 {
1406 #ifdef HAVE_LIBREADLINE
1407   add_history (line);
1408   nr_history_lines++;
1409 #endif
1410 }
1411
1412 int
1413 xwrite (int fd, const void *v_buf, size_t len)
1414 {
1415   int r;
1416   const char *buf = v_buf;
1417
1418   while (len > 0) {
1419     r = write (fd, buf, len);
1420     if (r == -1) {
1421       perror ("write");
1422       return -1;
1423     }
1424     buf += r;
1425     len -= r;
1426   }
1427
1428   return 0;
1429 }
1430
1431 /* Resolve the special "win:..." form for Windows-specific paths.
1432  * This always returns a newly allocated string which is freed by the
1433  * caller function in "cmds.c".
1434  */
1435 char *
1436 resolve_win_path (const char *path)
1437 {
1438   char *ret;
1439   size_t i;
1440
1441   if (STRCASENEQLEN (path, "win:", 4)) {
1442     ret = strdup (path);
1443     if (ret == NULL)
1444       perror ("strdup");
1445     return ret;
1446   }
1447
1448   path += 4;
1449
1450   /* Drop drive letter, if it's "C:". */
1451   if (STRCASEEQLEN (path, "c:", 2))
1452     path += 2;
1453
1454   if (!*path) {
1455     ret = strdup ("/");
1456     if (ret == NULL)
1457       perror ("strdup");
1458     return ret;
1459   }
1460
1461   ret = strdup (path);
1462   if (ret == NULL) {
1463     perror ("strdup");
1464     return NULL;
1465   }
1466
1467   /* Blindly convert any backslashes into forward slashes.  Is this good? */
1468   for (i = 0; i < strlen (ret); ++i)
1469     if (ret[i] == '\\')
1470       ret[i] = '/';
1471
1472   char *t = guestfs_case_sensitive_path (g, ret);
1473   free (ret);
1474   ret = t;
1475
1476   return ret;
1477 }
1478
1479 /* Resolve the special FileIn paths ("-" or "-<<END" or filename).
1480  * The caller (cmds.c) will call free_file_in after the command has
1481  * run which should clean up resources.
1482  */
1483 static char *file_in_heredoc (const char *endmarker);
1484 static char *file_in_tmpfile = NULL;
1485
1486 char *
1487 file_in (const char *arg)
1488 {
1489   char *ret;
1490
1491   if (STREQ (arg, "-")) {
1492     ret = strdup ("/dev/stdin");
1493     if (!ret) {
1494       perror ("strdup");
1495       return NULL;
1496     }
1497   }
1498   else if (STRPREFIX (arg, "-<<")) {
1499     const char *endmarker = &arg[3];
1500     if (*endmarker == '\0') {
1501       fprintf (stderr, "%s: missing end marker in -<< expression\n",
1502                program_name);
1503       return NULL;
1504     }
1505     ret = file_in_heredoc (endmarker);
1506     if (ret == NULL)
1507       return NULL;
1508   }
1509   else {
1510     ret = strdup (arg);
1511     if (!ret) {
1512       perror ("strdup");
1513       return NULL;
1514     }
1515   }
1516
1517   return ret;
1518 }
1519
1520 static char *
1521 file_in_heredoc (const char *endmarker)
1522 {
1523   static const char template[] = "/tmp/heredocXXXXXX";
1524   file_in_tmpfile = strdup (template);
1525   if (file_in_tmpfile == NULL) {
1526     perror ("strdup");
1527     return NULL;
1528   }
1529
1530   int fd = mkstemp (file_in_tmpfile);
1531   if (fd == -1) {
1532     perror ("mkstemp");
1533     goto error1;
1534   }
1535
1536   size_t markerlen = strlen (endmarker);
1537
1538   char buffer[BUFSIZ];
1539   int write_error = 0;
1540   while (fgets (buffer, sizeof buffer, stdin) != NULL) {
1541     /* Look for "END"<EOF> or "END\n" in input. */
1542     size_t blen = strlen (buffer);
1543     if (STREQLEN (buffer, endmarker, markerlen) &&
1544         (blen == markerlen ||
1545          (blen == markerlen+1 && buffer[markerlen] == '\n')))
1546       goto found_end;
1547
1548     if (xwrite (fd, buffer, blen) == -1) {
1549       if (!write_error) perror ("write");
1550       write_error = 1;
1551       /* continue reading up to the end marker */
1552     }
1553   }
1554
1555   /* Reached EOF of stdin without finding the end marker, which
1556    * is likely to be an error.
1557    */
1558   fprintf (stderr, "%s: end of input reached without finding '%s'\n",
1559            program_name, endmarker);
1560   goto error2;
1561
1562  found_end:
1563   if (write_error) {
1564     close (fd);
1565     goto error2;
1566   }
1567
1568   if (close (fd) == -1) {
1569     perror ("close");
1570     goto error2;
1571   }
1572
1573   return file_in_tmpfile;
1574
1575  error2:
1576   unlink (file_in_tmpfile);
1577
1578  error1:
1579   free (file_in_tmpfile);
1580   file_in_tmpfile = NULL;
1581   return NULL;
1582 }
1583
1584 void
1585 free_file_in (char *s)
1586 {
1587   if (file_in_tmpfile) {
1588     if (unlink (file_in_tmpfile) == -1)
1589       perror (file_in_tmpfile);
1590     file_in_tmpfile = NULL;
1591   }
1592
1593   /* Free the device or file name which was strdup'd in file_in().
1594    * Note it's not immediately clear, but for -<< heredocs,
1595    * s == file_in_tmpfile, so this frees up that buffer.
1596    */
1597   free (s);
1598 }
1599
1600 /* Resolve the special FileOut paths ("-" or filename).
1601  * The caller (cmds.c) will call free (str) after the command has run.
1602  */
1603 char *
1604 file_out (const char *arg)
1605 {
1606   char *ret;
1607
1608   if (STREQ (arg, "-"))
1609     ret = strdup ("/dev/stdout");
1610   else
1611     ret = strdup (arg);
1612
1613   if (!ret) {
1614     perror ("strdup");
1615     return NULL;
1616   }
1617   return ret;
1618 }