less 322.

This commit is contained in:
mrg 1997-09-21 12:22:44 +00:00
parent f83ae6979b
commit 5eb1412525
39 changed files with 1388 additions and 653 deletions

View File

@ -4,8 +4,62 @@
======================================================================
For the latest news about less, see the "less" Web page:
http://members.aol.com/marknudel/less
You can also download the latest version of less there.
http://www.fog.net/markn/less
You can also download the latest version of less from there.
The email address for questions about less
has been changed to markn@fog.net.
======================================================================
Major changes between "less" versions 330 and 332
* Filenames from the command line are entered into the command history,
so UPARROW/DOWNARROW can be used to retrieve them from the :e command.
* Now works correctly on Windows when using a scrolling terminal
window (buffer larger than display window).
* On Windows, now restores the console screen on exit.
Use -X to get the old behavior.
* Fixed bug on Windows when CAPS-LOCK or NUM-LOCK is pressed.
* Fixed bug on Windows when piping output of an interactive program.
* Fixed bug in tags file processing when tags file has DOS-style
line terminators (CR/LF).
* Fixed compilation problem on OS/2.
======================================================================
Major changes between "less" versions 321 and 330
* Now supports filenames containing spaces (in double quotes).
New option -" can be used to change the quoting characters.
* In filename completion, a slash is appended to a directory name.
If the environment variable LESSSEPARATOR is set, the value of
that variable, rather than a slash, is appended.
* LeftArrow and RightArrow are same as ESC-[ and ESC-].
* Added commands ESC-( and ESC-), same as ESC-[ and ESC-].
* A "quit" command defined in a lesskey file may now have an "extra"
string, which is used to return an exit code from less when it quits.
* New environment variables LESSMETACHARS and LESSMETAESCAPE provide
more control over how less interfaces to the shell.
* Ported to Microsoft Visual C compiler for Windows.
* Ported to DJGPP compiler for MS-DOS.
* Bug fixes.
======================================================================

View File

@ -1,7 +1,8 @@
=========================================================================
=== This is the distribution of less, version 321, released 18 Jul 96 ===
=== Please report any problems to the author at markn@3do.com. ===
=== See http://members.aol.com/marknudel/less for the latest info. ===
This is the distribution of less, version 332, released 22 Apr 97
Please report any problems to the author at markn@fog.net.
(Please note change of email address.)
See http://www.fog.net/markn/less for the latest info.
=========================================================================
This is the distribution of "less", a paginator similar to "more" or "pg".
@ -9,18 +10,17 @@ This is the distribution of "less", a paginator similar to "more" or "pg".
The formatted manual page is in less.man.
The manual page nroff source is in less.nro.
Major changes made since the last posted version are in NEWS.
Known bugs in this version are in BUGS.
===================
===== WARNING =====
===================
The Microsoft C port for MS-DOS and the Ultra C port
for OS-9 are not currently working.
Until these are fixed, for MS-DOS use Borland C,
Until these are fixed, for MS-DOS use Borland C or DJGPP,
and for OS-9 use Microware C.
If you have fixes for either of these ports,
send them to markn@3do.com.
send them to markn@fog.net.
=======================================================================
INSTALLATION (Unix systems only):
@ -47,20 +47,21 @@ INSTALLATION (Unix systems only):
4. Type "make" and watch the fun.
5. If the make succeeds, it will generate the programs "less" and
"lesskey" in your current directory. Test the generated programs.
5. If the make succeeds, it will generate the programs "less",
"lesskey" and "lessecho" in your current directory. Test the
generated programs.
6. When satisfied that it works, if you wish to install it
in a public place, type "make install".
The default install destinations are:
Executables (less, lesskey) in /usr/local/bin
Documentation (less.nro, lesskey.nro) in /usr/local/man/man1
Executables (less, lesskey, lessecho) in /usr/local/bin
Documentation (less.nro, lesskey.nro) in /usr/local/man/man1
If you want to install any of these files elsewhere, define
bindir and/or mandir to the appropriate directories.
If you have any problems building or running "less", suggestions,
complaints, etc., you may mail to the author at markn@3do.com
complaints, etc., you may mail to the author at markn@fog.net.
Note to hackers: comments noting possible improvements are enclosed
in double curly brackets {{ like this }}.
@ -68,23 +69,26 @@ in double curly brackets {{ like this }}.
=======================================================================
INSTALLATION (MS-DOS systems only)
INSTALLATION (MS-DOS systems only,
with Microsoft C, Borland C, or DJGPP)
1. Move the distributed source to its own directory.
Make sure the source has been converted to have CR-LF rather than
LF as line terminators.
Depending on your compiler, you may need to convert the source
to have CR-LF rather than LF as line terminators.
2. If you are using Microsoft C, rename MAKEFILE.DOS to MAKEFILE.
If you are using Borland C, rename MAKEFILE.BCC to MAKEFILE.
2. If you are using Microsoft C, rename MAKEFILE.DSM to MAKEFILE.
If you are using Borland C, rename MAKEFILE.DSB to MAKEFILE.
If you are using DJGPP, rename MAKEFILE.DSG to MAKEFILE.
3. Look at MAKEFILE to make sure that the definitions for CC and LIBDIR
are correct. CC should be the name of your C compiler and
LIBDIR should be the directory where the C libraries
reside. If these definitions need to be changed, you can either
modify the definitions directly in MAKEFILE, or set your environment
variables CC and/or LIBDIR to override the definitions in MAKEFILE.
LIBDIR should be the directory where the C libraries reside (for
Microsoft C only). If these definitions need to be changed, you can
either modify the definitions directly in MAKEFILE, or set your
environment variables CC and/or LIBDIR to override the definitions
in MAKEFILE.
4. If you wish, you may edit DEFINES.DOS to remove some optional features.
4. If you wish, you may edit DEFINES.DS to remove some optional features.
If you choose not to include some features in your version, you may
wish to edit the manual page LESS.MAN and the help page HELP.C
to remove the descriptions of the features which you are removing.
@ -104,15 +108,17 @@ INSTALLATION (MS-DOS systems only)
=======================================================================
INSTALLATION (Windows-95 and Windows-NT systems only)
INSTALLATION (Windows-95 and Windows-NT systems only,
with Borland C or Microsoft Visual C++)
1. Move the distributed source to its own directory.
2. Rename Makefile.w32 to Makefile.
2. If you are using Borland C, rename Makefile.wnb to Makefile.
If you are using Microsoft Visual C++, rename Makefile.wnm to Makefile.
3. Check the Makefile to make sure the definitions look ok.
4. If you wish, you may edit defines.w32 to remove some optional features.
4. If you wish, you may edit defines.wn to remove some optional features.
If you choose not to include some features in your version, you may
wish to edit the manual page less.man and the help page help.c
to remove the descriptions of the features which you are removing.
@ -130,15 +136,16 @@ INSTALLATION (Windows-95 and Windows-NT systems only)
=======================================================================
INSTALLATION (OS/2 systems only)
INSTALLATION (OS/2 systems only,
with EMX C)
1. Move the distributed source to its own directory.
2. Rename Makefile.os2 to Makefile.
2. Rename Makefile.o2e to Makefile.
3. Check the Makefile to make sure the definitions look ok.
4. If you wish, you may edit defines.os2 to remove some optional features.
4. If you wish, you may edit defines.o2 to remove some optional features.
If you choose not to include some features in your version, you may
wish to edit the manual page less.man and the help page help.c
to remove the descriptions of the features which you are removing.
@ -160,7 +167,8 @@ INSTALLATION (OS/2 systems only)
=======================================================================
INSTALLATION (OS-9 systems only)
INSTALLATION (OS-9 systems only,
with Microware C or Ultra C)
1. Move the distributed source to its own directory.

View File

@ -1,4 +1,4 @@
/* $NetBSD: acconfig.h,v 1.1.1.2 1997/04/22 13:45:27 mrg Exp $ */
/* $NetBSD: acconfig.h,v 1.1.1.3 1997/09/21 12:22:57 mrg Exp $ */
/*
* Copyright (c) 1984,1985,1989,1994,1995,1996 Mark Nudelman

View File

@ -1,4 +1,4 @@
/* $NetBSD: brac.c,v 1.1.1.2 1997/04/22 13:45:41 mrg Exp $ */
/* $NetBSD: brac.c,v 1.1.1.3 1997/09/21 12:23:11 mrg Exp $ */
/*
* Copyright (c) 1984,1985,1989,1994,1995,1996 Mark Nudelman

View File

@ -1,4 +1,4 @@
/* $NetBSD: ch.c,v 1.1.1.2 1997/04/22 13:45:13 mrg Exp $ */
/* $NetBSD: ch.c,v 1.1.1.3 1997/09/21 12:22:45 mrg Exp $ */
/*
* Copyright (c) 1984,1985,1989,1994,1995,1996 Mark Nudelman
@ -36,6 +36,7 @@
#include "less.h"
#if MSDOS_COMPILER==WIN32C
#include <errno.h>
#include <windows.h>
#endif
public int ignore_eoi;
@ -250,6 +251,10 @@ fch_get()
ierror("Waiting for data", NULL_PARG);
#if !MSDOS_COMPILER
sleep(1);
#else
#if MSDOS_COMPILER==WIN32C
Sleep(1000);
#endif
#endif
slept = TRUE;
}
@ -672,6 +677,17 @@ ch_delbufs()
seekable(f)
int f;
{
#if MSDOS_COMPILER
extern int fd0;
if (f == fd0 && !isatty(fd0))
{
/*
* In MS-DOS, pipes are seekable. Check for
* standard input, and pretend it is not seekable.
*/
return (0);
}
#endif
return (lseek(f, (off_t)1, 0) != BAD_LSEEK);
}
@ -707,8 +723,8 @@ ch_init(f, flags)
/*
* Try to seek; set CH_CANSEEK if it works.
*/
if (!(flags & CH_HELPFILE) && seekable(f))
ch_flags |= CH_CANSEEK;
if ((flags & CH_CANSEEK) && !seekable(f))
ch_flags &= ~CH_CANSEEK;
set_filestate(curr_ifile, (void *) thisfile);
}
if (thisfile->file == -1)

View File

