From: Richard W.M. Jones Date: Mon, 29 Jun 2009 11:05:58 +0000 (+0100) Subject: Implement "more" and "less" commands in guestfish. X-Git-Tag: 1.0.54~11 X-Git-Url: http://git.annexia.org/?p=libguestfs.git;a=commitdiff_plain;h=19a1382fc9317ab88cdbf1dde76a8015868af51d Implement "more" and "less" commands in guestfish. Use commands such as: more /etc/passwd less /etc/fstab These commands are specific to guestfish. --- diff --git a/TODO b/TODO index 255cef8..131f4d8 100644 --- a/TODO +++ b/TODO @@ -156,7 +156,6 @@ Extra commands / functionality: fts(3) / ftw(3) guestfish only: - more/less (like cat, but pipes it through $PAGER) cat file | pipe-cmd should have a generic form? like 'file | less' or 'file | sort'? diff --git a/fish/Makefile.am b/fish/Makefile.am index 1e5b108..34b1a0b 100644 --- a/fish/Makefile.am +++ b/fish/Makefile.am @@ -27,7 +27,8 @@ guestfish_SOURCES = \ fish.c \ fish.h \ glob.c \ - lcd.c + lcd.c \ + more.c guestfish_CFLAGS = \ -I$(top_builddir)/src -Wall \ diff --git a/fish/edit.c b/fish/edit.c index 5519bb9..c72ad1d 100644 --- a/fish/edit.c +++ b/fish/edit.c @@ -29,24 +29,6 @@ /* guestfish edit command, suggested by Ján Ondrej, implemented by RWMJ */ -static int -xwrite (int fd, const void *buf, size_t len) -{ - int r; - - while (len > 0) { - r = write (fd, buf, len); - if (r == -1) { - perror ("write"); - return -1; - } - buf += r; - len -= r; - } - - return 0; -} - static char * load_file (const char *filename, int *len_r) { diff --git a/fish/fish.c b/fish/fish.c index 5b0a065..90740d5 100644 --- a/fish/fish.c +++ b/fish/fish.c @@ -724,6 +724,9 @@ issue_command (const char *cmd, char *argv[], const char *pipecmd) r = do_lcd (cmd, argc, argv); else if (strcasecmp (cmd, "glob") == 0) r = do_glob (cmd, argc, argv); + else if (strcasecmp (cmd, "more") == 0 || + strcasecmp (cmd, "less") == 0) + r = do_more (cmd, argc, argv); else r = run_action (cmd, argc, argv); @@ -818,6 +821,21 @@ display_builtin_command (const char *cmd) " Glob runs with wildcards expanded in any\n" " command args. Note that the command is run repeatedly\n" " once for each expanded argument.\n")); + else if (strcasecmp (cmd, "more") == 0 || + strcasecmp (cmd, "less") == 0) + printf (_("more - view a file in the pager\n" + " more \n" + "\n" + " This is used to view a file in the pager.\n" + "\n" + " It is the equivalent of (and is implemented by)\n" + " running \"cat\" and using the pager.\n" + "\n" + " Normally it uses $PAGER, but if you use the alias\n" + " \"less\" then it always uses \"less\".\n" + "\n" + " NOTE: This will not work reliably for large files\n" + " (> 2 MB) or binary files containing \\0 bytes.\n")); else if (strcasecmp (cmd, "help") == 0) printf (_("help - display a list of commands or help on a command\n" " help cmd\n" @@ -959,3 +977,21 @@ add_history_line (const char *line) nr_history_lines++; #endif } + +int +xwrite (int fd, const void *buf, size_t len) +{ + int r; + + while (len > 0) { + r = write (fd, buf, len); + if (r == -1) { + perror ("write"); + return -1; + } + buf += r; + len -= r; + } + + return 0; +} diff --git a/fish/fish.h b/fish/fish.h index 8f57595..ac84647 100644 --- a/fish/fish.h +++ b/fish/fish.h @@ -45,6 +45,7 @@ extern void print_table (char * const * const argv); extern int launch (guestfs_h *); extern int is_true (const char *str); extern char **parse_string_list (const char *str); +extern int xwrite (int fd, const void *buf, size_t len); /* in cmds.c (auto-generated) */ extern void list_commands (void); @@ -73,6 +74,9 @@ extern int do_lcd (const char *cmd, int argc, char *argv[]); /* in glob.c */ extern int do_glob (const char *cmd, int argc, char *argv[]); +/* in more.c */ +extern int do_more (const char *cmd, int argc, char *argv[]); + /* This should just list all the built-in commands so they can * be added to the generated auto-completion code. */ @@ -83,6 +87,7 @@ extern int do_glob (const char *cmd, int argc, char *argv[]); "echo", \ "edit", "vi", "emacs", \ "lcd", \ - "glob" + "glob", \ + "more", "less" #endif /* FISH_H */ diff --git a/fish/more.c b/fish/more.c new file mode 100644 index 0000000..8bc9d95 --- /dev/null +++ b/fish/more.c @@ -0,0 +1,93 @@ +/* guestfish - the filesystem interactive shell + * Copyright (C) 2009 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include "fish.h" + +int +do_more (const char *cmd, int argc, char *argv[]) +{ + char filename[] = "/tmp/guestfishXXXXXX"; + char buf[256]; + const char *pager; + char *content; + int r, fd; + + if (argc != 1) { + fprintf (stderr, _("use '%s filename' to page a file\n"), cmd); + return -1; + } + + /* Choose a pager. */ + if (strcasecmp (cmd, "less") == 0) + pager = "less"; + else { + pager = getenv ("PAGER"); + if (pager == NULL) + pager = "more"; + } + + /* Download the file and write it to a temporary. */ + fd = mkstemp (filename); + if (fd == -1) { + perror ("mkstemp"); + return -1; + } + + if ((content = guestfs_cat (g, argv[0])) == NULL) { + close (fd); + unlink (filename); + return -1; + } + + if (xwrite (fd, content, strlen (content)) == -1) { + close (fd); + unlink (filename); + free (content); + return -1; + } + + free (content); + + if (close (fd) == -1) { + perror (filename); + unlink (filename); + return -1; + } + + /* View it. */ + /* XXX Safe? */ + snprintf (buf, sizeof buf, "%s %s", pager, filename); + + r = system (buf); + unlink (filename); + if (r != 0) { + perror (buf); + return -1; + } + + return 0; +}