bin/60510: [PATCH]

Elmar Bartel elmar at devsoft.com
Mon Dec 22 07:20:13 PST 2003


>Number:         60510
>Category:       bin
>Synopsis:       [PATCH]
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Mon Dec 22 07:20:08 PST 2003
>Closed-Date:
>Last-Modified:
>Originator:     Elmar Bartel
>Release:        FreeBSD 4.9-RELEASE i386
>Organization:
leo.org
>Environment:
System: FreeBSD hermes.devsoft.com  4.9-RELEASE FreeBSD 4.9-RELEASE #0: Mon Dec 22 10:37:10 CET 2003  elmar at eldev.devsoft.com:/usr/src/sys/compile/ELDEV  i386
>Description:
	The current version of less cannot deal with compressed files.
	The author of less proposes to use INPUT PREPROCESSOR. But hhis
	mechanism requires a complete decompression of the file even when
	only the first few lines will be looked at.  So, most of the time
	this is simply waste of time and space.
	Instead the attached patch add's little code to recognize the type
	of compression and to read the decompressed content from a pipe.
	Some time ago I offered this patch to the original author, but he
	refused to accept it refering to its INPUT PREPROCESSOR feature.
	The given patch just extends the features of less and should not
	have any further impact.  I'am using it for a long time now and I
	think its worth while, so I offer it to your project.
	
>How-To-Repeat:

>Fix:

>Release-Note:
>Audit-Trail:
>Unformatted:
 >Patch:
 --- usr.bin/less/Makefile.orig	Mon Dec 22 15:51:50 2003
 +++ usr.bin/less/Makefile	Mon Dec 22 15:22:24 2003
 @@ -4,7 +4,7 @@
  SRCS=	main.c screen.c brac.c ch.c charset.c cmdbuf.c command.c decode.c \
  	edit.c filename.c forwback.c help.c ifile.c input.c jump.c line.c \
  	linenum.c lsystem.c mark.c optfunc.c option.c opttbl.c os.c output.c \
 -	position.c prompt.c search.c signal.c tags.c ttyin.c version.c
 +	position.c prompt.c search.c signal.c tags.c ttyin.c version.c zfile.c
  DPADD=	${LIBTERMCAP}
  LDADD=	-ltermcap
  LINKS=	${BINDIR}/less ${BINDIR}/more
 --- contrib/less/Makefile.in.orig	Fri Jun 30 03:03:07 2000
 +++ contrib/less/Makefile.in	Mon Dec 22 15:12:17 2003
 @@ -42,7 +42,7 @@
  	help.${O} ifile.${O} input.${O} jump.${O} line.${O} linenum.${O} \
  	lsystem.${O} mark.${O} optfunc.${O} option.${O} opttbl.${O} os.${O} \
  	output.${O} position.${O} prompt.${O} search.${O} signal.${O} \
 -	tags.${O} ttyin.${O} version.${O}  @REGEX_O@
 +	tags.${O} ttyin.${O} version.${O}  zfile.${O} @REGEX_O@
  
  all: less lesskey lessecho
  
 --- contrib/less/ch.c.orig	Fri Jun 30 03:03:07 2000
 +++ contrib/less/ch.c	Mon Dec 22 15:12:17 2003
 @@ -740,6 +740,8 @@
  		 */
  		if (!(ch_flags & (CH_POPENED|CH_HELPFILE)))
  			close(ch_file);
 +		if (ch_flags & CH_COMPRESSED)
 +			Zclose(ch_file);
  		ch_file = -1;
  	} else
  		keepstate = TRUE;
 --- contrib/less/edit.c.orig	Fri Jun 30 03:03:08 2000
 +++ contrib/less/edit.c	Mon Dec 22 15:12:17 2003
 @@ -307,6 +307,16 @@
  		 */
  		reedit_ifile(was_curr_ifile);
  		return (1);
 +	} else if ((answer=IsZfile(open_filename)) >= 0)
 +	{
 +		if ((f=Zopen(open_filename, answer)) < 0)
 +		{
 +			parg.p_string = errno_message(filename);
 +			error("%s", &parg); 
 +			free(parg.p_string);
 +			return (1);
 +		}
 +		chflags |= CH_COMPRESSED;
  	} else if ((f = open(open_filename, OPEN_READ)) < 0)
  	{
  		/*
 --- contrib/less/less.h.orig	Wed Jul 19 11:24:26 2000
 +++ contrib/less/less.h	Mon Dec 22 15:12:17 2003
 @@ -388,6 +388,7 @@
  #define	CH_KEEPOPEN	002
  #define	CH_POPENED	004
  #define	CH_HELPFILE	010
 +#define CH_COMPRESSED	020
  
  #define	ch_zero()	((POSITION)0)
  
 --- contrib/less/less.nro.orig	Wed Jul 19 11:24:26 2000
 +++ contrib/less/less.nro	Mon Dec 22 15:25:33 2003
 @@ -34,6 +34,22 @@
  so with large input files it starts up faster than text editors like
  .I vi
  (1).
 +This version of
 +.I less 
 +automagically detectets if a file (not stdin) is compressed via
 +.I bzip2
 +(1),
 +.I gzip
 +(1),
 +.I compress
 +(1),
 +or
 +.I pack
 +(1)
 +and decompresses it before presenting the
 +contents of the file. This feature is implemented independent of the 
 +.BR "INPUT PREPROCESSOR" s.
 +to conserve the fast startup even for compressed files.
  .I Less
  uses termcap (or terminfo on some systems),
  so it can run on a variety of terminals.
 @@ -1512,4 +1528,9 @@
  Mark Nudelman <marknu at flash.net>
  .br
  Send bug reports or comments to the above address or to bug-less at gnu.org.
 +  
 +.SH HACKED
 +by Elmar Bartel (elmar at leo.org) based on
 +an earlier hack of Kai-Uwe Rommel (rommel at leo.org))
 +for less-177, to automatically detect compressed files.
  
 --- contrib/less/zfile.c.orig	Mon Dec 22 15:12:17 2003
 +++ contrib/less/zfile.c	Mon Dec 22 15:12:17 2003
 @@ -0,0 +1,83 @@
 +#include <stdio.h>
 +#include <fcntl.h>
 +#include <signal.h>
 +
 +extern int errno;
 +
 +typedef struct {
 +    unsigned char magic[2];
 +    char *cmd;
 +    char *opt;
 +}  CompressMethod;
 +static CompressMethod zTable[] = {
 +    0x1f, 0x9d, "compress", "-dc",
 +    0x1f, 0x1e, "gunzip", NULL,	/* this is old packed Unix-Format, but
 +				 * pcat doesn't know stdin ...
 +				 * ... but gunzip does
 +				 */ 
 +    0x1f, 0x8b, "gunzip", NULL,	/* this is gzip itself */
 +    0x42, 0x5a, "bzip2", "-d"	/* this is bzip2 */
 +};
 +#define MethodCnt       sizeof(zTable)/sizeof(CompressMethod)
 +static int pid[64]= { 0 };
 +
 +int IsZfile(name) char *name;
 +{    
 +    int Method, res, file;
 +    unsigned char magic[2];
 +     
 +    file = open(name, O_RDONLY);
 +    res = read(file, magic, 2);
 +    close(file);
 +    if (res != 2)
 +	return -1;
 +     
 +    for (Method=0; Method < MethodCnt; Method++)
 +	if (zTable[Method].magic[0] == magic[0] &&
 +	    zTable[Method].magic[1] == magic[1]) {
 +		return Method; 
 +	  }       
 +    return -1;
 +}    
 +
 +int Zopen(open_file, Method) char *open_file; int Method; {
 +    int p, ph[2], file;
 +
 +    if (Method < 0 || Method >= MethodCnt)
 +	return -1;
 +
 +    if (pipe(ph))
 +    	return -1;
 +
 +    if ((p = fork()) == -1)
 +	return -1;
 +
 +    if (p == 0) {
 +	if ((file = open(open_file, O_RDONLY)) == -1)
 +	    exit(1);
 +	dup2(file, 0);
 +	dup2(ph[1], 1);
 +	dup2(ph[1], 2);
 +	close(ph[1]);
 +	close(ph[0]);
 +	close(file);
 +	if (execlp(zTable[Method].cmd, zTable[Method].cmd,
 +	  zTable[Method].opt, NULL) == -1) {
 +	    fprintf(stderr,
 +	      "cannot exec decompression command \"%s\": %s",
 +	      zTable[Method].cmd, strerror(errno));
 +	    exit(1);
 +	}
 +    }
 +    else
 +	close(ph[1]);
 +    pid[ph[0]] = p;
 +    return ph[0];
 +}
 +
 +void Zclose(handle) int handle; {
 +    close(handle);
 +    kill(pid[handle], SIGPIPE);
 +    waitpid(pid[handle], NULL, 0);
 +    return;
 +}


More information about the freebsd-bugs mailing list