@ -1,4 +1,4 @@
/* $NetBSD: charset.c,v 1.1.1.2 1997/04/22 13:45:28 mrg Exp $ */
/* $NetBSD: charset.c,v 1.1.1.3 1997/09/21 12:22:58 mrg Exp $ */
/*
* Copyright (c) 1984,1985,1989,1994,1995,1996 Mark Nudelman
@ -165,7 +165,7 @@ ilocale()
{
register int c;
setlocale(LC_CTYPE, "");
setlocale(LC_ALL, "");
for (c = 0; c < sizeof(chardef); c++)
{
if (isprint(c))
@ -249,7 +249,7 @@ init_charset()
*/
public int
binary_char(c)
int c;
unsigned char c;
{
c &= 0377;
return (chardef[c] & IS_BINARY_CHAR);

View File

@ -1,4 +1,4 @@
/* $NetBSD: cmd.h,v 1.1.1.2 1997/04/22 13:45:43 mrg Exp $ */
/* $NetBSD: cmd.h,v 1.1.1.3 1997/09/21 12:23:11 mrg Exp $ */
/*
* Copyright (c) 1984,1985,1989,1994,1995,1996 Mark Nudelman
@ -110,6 +110,7 @@
#define EC_B_COMPLETE 18
#define EC_LITERAL 19
#define EC_NOACTION 101
#define EC_UINVALID 102
/* Flags for editchar() */

View File

@ -1,4 +1,4 @@
/* $NetBSD: cmdbuf.c,v 1.1.1.2 1997/04/22 13:45:14 mrg Exp $ */
/* $NetBSD: cmdbuf.c,v 1.1.1.3 1997/09/21 12:22:46 mrg Exp $ */
/*
* Copyright (c) 1984,1985,1989,1994,1995,1996 Mark Nudelman
@ -60,6 +60,11 @@ static struct textlist tk_tlist;
static int cmd_left();
static int cmd_right();
#if SPACES_IN_FILENAMES
public char openquote = '"';
public char closequote = '"';
#endif
#if CMD_HISTORY
/*
* A mlist structure represents a command history.
@ -307,7 +312,6 @@ cmd_left()
cmd_ichar(c)
int c;
{
int col;
char *s;
if (strlen(cmdbuf) >= sizeof(cmdbuf)-2)
@ -341,8 +345,6 @@ cmd_ichar(c)
cmd_erase()
{
register char *s;
char *p;
int col;
if (cp == cmdbuf)
{
@ -386,8 +388,6 @@ cmd_erase()
static int
cmd_delete()
{
char *p;
if (*cp == '\0')
{
/*
@ -499,7 +499,6 @@ set_mlist(mlist)
cmd_updown(action)
int action;
{
char *p;
char *s;
if (curr_mlist == NULL)
@ -535,6 +534,53 @@ cmd_updown(action)
}
#endif
/*
* Add a string to a history list.
*/
public void
cmd_addhist(mlist, cmd)
struct mlist *mlist;
char *cmd;
{
#if CMD_HISTORY
struct mlist *ml;
/*
* Don't save a trivial command.
*/
if (strlen(cmd) == 0)
return;
/*
* Don't save if a duplicate of a command which is already
* in the history.
* But select the one already in the history to be current.
*/
for (ml = mlist->next; ml != mlist; ml = ml->next)
{
if (strcmp(ml->string, cmd) == 0)
break;
}
if (ml == mlist)
{
/*
* Did not find command in history.
* Save the command and put it at the end of the history list.
*/
ml = (struct mlist *) ecalloc(1, sizeof(struct mlist));
ml->string = save(cmd);
ml->next = mlist;
ml->prev = mlist->prev;
mlist->prev->next = ml;
mlist->prev = ml;
}
/*
* Point to the cmd just after the just-accepted command.
* Thus, an UPARROW will always retrieve the previous command.
*/
mlist->curr_mp = ml->next;
#endif
}
/*
* Accept the command in the command buffer.
* Add it to the currently selected history list.
@ -543,45 +589,12 @@ cmd_updown(action)
cmd_accept()
{
#if CMD_HISTORY
struct mlist *ml;
/*
* Nothing to do if there is no currently selected history list.
*/
if (curr_mlist == NULL)
return;
/*
* Don't save a trivial command.
*/
if (strlen(cmdbuf) == 0)
return;
/*
* Don't save if a duplicate of a command which is already in the history.
* But select the one already in the history to be current.
*/
for (ml = curr_mlist->next; ml != curr_mlist; ml = ml->next)
{
if (strcmp(ml->string, cmdbuf) == 0)
break;
}
if (ml == curr_mlist)
{
/*
* Did not find command in history.
* Save the command and put it at the end of the history list.
*/
ml = (struct mlist *) ecalloc(1, sizeof(struct mlist));
ml->string = save(cmdbuf);
ml->next = curr_mlist;
ml->prev = curr_mlist->prev;
curr_mlist->prev->next = ml;
curr_mlist->prev = ml;
}
/*
* Point to the cmd just after the just-accepted command.
* Thus, an UPARROW will always retrieve the previous command.
*/
curr_mlist->curr_mp = ml->next;
cmd_addhist(curr_mlist, cmdbuf);
#endif
}
@ -693,6 +706,8 @@ cmd_edit(c)
case EC_EXPAND:
return (cmd_complete(action));
#endif
case EC_NOACTION:
return (CC_OK);
default:
not_in_completion();
return (CC_PASS);
@ -732,6 +747,10 @@ cmd_istr(str)
delimit_word()
{
char *word;
#if SPACES_IN_FILENAMES
char *p;
int quoted;
#endif
/*
* Move cursor to end of word.
@ -764,6 +783,27 @@ delimit_word()
*/
if (cp == cmdbuf)
return (NULL);
#if SPACES_IN_FILENAMES
/*
* If we have an unbalanced quote (that is, an open quote
* without a corresponding close quote), we return everything
* from the open quote, including spaces.
*/
quoted = 0;
for (p = cmdbuf; p < cp; p++)
{
if (!quoted && *p == openquote)
{
quoted = 1;
word = p;
} else if (quoted && *p == closequote)
{
quoted = 0;
}
}
if (quoted)
return (word);
#endif
for (word = cp-1; word > cmdbuf; word--)
if (word[-1] == ' ')
break;
@ -814,6 +854,10 @@ init_compl()
*/
c = *cp;
*cp = '\0';
#if SPACES_IN_FILENAMES
if (*word == openquote)
word++;
#endif
tk_text = fcomplete(word);
*cp = c;
}
@ -847,6 +891,7 @@ next_compl(action, prev)
cmd_complete(action)
int action;
{
char *s;
if (!in_completion || action == EC_EXPAND)
{
@ -907,6 +952,19 @@ cmd_complete(action)
*/
if (cmd_istr(tk_trial) != CC_OK)
goto fail;
/*
* If it is a directory, append a slash.
*/
if (is_dir(tk_trial))
{
if (cp > cmdbuf && cp[-1] == closequote)
(void) cmd_erase();
s = lgetenv("LESSSEPARATOR");
if (s == NULL)
s = PATHNAME_SEP;
if (cmd_istr(s) != CC_OK)
goto fail;
}
}
return (CC_OK);
@ -961,10 +1019,7 @@ cmd_char(c)
/*
* Insert the char into the command buffer.
*/
action = cmd_ichar(c);
if (action != CC_OK)
return (action);
return (CC_OK);
return (cmd_ichar(c));
}
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: decode.c,v 1.1.1.2 1997/04/22 13:45:44 mrg Exp $ */
/* $NetBSD: decode.c,v 1.1.1.3 1997/09/21 12:23:12 mrg Exp $ */
/*
* Copyright (c) 1984,1985,1989,1994,1995,1996 Mark Nudelman
@ -102,6 +102,8 @@ static unsigned char cmdtable[] =
'%',0, A_PERCENT,
ESC,'[',0, A_LSHIFT,
ESC,']',0, A_RSHIFT,
ESC,'(',0, A_LSHIFT,
ESC,')',0, A_RSHIFT,
'{',0, A_F_BRACKET|A_EXTRA, '{','}',0,
'}',0, A_B_BRACKET|A_EXTRA, '{','}',0,
'(',0, A_F_BRACKET|A_EXTRA, '(',')',0,
@ -547,7 +549,9 @@ lesskey(filename)
/*
* Try to open the lesskey file.
*/
filename = unquote_file(filename);
f = open(filename, OPEN_READ);
free(filename);
if (f < 0)
return (1);
@ -606,7 +610,9 @@ add_hometable()
char *filename;
PARG parg;
if ((filename = lgetenv("LESSKEY")) == NULL)
if ((filename = lgetenv("LESSKEY")) != NULL)
filename = save(filename);
else
filename = homefile(LESSKEYFILE);
if (filename == NULL)
return;

View File

@ -1,4 +1,4 @@
/* $NetBSD: defines.h,v 1.1.1.2 1997/04/22 13:45:15 mrg Exp $ */
/* $NetBSD: defines.h,v 1.1.1.3 1997/09/21 12:22:47 mrg Exp $ */
/* defines.h. Generated automatically by configure. */
/* defines.h.in. Generated automatically from configure.in by autoheader. */
@ -133,11 +133,6 @@
*/
/* #undef HAVE_SGSTAT_H */
/*
* HAVE_STAT is 1 if your system has the stat() call.
*/
#define HAVE_STAT 1
/*
* HAVE_PERROR is 1 if your system has the perror() call.
* (Actually, if it has sys_errlist, sys_nerr and errno.)
@ -154,6 +149,12 @@
*/
#define HAVE_SHELL 1
/*
* Default shell metacharacters and meta-escape character.
*/
#define DEF_METACHARS "; \t\n'\"()<>|&^`\\"
#define DEF_METAESCAPE "\\"
/*
* HAVE_DUP is 1 if your system has the dup() call.
*/
@ -245,9 +246,15 @@
/* Define if you have the memcpy function. */
#define HAVE_MEMCPY 1
/* Define if you have the popen function. */
#define HAVE_POPEN 1
/* Define if you have the sigsetmask function. */
#define HAVE_SIGSETMASK 1
/* Define if you have the stat function. */
#define HAVE_STAT 1
/* Define if you have the strchr function. */
#define HAVE_STRCHR 1

View File

