Implement "more" and "less" commands in guestfish.

Use commands such as:
  more /etc/passwd
  less /etc/fstab

These commands are specific to guestfish.
This commit is contained in:
Richard W.M. Jones
2009-06-29 12:05:58 +01:00
parent 17a4506396
commit 19a1382fc9
6 changed files with 137 additions and 21 deletions

1
TODO
View File

@@ -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'?

View File

@@ -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 \

View File

@@ -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)
{

View File

@@ -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 <command> 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 <filename>\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;
}

View File

@@ -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 */

93
fish/more.c Normal file
View File

@@ -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 <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <inttypes.h>
#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;
}