#include <sys/types.h>
#include <libgen.h>
#include <stdarg.h>
#include "less.h"
char *every_first_cmd = NULL;
int new_file;
int is_tty;
IFILE curr_ifile = NULL;
IFILE old_ifile = NULL;
struct scrpos initial_scrpos;
int any_display = FALSE;
off_t start_attnpos = -1;
off_t end_attnpos = -1;
int wscroll;
static char *progname;
int quitting;
int secure;
int dohelp;
int logfile = -1;
int force_logfile = FALSE;
char *namelogfile = NULL;
char *editor;
char *editproto;
extern char *tags;
extern char *tagoption;
extern int jump_sline;
extern int less_is_more;
extern int missing_cap;
extern int know_dumb;
extern int quit_if_one_screen;
extern int quit_at_eof;
extern int pr_type;
extern int hilite_search;
extern int no_init;
extern int top_scroll;
extern int errmsgs;
int
main(int argc, char *argv[])
{
IFILE ifile;
char *s;
progname = basename(argv[0]);
argv++;
argc--;
if (strcmp(progname, "more") == 0)
less_is_more = 1;
else {
s = lgetenv("LESS_IS_MORE");
if (s != NULL && *s != '\0')
less_is_more = 1;
}
secure = 0;
s = lgetenv("LESSSECURE");
if (s != NULL && *s != '\0')
secure = 1;
if (secure) {
if (pledge("stdio rpath tty", NULL) == -1) {
perror("pledge");
exit(1);
}
} else {
if (pledge("stdio rpath wpath cpath fattr proc exec tty", NULL) == -1) {
perror("pledge");
exit(1);
}
}
is_tty = isatty(1);
get_term();
init_cmds();
init_charset();
init_line();
init_cmdhist();
init_option();
init_search();
init_prompt();
if (less_is_more) {
quit_at_eof = OPT_ON;
know_dumb = OPT_ON;
pr_type = OPT_ON;
hilite_search = OPT_OFF;
no_init = OPT_ON;
top_scroll = OPT_OFF;
}
s = lgetenv(less_is_more ? "MORE" : "LESS");
if (s != NULL)
scan_option(estrdup(s), 1);
#define isoptstring(s) (((s)[0] == '-' || (s)[0] == '+') && (s)[1] != '\0')
while (argc > 0 && (isoptstring(*argv) || isoptpending())) {
s = *argv++;
argc--;
if (strcmp(s, "--") == 0)
break;
scan_option(s, 0);
}
#undef isoptstring
if (isoptpending()) {
nopendopt();
quit(QUIT_OK);
}
if (errmsgs) {
quit(QUIT_ERROR);
}
if (less_is_more && quit_at_eof == OPT_ONPLUS) {
extern int no_init;
no_init = OPT_ON;
}
if (less_is_more && pr_type == OPT_ONPLUS) {
extern int quiet;
quiet = VERY_QUIET;
}
editor = lgetenv("VISUAL");
if (editor == NULL || *editor == '\0') {
editor = lgetenv("EDITOR");
if (editor == NULL || *editor == '\0')
editor = EDIT_PGM;
}
editproto = lgetenv("LESSEDIT");
if (editproto == NULL || *editproto == '\0')
editproto = "%E ?lm+%lm. %f";
ifile = NULL;
if (dohelp)
ifile = get_ifile(helpfile(), ifile);
while (argc-- > 0) {
char *filename;
filename = shell_quote(*argv);
if (filename == NULL)
filename = *argv;
argv++;
(void) get_ifile(filename, ifile);
ifile = prev_ifile(NULL);
free(filename);
}
if (!is_tty) {
if (nifile() == 0) {
if (edit_stdin() == 0)
cat_file();
} else if (edit_first() == 0) {
do {
cat_file();
} while (edit_next(1) == 0);
}
quit(QUIT_OK);
}
if (missing_cap && !know_dumb)
error("WARNING: terminal is not fully functional", NULL);
init_mark();
open_getchr();
if (secure)
if (pledge("stdio rpath tty", NULL) == -1) {
perror("pledge");
exit(1);
}
raw_mode(1);
init_signals(1);
if (tagoption != NULL || strcmp(tags, "-") == 0) {
if (nifile() > 0) {
error("No filenames allowed with -t option", NULL);
quit(QUIT_ERROR);
}
findtag(tagoption);
if (edit_tagfile())
quit(QUIT_ERROR);
initial_scrpos.pos = tagsearch();
if (initial_scrpos.pos == -1)
quit(QUIT_ERROR);
initial_scrpos.ln = jump_sline;
} else if (nifile() == 0) {
if (edit_stdin())
quit(QUIT_ERROR);
} else {
if (edit_first())
quit(QUIT_ERROR);
}
init();
commands();
quit(QUIT_OK);
return (0);
}
void *
ecalloc(int count, unsigned int size)
{
void *p;
p = calloc(count, size);
if (p != NULL)
return (p);
error("Cannot allocate memory", NULL);
quit(QUIT_ERROR);
return (NULL);
}
char *
easprintf(const char *fmt, ...)
{
char *p = NULL;
int rv;
va_list ap;
va_start(ap, fmt);
rv = vasprintf(&p, fmt, ap);
va_end(ap);
if (rv == -1) {
error("Cannot allocate memory", NULL);
quit(QUIT_ERROR);
}
return (p);
}
char *
estrdup(const char *str)
{
char *n;
n = strdup(str);
if (n == NULL) {
error("Cannot allocate memory", NULL);
quit(QUIT_ERROR);
}
return (n);
}
char *
skipsp(char *s)
{
while (*s == ' ' || *s == '\t')
s++;
return (s);
}
int
sprefix(char *ps, char *s, int uppercase)
{
int c;
int sc;
int len = 0;
for (; *s != '\0'; s++, ps++) {
c = *ps;
if (uppercase) {
if (len == 0 && islower(c))
return (-1);
c = tolower(c);
}
sc = *s;
if (len > 0)
sc = tolower(sc);
if (c != sc)
break;
len++;
}
return (len);
}
void
quit(int status)
{
static int save_status;
if (status < 0)
status = save_status;
else
save_status = status;
quitting = 1;
edit(NULL);
if (!secure)
save_cmdhist();
if (any_display && is_tty)
clear_bot();
deinit();
flush(1);
raw_mode(0);
exit(status);
}
char *
helpfile(void)
{
return (less_is_more ? HELPDIR "/more.help" : HELPDIR "/less.help");
}