@ -1,4 +1,4 @@
/* $NetBSD: edit.c,v 1.1.1.2 1997/04/22 13:45:45 mrg Exp $ */
/* $NetBSD: edit.c,v 1.1.1.3 1997/09/21 12:23:13 mrg Exp $ */
/*
* Copyright (c) 1984,1985,1989,1994,1995,1996 Mark Nudelman
@ -38,9 +38,15 @@ extern char *every_first_cmd;
extern int any_display;
extern int force_open;
extern int is_tty;
extern int sigs;
extern IFILE curr_ifile;
extern IFILE old_ifile;
extern struct scrpos initial_scrpos;
extern void constant *ml_examine;
#if SPACES_IN_FILENAMES
extern char openquote;
extern char closequote;
#endif
#if LOGFILE
extern int logfile;
@ -65,13 +71,25 @@ init_textlist(tlist, str)
char *str;
{
char *s;
#if SPACES_IN_FILENAMES
int quoted = 0;
#endif
tlist->string = skipsp(str);
tlist->endstring = tlist->string + strlen(tlist->string);
for (s = str; s < tlist->endstring; s++)
{
#if SPACES_IN_FILENAMES
if (*s == ' ' && !quoted)
*s = '\0';
if (!quoted && *s == openquote)
quoted = 1;
else if (quoted && *s == closequote)
quoted = 0;
#else
if (*s == ' ')
*s = '\0';
#endif
}
}
@ -132,6 +150,7 @@ back_textlist(tlist, prev)
close_file()
{
struct scrpos scrpos;
char *filename;
if (curr_ifile == NULL_IFILE)
return;
@ -156,8 +175,9 @@ close_file()
*/
if (curr_altfilename != NULL)
{
close_altfile(curr_altfilename, get_filename(curr_ifile),
curr_altpipe);
filename = unquote_file(get_filename(curr_ifile));
close_altfile(curr_altfilename, filename, curr_altpipe);
free(filename);
free(curr_altfilename);
curr_altfilename = NULL;
}
@ -215,12 +235,12 @@ edit_ifile(ifile)
#if LOGFILE
end_logfile();
#endif
was_curr_ifile = curr_ifile;
was_curr_ifile = save_curr_ifile();
if (curr_ifile != NULL_IFILE)
{
chflags = ch_getflags();
close_file();
if (chflags & CH_HELPFILE)
if ((chflags & CH_HELPFILE) && held_ifile(was_curr_ifile) <= 1)
{
/*
* Don't keep the help file in the ifile list.
@ -238,10 +258,11 @@ edit_ifile(ifile)
* you're supposed to have saved curr_ifile yourself,
* and you'll restore it if necessary.)
*/
unsave_ifile(was_curr_ifile);
return (0);
}
filename = get_filename(ifile);
filename = unquote_file(get_filename(ifile));
/*
* See if LESSOPEN specifies an "alternate" file to open.
*/
@ -268,14 +289,17 @@ edit_ifile(ifile)
*/
f = fd0;
chflags |= CH_KEEPOPEN;
#if MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==WIN32C
/*
* Must switch stdin to BINARY mode.
*/
setmode(f, O_BINARY);
#endif
#if MSDOS_COMPILER==MSOFTC
_setmode(f, _O_BINARY);
SET_BINARY(f);
#if MSDOS_COMPILER==DJGPPC
/*
* Setting stdin to binary by default causes
* Ctrl-C to not raise SIGINT. We must undo
* that side-effect.
*/
__djgpp_set_ctrl_c(1);
#endif
} else if (strcmp(open_filename, FAKE_HELPFILE) == 0)
{
@ -295,10 +319,11 @@ edit_ifile(ifile)
free(alt_filename);
}
del_ifile(ifile);
free(filename);
/*
* Re-open the current file.
*/
(void) edit_ifile(was_curr_ifile);
reedit_ifile(was_curr_ifile);
return (1);
} else if ((f = open(open_filename, OPEN_READ)) < 0)
{
@ -309,18 +334,23 @@ edit_ifile(ifile)
error("%s", &parg);
free(parg.p_string);
goto err1;
} else if (!force_open && !opened(ifile) && bin_file(f))
} else
{
/*
* Looks like a binary file. Ask user if we should proceed.
*/
parg.p_string = filename;
answer = query("\"%s\" may be a binary file. See it anyway? ",
&parg);
if (answer != 'y' && answer != 'Y')
chflags |= CH_CANSEEK;
if (!force_open && !opened(ifile) && bin_file(f))
{
close(f);
goto err1;
/*
* Looks like a binary file.
* Ask user if we should proceed.
*/
parg.p_string = filename;
answer = query("\"%s\" may be a binary file. See it anyway? ",
&parg);
if (answer != 'y' && answer != 'Y')
{
close(f);
goto err1;
}
}
}
@ -329,7 +359,10 @@ edit_ifile(ifile)
* Get the saved position for the file.
*/
if (was_curr_ifile != NULL_IFILE)
{
old_ifile = was_curr_ifile;
unsave_ifile(was_curr_ifile);
}
curr_ifile = ifile;
curr_altfilename = alt_filename;
curr_altpipe = alt_pipe;
@ -366,6 +399,7 @@ edit_ifile(ifile)
#if HILITE_SEARCH
clr_hilite();
#endif
cmd_addhist(ml_examine, filename);
if (no_display && errmsgs > 0)
{
/*
@ -378,6 +412,7 @@ edit_ifile(ifile)
error("%s", &parg);
}
}
free(filename);
return (0);
}
@ -390,7 +425,7 @@ edit_ifile(ifile)
edit_list(filelist)
char *filelist;
{
IFILE save_curr_ifile;
IFILE save_ifile;
char *good_filename;
char *filename;
char *gfilelist;
@ -398,7 +433,7 @@ edit_list(filelist)
struct textlist tl_files;
struct textlist tl_gfiles;
save_curr_ifile = curr_ifile;
save_ifile = save_curr_ifile();
good_filename = NULL;
/*
@ -425,13 +460,19 @@ edit_list(filelist)
* Edit the first valid filename in the list.
*/
if (good_filename == NULL)
{
unsave_ifile(save_ifile);
return (1);
}
if (get_ifile(good_filename, curr_ifile) == curr_ifile)
{
/*
* Trying to edit the current file; don't reopen it.
*/
unsave_ifile(save_ifile);
return (0);
reedit_ifile(save_curr_ifile);
}
reedit_ifile(save_ifile);
return (edit(good_filename));
}
@ -457,12 +498,13 @@ edit_last()
/*
* Edit the next file in the command line (ifile) list.
* Edit the next or previous file in the command line (ifile) list.
*/
static int
edit_inext(h, n)
edit_istep(h, n, dir)
IFILE h;
int n;
int dir;
{
IFILE next;
@ -471,7 +513,7 @@ edit_inext(h, n)
*/
for (;;)
{
next = next_ifile(h);
next = (dir > 0) ? next_ifile(h) : prev_ifile(h);
if (--n < 0)
{
if (edit_ifile(h) == 0)
@ -484,46 +526,11 @@ edit_inext(h, n)
*/
return (1);
}
h = next;
}
/*
* Found a file that we can edit.
*/
return (0);
}
public int
edit_next(n)
int n;
{
return edit_inext(curr_ifile, n);
}
/*
* Edit the previous file in the command line list.
*/
static int
edit_iprev(h, n)
IFILE h;
int n;
{
IFILE next;
/*
* Skip n filenames, then try to edit each filename.
*/
for (;;)
{
next = prev_ifile(h);
if (--n < 0)
{
if (edit_ifile(h) == 0)
break;
}
if (next == NULL_IFILE)
if (ABORT_SIGS())
{
/*
* Reached beginning of the ifile list.
* Interrupt breaks out, if we're in a long
* list of files that can't be opened.
*/
return (1);
}
@ -535,11 +542,34 @@ edit_iprev(h, n)
return (0);
}
static int
edit_inext(h, n)
IFILE h;
int n;
{
return (edit_istep(h, n, 1));
}
public int
edit_next(n)
int n;
{
return edit_istep(curr_ifile, n, 1);
}
static int
edit_iprev(h, n)
IFILE h;
int n;
{
return (edit_istep(h, n, -1));
}
public int
edit_prev(n)
int n;
{
return edit_iprev(curr_ifile, n);
return edit_istep(curr_ifile, n, -1);
}
/*
@ -566,6 +596,22 @@ edit_index(n)
return (edit_ifile(h));
}
public IFILE
save_curr_ifile()
{
if (curr_ifile != NULL_IFILE)
hold_ifile(curr_ifile, 1);
return (curr_ifile);
}
public void
unsave_ifile(save_ifile)
IFILE save_ifile;
{
if (save_ifile != NULL_IFILE)
hold_ifile(save_ifile, -1);
}
/*
* Reedit the ifile which was previously open.
*/
@ -582,6 +628,7 @@ reedit_ifile(save_ifile)
* in which case the ifile will be deleted from the list.
* So save the next and prev ifiles first.
*/
unsave_ifile(save_ifile);
next = next_ifile(save_ifile);
prev = prev_ifile(save_ifile);
if (edit_ifile(save_ifile) == 0)
@ -658,6 +705,7 @@ use_logfile(filename)
/*
* {{ We could use access() here. }}
*/
filename = unquote_file(filename);
exists = open(filename, OPEN_READ);
close(exists);
exists = (exists >= 0);
@ -705,6 +753,7 @@ loop:
/*
* Don't do anything.
*/
free(filename);
return;
case 'q':
quit(QUIT_OK);
@ -724,7 +773,11 @@ loop:
*/
parg.p_string = filename;
error("Cannot write to \"%s\"", &parg);
free(filename);
return;
}
free(filename);
SET_BINARY(logfile);
}
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: filename.c,v 1.1.1.2 1997/04/22 13:45:16 mrg Exp $ */
/* $NetBSD: filename.c,v 1.1.1.3 1997/09/21 12:22:47 mrg Exp $ */
/*
* Copyright (c) 1984,1985,1989,1994,1995,1996 Mark Nudelman
@ -33,11 +33,18 @@
*/
#include "less.h"
#include "lglob.h"
#if MSDOS_COMPILER
#include <dos.h>
#if MSDOS_COMPILER==WIN32C
#if MSDOS_COMPILER==WIN32C && !defined(_MSC_VER)
#include <dir.h>
#endif
#if MSDOS_COMPILER==DJGPPC
#include <glob.h>
#include <dir.h>
#include <limits.h>
#define _MAX_PATH PATH_MAX
#endif
#endif
#ifdef _OSK
#include <rbf.h>
@ -46,10 +53,49 @@
#endif
#endif
#if HAVE_STAT
#include <sys/stat.h>
#ifndef S_ISDIR
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
#ifndef S_ISREG
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#endif
#endif
extern int force_open;
extern int secure;
extern IFILE curr_ifile;
extern IFILE old_ifile;
#if SPACES_IN_FILENAMES
extern char openquote;
extern char closequote;
#endif
/*
* Remove quotes around a filename.
*/
public char *
unquote_file(str)
char *str;
{
#if SPACES_IN_FILENAMES
char *name;
char *p;
if (*str != openquote)
return (save(str));
name = (char *) ecalloc(strlen(str), sizeof(char));
strcpy(name, str+1);
p = name + strlen(name) - 1;
if (*p == closequote)
*p = '\0';
return (name);
#else
return (save(str));
#endif
}
/*
* Return a pathname that points to a specified file in a specified directory.
@ -61,6 +107,7 @@ dirfile(dirname, filename)
char *filename;
{
char *pathname;
char *qpathname;
int f;
if (dirname == NULL || *dirname == '\0')
@ -76,7 +123,8 @@ dirfile(dirname, filename)
/*
* Make sure the file exists.
*/
f = open(pathname, OPEN_READ);
qpathname = unquote_file(pathname);
f = open(qpathname, OPEN_READ);
if (f < 0)
{
free(pathname);
@ -85,6 +133,7 @@ dirfile(dirname, filename)
{
close(f);
}
free(qpathname);
return (pathname);
}
@ -116,7 +165,17 @@ homefile(filename)
* Look for the file anywhere on search path.
*/
pathname = (char *) calloc(_MAX_PATH, sizeof(char));
#if MSDOS_COMPILER==DJGPPC
{
char *res = searchpath(filename);
if (res == 0)
*pathname = '\0';
else
strcpy(pathname, res);
}
#else
_searchenv(filename, "PATH", pathname);
#endif
if (*pathname != '\0')
return (pathname);
free(pathname);
@ -169,8 +228,9 @@ fexpand(s)
*/
ifile = fchar_ifile(*fr);
if (ifile == NULL_IFILE)
return (save(s));
n += strlen(get_filename(ifile));
n++;
else
n += strlen(get_filename(ifile));
}
/*
* Else it is the first char in a string of
@ -201,8 +261,13 @@ fexpand(s)
} else if (fr[1] != *fr)
{
ifile = fchar_ifile(*fr);
strcpy(to, get_filename(ifile));
to += strlen(to);
if (ifile == NULL_IFILE)
*to++ = *fr;
else
{
strcpy(to, get_filename(ifile));
to += strlen(to);
}
}
break;
default:
@ -231,7 +296,7 @@ fcomplete(s)
/*
* Complete the filename "s" by globbing "s*".
*/
#if MSDOS_COMPILER
#if MSDOS_COMPILER && (MSDOS_COMPILER == MSOFTC || MSDOS_COMPILER == BORLANDC)
/*
* But in DOS, we have to glob "s*.*".
* But if the final component of the filename already has
@ -242,7 +307,7 @@ fcomplete(s)
{
char *slash;
for (slash = s+strlen(s)-1; slash > s; slash--)
if (*slash = *PATHNAME_SEP || *slash == '/')
if (*slash == *PATHNAME_SEP || *slash == '/')
break;
fpat = (char *) ecalloc(strlen(s)+4, sizeof(char));
if (strchr(slash, '.') == NULL)
@ -306,10 +371,11 @@ seek_filesize(f)
return ((POSITION) spos);
}
#if GLOB
#if HAVE_POPEN
FILE *popen();
/*
* Read a string from a file.
* Return a pointer to the string in memory.
@ -353,121 +419,360 @@ readfd(fd)
return (buf);
}
#if HAVE_SHELL
/*
* Get the shell's escape character.
*/
static char *
get_meta_escape()
{
char *s;
s = lgetenv("LESSMETAESCAPE");
if (s == NULL)
s = DEF_METAESCAPE;
return (s);
}
/*
* Is this a shell metacharacter?
*/
static int
metachar(c)
char c;
{
static char *metachars = NULL;
if (metachars == NULL)
{
metachars = lgetenv("LESSMETACHARS");
if (metachars == NULL)
metachars = DEF_METACHARS;
}
return (strchr(metachars, c) != NULL);
}
/*
* Insert a backslash before each metacharacter in a string.
*/
static char *
esc_metachars(s)
char *s;
{
char *p;
char *newstr;
int len;
char *esc;
int esclen;
/*
* Determine how big a string we need to allocate.
*/
esc = get_meta_escape();
esclen = strlen(esc);
len = 1; /* Trailing null byte */
for (p = s; *p != '\0'; p++)
{
len++;
if (metachar(*p))
{
if (*esc == '\0')
{
/*
* We've got a metachar, but this shell
* doesn't support escape chars. Give up.
*/
return (NULL);
}
/*
* Allow space for the escape char.
*/
len += esclen;
}
}
/*
* Allocate and construct the new string.
*/
newstr = p = (char *) ecalloc(len, sizeof(char));
while (*s != '\0')
{
if (metachar(*s))
{
/*
* Add the escape char.
*/
strcpy(p, esc);
p += esclen;
}
*p++ = *s++;
}
*p = '\0';
return (newstr);
}
#else /* HAVE_SHELL */
static char *
esc_metachars(s)
char *s;
{
return (save(s));
}
#endif /* HAVE_SHELL */
/*
* Execute a shell command.
* Return a pointer to a pipe connected to the shell command's standard output.
*/
static FILE *
shellcmd(cmd, s1, s2)
shellcmd(cmd)
char *cmd;
char *s1;
char *s2;
{
char *scmd;
char *shell;
FILE *fd;
int len;
len = strlen(cmd) +
(s1 == NULL ? 0 : strlen(s1)) +
(s2 == NULL ? 0 : strlen(s2)) + 1;
scmd = (char *) ecalloc(len, sizeof(char));
sprintf(scmd, cmd, s1, s2);
#if HAVE_SHELL
char *shell;
shell = lgetenv("SHELL");
if (shell != NULL && *shell != '\0')
{
char *scmd;
char *esccmd;
/*
* Read the output of <$SHELL -c "cmd">.
* Try to escape any metacharacters in the command.
* If we can't do that, just put the command in quotes.
* (But that doesn't work well if the command itself
* contains quotes.)
*/
char *scmd2;
scmd2 = (char *) ecalloc(strlen(shell) + strlen(scmd) + 7,
sizeof(char));
sprintf(scmd2, "%s -c \"%s\"", shell, scmd);
if ((esccmd = esc_metachars(cmd)) == NULL)
{
/*
* Cannot escape the metacharacters, so use quotes.
* Read the output of <$SHELL -c "cmd">.
*/
scmd = (char *) ecalloc(strlen(shell) + strlen(cmd) + 7,
sizeof(char));
sprintf(scmd, "%s -c \"%s\"", shell, cmd);
} else
{
/*
* Read the output of <$SHELL -c cmd>.
* No quotes; use the escaped cmd.
*/
scmd = (char *) ecalloc(strlen(shell) + strlen(esccmd) + 5,
sizeof(char));
sprintf(scmd, "%s -c %s", shell, esccmd);
free(esccmd);
}
fd = popen(scmd, "r");
free(scmd);
scmd = scmd2;
}
} else
#endif
fd = popen(scmd, "r");
free(scmd);
{
fd = popen(cmd, "r");
/*
* Redirection in `popen' might have messed with the
* standard devices. Restore binary input mode.
*/
SET_BINARY(0);
}
return (fd);
}
#endif /* HAVE_POPEN */
/*
* Expand a filename, doing any shell-level substitutions.
* Expand a filename, doing any system-specific metacharacter substitutions.
*/
public char *
lglob(filename)
char *filename;
{
char *gfilename;
char *ofilename;
filename = fexpand(filename);
ofilename = fexpand(filename);
if (secure)
return (filename);
#if OS2
{
char **list;
int cnt;
int length;
return (ofilename);
filename = unquote_file(ofilename);
list = _fnexplode(filename);
if (list == NULL)
return (filename);
length = 1; /* Room for trailing null byte */
for (cnt = 0; list[cnt] != NULL; cnt++)
length += strlen(list[cnt]) + 1;
gfilename = (char *) ecalloc(length, sizeof(char));
for (cnt = 0; list[cnt] != NULL; cnt++)
#ifdef DECL_GLOB_LIST
{
/*
* The globbing function returns a list of names.
*/
int length;
char *p;
DECL_GLOB_LIST(list)
GLOB_LIST(filename, list);
if (GLOB_LIST_FAILED(list))
{
strcat(gfilename, list[cnt]);
strcat(gfilename, " ");
free(filename);
return (ofilename);
}
_fnexplodefree(list);
length = 1; /* Room for trailing null byte */
for (SCAN_GLOB_LIST(list, p))
{
INIT_GLOB_LIST(list, p);
length += strlen(p) + 1;
#if SPACES_IN_FILENAMES
if (strchr(p, ' ') != NULL)
length += 2; /* Allow for quotes */
#endif
}
gfilename = (char *) ecalloc(length, sizeof(char));
for (SCAN_GLOB_LIST(list, p))
{
INIT_GLOB_LIST(list, p);
#if SPACES_IN_FILENAMES
if (strchr(p, ' ') != NULL)
sprintf(gfilename + strlen(gfilename), "%c%s%c ",
openquote, p, closequote);
else
#endif
sprintf(gfilename + strlen(gfilename), "%s ", p);
}
/*
* Overwrite the final trailing space with a null terminator.
*/
*--p = '\0';
GLOB_LIST_DONE(list);
}
#else
#ifdef DECL_GLOB_NAME
{
FILE *fd;
char *s;
/*
* We get the shell to expand the filename for us by passing
* an "echo" command to the shell and reading its output.
* The globbing function returns a single name, and
* is called multiple times to walk thru all names.
*/
/*
* Certain characters will cause problems if passed to the shell,
* so we disallow them.
* {{ This presumes too much knowlege about the shell, but not
* doing this can cause serious problems. For example, do
* "!;TAB" when the first file in the dir is named "rm". }}
*/
for (s = filename; *s != '\0'; s++)
register char *p;
register int len;
register int n;
#if SPACES_IN_FILENAMES
register int spaces_in_file;
#endif
DECL_GLOB_NAME(fnd,drive,dir,fname,ext,handle)
GLOB_FIRST_NAME(filename, &fnd, handle);
if (GLOB_FIRST_FAILED(handle))
{
if (*s == ';' || *s == '\'' || *s == '\"' || *s == '\\')
return (filename);
free(filename);
return (ofilename);
}
fd = shellcmd("echo %s", filename, (char*)NULL);
_splitpath(filename, drive, dir, fname, ext);
len = 100;
gfilename = (char *) ecalloc(len, sizeof(char));
p = gfilename;
do {
n = strlen(drive) + strlen(dir) + strlen(fnd.GLOB_NAME) + 1;
#if SPACES_IN_FILENAMES
spaces_in_file = 0;
if (strchr(fnd.GLOB_NAME, ' ') != NULL ||
strchr(filename, ' ') != NULL)
{
spaces_in_file = 1;
n += 2;
}
#endif
while (p - gfilename + n+2 >= len)
{
/*
* No room in current buffer. Allocate a bigger one.
*/
len *= 2;
*p = '\0';
p = (char *) ecalloc(len, sizeof(char));
strcpy(p, gfilename);
free(gfilename);
gfilename = p;
p = gfilename + strlen(gfilename);
}
#if SPACES_IN_FILENAMES
if (spaces_in_file)
sprintf(p, "%c%s%s%s%c ", openquote,
drive, dir, fnd.GLOB_NAME, closequote);
else
#endif
sprintf(p, "%s%s%s ", drive, dir, fnd.GLOB_NAME);
p += n;
} while (GLOB_NEXT_NAME(handle, &fnd) == 0);
/*
* Overwrite the final trailing space with a null terminator.
*/
*--p = '\0';
GLOB_NAME_DONE(handle);
}
#else
#if HAVE_POPEN
{
/*
* We get the shell to glob the filename for us by passing
* an "echo" command to the shell and reading its output.
*/
FILE *fd;
char *s;
char *lessecho;
char *cmd;
lessecho = lgetenv("LESSECHO");
if (lessecho == NULL || *lessecho == '\0')
lessecho = "lessecho";
s = esc_metachars(filename);
if (s == NULL)
{
/*
* There may be dangerous metachars in this name.
* We can't risk passing it to the shell.
* {{ For example, do "!;TAB" when the first file
* in the dir is named "rm". }}
*/
free(filename);
return (ofilename);
}
/*
* Invoke lessecho, and read its output (a globbed list of filenames).
*/
cmd = (char *) ecalloc(strlen(lessecho) + strlen(s) + 24, sizeof(char));
sprintf(cmd, "%s -p0x%x -d0x%x -- %s",
lessecho, openquote, closequote, s);
fd = shellcmd(cmd);
free(s);
free(cmd);
if (fd == NULL)
{
/*
* Cannot create the pipe.
* Just return the original (fexpanded) filename.
*/
return (filename);
free(filename);
return (ofilename);
}
gfilename = readfd(fd);
pclose(fd);
if (*gfilename == '\0')
{
free(gfilename);
return (filename);
free(filename);
return (ofilename);
}
free(filename);
}
#else
/*
* No globbing functions at all. Just use the fexpanded filename.
*/
gfilename = save(filename);
#endif
#endif
#endif
free(filename);
free(ofilename);
return (gfilename);
}
@ -481,8 +786,12 @@ open_altfile(filename, pf, pfd)
int *pf;
void **pfd;
{
#if !HAVE_POPEN
return (NULL);
#else
char *lessopen;
char *gfilename;
char *cmd;
FILE *fd;
#if HAVE_FILENO
int returnfd = 0;
@ -509,7 +818,21 @@ open_altfile(filename, pf, pfd)
return (NULL);
#endif
}
fd = shellcmd(lessopen, filename, (char*)NULL);
gfilename = esc_metachars(filename);
if (gfilename == NULL)
{
/*
* Cannot escape metacharacters.
*/
return (NULL);
}
cmd = (char *) ecalloc(strlen(lessopen) + strlen(gfilename) + 2,
sizeof(char));
sprintf(cmd, lessopen, gfilename);
fd = shellcmd(cmd);
free(gfilename);
free(cmd);
if (fd == NULL)
{
/*
@ -528,6 +851,7 @@ open_altfile(filename, pf, pfd)
* If it does, push the char back on the pipe.
*/
f = fileno(fd);
SET_BINARY(f);
if (read(f, &c, 1) != 1)
{
/*
@ -550,6 +874,7 @@ open_altfile(filename, pf, pfd)
*/
return (NULL);
return (gfilename);
#endif /* HAVE_POPEN */
}
/*
@ -561,8 +886,12 @@ close_altfile(altfilename, filename, pipefd)
char *filename;
void *pipefd;
{
#if HAVE_POPEN
char *lessclose;
char *gfilename;
char *galtfilename;
FILE *fd;
char *cmd;
if (secure)
return;
@ -570,142 +899,62 @@ close_altfile(altfilename, filename, pipefd)
pclose((FILE*) pipefd);
if ((lessclose = lgetenv("LESSCLOSE")) == NULL)
return;
fd = shellcmd(lessclose, filename, altfilename);
pclose(fd);
gfilename = esc_metachars(filename);
if (gfilename == NULL)
{
return;
}
galtfilename = esc_metachars(altfilename);
if (galtfilename == NULL)
{
free(gfilename);
return;
}
cmd = (char *) ecalloc(strlen(lessclose) + strlen(gfilename) +
strlen(galtfilename) + 2, sizeof(char));
sprintf(cmd, lessclose, gfilename, galtfilename);
fd = shellcmd(cmd);
free(galtfilename);
free(gfilename);
free(cmd);
if (fd != NULL)
pclose(fd);
#endif
}
#else
#if MSDOS_COMPILER
/*
* Define macros for the MS-DOS "find file" interfaces.
* Is the specified file a directory?
*/
#if MSDOS_COMPILER==WIN32C
#define FIND_FIRST(filename,fndp) findfirst(filename, fndp, ~0)
#define FIND_NEXT(fndp) findnext(fndp)
#define FND_NAME ff_name
#define DECLARE_FIND(fnd,drive,dir,fname,ext) \
struct ffblk fnd; \
char drive[MAXDRIVE]; \
char dir[MAXDIR]; \
char fname[MAXFILE]; \
char ext[MAXEXT];
#else
#define FIND_FIRST(filename,fndp) _dos_findfirst(filename, ~0, fndp)
#define FIND_NEXT(fndp) _dos_findnext(fndp)
#define FND_NAME name
#define DECLARE_FIND(fnd,drive,dir,fname,ext) \
struct find_t fnd; \
char drive[_MAX_DRIVE]; \
char dir[_MAX_DIR]; \
char fname[_MAX_FNAME]; \
char ext[_MAX_EXT];
#endif
public char *
lglob(filename)
public int
is_dir(filename)
char *filename;
{
register char *gfilename;
register char *p;
register int len;
register int n;
DECLARE_FIND(fnd,drive,dir,fname,ext)
filename = fexpand(filename);
if (secure)
return (filename);
if (FIND_FIRST(filename, &fnd) != 0)
return (filename);
_splitpath(filename, drive, dir, fname, ext);
len = 100;
gfilename = (char *) ecalloc(len, sizeof(char));
p = gfilename;
do {
n = strlen(drive) + strlen(dir) + strlen(fnd.FND_NAME);
while (p - gfilename + n+2 >= len)
{
/*
* No room in current buffer. Allocate a bigger one.
*/
len *= 2;
*p = '\0';
p = (char *) ecalloc(len, sizeof(char));
strcpy(p, gfilename);
free(gfilename);
gfilename = p;
p = gfilename + strlen(gfilename);
}
sprintf(p, "%s%s%s", drive, dir, fnd.FND_NAME);
p += n;
*p++ = ' ';
} while (FIND_NEXT(&fnd) == 0);
/*
* Overwrite the final trailing space with a null terminator.
*/
*--p = '\0';
return (gfilename);
}
public char *
open_altfile(filename)
char *filename;
{
return (NULL);
}
public void
close_altfile(altfilename, filename)
char *altfilename;
char *filename;
{
}
#else
public char *
lglob(filename)
char *filename;
{
return (fexpand(filename));
}
public char *
open_altfile(filename)
char *filename;
{
return (NULL);
}
public void
close_altfile(altfilename, filename)
char *altfilename;
char *filename;
{
}
#endif
#endif
int isdir = 0;
filename = unquote_file(filename);
#if HAVE_STAT
{
int r;
struct stat statbuf;
#include <sys/stat.h>
#ifndef S_ISDIR
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
r = stat(filename, &statbuf);
isdir = (r >= 0 && S_ISDIR(statbuf.st_mode));
}
#else
#ifdef _OSK
{
register int f;
f = open(filename, S_IREAD | S_IFDIR);
if (f >= 0)
close(f);
isdir = (f >= 0);
}
#endif
#ifndef S_ISREG
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#endif
free(filename);
return (isdir);
}
/*
* Returns NULL if the file can be opened and
@ -716,35 +965,42 @@ close_altfile(altfilename, filename)
bad_file(filename)
char *filename;
{
register char *m;
struct stat statbuf;
register char *m = NULL;
if (stat(filename, &statbuf) < 0)
return (errno_message(filename));
if (force_open)
return (NULL);
if (S_ISDIR(statbuf.st_mode))
filename = unquote_file(filename);
if (is_dir(filename))
{
static char is_dir[] = " is a directory";
m = (char *) ecalloc(strlen(filename) + sizeof(is_dir),
sizeof(char));
strcpy(m, filename);
strcat(m, is_dir);
return (m);
}
if (!S_ISREG(statbuf.st_mode))
} else
{
static char not_reg[] = " is not a regular file";
m = (char *) ecalloc(strlen(filename) + sizeof(not_reg),
sizeof(char));
strcpy(m, filename);
strcat(m, not_reg);
return (m);
}
#if HAVE_STAT
int r;
struct stat statbuf;
return (NULL);
r = stat(filename, &statbuf);
if (r < 0)
{
m = errno_message(filename);
} else if (force_open)
{
m = NULL;
} else if (!S_ISREG(statbuf.st_mode))
{
static char not_reg[] = " is not a regular file (use -f to see it)";
m = (char *) ecalloc(strlen(filename) + sizeof(not_reg),
sizeof(char));
strcpy(m, filename);
strcat(m, not_reg);
}
#endif
}
free(filename);
return (m);
}
/*
@ -755,81 +1011,20 @@ bad_file(filename)
filesize(f)
int f;
{
#if HAVE_STAT
struct stat statbuf;
if (fstat(f, &statbuf) < 0)
/*
* Can't stat; try seeking to the end.
*/
return (seek_filesize(f));
return ((POSITION) statbuf.st_size);
}
if (fstat(f, &statbuf) >= 0)
return ((POSITION) statbuf.st_size);
#else
#ifdef _OSK
public char *
bad_file(filename)
char *filename;
{
register int f;
register char *m;
if ((f = open(filename, S_IREAD | S_IFDIR)) >= 0)
{
static char is_dir[] = " is a directory";
close(f);
if (force_open)
return (NULL);
m = (char *) ecalloc(strlen(filename) + sizeof(is_dir),
sizeof(char));
strcpy(m, filename);
strcat(m, is_dir);
return (m);
}
if ((f = open(filename, S_IREAD)) < 0)
return (errno_message(filename));
close(f);
return (NULL);
}
public POSITION
filesize(f)
int f;
{
long size;
if ((size = (long)_gs_size(f)) < 0)
/*
* Can't stat; try seeking to the end.
*/
return (seek_filesize(f));
return ((POSITION) size);
}
if ((size = (long) _gs_size(f)) >= 0)
return ((POSITION) size);
#else
/*
* If we have no way to find out, just say the file is good.
*/
public char *
bad_file(filename)
char *filename;
{
return (NULL);
}
/*
* We can find the file size by seeking.
*/
public POSITION
filesize(f)
int f;
{
return (seek_filesize(f));
#endif
#endif
}
#endif
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: funcs.h,v 1.1.1.2 1997/04/22 13:45:46 mrg Exp $ */
/* $NetBSD: funcs.h,v 1.1.1.3 1997/09/21 12:23:14 mrg Exp $ */
public void strtcpy ();
public char * save ();
@ -13,7 +13,9 @@
public void deinit ();
public void home ();
public void add_line ();
public void remove_top ();
public void lower_left ();
public void check_winch ();
public void goto_line ();
public void vbell ();
public void bell ();
@ -58,6 +60,7 @@
public void cmd_putstr ();
public int len_cmdbuf ();
public void set_mlist ();
public void cmd_addhist ();
public void cmd_accept ();
public int cmd_char ();
public int cmd_int ();
@ -90,10 +93,13 @@
public int edit_next ();
public int edit_prev ();
public int edit_index ();
public IFILE save_curr_ifile ();
public void unsave_ifile ();
public void reedit_ifile ();
public int edit_stdin ();
public void cat_file ();
public void use_logfile ();
public char * unquote_file ();
public char * homefile ();
public char * fexpand ();
public char * fcomplete ();
@ -101,16 +107,7 @@
public char * lglob ();
public char * open_altfile ();
public void close_altfile ();
public char * lglob ();
public char * open_altfile ();
public void close_altfile ();
public char * lglob ();
public char * open_altfile ();
public void close_altfile ();
public char * bad_file ();
public POSITION filesize ();
public char * bad_file ();
public POSITION filesize ();
public int is_dir ();
public char * bad_file ();
public POSITION filesize ();
public void forw ();
@ -130,6 +127,8 @@
public void get_pos ();
public void set_open ();
public int opened ();
public void hold_ifile ();
public int held_ifile ();
public void * get_filestate ();
public void set_filestate ();
public void if_dump ();
@ -175,6 +174,7 @@
public void opt_i ();
public void opt__V ();
public void opt_D ();
public void opt_quote ();
public void opt_query ();
public int get_swindow ();
public void scan_option ();
@ -229,6 +229,7 @@
public void init_signals ();
public void psignals ();
public void findtag ();
public int edit_tagfile ();
public POSITION tagsearch ();
public void open_getchr ();
public void close_getchr ();

