#include <ctype.h>
#include <signal.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <curses.h>
#include <term.h>
#include <sys/ioctl.h>
#include <setjmp.h>
#include <sys/stat.h>
#include <values.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <libgen.h>
#include <euc.h>
#include <getwidth.h>
#include <locale.h>
#include <widec.h>
#include <wctype.h>
#include <limits.h>
eucwidth_t wp;
int cw[4];
int scw[4];
#include <locale.h>
#ifdef INGRES
#define VI "/usr/bin/vi"
#define HELPFILE "/mntp/doucette/more/more.help"
#define LOCAL_HELP "/usr/lib/locale/%s/LC_MESSAGES/more.help"
#endif
#ifndef INGRES
#ifndef HELPFILE
#define HELPFILE "/usr/lib/more.help"
#define LOCAL_HELP "/usr/lib/locale/%s/LC_MESSAGES/more.help"
#endif
#define VI "vi"
#endif
#define Fopen(s,m) (Currline = 0,file_pos=0,fopen(s,m))
#define Ftell(f) file_pos
#define Fseek(f,off) (file_pos=off,fseeko(f,off,0))
#define Getc(f) (++file_pos, getc(f))
#define Ungetc(c,f) (--file_pos, ungetc(c,f))
#define pr(s1) fputs(s1, stdout)
#define clreos() putp(clr_eos)
#define cleareol() putp(clr_eol)
#define home() putp(cursor_home)
#define LINSIZ 512
#define ctrl(letter) ((letter) & 077)
#define RUBOUT '\177'
#define ESC '\033'
#define QUIT '\034'
struct termio otty;
struct termio ntty;
off_t file_pos, file_size;
int fnum, no_intty, no_tty;
int dum_opt;
off_t dlines;
void end_it(int sig) __NORETURN;
void onquit(int sig);
void chgwinsz(int sig);
#ifdef SIGTSTP
void onsusp(int sig);
#endif
int nscroll = 11;
int fold_opt = 1;
int stop_opt = 1;
int ssp_opt = 0;
int ul_opt = 1;
int cr_opt = 0;
int wait_opt = 0;
int promptlen;
off_t Currline;
int startup = 1;
int firstf = 1;
int notell = 1;
int inwait, Pause, errors;
int within;
int hard, dumb, noscroll, hardtabs, clreol;
int catch_susp;
char **fnames;
int nfiles;
char *shell;
int shellp;
char ch;
jmp_buf restore;
char obuf[BUFSIZ];
char Line[LINSIZ];
int Lpp = 24;
char *ULenter, *ULexit;
int Mcol = 80;
int Wrap = 1;
int fseeko();
struct {
off_t chrctr, line;
} context, screen_start;
int exitstat = 0;
static void execute(char *filename, char *cmd, ...);
static void error(char *mess);
static void wait_eof(void);
static void prompt(char *filename);
static void argscan(char *s);
static void copy_file(register FILE *f);
static void initterm(void);
static void do_shell(char *filename);
static FILE *checkf(register char *fs, int *clearfirst);
static void screen(register FILE *f, register off_t num_lines);
static void skiplns(register off_t n, register FILE *f);
static void skipf(register int nskip);
static int readch(void);
static void prmpt_erase(register int col);
static void kill_line(void);
static void prbuf(register char *s, register int n);
static void search(char buf[], FILE *file, register off_t n);
static void doclear(void);
static void ttyin(char buf[], register int nmax, char pchar);
static int expand(char *outbuf, char *inbuf);
static void show(register char ch);
static void set_tty(void);
static void reset_tty(void);
static void rdline(register FILE *f);
static off_t command(char *filename, register FILE *f);
static int getaline(register FILE *f, int *length);
static int number(char *cmd);
static int colon(char *filename, int cmd, off_t nlines);
int
main(int argc, char *argv[])
{
register FILE *f;
register char *s;
register char *p;
register int ch;
register off_t left;
int prnames = 0;
int initopt = 0;
int srchopt = 0;
int clearit = 0;
off_t initline;
char initbuf[80];
setlocale( LC_ALL, "" );
getwidth(&wp);
cw[0] = 1;
cw[1] = wp._eucw1;
cw[2] = wp._eucw2+1;
cw[3] = wp._eucw3+1;
scw[0] = 1;
scw[1] = wp._scrw1;
scw[2] = wp._scrw2;
scw[3] = wp._scrw3;
nfiles = argc;
fnames = argv;
(void) setlocale(LC_ALL,"");
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SYS_TEST"
#endif
(void) textdomain(TEXT_DOMAIN);
initterm ();
if(s = getenv("MORE")) argscan(s);
while (--nfiles > 0) {
if ((ch = (*++fnames)[0]) == '-') {
argscan(*fnames+1);
}
else if (ch == '+') {
s = *fnames;
if (*++s == '/') {
srchopt++;
for (++s, p = initbuf; p < initbuf + 79 && *s != '\0';)
*p++ = *s++;
*p = '\0';
}
else {
initopt++;
for (initline = 0; *s != '\0'; s++)
if (isdigit (*s))
initline = initline*10 + *s -'0';
--initline;
}
}
else break;
}
if(clreol)
{
if (!cursor_home || !clr_eol || !clr_eos) {
clreol = 0;
}
else noscroll = 1;
}
if (dlines == 0)
dlines =(off_t) (Lpp - (noscroll ? 1 : 2));
left = dlines;
if (nfiles > 1)
prnames++;
if (!no_intty && nfiles == 0) {
fprintf(stderr, gettext("Usage: %s\
[-cdflrsuw] [-lines] [+linenumber] [+/pattern] [filename ...].\n")
, argv[0]);
exit(1);
}
else
f = stdin;
if (!no_tty) {
signal(SIGQUIT, onquit);
signal(SIGINT, end_it);
signal(SIGWINCH, chgwinsz);
#ifdef SIGTSTP
if (signal (SIGTSTP, SIG_IGN) == SIG_DFL) {
signal(SIGTSTP, onsusp);
catch_susp++;
}
#endif
set_tty();
}
if (no_intty) {
if (no_tty)
copy_file (stdin);
else {
if ((ch = Getc (f)) == '\f')
doclear();
else {
Ungetc (ch, f);
if (noscroll && (ch != EOF)) {
if (clreol)
home ();
else
doclear ();
}
}
if (!setjmp(restore)) {
if (srchopt) {
search (initbuf, stdin,(off_t) 1);
if (noscroll)
left--;
}
else if (initopt)
skiplns (initline, stdin);
}
else
left = command(NULL, f);
screen (stdin, left);
}
no_intty = 0;
prnames++;
firstf = 0;
}
while (fnum < nfiles) {
if ((f = checkf (fnames[fnum], &clearit)) != NULL) {
context.line = context.chrctr = 0;
Currline = 0;
if (firstf) setjmp (restore);
if (firstf) {
firstf = 0;
if (srchopt)
{
search (initbuf, f,(off_t) 1);
if (noscroll)
left--;
}
else if (initopt)
skiplns (initline, f);
}
else if (fnum < nfiles && !no_tty) {
setjmp (restore);
left = command (fnames[fnum], f);
}
if (left != 0) {
if ((noscroll || clearit) && (file_size != LLONG_MAX))
if (clreol)
home ();
else
doclear ();
if (prnames) {
if (ceol_standout_glitch)
prmpt_erase (0);
if (clreol)
cleareol ();
pr("::::::::::::::");
if (promptlen > 14)
prmpt_erase (14);
printf ("\n");
if(clreol) cleareol();
printf("%s\n", fnames[fnum]);
if(clreol) cleareol();
pr("::::::::::::::\n");
if (left > (off_t)(Lpp - 4))
left =(off_t)(Lpp - 4);
}
if (no_tty)
copy_file (f);
else {
within++;
screen(f, left);
within = 0;
}
}
setjmp (restore);
fflush(stdout);
fclose(f);
screen_start.line = screen_start.chrctr = 0LL;
context.line = context.chrctr = 0LL;
} else
exitstat |= 1;
fnum++;
firstf = 0;
}
if (wait_opt) wait_eof();
reset_tty ();
return (exitstat);
}
static void
argscan(char *s)
{
for (dlines = 0; *s != '\0'; s++)
if (isdigit(*s))
dlines = dlines*10 + *s - '0';
else if (*s == 'd')
dum_opt = 1;
else if (*s == 'l')
stop_opt = 0;
else if (*s == 'f')
fold_opt = 0;
else if (*s == 'p')
noscroll++;
else if (*s == 'c')
clreol++;
else if (*s == 's')
ssp_opt = 1;
else if (*s == 'u')
ul_opt = 0;
else if (*s == 'r')
cr_opt = 1;
else if (*s == 'w')
wait_opt = 1;
}
static FILE *
checkf(register char *fs, int *clearfirst)
{
struct stat stbuf;
register FILE *f;
int c;
if (stat (fs, &stbuf) == -1) {
fflush(stdout);
if (clreol)
cleareol ();
perror(fs);
return (NULL);
}
if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
printf(gettext("\n*** %s: directory ***\n\n"), fs);
return (NULL);
}
if ((f=Fopen(fs, "r")) == NULL) {
fflush(stdout);
perror(fs);
return (NULL);
}
if ((c = Getc(f)) == '\f')
*clearfirst = 1;
else {
*clearfirst = 0;
Ungetc (c, f);
}
if ((file_size = (off_t)stbuf.st_size) == 0)
file_size = LLONG_MAX;
return (f);
}
#define STOP -10
static void
screen(register FILE *f, register off_t num_lines)
{
register int c;
register int nchars;
int length;
static int prev_len = 1;
for (;;) {
while (num_lines > 0 && !Pause) {
if ((nchars = getaline (f, &length)) == EOF)
{
if (clreol) clreos();
return;
}
if (ssp_opt && length == 0 && prev_len == 0)
continue;
prev_len = length;
if (ceol_standout_glitch ||
(enter_standout_mode && *enter_standout_mode == ' ')
&& promptlen > 0)
prmpt_erase (0);
if (clreol)
cleareol ();
prbuf (Line, length);
if (nchars < promptlen)
prmpt_erase (nchars);
else promptlen = 0;
if (nchars < Mcol || !fold_opt)
putchar('\n');
if (nchars == STOP)
break;
num_lines--;
}
fflush(stdout);
if ((c = Getc(f)) == EOF)
{
if (clreol) clreos ();
return;
}
if (Pause && clreol)
clreos ();
Ungetc (c, f);
setjmp (restore);
Pause = 0; startup = 0;
if ((num_lines = command (NULL, f)) == 0)
return;
if (hard && promptlen > 0)
prmpt_erase (0);
if (noscroll && num_lines == dlines) {
if (clreol)
home();
else
doclear ();
}
screen_start.line = Currline;
screen_start.chrctr = Ftell (f);
}
}
void
onquit(int sig)
{
signal(SIGQUIT, SIG_IGN);
if (!inwait) {
putchar ('\n');
if (!startup) {
signal(SIGQUIT, onquit);
longjmp (restore, 1);
}
else
Pause++;
}
else if (!dum_opt && notell) {
write (2, gettext("[Use q or Q to quit]"), 20);
promptlen += 20;
notell = 0;
}
signal(SIGQUIT, onquit);
}
void
chgwinsz(int sig)
{
struct winsize win;
(void) signal(SIGWINCH, SIG_IGN);
if (ioctl(fileno(stdout), TIOCGWINSZ, &win) != -1) {
if (win.ws_row != 0) {
Lpp = win.ws_row;
nscroll = Lpp/2 - 1;
if (nscroll <= 0)
nscroll = 1;
dlines = (off_t)(Lpp - (noscroll ? 1 : 2));
}
if (win.ws_col != 0)
Mcol = win.ws_col;
}
(void) signal(SIGWINCH, chgwinsz);
}
void
end_it(int sig)
{
reset_tty ();
if (clreol) {
putchar ('\r');
clreos ();
fflush (stdout);
}
else if (!clreol && (promptlen > 0)) {
kill_line ();
fflush (stdout);
}
else
write (2, "\n", 1);
_exit(exitstat);
}
static void
copy_file(register FILE *f)
{
register int c;
while ((c = getc(f)) != EOF)
putchar(c);
}
static char Bell = ctrl('G');
int
tailequ(char *path, char *string)
{
return (!strcmp(basename(path), string));
}
static void
prompt(char *filename)
{
if (clreol)
cleareol ();
else if (promptlen > 0)
kill_line ();
if (!hard) {
promptlen = 8;
if (enter_standout_mode && exit_standout_mode)
putp (enter_standout_mode);
if (clreol)
cleareol ();
pr(gettext("--More--"));
if (filename != NULL) {
promptlen += printf (gettext("(Next file: %s)"), filename);
}
else if (!no_intty) {
promptlen += printf ("(%d%%)", (int)((file_pos * 100) / file_size));
}
if (dum_opt) {
promptlen += pr(gettext("[Hit space to continue, Del to abort]"));
}
if (enter_standout_mode && exit_standout_mode)
putp (exit_standout_mode);
if (clreol) clreos ();
fflush(stdout);
}
else
write (2, &Bell, 1);
inwait++;
}
static void
wait_eof(void)
{
if (enter_standout_mode && exit_standout_mode)
putp (enter_standout_mode);
promptlen = pr(gettext("--No more--"));
if (dum_opt)
promptlen += pr(gettext("[Hit any key to continue]"));
if (enter_standout_mode && exit_standout_mode)
putp(exit_standout_mode);
if (clreol) clreos();
fflush(stdout);
readch();
prmpt_erase (0);
fflush(stdout);
}
static int
getaline(register FILE *f, int *length)
{
register int c;
register char *p;
register int column;
static int colflg;
register int oldcolumn;
int csno;
p = Line;
column = 0;
oldcolumn = 0;
c = Getc (f);
if (colflg && c == '\n') {
Currline++;
c = Getc (f);
}
while (p < &Line[LINSIZ - 1]) {
csno = csetno(c);
if (c == EOF) {
if (p > Line) {
*p = '\0';
*length = p - Line;
return (column);
}
*length = p - Line;
return (EOF);
}
if (!csno) {
if (c == '\n') {
if (p>Line && p[-1] == '\r') {
column = oldcolumn;
p--;
}
Currline++;
break;
}
*p++ = c;
if (c == '\t')
if (hardtabs && column < promptlen && !hard) {
if (clr_eol && !dumb) {
column = 1 + (column | 7);
putp (clr_eol);
promptlen = 0;
}
else {
for (--p; column & 7 && p < &Line[LINSIZ - 1]; column++) {
*p++ = ' ';
}
if (column >= promptlen) promptlen = 0;
}
}
else
column = 1 + (column | 7);
else if ((c == '\b') && (ul_opt || !cr_opt) && (column > 0))
column--;
else if ((c == '\r') && !cr_opt) {
oldcolumn = column;
column = 0;
}
else if (c == '\f' && stop_opt) {
p[-1] = '^';
*p++ = 'L';
column += 2;
Pause++;
}
else if (c == EOF) {
*length = p - Line;
return (column);
}
else if (c < ' ' && cr_opt){
p[-1] = '^';
*p++ = c | ('A' - 1);
column += 2;
}
else if (c >= ' ' && c != RUBOUT)
column++;
}
else {
column += scw[csno];
if ( column > Mcol && fold_opt ) {
column -= scw[csno];
while ( column < Mcol ) {
column++;
*p++ = ' ';
}
column = Mcol;
Ungetc(c,f);
} else {
int i;
*p++ = c;
for(i=1; i<cw[csno];i++)
*p++ = Getc(f);
}
}
if (column >= Mcol && fold_opt) break;
c = Getc (f);
}
if (column >= Mcol && Mcol > 0) {
if (!Wrap) {
*p++ = '\n';
}
}
colflg = column == Mcol && fold_opt;
if (colflg && eat_newline_glitch && Wrap) {
*p++ = '\n';
}
*length = p - Line;
*p = 0;
return (column);
}
static void
prmpt_erase(register int col)
{
if (promptlen == 0)
return;
if (hard) {
putchar ('\n');
}
else {
if (col == 0)
putchar ('\r');
if (!dumb && clr_eol)
putp (clr_eol);
else
for (col = promptlen - col; col > 0; col--)
putchar (' ');
}
promptlen = 0;
}
static void
kill_line(void)
{
prmpt_erase (0);
if (!clr_eol || dumb) putchar ('\r');
}
static void
prbuf(register char *s, register int n)
{
char c;
register int state = 0;
static int pstate = 0;
while (--n >= 0)
if (!ul_opt)
putchar (*s++);
else {
if (n >= 2 && s[0] == '_' && s[1] == '\b') {
n -= 2;
s += 2;
c = *s++;
state = 1;
} else if (n >= 2 && s[1] == '\b' && s[2] == '_') {
n -= 2;
c = *s++;
s += 2;
state = 1;
} else {
c = *s++;
state = 0;
}
if (state != pstate)
putp(state ? ULenter : ULexit);
pstate = state;
putchar(c);
if (state && underline_char) {
putp(cursor_left);
putp(underline_char);
}
}
if (state && !underline_char) {
putp(ULexit);
pstate = 0;
}
}
static void
doclear(void)
{
if (clear_screen && !hard) {
putp(clear_screen);
putchar ('\r');
promptlen = 0;
}
}
static int lastcmd, lastp;
static off_t lastarg;
static int lastcolon;
char shell_line[PATH_MAX];
static off_t
command(char *filename, register FILE *f)
{
register off_t nlines;
register off_t retval;
register int c;
char colonch;
FILE *helpf;
int done;
char comchar, cmdbuf[80];
char filebuf[128];
char *loc;
#define ret(val) retval=val;done++;break
done = 0;
if (!errors)
prompt (filename);
else
errors = 0;
for (;;) {
nlines = number (&comchar);
lastp = colonch = 0;
if (comchar == '.') {
lastp++;
comchar = lastcmd;
nlines = lastarg;
if (lastcmd == ':')
colonch = lastcolon;
}
lastcmd = comchar;
lastarg = nlines;
if((comchar != RUBOUT) && !dum_opt) {
if (comchar == otty.c_cc[VERASE]) {
kill_line ();
prompt (filename);
continue;
}
}
switch (comchar) {
case ':':
retval = colon (filename, colonch, nlines);
if (retval >= 0)
done++;
break;
case 'b':
case ctrl('B'):
{
register off_t initline;
if (no_intty) {
write(2, &bell, 1);
return (-1);
}
if (nlines == 0) nlines++;
putchar ('\r');
prmpt_erase (0);
printf ("\n");
if (clreol)
cleareol ();
printf (gettext("...back %lld page"), nlines);
if (nlines > 1)
pr ("s\n");
else
pr ("\n");
if (clreol)
cleareol ();
pr ("\n");
initline = Currline - dlines * (nlines + 1);
if (! noscroll)
--initline;
if (initline < 0) initline = 0;
Fseek(f, 0LL);
Currline = 0;
skiplns(initline, f);
if (! noscroll) {
ret(dlines + 1);
}
else {
ret(dlines);
}
}
case ' ':
case 'z':
if (nlines == 0) nlines = dlines;
else if (comchar == 'z') dlines = nlines;
ret (nlines);
case 'd':
case ctrl('D'):
if (nlines != 0) nscroll = nlines;
ret (nscroll);
case RUBOUT:
case 'q':
case 'Q':
end_it(0);
case 's':
case 'f':
if (nlines == 0) nlines++;
if (comchar == 'f')
nlines *= dlines;
putchar ('\r');
prmpt_erase (0);
printf ("\n");
if (clreol)
cleareol ();
printf (gettext("...skipping %lld line"), nlines);
if (nlines > 1)
pr ("s\n");
else
pr ("\n");
if (clreol)
cleareol ();
pr ("\n");
while (nlines > 0) {
while ((c = Getc (f)) != '\n')
if (c == EOF) {
retval = 0;
done++;
goto endsw;
}
Currline++;
nlines--;
}
ret (dlines);
case '\n':
if (nlines != 0)
dlines = nlines;
else
nlines = 1;
ret (nlines);
case '\f':
if (!no_intty) {
doclear ();
Fseek (f, screen_start.chrctr);
Currline = screen_start.line;
ret (dlines);
}
else {
write (2, &Bell, 1);
break;
}
case '\'':
if (!no_intty) {
kill_line ();
pr (gettext("\n***Back***\n\n"));
Fseek (f, context.chrctr);
Currline = context.line;
ret (dlines);
}
else {
write (2, &Bell, 1);
break;
}
case '=':
kill_line ();
promptlen = printf ("%lld", Currline);
fflush (stdout);
break;
case 'n':
lastp++;
case '/':
if (nlines == 0) nlines++;
kill_line ();
pr ("/");
promptlen = 1;
fflush (stdout);
if (lastp) {
write (2,"\r", 1);
search (NULL, f, nlines);
}
else {
ttyin (cmdbuf, 78, '/');
write (2, "\r", 1);
search (cmdbuf, f, nlines);
}
ret (dlines-1);
case '!':
do_shell (filename);
break;
case 'h':
case '?':
loc = setlocale(LC_MESSAGES, 0);
sprintf(filebuf, LOCAL_HELP, loc);
if ((strcmp(loc, "C") == 0) || (helpf = fopen (filebuf, "r")) == NULL) {
if ((helpf = fopen (HELPFILE, "r")) == NULL)
error (gettext("Can't open help file"));
}
if (noscroll) doclear ();
copy_file (helpf);
fclose (helpf);
prompt (filename);
break;
case 'v':
if (!no_intty) {
kill_line ();
cmdbuf[0] = '+';
sprintf(&cmdbuf[1], "%lld", Currline);
pr ("vi "); pr (cmdbuf); putchar (' '); pr (fnames[fnum]);
execute (filename, VI, "vi", cmdbuf, fnames[fnum], 0);
break;
}
default:
if (dum_opt) {
kill_line ();
promptlen = pr(gettext("[Press 'h' for instructions.]"));
fflush (stdout);
}
else
write (2, &Bell, 1);
break;
}
if (done) break;
}
putchar ('\r');
endsw:
inwait = 0;
notell++;
return (retval);
}
char ch;
static int
colon(char *filename, int cmd, off_t nlines)
{
if (cmd == 0)
ch = readch ();
else
ch = cmd;
lastcolon = ch;
switch (ch) {
case 'f':
kill_line ();
if (!no_intty)
promptlen = printf (gettext("\"%s\" line %lld"),
fnames[fnum], Currline);
else
promptlen = printf(
gettext("[Not a file] line %lld"), Currline);
fflush (stdout);
return (-1);
case 'n':
if (nlines == 0) {
if (fnum >= nfiles - 1)
end_it(0);
nlines++;
}
putchar ('\r');
prmpt_erase (0);
skipf ((int)nlines);
return (0);
case 'p':
if (no_intty) {
write (2, &Bell, 1);
return (-1);
}
putchar ('\r');
prmpt_erase (0);
if (nlines == 0)
nlines++;
skipf ((int)-nlines);
return (0);
case '!':
do_shell (filename);
return (-1);
case 'q':
case 'Q':
end_it(0);
default:
write (2, &Bell, 1);
return (-1);
}
}
static int
number(char *cmd)
{
register int i;
i = 0; ch = otty.c_cc[VKILL];
for (;;) {
ch = readch ();
if (ch >= '0' && ch <= '9') {
i = i*10 + ch - '0';
} else if (ch == RUBOUT) {
i = 0;
*cmd = ch;
break;
} else if (ch == otty.c_cc[VKILL]) {
i = 0;
} else {
*cmd = ch;
break;
}
}
return (i);
}
static void
do_shell(char *filename)
{
char cmdbuf[80];
kill_line ();
pr ("!");
fflush (stdout);
promptlen = 1;
if (lastp)
pr (shell_line);
else {
ttyin (cmdbuf, 78, '!');
if (expand (shell_line, cmdbuf)) {
kill_line ();
promptlen = printf ("!%s", shell_line);
}
}
fflush (stdout);
write (2, "\n", 1);
promptlen = 0;
shellp = 1;
execute (filename, shell, shell, "-c", shell_line, 0);
}
static void
search(char buf[], FILE *file, register off_t n)
{
off_t startline = Ftell (file);
register off_t line1 = startline;
register off_t line2 = startline;
register off_t line3 = startline;
register off_t lncount;
off_t saveln;
static char *s = NULL;
static char lastbuf[80];
if (buf != NULL) {
if (s != NULL)
free(s);
if (*buf != '\0') {
if ((s = regcmp(buf, (char *) NULL)) == NULL)
error(gettext("Regular expression botch"));
else
strcpy(lastbuf, buf);
} else {
if ((s = regcmp(lastbuf, (char *) NULL)) == NULL)
error(gettext("No previous regular expression"));
}
} else {
if (s == NULL)
error(gettext("No previous regular expression"));
}
context.line = saveln = Currline;
context.chrctr = startline;
lncount = 0;
while (!feof (file)) {
line3 = line2;
line2 = line1;
line1 = Ftell (file);
rdline (file);
lncount++;
if (regex(s, Line) != NULL)
if (--n == 0) {
if (lncount > 3 || (lncount > 1 && no_intty))
{
pr ("\n");
if (clreol)
cleareol ();
pr(gettext("...skipping\n"));
}
if (!no_intty) {
Currline -= (lncount >= 3 ? 3 : lncount);
Fseek (file, line3);
if (noscroll)
if (clreol) {
home ();
cleareol ();
}
else
doclear ();
}
else {
kill_line ();
if (noscroll)
if (clreol) {
home ();
cleareol ();
} else
doclear ();
pr (Line);
putchar ('\n');
}
break;
}
}
if (feof (file)) {
if (!no_intty) {
Currline = saveln;
Fseek (file, startline);
}
else {
pr (gettext("\nPattern not found\n"));
end_it (0);
}
error (gettext("Pattern not found"));
}
}
#define MAXARGS 10
static void
execute (char *filename, char *cmd, ...)
{
pid_t id;
va_list ap;
char *argp[MAXARGS];
int count;
fflush (stdout);
reset_tty ();
while ((id = fork ()) < 0)
sleep (5);
if (id == 0) {
if (no_intty) {
close(0);
dup(2);
}
va_start(ap, cmd);
count = 0;
do {
#ifndef lint
argp[count] = va_arg(ap, char *);
#else
ap = ap;
#endif
count++;
if (count > MAXARGS)
error (gettext("Too many arguments in execute()\n"));
} while (argp[count - 1] != NULL);
va_end(ap);
execvp(cmd, argp);
write (2, "exec failed\n", 12);
exit (1);
}
signal (SIGINT, SIG_IGN);
signal (SIGQUIT, SIG_IGN);
signal (SIGWINCH, SIG_IGN);
#ifdef SIGTSTP
if (catch_susp)
signal(SIGTSTP, SIG_DFL);
#endif
wait ((pid_t)0);
signal (SIGINT, end_it);
signal (SIGQUIT, onquit);
signal (SIGWINCH, chgwinsz);
#ifdef SIGTSTP
if (catch_susp)
signal(SIGTSTP, onsusp);
#endif
(void) chgwinsz(0);
set_tty ();
pr ("------------------------\n");
prompt (filename);
}
static void
skiplns(register off_t n, register FILE *f)
{
register int c;
while (n > 0) {
while ((c = Getc (f)) != '\n')
if (c == EOF)
return;
n--;
Currline++;
}
}
static void
skipf(register int nskip)
{
if (nskip == 0) return;
if (nskip > 0) {
if (fnum + nskip > nfiles - 1)
nskip = nfiles - fnum - 1;
}
else if (within)
++fnum;
fnum += nskip;
if (fnum < 0)
fnum = 0;
pr (gettext("\n...Skipping "));
pr ("\n");
if (clreol)
cleareol ();
if (nskip > 0)
printf(gettext("...Skipping to file %s\n"), fnames[fnum]);
else
printf(gettext("...Skipping back to file %s\n"), fnames[fnum]);
if (clreol)
cleareol ();
pr ("\n");
--fnum;
}
static void
initterm(void)
{
int erret = 0;
setbuf(stdout, obuf);
if (!(no_tty = ioctl(1, TCGETA, &otty))) {
if (setupterm(NULL, 1, &erret) != OK) {
dumb++; ul_opt = 0;
}
else {
int row, col;
struct winsize w;
char *s;
reset_shell_mode();
row = col = -1;
if (ioctl(fileno(stdout), TIOCGWINSZ, &w) == 0) {
if (w.ws_row > 0)
row = w.ws_row;
if (w.ws_col > 0)
col = w.ws_col;
}
if (row < 0) {
if ((s = getenv("LINES")) != NULL)
row = atoi(s);
}
if (col < 0) {
if ((s = getenv("COLUMNS")) != NULL)
col = atoi(s);
}
if (row > 0)
Lpp = row;
else if (((Lpp = lines) < 0) || hard_copy) {
hard++;
Lpp = 24;
}
if (col > 0)
Mcol = col;
else if ((Mcol = columns) < 0)
Mcol = 80;
if (tailequ(fnames[0], "page") || !hard && (scroll_forward == NULL))
noscroll++;
Wrap = tigetflag("am");
if (transparent_underline || over_strike)
ul_opt = 0;
if ((ULenter = tigetstr("smul")) == NULL &&
(!underline_char) && (ULenter = tigetstr("smso")) == NULL)
ULenter = "";
if ((ULexit = tigetstr("rmul")) == NULL &&
(!underline_char) && (ULexit = tigetstr("rmso")) == NULL)
ULexit = "";
}
if ((shell = getenv("SHELL")) == NULL)
shell = "/usr/bin/sh";
}
no_intty = ioctl(0, TCGETA, &otty);
ioctl(2, TCGETA, &otty);
hardtabs = !(otty.c_oflag & TAB3);
}
static int
readch(void)
{
char ch;
extern int errno;
if (read (2, &ch, 1) <= 0)
if (errno != EINTR)
end_it(0);
else
ch = otty.c_cc[VKILL];
return (ch);
}
static char BS = '\b';
static char CARAT = '^';
static void
ttyin(char buf[], register int nmax, char pchar)
{
register char *sptr;
register unsigned char ch;
int LengthBuffer[80];
int *BufferPointer;
int csno;
register int slash = 0;
int maxlen;
char cbuf;
BufferPointer = LengthBuffer;
sptr = buf;
maxlen = 0;
while (sptr - buf < nmax) {
if (promptlen > maxlen)
maxlen = promptlen;
ch = readch ();
csno = csetno(ch);
if (!csno) {
if (ch == '\\') {
slash++;
} else if ((ch == otty.c_cc[VERASE]) && !slash) {
if (sptr > buf) {
--promptlen;
write (2, &BS, 1);
sptr -= (*--BufferPointer);
if ((*sptr < ' ' && *sptr != '\n') || *sptr == RUBOUT) {
--promptlen;
write (2, &BS, 1);
}
continue;
} else {
if (!clr_eol)
promptlen = maxlen;
longjmp (restore, 1);
}
} else if ((ch == otty.c_cc[VKILL]) && !slash) {
if (hard) {
show(ch);
putchar ('\n');
putchar (pchar);
} else {
putchar ('\r');
putchar (pchar);
if (clr_eol)
prmpt_erase (1);
promptlen = 1;
}
sptr = buf;
fflush (stdout);
continue;
}
if (slash && (ch == otty.c_cc[VKILL] || ch == otty.c_cc[VERASE])) {
write (2, &BS, 1);
sptr -= (*--BufferPointer);
}
if (ch != '\\')
slash = 0;
*BufferPointer++ = 1;
*sptr++ = ch;
if ((ch < ' ' && ch != '\n' && ch != ESC) || ch == RUBOUT) {
ch += ch == RUBOUT ? -0100 : 0100;
write (2, &CARAT, 1);
promptlen++;
}
cbuf = ch;
if (ch != '\n' && ch != ESC) {
write (2, &cbuf, 1);
promptlen++;
} else
break;
} else {
int i;
u_char buffer[5];
*BufferPointer++ = cw[csno];
buffer[0] = *sptr++ = ch;
for(i=1; i<cw[csno]; i++) {
buffer[i] = *sptr++ = readch();
}
buffer[i]='\0';
write(2, buffer, strlen((char *)buffer));
}
}
*--sptr = '\0';
if (!clr_eol) promptlen = maxlen;
if (sptr - buf >= nmax - 1)
error (gettext("Line too long"));
}
static int
expand(char *outbuf, char *inbuf)
{
char *in_str;
char *out_str;
char ch;
char temp[PATH_MAX];
int changed = 0;
in_str = inbuf;
out_str = temp;
while ((ch = *in_str++) != '\0')
switch (ch) {
case '%':
if (!no_intty) {
if (strlcpy(out_str, fnames[fnum], sizeof (temp))
>= sizeof (temp))
error(gettext("Command too long"));
out_str += strlen (fnames[fnum]);
changed++;
}
else
*out_str++ = ch;
break;
case '!':
if (!shellp)
error (gettext("No previous command to substitute for"));
if (strlcpy(out_str, shell_line, sizeof (temp)) >= sizeof (temp))
error(gettext("Command too long"));
out_str += strlen (shell_line);
changed++;
break;
case '\\':
if (*in_str == '%' || *in_str == '!') {
*out_str++ = *in_str++;
break;
}
default:
*out_str++ = ch;
}
*out_str++ = '\0';
if (strlcpy(outbuf, temp, sizeof (shell_line)) >= sizeof (shell_line))
error(gettext("Command too long"));
return (changed);
}
static void
show(register char ch)
{
char cbuf;
if ((ch < ' ' && ch != '\n' && ch != ESC) || ch == RUBOUT) {
ch += ch == RUBOUT ? -0100 : 0100;
write (2, &CARAT, 1);
promptlen++;
}
cbuf = ch;
write (2, &cbuf, 1);
promptlen++;
}
static void
error (char *mess)
{
if (clreol)
cleareol ();
else
kill_line ();
promptlen += strlen (mess);
if (enter_standout_mode && exit_standout_mode) {
putp (enter_standout_mode);
pr(mess);
putp (exit_standout_mode);
}
else
pr (mess);
fflush(stdout);
errors++;
longjmp (restore, 1);
}
static void
set_tty(void)
{
ioctl(2, TCGETA, &otty);
ioctl(2, TCGETA, &ntty);
ntty.c_lflag &= ~ECHO & ~ICANON;
ntty.c_cc[VMIN] = (char)1;
ntty.c_cc[VTIME] = (char)0;
ioctl (2, TCSETAF, &ntty);
}
static void
reset_tty(void)
{
ioctl (2, TCSETAF, &otty);
}
static void
rdline(register FILE *f)
{
register int c;
register char *p;
p = Line;
while ((c = Getc (f)) != '\n' && c != EOF && p - Line < LINSIZ - 1)
*p++ = c;
if (c == '\n')
Currline++;
*p = '\0';
}
#ifdef SIGTSTP
void
onsusp(int sig)
{
signal(SIGTTOU, SIG_IGN);
reset_tty ();
fflush (stdout);
signal(SIGTTOU, SIG_DFL);
kill (0, SIGTSTP);
signal (SIGTSTP, onsusp);
set_tty ();
if (inwait)
longjmp (restore, 1);
}
#endif