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