View File

@ -1,4 +1,4 @@
/* $NetBSD: help.c,v 1.1.1.2 1997/04/22 13:45:17 mrg Exp $ */
/* $NetBSD: help.c,v 1.1.1.3 1997/09/21 12:22:48 mrg Exp $ */
/* This file was generated by mkhelp from less.hlp */
#include "less.h"
@ -21,8 +21,8 @@ constant char helpdata[] = {
' ',' ','E','S','C','-','S','P','A','C','E',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','F','o','r','w','a','r','d',' ',' ','o','n','e',' ','w','i','n','d','o','w',',',' ','b','u','t',' ','d','o','n','\'','t',' ','s','t','o','p',' ','a','t',' ','e','n','d','-','o','f','-','f','i','l','e','.','\n',
' ',' ','d',' ',' ','^','D',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','F','o','r','w','a','r','d',' ',' ','o','n','e',' ','h','a','l','f','-','w','i','n','d','o','w',' ','(','a','n','d',' ','s','e','t',' ','h','a','l','f','-','w','i','n','d','o','w',' ','t','o',' ','_','\b','N',')','.','\n',
' ',' ','u',' ',' ','^','U',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','B','a','c','k','w','a','r','d',' ','o','n','e',' ','h','a','l','f','-','w','i','n','d','o','w',' ','(','a','n','d',' ','s','e','t',' ','h','a','l','f','-','w','i','n','d','o','w',' ','t','o',' ','_','\b','N',')','.','\n',
' ',' ','E','S','C','-','[',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','L','e','f','t',' ',' ','8',' ','c','h','a','r','a','c','t','e','r',' ','p','o','s','i','t','i','o','n','s',' ','(','o','r',' ','_','\b','N',' ','p','o','s','i','t','i','o','n','s',')','.','\n',
' ',' ','E','S','C','-',']',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','R','i','g','h','t',' ','8',' ','c','h','a','r','a','c','t','e','r',' ','p','o','s','i','t','i','o','n','s',' ','(','o','r',' ','_','\b','N',' ','p','o','s','i','t','i','o','n','s',')','.','\n',
' ',' ','E','S','C','-','(',' ',' ','R','i','g','h','t','A','r','r','o','w',' ','*',' ',' ','L','e','f','t',' ',' ','8',' ','c','h','a','r','a','c','t','e','r',' ','p','o','s','i','t','i','o','n','s',' ','(','o','r',' ','_','\b','N',' ','p','o','s','i','t','i','o','n','s',')','.','\n',
' ',' ','E','S','C','-',')',' ',' ','L','e','f','t','A','r','r','o','w',' ',' ','*',' ',' ','R','i','g','h','t',' ','8',' ','c','h','a','r','a','c','t','e','r',' ','p','o','s','i','t','i','o','n','s',' ','(','o','r',' ','_','\b','N',' ','p','o','s','i','t','i','o','n','s',')','.','\n',
' ',' ','F',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','F','o','r','w','a','r','d',' ','f','o','r','e','v','e','r',';',' ','l','i','k','e',' ','"','t','a','i','l',' ','-','f','"','.','\n',
' ',' ','r',' ',' ','^','R',' ',' ','^','L',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','R','e','p','a','i','n','t',' ','s','c','r','e','e','n','.','\n',
' ',' ','R',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','R','e','p','a','i','n','t',' ','s','c','r','e','e','n',',',' ','d','i','s','c','a','r','d','i','n','g',' ','b','u','f','f','e','r','e','d',' ','i','n','p','u','t','.','\n',

View File

@ -1,4 +1,4 @@
/* $NetBSD: ifile.c,v 1.1.1.2 1997/04/22 13:45:30 mrg Exp $ */
/* $NetBSD: ifile.c,v 1.1.1.3 1997/09/21 12:23:01 mrg Exp $ */
/*
* Copyright (c) 1984,1985,1989,1994,1995,1996 Mark Nudelman
@ -48,7 +48,8 @@ struct ifile {
char *h_filename; /* Name of the file */
void *h_filestate; /* File state (used in ch.c) */
int h_index; /* Index within command line list */
int h_opened; /* Only need one bit */
int h_hold; /* Hold count */
char h_opened; /* Has this ifile been opened? */
struct scrpos h_scrpos; /* Saved position within the file */
};
@ -127,6 +128,8 @@ new_ifile(filename, prev)
p->h_filename = save(filename);
p->h_scrpos.pos = NULL_POSITION;
p->h_opened = 0;
p->h_hold = 0;
p->h_filestate = NULL;
link_ifile(p, prev);
return (p);
}
@ -306,6 +309,21 @@ opened(ifile)
return (int_ifile(ifile)->h_opened);
}
public void
hold_ifile(ifile, incr)
IFILE ifile;
int incr;
{
int_ifile(ifile)->h_hold += incr;
}
public int
held_ifile(ifile)
IFILE ifile;
{
return (int_ifile(ifile)->h_hold);
}
public void *
get_filestate(ifile)
IFILE ifile;

