home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
531.lha
/
Less_v1.4Z
/
src.LZH
/
src
/
main.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-07-03
|
17KB
|
635 lines
/*
* Entry point, initialization, miscellaneous routines.
*/
#ifdef AMIGA
/* Compile with -HPreHeader.q to get "less.h"! */
#else
#include "less.h"
#endif
#include "position.h"
#include <setjmp.h>
#include <signal.h>
public int ispipe;
public jmp_buf main_loop;
public char * first_cmd;
public char * every_first_cmd;
public int new_file;
public int is_tty;
public char current_file[FILENAME];
public char previous_file[FILENAME];
public POSITION prev_pos;
public int any_display;
public int ac;
public char ** av;
public int curr_ac;
#if LOGFILE
public int logfile = -1;
public int force_logfile = 0;
public char * namelogfile = NULL;
#endif
#if EDITOR
public char * editor;
#endif
extern int file;
extern int nbufs;
extern int sigs;
extern int quit_at_eof;
extern int p_nbufs, f_nbufs;
extern int back_scroll;
extern int top_scroll;
extern int sc_height;
extern int errmsgs;
/* Prototypes for functions defined in main.c */
static void SeekRoot __PROTO((ULONG lock));
#ifdef AMIGA
/********** amiga **************/
#include <ctype.h>
#include <dos.h>
#include <intuition/intuition.h>
#include <exec/memory.h>
#include <ios1.h>
extern struct UFB _ufbs[];
/* Used by SeekRoot */
#define MAXPATHSTRING 256
static char absDir[MAXPATHSTRING];
struct IntuitionBase *IntuitionBase;
struct Remember *RememberKey;
int called_from_WB = 0;
/* max items and chars that *.c can expand to */
#define MAXTEMPLATES 100
public char *local_argv[MAXTEMPLATES];
public int local_argc;
#endif
/*
* Edit a new file.
* Filename "-" means standard input.
* No filename means the "current" file, from the command line.
*/
#ifdef __STDC__
void edit (register char *filename)
#else
public void
edit(filename)
register char *filename;
#endif
{
register int f;
register char *m;
POSITION initial_pos;
char message[100];
char tempfile[FILENAME];
static int didpipe;
initial_pos = NULL_POSITION;
if (filename == NULL || *filename == '\0')
{
if (curr_ac >= ac)
{
error("No current file");
return;
}
filename = av[curr_ac];
}
if (strcmp(filename, "#") == 0)
{
if (*previous_file == '\0')
{
error("no previous file");
return;
}
strtcpy(tempfile, previous_file, sizeof(tempfile));
filename = tempfile;
initial_pos = prev_pos;
}
if (strcmp(filename, "-") == 0)
{
/*
* Use standard input.
*/
if (didpipe)
{
error("Can view standard input only once");
return;
}
f = 0;
#ifdef AMIGA
/* get standard input */
if ( !chkufb(0) ) /* if linked with tinymain, we get no stdin */
{
_ufbs[0].ufbfh = Input();
_ufbs[0].ufbflg |= UFB_RA | O_RAW;
if ( !called_from_WB ) _ufbs[0].ufbflg |= UFB_NC;
}
#endif
} else if ((m = bad_file(filename, message, sizeof(message))) != NULL)
{
error(m);
return;
} else if ((f = open(filename, 0)) < 0)
{
error(errno_message(filename, message, sizeof(message)));
return;
}
#ifdef AMIGA
/* SAS 5.10a isatty is broken; reports that pipe:x is a tty */
if (isatty(f) && f==0)
#else
if (isatty(f))
#endif
{
/*
* Not really necessary to call this an error,
* but if the control terminal (for commands)
* and the input file (for data) are the same,
* we get weird results at best.
*/
error("Can't take input from a terminal");
if (f > 0)
close(f);
return;
}
#if LOGFILE
/*
* If he asked for a log file and we have opened standard input,
* create the log file.
* We take care not to blindly overwrite an existing file.
*/
end_logfile();
if (f == 0 && namelogfile != NULL && is_tty)
{
int exists;
int answer;
/*
* {{ We could use access() here. }}
*/
exists = open(namelogfile, 0);
close(exists);
exists = (exists >= 0);
if (exists && !force_logfile)
{
static char w[] = "WARNING: log file exists: ";
strcpy(message, w);
strtcpy(message+sizeof(w)-1, namelogfile,
sizeof(message)-sizeof(w));
error(message);
answer = 'X'; /* Ask the user what to do */
} else
answer = 'O'; /* Create the log file */
loop:
switch (answer)
{
case 'O': case 'o':
logfile = creat(namelogfile, 0644);
break;
case 'A': case 'a':
logfile = open(namelogfile, 1);
if (lseek(logfile, (offset_t)0, 2) < 0)
{
close(logfile);
logfile = -1;
}
break;
case 'D': case 'd':
answer = 0; /* Don't print an error message */
break;
case 'q':
quit();
default:
putstr("\n Overwrite, Append, or Don't log? ");
answer = getchr();
putstr("\n");
flush();
goto loop;
}
if (logfile < 0 && answer != 0)
{
sprintf(message, "Cannot write to \"%s\"",
namelogfile);
error(message);
}
}
#endif
/*
* We are now committed to using the new file.
* Close the current input file and set up to use the new one.
*/
if (file > 0)
close(file);
new_file = 1;
strtcpy(previous_file, current_file, sizeof(previous_file));
strtcpy(current_file, filename, sizeof(current_file));
prev_pos = position(TOP);
#ifdef AMIGA
/* Some heuristics to determine if we've been given a pipe.
(there must be a better way...)
*/
ispipe = ((f == 0) && !called_from_WB)
|| (strnicmp(filename, "pipe:", 5) == 0); /* kludge! */
#else
ispipe = (f == 0);
#endif
if (ispipe)
didpipe = 1;
file = f;
ch_init( (ispipe) ? p_nbufs : f_nbufs );
init_mark();
if (every_first_cmd != NULL)
first_cmd = every_first_cmd;
if (is_tty)
{
int no_display = !any_display;
any_display = 1;
if (no_display && errmsgs > 0)
{
/*
* We displayed some messages on error output
* (file descriptor 2; see error() function).
* Before erasing the screen contents,
* display the file name and wait for a keystroke.
*/
error(filename);
}
/*
* Indicate there is nothing displayed yet.
*/
pos_clear();
if (initial_pos != NULL_POSITION)
jump_loc(initial_pos);
}
}
/*
* Edit the next file in the command line list.
*/
#ifdef __STDC__
void next_file (int n)
#else
public void
next_file(n)
int n;
#endif
{
if (curr_ac + n >= ac)
{
if (quit_at_eof)
quit();
error("No (N-th) next file");
} else
edit(av[curr_ac += n]);
}
/*
* Edit the previous file in the command line list.
*/
#ifdef __STDC__
void prev_file (int n)
#else
public void
prev_file(n)
int n;
#endif
{
if (curr_ac - n < 0)
error("No (N-th) previous file");
else
edit(av[curr_ac -= n]);
}
#ifndef AMIGA
/*
* Copy a file directly to standard output.
* Used if standard output is not a tty.
*/
static void
cat_file()
{
register int c;
while ((c = ch_forw_get()) != EOF)
putchr(c);
flush();
}
#endif
#ifdef AMIGA
/**************** amiga *****************************/
/* Bob Leivian 4/28/87 fudge up things so it will work
when called from Work Bench */
char argvbuf[80];
#include "workbench/startup.h"
#ifdef MANX
/* ignore AZTECs wb stuff */
_wb_parse(ignore, ignore2)
char *ignore;
char *ignore2;
{
return;
}
#endif
#endif
#ifdef NO_GETENV
/* this requires the workbench disk --
ignore all environment variables for now */
char * getenv(ignore)
{
return NULL;
}
#endif
/*
* Entry point.
*/
#ifdef __STDC__
int main (int argc, char **argv)
#else
main(argc, argv)
int argc;
char *argv[];
#endif
{
char *getenv();
#ifdef AMIGA
/***************** amiga ********************/
IntuitionBase = OpenLibrary ( "intuition.library", 0 );
RememberKey = NULL;
/* if we were called from the workbench we will have no args
but a pointer to WBstruct, get the filename from this structure */
if(argc == 0) {
struct WBStartup *WBmsg;
struct WBArg *p;
char *cp, c;
BPTR newlock;
/* the argv is really the work bench structure */
WBmsg = (struct WBStartup *) argv;
p = WBmsg->sm_ArgList;
/* fake up the args now */
/* argv[0] = p->wa_Name; */
p++; /* ignore first parm (name), since Less don't use it */
for ( local_argc = 1; local_argc < WBmsg->sm_NumArgs
&& local_argc < MAXTEMPLATES; local_argc++ )
{
*absDir = '\0';
/* SeekRoot UnLocks its argument */
newlock = DupLock ( p->wa_Lock );
SeekRoot ( newlock );
/* The first part is really a device name */
for ( cp=absDir; (c = *cp) && c != '/'; cp++ )
/* nothing */;
*cp = ':';
if ( c == '\0' ) /* root dir of a device */
*++cp = '\0';
else
strcat(cp, "/");
if ( !(cp = AllocRemember(&RememberKey,
strlen(absDir)+strlen(p->wa_Name)+1, 0L)) )
quit();
strcpy ( cp, absDir );
local_argv[local_argc] = strcat(cp, p->wa_Name);
p++;
}
local_argv[local_argc] = NULL;
called_from_WB = 1;
}
#endif
/*
* Process command line arguments and LESS environment arguments.
* Command line arguments override environment arguments.
*/
init_option();
scan_option(getenv("LESS"));
argv++;
while ( (--argc > 0) &&
(argv[0][0] == '-' || argv[0][0] == '+') &&
argv[0][1] != '\0')
scan_option(*argv++);
#if EDITOR
editor = getenv("EDITOR");
if (editor == NULL || *editor == '\0')
editor = "ed";
#endif
/*
* Set up list of files to be examined.
*/
#ifdef AMIGA
if ( called_from_WB )
{
ac = local_argc-1;
av = local_argv+1; /* CLI case did an argv++ */
}
else
{
#endif
ac = argc;
av = argv;
#ifdef AMIGA
}
#endif
curr_ac = 0;
/*
* Set up terminal, etc.
*/
#ifdef AMIGA
is_tty = 1;
ttopen();
#else
is_tty = isatty(1);
if (!is_tty)
{
/*
* Output is not a tty.
* Just copy the input file(s) to output.
*/
if (ac < 1)
{
edit("-");
cat_file();
} else
{
do
{
edit((char *)NULL);
if (file >= 0)
cat_file();
} while (++curr_ac < ac);
}
quit();
}
#endif
raw_mode(1);
get_term();
open_getchr();
init();
if (setjmp(main_loop))
quit();
init_signals();
/*
* Select the first file to examine.
*/
if (ac < 1)
edit("-"); /* Standard input */
else
{
/*
* Try all the files named as command arguments.
* We are simply looking for one which can be
* opened without error.
*/
do
{
edit((char *)NULL);
} while (file < 0 && ++curr_ac < ac);
}
if (file >= 0)
commands();
quit();
/*NOTREACHED*/
}
/*
* Copy a string, truncating to the specified length if necessary.
* Unlike strncpy(), the resulting string is guaranteed to be null-terminated.
*/
#ifdef __STDC__
void strtcpy (char *to, char *from, int len)
#else
strtcpy(to, from, len)
char *to;
char *from;
int len;
#endif
{
strncpy(to, from, len);
to[len-1] = '\0';
}
/*
* Exit the program.
*/
#ifdef __STDC__
void quit (void)
#else
public void
quit()
#endif
{
/*
* Put cursor at bottom left corner, clear the line,
* reset the terminal modes, and exit.
*/
#if LOGFILE
end_logfile();
#endif
#ifdef AMIGA
ttclose();
if (IntuitionBase)
{
FreeRemember( &RememberKey, 1 );
CloseLibrary(IntuitionBase);
}
#else
lower_left();
clear_eol();
deinit();
flush();
raw_mode(0);
#endif
exit(0);
}
#ifdef AMIGA
/* Thanks to Bruce Rogers for a UseNet posting including the following
useful function...
*/
/*!*******************************************************************
* FindRoot by Bruce Rogers 1/20/90
*********************************************************************/
/*
------------------------------------------------------ Quantum _\/_
2727 Eel Bruce (6502 RULES!) Rogers |\ Duck ( 0 0)
Davis, Ca 95616 Quantum Duck Software, |\ \______/ / \\\
916-756-2684 rogers@iris.ucdavis.edu |\ < < | \/
"My brain is on fire!" \________/ Quark!
*/
/*!*******************************************************************
* Recursively go up parent chain, looking for oldest parent.
* Create the absolute path string as we go.
*********************************************************************/
static void SeekRoot(lock)
ULONG lock;
{
struct FileInfoBlock *fileInfo;
ULONG newlock;
char NameEnd[MAXPATHSTRING], sep;
fileInfo=AllocMem(sizeof(struct FileInfoBlock),0);
Examine(lock,fileInfo);
strcpy ( NameEnd, absDir );
strcpy ( absDir, fileInfo->fib_FileName );
sep = 0; if ( *absDir ) sep = absDir[strlen(absDir) - 1];
if ( sep && *NameEnd && sep != '/' && sep != ':' ) strcat ( absDir, "/" );
strcat ( absDir, NameEnd );
newlock = ParentDir(lock);
UnLock(lock);
if (newlock!=NULL) SeekRoot(newlock);
FreeMem(fileInfo,sizeof(struct FileInfoBlock));
}
#endif