View File

@ -1,4 +1,4 @@
/* $NetBSD: input.c,v 1.1.1.2 1997/04/22 13:45:46 mrg Exp $ */
/* $NetBSD: input.c,v 1.1.1.3 1997/09/21 12:23:15 mrg Exp $ */
/*
* Copyright (c) 1984,1985,1989,1994,1995,1996 Mark Nudelman

View File

@ -1,4 +1,4 @@
/* $NetBSD: jump.c,v 1.1.1.2 1997/04/22 13:45:18 mrg Exp $ */
/* $NetBSD: jump.c,v 1.1.1.3 1997/09/21 12:22:50 mrg Exp $ */
/*
* Copyright (c) 1984,1985,1989,1994,1995,1996 Mark Nudelman

View File

@ -1,4 +1,4 @@
/* $NetBSD: less.h,v 1.1.1.2 1997/04/22 13:45:47 mrg Exp $ */
/* $NetBSD: less.h,v 1.1.1.3 1997/09/21 12:23:16 mrg Exp $ */
/*
* Copyright (c) 1984,1985,1989,1994,1995,1996 Mark Nudelman
@ -36,7 +36,8 @@
*/
#define MSOFTC 1 /* Microsoft C */
#define BORLANDC 2 /* Borland C */
#define WIN32C 3 /* Windows (Borland C) */
#define WIN32C 3 /* Windows (Borland C or Microsoft C) */
#define DJGPPC 4 /* DJGPP C */
/*
* Include the file of compile-time options.
@ -95,7 +96,7 @@
#include <modes.h>
#include <strings.h>
#endif
#if MSDOS_COMPILER==WIN32C
#if MSDOS_COMPILER==WIN32C || MSDOS_COMPILER==DJGPPC
#include <io.h>
#endif
@ -128,7 +129,7 @@ void free();
#define OPT_ON 1
#define OPT_ONPLUS 2
#ifndef HAVE_MEMCPY
#if !HAVE_MEMCPY
#ifndef memcpy
#define memcpy(to,from,len) bcopy((from),(to),(len))
#endif
@ -175,18 +176,30 @@ typedef long POSITION;
#endif
#endif
#if MSDOS_COMPILER || OS2
#define OPEN_TTYIN() open("CON", OPEN_READ)
/*
* Set a file descriptor to binary mode.
*/
#if MSDOS_COMPILER==MSOFTC
#define SET_BINARY(f) _setmode(f, _O_BINARY);
#else
#define OPEN_TTYIN() open("/dev/tty", OPEN_READ)
#if MSDOS_COMPILER
#define SET_BINARY(f) setmode(f, O_BINARY)
#else
#define SET_BINARY(f)
#endif
#endif
/*
* Does the shell treat "?" as a metacharacter?
*/
#if MSDOS_COMPILER || OS2 || _OSK
#define SHELL_META_QUEST 0
#else
#define SHELL_META_QUEST 1
#endif
#define SPACES_IN_FILENAMES 1
/*
* An IFILE represents an input file.
*/
@ -300,3 +313,4 @@ struct textlist
#define FAKE_HELPFILE "@/\\less/\\help/\\file/\\@"
#include "funcs.h"

View File

@ -1,4 +1,4 @@
/* $NetBSD: line.c,v 1.1.1.2 1997/04/22 13:45:19 mrg Exp $ */
/* $NetBSD: line.c,v 1.1.1.3 1997/09/21 12:22:51 mrg Exp $ */
/*
* Copyright (c) 1984,1985,1989,1994,1995,1996 Mark Nudelman

View File

@ -1,4 +1,4 @@
/* $NetBSD: linenum.c,v 1.1.1.2 1997/04/22 13:45:31 mrg Exp $ */
/* $NetBSD: linenum.c,v 1.1.1.3 1997/09/21 12:23:02 mrg Exp $ */
/*
* Copyright (c) 1984,1985,1989,1994,1995,1996 Mark Nudelman

View File

@ -1,4 +1,4 @@
/* $NetBSD: lsystem.c,v 1.1.1.2 1997/04/22 13:45:48 mrg Exp $ */
/* $NetBSD: lsystem.c,v 1.1.1.3 1997/09/21 12:23:17 mrg Exp $ */
/*
* Copyright (c) 1984,1985,1989,1994,1995,1996 Mark Nudelman
@ -38,6 +38,12 @@
#if MSDOS_COMPILER
#include <dos.h>
#ifdef _MSC_VER
#include <direct.h>
#define setdisk(n) _chdrive((n)+1)
#else
#include <dir.h>
#endif
#endif
extern int screen_trashed;
@ -56,9 +62,14 @@ lsystem(cmd, donemsg)
char *donemsg;
{
register int inp;
#if HAVE_SHELL
register char *shell;
register char *p;
#endif
IFILE save_ifile;
#if MSDOS_COMPILER
char cwd[FILENAME_MAX+1];
#endif
/*
* Print the command which is to be executed,
@ -74,10 +85,21 @@ lsystem(cmd, donemsg)
putstr("\n");
}
#if MSDOS_COMPILER
/*
* Working directory is global on MSDOS.
* The child might change the working directory, so we
* must save and restore CWD across calls to `system',
* or else we won't find our file when we return and
* try to `reedit_ifile' it.
*/
getcwd(cwd, FILENAME_MAX);
#endif
/*
* Close the current input file.
*/
save_ifile = curr_ifile;
save_ifile = save_curr_ifile();
(void) edit_ifile(NULL_IFILE);
/*
@ -86,6 +108,9 @@ lsystem(cmd, donemsg)
deinit();
flush(); /* Make sure the deinit chars get out */
raw_mode(0);
#if MSDOS_COMPILER==WIN32C
close_getchr();
#endif
/*
* Restore signals to their defaults.
@ -100,7 +125,7 @@ lsystem(cmd, donemsg)
*/
inp = dup(0);
close(0);
if (OPEN_TTYIN() < 0)
if (open("/dev/tty", OPEN_READ) < 0)
dup(inp);
#endif
@ -133,9 +158,19 @@ lsystem(cmd, donemsg)
system(p);
free(p);
#else
#if MSDOS_COMPILER==DJGPPC
/*
* We don't need to catch signals of the child (it
* also makes trouble with some DPMI servers).
*/
__djgpp_exception_toggle();
system(cmd);
__djgpp_exception_toggle();
#else
system(cmd);
#endif
#endif
#if HAVE_DUP
/*
@ -146,6 +181,9 @@ lsystem(cmd, donemsg)
close(inp);
#endif
#if MSDOS_COMPILER==WIN32C
open_getchr();
#endif
init_signals(1);
raw_mode(1);
if (donemsg != NULL)
@ -157,6 +195,27 @@ lsystem(cmd, donemsg)
init();
screen_trashed = 1;
#if MSDOS_COMPILER
/*
* Restore the previous directory (possibly
* changed by the child program we just ran).
*/
chdir(cwd);
#if MSDOS_COMPILER != DJGPPC
/*
* Some versions of chdir() don't change to the drive
* which is part of CWD. (DJGPP does this in chdir.)
*/
if (cwd[1] == ':')
{
if (cwd[0] >= 'a' && cwd[0] <= 'z')
setdisk(cwd[0] - 'a');
else if (cwd[0] >= 'A' && cwd[0] <= 'Z')
setdisk(cwd[0] - 'A');
}
#endif
#endif
/*
* Reopen the current input file.
*/
@ -259,6 +318,9 @@ pipe_data(cmd, spos, epos)
flush();
raw_mode(0);
init_signals(0);
#if MSDOS_COMPILER==WIN32C
close_getchr();
#endif
#ifdef SIGPIPE
LSIGNAL(SIGPIPE, SIG_IGN);
#endif
@ -292,6 +354,9 @@ pipe_data(cmd, spos, epos)
#ifdef SIGPIPE
LSIGNAL(SIGPIPE, SIG_DFL);
#endif
#if MSDOS_COMPILER==WIN32C
open_getchr();
#endif
init_signals(1);
raw_mode(1);
@ -308,91 +373,140 @@ pipe_data(cmd, spos, epos)
#ifdef _OSK
/*
* Popen, and Pclose, for OS-9.
* Popen, and Pclose, for OS-9.
*
* Based on code copyright (c) 1988 by Wolfgang Ocker, Puchheim,
* Ulli Dessauer, Germering and
* Reimer Mellin, Muenchen
* (W-Germany)
*
* These functions can be copied and distributed freely for any
* non-commercial purposes. It can only be incorporated into
* commercial software with the written permission of the authors.
*
* TOP-specific code stripped out and adapted for less by M.Gregorie, 1996
*
* address: Wolfgang Ocker
* Lochhauserstrasse 35a
* D-8039 Puchheim
* West Germany
*
* e-mail: weo@altger.UUCP, ud@altger.UUCP, ram@altger.UUCP
* pyramid!tmpmbx!recco!weo
* pyramid!tmpmbx!nitmar!ud
* pyramid!tmpmbx!ramsys!ram
*
* Martin Gregorie
* 10 Sadlers Mead
* Harlow
* Essex, CM18 6HG
* U.K.
*
* gregorie@logica.com
*/
#define ERR (-1)
#define PIPEMAX _NFILE
#define READ 1 /* For OS-9 */
#define WRITE 2 /* For OS-9 */
#define STDIN 0 /* For OS-9 */
#define STDOUT 1 /* For OS-9 */
#define RESTORE free(parameter); close(path); dup(save); close(save);
static int _pid[PIPEMAX];
FILE *popen(command, type)
char *command, *type;
#include <strings.h>
#include <errno.h>
extern char **environ;
extern char *getenv();
extern int os9forkc();
static int pids[_NFILE] = { 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0 };
/*
* p o p e n
*/
FILE *popen(name, mode)
char *name,
*mode;
{
register char *p = command;
char *parameter;
FILE *_pfp;
int l, path, pipe, pcnt, save;
path = (*type == 'w') ? STDIN : STDOUT;
if ((pipe = open("/pipe", READ+WRITE)) == ERR)
return (NULL);
pcnt = pipe;
if ((save = dup(path)) == ERR)
{
close(pipe);
return (NULL);
}
close(path);
if (dup(pipe) == ERR)
{
dup(save);
close(save);
close(pipe);
return (NULL);
}
while (*p != ' ' && *p)
p++;
if (*p == ' ')
p++;
l = strlen(p);
parameter = (char *) malloc(l+2);
strcpy(parameter,p);
strcat(parameter,"\n");
if ((_pid[pcnt] = os9fork(command,l+1,parameter,1,1,0)) == ERR)
{
{ RESTORE }
close(pipe);
_pid[pcnt] = 0;
return (NULL);
}
{ RESTORE }
if ((_pfp = fdopen(pipe,type)) == NULL)
{
close(pipe);
while (((l=wait(0)) != _pid[pcnt]) && l != ERR)
;
_pid[pcnt] = 0;
return (NULL);
}
return (_pfp);
int fd, fd2, fdsav, pid;
static char *argv[] = {NULL, NULL, NULL };
static char cmd[200];
static char cmd_path[200];
char *cp;
char *shell;
FILE *r;
if ((shell = getenv("SHELL")) == NULL)
return(NULL);
cp = name;
while (*cp == ' ')
cp++;
strcpy(cmd_path, cp);
if (cp = index(cmd_path, ' '))
*cp++ = '\0';
strcpy(cmd, "ex ");
strcat(cmd, cmd_path);
if (cp)
{
strcat(cmd, " ");
strcat(cmd, cp);
}
argv[0] = shell;
argv[1] = cmd;
/*
mode is "r" (stdout) or "w" (stdin)
*/
switch(mode[0])
{
case 'w': fd = 0;
break;
case 'r': fd = 1;
break;
default: return(NULL);
}
if (fd == 1)
fflush(stdout);
fdsav = dup(fd);
close(fd);
creat("/pipe", S_IWRITE+S_IREAD);
pid = os9exec(os9forkc, argv[0], argv, environ, 0, 0, 3);
fd2 = dup(fd);
close(fd);
dup(fdsav);
close(fdsav);
if (pid > 0)
{
pids[fd2] = pid;
r = fdopen(fd2, mode);
}
else
{
close(fd2);
r = NULL;
}
return(r);
}
int pclose(stream)
FILE *stream;
/*
* p c l o s e
*/
int pclose(fp)
FILE *fp;
{
register int i;
int f, status;
f = fileno(stream);
fclose(stream);
while ((i = wait(&status)) != _pid[f] && i != ERR)
;
_pid[f] = 0;
return ((i == ERR) ? ERR : status);
unsigned int status;
int pid;
int fd,
i;
fd = fileno(fp);
if (pids[fd] == 0)
return(-1);
fflush(fp);
fclose(fp);
while ((pid = wait(&status)) != -1)
if (pid == pids[fd])
break;
else
for (i = 0; i < _NFILE; i++)
if (pids[i] == pid)
{
pids[i] = 0;
break;
}
if (pid == -1)
status = -1;
pids[fd] = 0;
return(status);
}
#endif /* _OSK */

View File

@ -1,4 +1,4 @@
/* $NetBSD: mark.c,v 1.1.1.2 1997/04/22 13:45:32 mrg Exp $ */
/* $NetBSD: mark.c,v 1.1.1.3 1997/09/21 12:23:03 mrg Exp $ */
/*
* Copyright (c) 1984,1985,1989,1994,1995,1996 Mark Nudelman

View File

@ -1,4 +1,4 @@
/* $NetBSD: optfunc.c,v 1.1.1.2 1997/04/22 13:45:21 mrg Exp $ */
/* $NetBSD: optfunc.c,v 1.1.1.3 1997/09/21 12:22:52 mrg Exp $ */
/*
* Copyright (c) 1984,1985,1989,1994,1995,1996 Mark Nudelman
@ -52,9 +52,10 @@ extern int pr_type;
extern int plusoption;
extern int swindow;
extern int sc_height;
extern int any_display;
extern int secure;
extern int dohelp;
extern char openquote;
extern char closequote;
extern char *prproto[];
extern char *eqproto;
extern char *hproto;
@ -66,7 +67,6 @@ extern int logfile;
#endif
#if TAGS
public char *tagoption = NULL;
extern char *tagfile;
extern char *tags;
extern int jump_sline;
#endif
@ -121,8 +121,9 @@ opt_o(type, s)
error("No log file", NULL_PARG);
else
{
parg.p_string = namelogfile;
parg.p_string = unquote_file(namelogfile);
error("Log file \"%s\"", &parg);
free(parg.p_string);
}
break;
}
@ -182,8 +183,9 @@ opt_k(type, s)
case INIT:
if (lesskey(s))
{
parg.p_string = s;
parg.p_string = unquote_file(s);
error("Cannot use lesskey file \"%s\"", &parg);
free(parg.p_string);
}
break;
}
@ -215,16 +217,15 @@ opt_t(type, s)
break;
}
findtag(skipsp(s));
if (tagfile == NULL)
break;
save_ifile = curr_ifile;
if (edit(tagfile))
save_ifile = save_curr_ifile();
if (edit_tagfile())
break;
if ((pos = tagsearch()) == NULL_POSITION)
{
reedit_ifile(save_ifile);
break;
}
unsave_ifile(save_ifile);
jump_loc(pos, jump_sline);
break;
}
@ -250,8 +251,9 @@ opt__T(type, s)
tags = lglob(s);
break;
case QUERY:
parg.p_string = tags;
parg.p_string = unquote_file(tags);
error("Tags file \"%s\"", &parg);
free(parg.p_string);
break;
}
}
@ -462,6 +464,42 @@ opt_D(type, s)
}
#endif
/*
* Handler for the -" option.
*/
public void
opt_quote(type, s)
int type;
register char *s;
{
char buf[3];
PARG parg;
switch (type)
{
case INIT:
case TOGGLE:
if (s[1] != '\0' && s[2] != '\0')
{
error("-\" must be followed by 1 or 2 chars", NULL_PARG);
return;
}
openquote = s[0];
if (s[1] == '\0')
closequote = openquote;
else
closequote = s[1];
break;
case QUERY:
buf[0] = openquote;
buf[1] = closequote;
buf[2] = '\0';
parg.p_string = buf;
error("quotes %s", &parg);
break;
}
}
/*
* "-?" means display a help message.
* If from the command line, exit immediately.

View File

@ -1,4 +1,4 @@
/* $NetBSD: option.c,v 1.1.1.2 1997/04/22 13:45:33 mrg Exp $ */
/* $NetBSD: option.c,v 1.1.1.3 1997/09/21 12:23:04 mrg Exp $ */
/*
* Copyright (c) 1984,1985,1989,1994,1995,1996 Mark Nudelman
@ -147,6 +147,7 @@ scan_option(s)
quit(QUIT_ERROR);
}
str = NULL;
switch (o->otype & OTYPE)
{
case BOOL:

View File

@ -1,4 +1,4 @@
/* $NetBSD: option.h,v 1.1.1.2 1997/04/22 13:45:49 mrg Exp $ */
/* $NetBSD: option.h,v 1.1.1.3 1997/09/21 12:23:17 mrg Exp $ */
/*
* Copyright (c) 1984,1985,1989,1994,1995,1996 Mark Nudelman

View File

@ -1,4 +1,4 @@
/* $NetBSD: os.c,v 1.1.1.2 1997/04/22 13:45:34 mrg Exp $ */
/* $NetBSD: os.c,v 1.1.1.3 1997/09/21 12:23:05 mrg Exp $ */
/*
* Copyright (c) 1984,1985,1989,1994,1995,1996 Mark Nudelman
@ -80,6 +80,8 @@ public int reading;
static jmp_buf read_label;
extern int sigs;
/*
* Like read() system call, but is deliberately interruptible.
* A call to intread() from a signal handler will interrupt
@ -93,7 +95,11 @@ iread(fd, buf, len)
{
register int n;
#if MSDOS_COMPILER
#if MSDOS_COMPILER==WIN32C
if (ABORT_SIGS())
return (READ_INTR);
#else
#if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC
if (kbhit())
{
int c;
@ -103,6 +109,7 @@ iread(fd, buf, len)
return (READ_INTR);
ungetch(c);
}
#endif
#endif
if (SET_JUMP(read_label))
{
@ -122,6 +129,23 @@ iread(fd, buf, len)
flush();
reading = 1;
#if MSDOS_COMPILER==DJGPPC
if (isatty(fd))
{
/*
* Don't try reading from a TTY until a character is
* available, because that makes some background programs
* believe DOS is busy in a way that prevents those
* programs from working while "less" waits.
*/
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(fd, &readfds);
if (select(fd+1, &readfds, 0, 0, 0) == -1)
return (-1);
}
#endif
n = read(fd, buf, len);
reading = 0;
if (n < 0)

View File

@ -1,4 +1,4 @@
/* $NetBSD: output.c,v 1.1.1.2 1997/04/22 13:45:50 mrg Exp $ */
/* $NetBSD: output.c,v 1.1.1.3 1997/09/21 12:23:18 mrg Exp $ */
/*
* Copyright (c) 1984,1985,1989,1994,1995,1996 Mark Nudelman
@ -135,16 +135,50 @@ flush()
register int n;
register int fd;
n = ob - obuf;
if (n == 0)
return;
#if MSDOS_COMPILER==WIN32C
if (is_tty && any_display)
{
{
char *p;
DWORD nwritten = 0;
CONSOLE_SCREEN_BUFFER_INFO scr;
DWORD nchars;
COORD cpos;
extern HANDLE con_out;
*ob = '\0';
WriteConsole(con_out, obuf, strlen(obuf), &nwritten, NULL);
GetConsoleScreenBufferInfo(con_out, &scr);
if (scr.dwCursorPosition.Y != scr.srWindow.Bottom ||
(p = strchr(obuf, '\n')) == NULL)
{
WriteConsole(con_out, obuf, strlen(obuf),
&nwritten, NULL);
} else
{
/*
* To avoid color problems, if we're writing a
* newline at the bottom of the screen, we write
* only up to the newline, then fill the bottom
* line with the correct attribute, then write
* the rest. When Windows-95 scrolls, it takes the
* attributes for the new line from the first char
* of the (previously) bottom line.
*/
WriteConsole(con_out, obuf, p - obuf + 1,
&nwritten, NULL);
cpos.X = 0;
cpos.Y = scr.dwCursorPosition.Y;
FillConsoleOutputAttribute(con_out, scr.wAttributes,
sc_width, cpos, &nchars);
WriteConsole(con_out, p + 1, strlen(p + 1),
&nwritten, NULL);
}
ob = obuf;
return;
}
}
#else
#if MSDOS_COMPILER==MSOFTC
if (is_tty && any_display)
@ -155,7 +189,7 @@ flush()
return;
}
#else
#if MSDOS_COMPILER==BORLANDC
#if MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC
if (is_tty && any_display)
{
*ob = '\0';
@ -166,9 +200,6 @@ flush()
#endif
#endif
#endif
n = ob - obuf;
if (n == 0)
return;
fd = (any_display) ? 1 : 2;
if (write(fd, obuf, n) != n)
screen_trashed = 1;
@ -182,8 +213,6 @@ flush()
putchr(c)
int c;
{
if (ob >= &obuf[sizeof(obuf)])
flush();
if (need_clr)
{
need_clr = 0;
@ -198,6 +227,12 @@ putchr(c)
putchr(0x0A);
#endif
#endif
/*
* Some versions of flush() write to *ob, so we must flush
* when we are still one char from the end of obuf.
*/
if (ob >= &obuf[sizeof(obuf)-1])
flush();
*ob++ = c;
return (c);
}
@ -324,7 +359,7 @@ error(fmt, parg)
errmsgs++;
if (any_display)
if (any_display && is_tty)
{
clear_bot();
so_enter();
@ -333,7 +368,7 @@ error(fmt, parg)
col += iprintf(fmt, parg);
if (!any_display)
if (!(any_display && is_tty))
{
putchr('\n');
return;
@ -391,13 +426,13 @@ query(fmt, parg)
register int c;
int col = 0;
if (any_display)
if (any_display && is_tty)
clear_bot();
(void) iprintf(fmt, parg);
c = getchr();
if (!any_display)
if (!(any_display && is_tty))
{
putchr('\n');
return (c);

View File

@ -1,4 +1,4 @@
/* $NetBSD: position.c,v 1.1.1.2 1997/04/22 13:45:35 mrg Exp $ */
/* $NetBSD: position.c,v 1.1.1.3 1997/09/21 12:23:06 mrg Exp $ */
/*
* Copyright (c) 1984,1985,1989,1994,1995,1996 Mark Nudelman

View File

@ -1,4 +1,4 @@
/* $NetBSD: position.h,v 1.1.1.2 1997/04/22 13:45:51 mrg Exp $ */
/* $NetBSD: position.h,v 1.1.1.3 1997/09/21 12:23:19 mrg Exp $ */
/*
* Copyright (c) 1984,1985,1989,1994,1995,1996 Mark Nudelman

View File

@ -1,4 +1,4 @@
/* $NetBSD: regexp.c,v 1.1.1.2 1997/04/22 13:45:36 mrg Exp $ */
/* $NetBSD: regexp.c,v 1.1.1.3 1997/09/21 12:23:07 mrg Exp $ */
/*
* regcomp and regexec -- regsub and regerror are elsewhere

View File

@ -1,4 +1,4 @@
/* $NetBSD: regexp.h,v 1.1.1.2 1997/04/22 13:45:52 mrg Exp $ */
/* $NetBSD: regexp.h,v 1.1.1.3 1997/09/21 12:23:20 mrg Exp $ */
/*
* Definitions etc. for regexp(3) routines.

View File

@ -1,4 +1,4 @@
/* $NetBSD: search.c,v 1.1.1.2 1997/04/22 13:45:37 mrg Exp $ */
/* $NetBSD: search.c,v 1.1.1.3 1997/09/21 12:23:08 mrg Exp $ */
/*
* Copyright (c) 1984,1985,1989,1994,1995,1996 Mark Nudelman
@ -125,9 +125,9 @@ cvt_text(odst, osrc, ops)
for (src = osrc, dst = odst; *src != '\0'; src++, dst++)
{
if ((ops & CVT_TO_LC) && isupper(*src))
if ((ops & CVT_TO_LC) && isupper((unsigned char) *src))
/* Convert uppercase to lowercase. */
*dst = tolower(*src);
*dst = tolower((unsigned char) *src);
else if ((ops & CVT_BS) && *src == '\b' && dst > odst)
/* Delete BS and preceding char. */
dst -= 2;
@ -148,7 +148,7 @@ is_ucase(s)
register char *p;
for (p = s; *p != '\0'; p++)
if (isupper(*p))
if (isupper((unsigned char) *p))
return (1);
return (0);
}
@ -159,6 +159,8 @@ is_ucase(s)
static int
prev_pattern()
{
if (last_search_type & SRCH_NO_REGEX)
return (last_pattern != NULL);
#if HAVE_POSIX_REGCOMP
return (regpattern != NULL);
#endif
@ -256,51 +258,55 @@ compile_pattern(pattern, search_type)
char *pattern;
int search_type;
{
#if HAVE_POSIX_REGCOMP
regex_t *s = (regex_t *) ecalloc(1, sizeof(regex_t));
if (regcomp(s, pattern, REGCOMP_FLAG))
if ((search_type & SRCH_NO_REGEX) == 0)
{
free(s);
error("Invalid pattern", NULL_PARG);
return (-1);
}
if (regpattern != NULL)
regfree(regpattern);
regpattern = s;
#if HAVE_POSIX_REGCOMP
regex_t *s = (regex_t *) ecalloc(1, sizeof(regex_t));
if (regcomp(s, pattern, REGCOMP_FLAG))
{
free(s);
error("Invalid pattern", NULL_PARG);
return (-1);
}
if (regpattern != NULL)
regfree(regpattern);
regpattern = s;
#endif
#if HAVE_RE_COMP
PARG parg;
if ((parg.p_string = re_comp(pattern)) != NULL)
{
error("%s", &parg);
return (-1);
}
re_pattern = 1;
PARG parg;
if ((parg.p_string = re_comp(pattern)) != NULL)
{
error("%s", &parg);
return (-1);
}
re_pattern = 1;
#endif
#if HAVE_REGCMP
char *s;
if ((s = regcmp(pattern, 0)) == NULL)
{
error("Invalid pattern", NULL_PARG);
return (-1);
}
if (cpattern != NULL)
free(cpattern);
cpattern = s;
char *s;
if ((s = regcmp(pattern, 0)) == NULL)
{
error("Invalid pattern", NULL_PARG);
return (-1);
}
if (cpattern != NULL)
free(cpattern);
cpattern = s;
#endif
#if HAVE_V8_REGCOMP
struct regexp *s;
if ((s = regcomp(pattern)) == NULL)
{
/*
* regcomp has already printed error message via regerror().
*/
return (-1);
}
if (regpattern != NULL)
free(regpattern);
regpattern = s;
struct regexp *s;
if ((s = regcomp(pattern)) == NULL)
{
/*
* regcomp has already printed an error message
* via regerror().
*/
return (-1);
}
if (regpattern != NULL)
free(regpattern);
regpattern = s;
#endif
}
if (last_pattern != NULL)
free(last_pattern);
@ -336,9 +342,7 @@ uncompile_pattern()
free(regpattern);
regpattern = NULL;
#endif
#if NO_REGEX
last_pattern = NULL;
#endif
}
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: signal.c,v 1.1.1.2 1997/04/22 13:45:52 mrg Exp $ */
/* $NetBSD: signal.c,v 1.1.1.3 1997/09/21 12:23:21 mrg Exp $ */
/*
* Copyright (c) 1984,1985,1989,1994,1995,1996 Mark Nudelman
@ -65,6 +65,15 @@ u_interrupt(type)
#endif
LSIGNAL(SIGINT, u_interrupt);
sigs |= S_INTERRUPT;
#if MSDOS_COMPILER==DJGPPC
/*
* If a keyboard has been hit, it must be Ctrl-C
* (as opposed to Ctrl-Break), so consume it.
* (Otherwise, Less will beep when it sees Ctrl-C from keyboard.)
*/
if (kbhit())
getkey();
#endif
if (reading)
intread();
}
@ -117,6 +126,29 @@ winch(type)
#endif
#endif
#if MSDOS_COMPILER==WIN32C
/*
* Handle CTRL-C and CTRL-BREAK keys.
*/
#include "windows.h"
static BOOL WINAPI
wbreak_handler(dwCtrlType)
DWORD dwCtrlType;
{
switch (dwCtrlType)
{
case CTRL_C_EVENT:
case CTRL_BREAK_EVENT:
sigs |= S_INTERRUPT;
return (TRUE);
default:
break;
}
return (FALSE);
}
#endif
/*
* Set up the signal handlers.
*/
@ -130,6 +162,9 @@ init_signals(on)
* Set signal handlers.
*/
(void) LSIGNAL(SIGINT, u_interrupt);
#if MSDOS_COMPILER==WIN32C
SetConsoleCtrlHandler(wbreak_handler, TRUE);
#endif
#ifdef SIGTSTP
(void) LSIGNAL(SIGTSTP, stop);
#endif
@ -146,6 +181,9 @@ init_signals(on)
* Restore signals to defaults.
*/
(void) LSIGNAL(SIGINT, SIG_DFL);
#if MSDOS_COMPILER==WIN32C
SetConsoleCtrlHandler(wbreak_handler, FALSE);
#endif
#ifdef SIGTSTP
(void) LSIGNAL(SIGTSTP, SIG_DFL);
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: tags.c,v 1.1.1.2 1997/04/22 13:45:25 mrg Exp $ */
/* $NetBSD: tags.c,v 1.1.1.3 1997/09/21 12:22:56 mrg Exp $ */
/*
* Copyright (c) 1984,1985,1989,1994,1995,1996 Mark Nudelman
@ -33,9 +33,9 @@
#if TAGS
public char *tagfile;
public char *tags = "tags";
static char *tagfile;
static char *tagpattern;
static int taglinenum;
static int tagendline;
@ -62,7 +62,10 @@ findtag(tag)
int err;
char tline[TAGLINE_SIZE];
if ((f = fopen(tags, "r")) == NULL)
p = unquote_file(tags);
f = fopen(p, "r");
free(p);
if (f == NULL)
{
error("No tags file", NULL_PARG);
tagfile = NULL;
@ -110,6 +113,7 @@ findtag(tag)
if (*p == '\0')
/* Pattern is missing! */
continue;
tagfile = save(tagfile);
/*
* First see if it is a line number.
@ -149,6 +153,19 @@ findtag(tag)
tagfile = NULL;
}
public int
edit_tagfile()
{
int r;
if (tagfile == NULL)
return (1);
r = edit(tagfile);
free(tagfile);
tagfile = NULL;
return (r);
}
/*
* Search for a tag.
* This is a stripped-down version of search().
@ -163,6 +180,7 @@ tagsearch()
{
POSITION pos, linepos;
int linenum;
int len;
char *line;
/*
@ -217,8 +235,9 @@ tagsearch()
* If tagendline is set, make sure we match all
* the way to end of line (no extra chars after the match).
*/
if (strncmp(tagpattern, line, strlen(tagpattern)) == 0 &&
(!tagendline || line[strlen(tagpattern)] == '\0'))
len = strlen(tagpattern);
if (strncmp(tagpattern, line, len) == 0 &&
(!tagendline || line[len] == '\0' || line[len] == '\r'))
break;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: ttyin.c,v 1.1.1.2 1997/04/22 13:45:39 mrg Exp $ */
/* $NetBSD: ttyin.c,v 1.1.1.3 1997/09/21 12:23:09 mrg Exp $ */
/*
* Copyright (c) 1984,1985,1989,1994,1995,1996 Mark Nudelman
@ -39,6 +39,7 @@ static DWORD console_mode;
#endif
static int tty;
extern int sigs;
/*
* Open keyboard for input.
@ -52,12 +53,12 @@ open_getchr()
memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = TRUE;
tty = (int) CreateFile("CONIN$", GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE, &sa,
tty = (int) CreateFile("CONIN$", GENERIC_READ,
FILE_SHARE_READ, &sa,
OPEN_EXISTING, 0L, NULL);
GetConsoleMode((HANDLE)tty, &console_mode);
/* Make sure we get Ctrl+C events. */
SetConsoleMode((HANDLE)tty, 0); /* doesn't work for some reason --jdp */
SetConsoleMode((HANDLE)tty, ENABLE_PROCESSED_INPUT);
#else
#if MSDOS_COMPILER || OS2
extern int fd0;
@ -67,7 +68,14 @@ open_getchr()
*/
fd0 = dup(0);
close(0);
tty = OPEN_TTYIN();
tty = open("CON", OPEN_READ);
#if MSDOS_COMPILER==DJGPPC
/*
* Setting stdin to binary causes Ctrl-C to not
* raise SIGINT. We must undo that side-effect.
*/
(void) __djgpp_set_ctrl_c(1);
#endif
#else
/*
* Try /dev/tty.
@ -75,7 +83,7 @@ open_getchr()
* which in Unix is usually attached to the screen,
* but also usually lets you read from the keyboard.
*/
tty = OPEN_TTYIN();
tty = open("/dev/tty", OPEN_READ);
if (tty < 0)
tty = 2;
#endif
@ -105,12 +113,14 @@ getchr()
do
{
#if MSDOS_COMPILER
#if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC
/*
* In raw read, we don't see ^C so look here for it.
*/
flush();
#if MSDOS_COMPILER==WIN32C
if (ABORT_SIGS())
return (READ_INTR);
c = WIN32getch(tty);
#else
c = getch();

View File

@ -1,4 +1,4 @@
/* $NetBSD: version.c,v 1.1.1.2 1997/04/22 13:45:53 mrg Exp $ */
/* $NetBSD: version.c,v 1.1.1.3 1997/09/21 12:23:21 mrg Exp $ */
/*
* Copyright (c) 1984,1985,1989,1994,1995,1996 Mark Nudelman
@ -550,6 +550,26 @@ v318 5/29/96 Port to OS-9 Microware compiler; minor fixes
v319 7/8/96 Fix Windows port (thanks to Jeff Paquette).
v320 7/11/96 Final fixes for Windows port.
v321 7/18/96 Minor fixes.
Posted to Web page.
-----------------------------------------------------------------
v322 8/13/96 Fix bug in shell escape from help file; add support for
Microsoft Visual C under Windows; numerous small fixes.
v323 8/19/96 Fixes for Windows version (thanks to Simon Munton);
fix for Linux library weirdness (thanks to Jim Diamond);
port to DJGPP (thanks to Eli Zaretskii).
v324 8/21/96 Add support for spaces in filenames (thanks to Simon Munton).
v325 8/21/96 Add lessecho, for spaces in filenames under Unix.
v326 8/27/96 Fix DJGPP version.
v327 9/1/96 Reorganize lglob, make spaces in filenames work better in Unix.
v328 10/7/96 Append / to directory name in filename completion.
Fix MS-DOS and OS-9 versions.
v329 10/11/96 Fix more MS-DOS bugs; add LESSSEPARATOR; add -" option.
Add LESSMETACHARS, LESSMETAESCAPE.
v330 10/21/96 Minor fixes.
Posted to Web page.
-----------------------------------------------------------------
v331 4/22/97 Various Windows fixes (thanks to Gurusamy Sarathy).
v332 4/22/97 Enter filenames from cmd line into edit history.
*/
char version[] = "321";
char version[] = "332";

View File

@ -1,4 +1,4 @@
.TH LESSKEY 1 "Version 321: 18 Jul 96"
.TH LESSKEY 1 "Version 332: 22 Apr 97"
.SH NAME
lesskey \- specify key bindings for less
.SH SYNOPSIS
@ -86,6 +86,10 @@ string is parsed, just as if it were typed in to
This feature can be used in certain cases to extend
the functionality of a command.
For example, see the "{" and ":t" commands in the example below.
The extra string has a special meaning for the "quit" action:
when
.I less
quits, first character of the extra string is used as its exit status.
.SH EXAMPLE
The following input file describes the set of
@ -292,4 +296,4 @@ This NUL character should be represented as \e340 in a lesskey file.
.SH COPYRIGHT
Copyright (c) 1984,1985,1989,1994,1995 Mark Nudelman
.br
Comments to: markn@3do.com
Comments to: markn@fog.net

View File

@ -1,4 +1,4 @@
/* $NetBSD: lesskey.c,v 1.1.1.2 1997/04/22 13:45:56 mrg Exp $ */
/* $NetBSD: lesskey.c,v 1.1.1.3 1997/09/21 12:23:24 mrg Exp $ */
/*
* Copyright (c) 1984,1985,1989,1994,1995,1996 Mark Nudelman
@ -185,8 +185,8 @@ struct cmdname editnames[] =
"up", EC_UP,
"word-backspace", EC_W_BACKSPACE,
"word-delete", EC_W_DELETE,
"word-left", EC_W_RIGHT,
"word-right", EC_W_LEFT,
"word-left", EC_W_LEFT,
"word-right", EC_W_RIGHT,
NULL, 0
};

View File

@ -1,4 +1,4 @@
/* $NetBSD: lesskey.h,v 1.1.1.2 1997/04/22 13:45:56 mrg Exp $ */
/* $NetBSD: lesskey.h,v 1.1.1.3 1997/09/21 12:23:25 mrg Exp $ */
/*
* Format of a lesskey file: