#include "HTUtils.h"
#include "HTInit.h"
#include "HTFile.h"
#include "LYCurses.h"
#include "HTML.h"
#include "HTAccess.h"
#include "LYUtils.h"
#include "LYGlobalDefs.h"
#include "LYSignal.h"
#include "LYGetFile.h"
#include "LYStrings.h"
#include "LYClean.h"
#include "LYCharSets.h"
#include "LYReadCFG.h"
#include "LYrcFile.h"
#include "LYKeymap.h"
#include "HTParse.h"
#ifdef VMS
#include <descrip.h>
#include <lib$routines.h>
#include "HTVMSUtils.h"
#endif /* VMS */

#ifndef VMS
#ifdef SYSLOG_REQUESTED_URLS
#include <syslog.h>
#endif /* SYSLOG_REQUESTED_URLS */
#endif /* !VMS */

#ifdef LOCALE
#include<locale.h>
#endif /* LOCALE */

#include "LYexit.h"
#include "LYLeaks.h"

/* ahhhhhhhhhh!! Global variables :-< */
int HTCacheSize = DEFAULT_CACHE_SIZE;  /* number of docs cached in memory */
#if defined(VMS) && defined(VAXC) && !defined(__DECC)
/* Don't dump doc cache unless this size is exceeded */
int HTVirtualMemorySize = DEFAULT_VIRTUAL_MEMORY_SIZE;
#endif /* VMS && VAXC && !_DECC */
char *empty_string = "\0";
int display_lines;  /* number of lines in display */
int www_search_result= -1;
lynx_printer_item_type *printers = NULL;    /* linked list of printers */
lynx_html_item_type *downloaders = NULL;    /* linked list of download options*/
lynx_html_item_type *uploaders = NULL;
char *log_file_name = NULL;  /* for WAIS log file name in libWWW */
int port_syntax = 1;

BOOLEAN LYShowCursor=SHOW_CURSOR; /* to show or not to show */
BOOLEAN LYforce_no_cache=FALSE;
BOOLEAN LYUserSpecifiedURL=TRUE;  /* always true the first time */
BOOLEAN LYJumpFileURL=FALSE;	  /* always false the first time */
BOOLEAN jump_buffer=JUMPBUFFER;   /* TRUE if recalling shortcuts */
BOOLEAN recent_sizechange=FALSE;  /* the window size changed recently? */
BOOLEAN user_mode=NOVICE_MODE;
BOOLEAN dump_output_immediately=FALSE;
BOOLEAN is_www_index=FALSE;
BOOLEAN lynx_mode=NORMAL_LYNX_MODE;
BOOLEAN bold_headers=FALSE;

#ifdef VMS
BOOLEAN UseFixedRecords = USE_FIXED_RECORDS;	/* create FIXED 512 binaries */
#endif /* VMS */

#ifdef DIRED_SUPPORT
BOOLEAN lynx_edit_mode = FALSE;
BOOLEAN dir_list_style = MIXED_STYLE;
taglink *tagged = NULL;
#endif /* DIRED_SUPPORT */
#ifdef IGNORE_CTRL_C
BOOLEAN sigint = FALSE;
#endif /* IGNORE_CTRL_C */

BOOLEAN child_lynx = FALSE;
#if defined(EXEC_LINKS) || defined(EXEC_SCRIPTS)
#ifndef NEVER_ALLOW_REMOTE_EXEC
BOOLEAN local_exec = LOCAL_EXECUTION_LINKS_ALWAYS_ON;
#else
BOOLEAN local_exec = FALSE;
#endif /* NEVER_ALLOW_REMOTE_EXEC */
BOOLEAN local_exec_on_local_files = LOCAL_EXECUTION_LINKS_ON_BUT_NOT_REMOTE;
#endif /* EXEC_LINKS || EXEC_SCRIPTS */
BOOLEAN error_logging = MAIL_SYSTEM_ERROR_LOGGING;
BOOLEAN check_mail = CHECKMAIL;
BOOLEAN vi_keys = VI_KEYS_ALWAYS_ON;
BOOLEAN emacs_keys = EMACS_KEYS_ALWAYS_ON;
BOOLEAN keypad_mode = DEFAULT_KEYPAD_MODE;
BOOLEAN case_sensitive = CASE_SENSITIVE_ALWAYS_ON;
BOOLEAN telnet_ok = TRUE;
BOOLEAN news_ok = TRUE;
BOOLEAN rlogin_ok = TRUE;
BOOLEAN ftp_ok = TRUE;
BOOLEAN system_editor = FALSE;
BOOLEAN no_inside_telnet = FALSE;
BOOLEAN no_outside_telnet = FALSE;
BOOLEAN no_telnet_port = FALSE;
BOOLEAN no_inside_news = FALSE;
BOOLEAN no_outside_news = FALSE;
BOOLEAN no_inside_ftp = FALSE;
BOOLEAN no_outside_ftp = FALSE;
BOOLEAN no_inside_rlogin = FALSE;
BOOLEAN no_outside_rlogin = FALSE;
BOOLEAN no_suspend = FALSE;
BOOLEAN no_editor = FALSE;
BOOLEAN no_shell = FALSE;
BOOLEAN no_bookmark = FALSE;
BOOLEAN no_option_save = FALSE;
BOOLEAN no_print = FALSE;
BOOLEAN no_download = FALSE;
BOOLEAN no_disk_save = FALSE;
BOOLEAN no_exec = FALSE;
BOOLEAN no_lynxcgi = FALSE;
BOOLEAN exec_frozen = FALSE;
BOOLEAN no_bookmark_exec = FALSE;
BOOLEAN no_goto = FALSE;
BOOLEAN no_jump = FALSE;
BOOLEAN no_file_url = FALSE;
BOOLEAN no_newspost = FALSE;
BOOLEAN no_mail = FALSE;
BOOLEAN nodotfiles = NO_DOT_FILES;
BOOLEAN no_statusline = FALSE;
BOOLEAN local_host_only = FALSE;

#ifdef DIRED_SUPPORT
BOOLEAN no_dired_support = FALSE;
#endif /* DIRED_SUPPORT */

BOOLEAN LYforce_HTML_mode=FALSE;
char *homepage = NULL;		    /* home page or main screen */
char *editor = NULL;  		    /* the name of the current editor */
char *jumpfile = NULL;		    /* the name of the file containing jumps */
char *bookmark_page = NULL;   	    /* the name of the current bookmark page */
char *startfile = NULL;		    /* the first file */
char *helpfile = NULL; 		    /* the help file */
char *indexfile = NULL;		    /* an index file if there is one */
char *personal_mail_address = NULL; /* the users mail address */
char *display=NULL;		    /* display environment variable */
char *personal_type_map = NULL;	    /* .mailcap */
char *global_type_map = NULL;	    /* global mailcap */
char *global_extension_map = NULL;  /* global mime.types */
char *personal_extension_map = NULL;/* .mime.types */
char *language = NULL;		    /* preferred language */
char *inews_path = NULL;	    /* the path for posting to news */
#ifndef VMS
char *http_proxy_putenv_cmd = NULL; /* lynx.cfg specified http_proxy */
char *ftp_proxy_putenv_cmd = NULL;  /* lynx.cfg specified ftp_proxy */
char *gopher_proxy_putenv_cmd=NULL; /* lynx.cfg specified gopher_proxy */
char *news_proxy_putenv_cmd = NULL; /* lynx.cfg specified news_proxy */
char *wais_proxy_putenv_cmd = NULL; /* lynx.cfg specified wais_proxy */
char *no_proxy_putenv_cmd = NULL;   /* lynx.cfg specified no_proxy */
#ifdef SYSLOG_REQUESTED_URLS
char *syslog_txt = NULL;            /* syslog arb text for session */
#endif /* SYSLOG_REQUESTED_URLS */
#endif /* !VMS */

BOOLEAN keep_mime_headers = FALSE;   /* Return mime headers */
BOOLEAN no_url_redirection = FALSE;  /* Don't follow URL redirections */
char *form_post_data = NULL;         /* User data for post form */
char *form_get_data = NULL;          /* User data for get form */
char *http_error_file = NULL;        /* Place HTTP status code in this file */
char *authentication_info[2] = {NULL, NULL}; /* Id:Password for protected forms */


int LYlines = 24;
int LYcols = 80;

linkstruct links[MAXLINKS] = {NULL};

histstruct history[MAXHIST] = {NULL};

int nlinks = 0;  /* number of links in memory */
int nhist = 0;   /* number of history entries */
int more = FALSE; /* is there more text to display? */

PRIVATE void parse_arg PARAMS((char **arg, int *i, int argc));
PRIVATE void FatalProblem PARAMS((int sig));
extern void mainloop();

PRIVATE BOOLEAN restrictions_set=FALSE;
PRIVATE BOOLEAN stack_dump=FALSE;
PRIVATE char *terminal=NULL;
PRIVATE char *pgm;

PUBLIC int main ARGS2(int,argc, char **,argv)
{
    int  i;  /* indexing variable */
    char *lynx_cfg_file=NULL;
    char *lynx_version_putenv_command=NULL;
    char *cp;
    FILE *fp;

    pgm = argv[0];
    if ((cp = strrchr(pgm, '/')) != NULL) {
	pgm = cp + 1;
    }

#ifdef ULTRIX
    if (!strcmp(getenv("TERM"), "xterm"))
        terminal = "vt100";
#endif /* ULTRIX */

#ifdef SOCKS
    SOCKSinit(argv[0]);
#endif /* SOCKS */

#ifdef LY_FIND_LEAKS
    /*
     *	Register the final function to be executed when being exited.
     *	Will display memory leaks if LY_FIND_LEAKS is defined.
     */
    atexit(LYLeaks);
#endif /* LY_FIND_LEAKS */

#ifdef LOCALE
    /* LOCALE support for international characters. */
    setlocale(LC_ALL, "");
#endif /* LOCALE */

    /* initialize some variables */
    /* zero the links struct array */
    memset((void *)links, 0, sizeof(linkstruct)*MAXLINKS);

#ifndef VMS
#ifdef SYSLOG_REQUESTED_URLS
    openlog("lynx", LOG_PID, LOG_LOCAL5);
#endif /* SYSLOG_REQUESTED_URLS */
#endif /* !VMS */

    StrAllocCopy(helpfile, HELPFILE);
    StrAllocCopy(startfile, STARTFILE);
#ifdef JUMPFILE
    StrAllocCopy(jumpfile, JUMPFILE);
#endif /* JUMPFILE */
    StrAllocCopy(indexfile, DEFAULT_INDEX_FILE);
    StrAllocCopy(global_type_map, GLOBAL_MAILCAP);
    StrAllocCopy(personal_type_map, PERSONAL_MAILCAP);
    StrAllocCopy(global_extension_map, GLOBAL_EXTENSION_MAP);
    StrAllocCopy(personal_extension_map, PERSONAL_EXTENSION_MAP);
    StrAllocCopy(language, PREFERRED_LANGUAGE);
    StrAllocCopy(inews_path, INEWS);

#ifdef UNIX
    StrAllocCopy(lynx_version_putenv_command,"LYNX_VERSION=");
    StrAllocCat(lynx_version_putenv_command,LYNX_VERSION);
    putenv(lynx_version_putenv_command);
#endif /* UNIX */

    /* set up trace, if requested, and an alternate
     * configuration file, if specified, now
     */
    for (i=1; i<argc; i++) {
	if (strncmp(argv[i], "-trace", 6) == 0)
	    WWW_TraceFlag = TRUE;
	else if (strncmp(argv[i], "-cfg", 4) == 0) {
	    if((cp=strchr(argv[i],'=')) != NULL)
                StrAllocCopy(lynx_cfg_file, cp+1);
            else {
                StrAllocCopy(lynx_cfg_file, argv[i+1]);
                i++;
            }
	}
    }

    /*
     * If no alternate configuration file was specified on
     * the command line, see if it's in the environment.
     */
    if (!lynx_cfg_file) {
        if (((cp=getenv("LYNX_CFG")) != NULL) ||
	    (cp=getenv("lynx_cfg")) != NULL)
	    StrAllocCopy(lynx_cfg_file, cp);
    }

    /*
     * If we still don't have a configuration file,
     * use the userdefs.h definition.
     */
    if (!lynx_cfg_file)
    	StrAllocCopy(lynx_cfg_file, LYNX_CFG_FILE);

    /*
     * On Unix, covert a '~' in the configuration file path to $HOME.
     */
#ifndef VMS 
    if ((cp = strchr(lynx_cfg_file, '~'))) {
        FILE *fp;
	char *temp = NULL;
	
	*(cp++) = '\0';
	StrAllocCopy(temp, lynx_cfg_file);
	StrAllocCat(temp, getenv("HOME"));
	StrAllocCat(temp, cp);
	StrAllocCopy(lynx_cfg_file, temp);
	free(temp);
    }
#endif /* !VMS */

    /*
     * If the configuration file is not readable,
     * inform the user and exit.
     */
    if ((fp = fopen(lynx_cfg_file, "r")) == NULL) {
        fprintf(stderr, "\nConfiguration file %s is not readable.\n\n",
			lynx_cfg_file);
	exit(1);
    }
    fclose(fp);

    /*
     * Process the configuration file.
     */
    read_cfg(lynx_cfg_file);
    free(lynx_cfg_file);

    /*
     * Set up the file extension and mime type maps from
     * src/HTInit.c and the global and personal mime.types
     * and mailcap files.  These will override any SUFFIX
     * or VIEWER maps in userdefs.h or the configuration
     * file, if they overlap.
     */
    HTFormatInit();
    HTFileInit();

    /*
     * Get WWW_HOME environment variable if it exists)
     */
    if((cp = getenv("WWW_HOME")) != NULL)
	StrAllocCopy(startfile, cp);

    /*
     * Process arguments - with none, look for the database in STARTDIR,
     * starting with STARTFILE.
     *
     * If a pathname is given, use it as the starting point.  Split it
     * into directory and file components, 'cd' to the directory, and
     * view the file.
     */

     /*
      * If the only argument is '-' then we expect to see the arguments on
      * stdin, this is to allow for the potentially very long command line that
      * can be associated with post or get data.
      */
     if (argc == 2 && strcmp(argv[1], "-") == 0) {
	 char buf[1025];
	 char *argv[2];
	 
	 argv[0] = buf;
	 argv[1] = NULL;
	 
	 while(fgets(buf, sizeof(buf) - 1, stdin)) {
	     int j;
	     
	     for(j = strlen(buf) - 1; j > 0 && 
		 (buf[j] == CR || buf[j] == LF); j--) {
		 buf[j] = '\0';
	     }
	     parse_arg(argv, NULL, -1);
	 }
     } else {
	 for (i=1; i<argc; i++) {
	     parse_arg(&argv[i], &i, argc);
	 }
     }
    
#ifndef VMS
#ifdef SYSLOG_REQUESTED_URLS
    if (syslog_txt) {
	syslog(LOG_INFO, "Session start:%s", syslog_txt);
    } else {
	syslog(LOG_INFO, "Session start");
    }
#endif /* SYSLOG_REQUESTED_URLS */
#endif /* !VMS */

    /* read the rc file */
    read_rc();
#if defined(EXEC_LINKS) || defined(EXEC_SCRIPTS)
#ifdef NEVER_ALLOW_REMOTE_EXEC
    if (local_exec) {
        local_exec = FALSE;
	local_exec_on_local_files=TRUE;
    }
#endif /* NEVER_ALLOW_REMOTE_EXEC */
#endif /* EXEC_LINKS || EXEC_SCRIPTS */


    if (emacs_keys)
        set_emacs_keys();
 
    if (vi_keys)
        set_vi_keys();
 
    if (keypad_mode == NUMBERS_AS_ARROWS)
        set_numbers_as_arrows();

    /* disable news posting if no posting command */
    if (*inews_path == '\0' || !strcasecomp(inews_path,"none"))
        no_newspost = TRUE;

#ifdef VMS
    set_vms_keys();
#endif /* VMS */


    /* trap interrupts */    
    if(!dump_output_immediately)
        (void) signal (SIGHUP, cleanup_sig);
    (void) signal (SIGTERM, cleanup_sig);
#ifdef SIGWINCH
    (void) signal (SIGWINCH, size_change);
#endif /* SIGWINCH */
#ifndef VMS
    if(!TRACE && !dump_output_immediately && !stack_dump) {
        (void) signal (SIGINT, cleanup_sig);
#ifndef __linux__
        (void) signal (SIGBUS, FatalProblem);
#endif /* !__linux__ */
        (void) signal (SIGSEGV, FatalProblem);
        (void) signal (SIGILL, FatalProblem);
        /*
	 * Since we're doing lots of TCP, just ignore SIGPIPE altogether.
	 *
	 * HTTCP.c should deal with a broken pipe for servers.
	 * Rick Mallet's check after c = GetChar() in LYStrings.c should
	 *  deal with a disconnected terminal.
	 * So the runaway CPU time problem on Unix should not occur any
	 *  more.
	 */
        (void) signal (SIGPIPE, SIG_IGN);
    }
#endif /* !VMS */

    /* set up the proper character set */
    HTMLUseCharacterSet(current_char_set);

    /*
     * If startfile is a file URL and the host is defaulted,
     * force in "//localhost".  We need this until all the
     * other Lynx code which performs security checks based
     * on the "localhost" string is changed to assume
     * "//localhost" when a host field is not present in file
     * URLs - FM
     */
    if(!strncmp(startfile, "file:", 5)) {
	char *temp=NULL;
        if (startfile[5] == '\0') {
            StrAllocCat(startfile, "//localhost");
        } else if(!strcmp(startfile, "file://")) {
            StrAllocCat(startfile, "localhost");
        } else if(!strncmp(startfile, "file:///", 8)) {
	    StrAllocCopy(temp, (startfile+7));
	    StrAllocCopy(startfile, "file://localhost");
	    StrAllocCat(startfile, temp);
	    free(temp);
        } else if (!strncmp(startfile, "file:/", 6) && startfile[6] != '/') {
	    StrAllocCopy(temp, (startfile+5));
	    StrAllocCopy(startfile, "file://localhost");
	    StrAllocCat(startfile, temp);
	    free(temp);
	}
    }

    /*
     * No path in a file://localhost URL for startfile means
     * a directory listing for the current default. - FM
     */
    if(!strcmp(startfile, "file://localhost")) {
#ifdef VMS
	StrAllocCat(startfile, HTVMS_wwwName(getenv("PATH")));
#else
        char curdir[DIRNAMESIZE];
#ifdef NO_GETCWD
      	getwd (curdir);
#else
    	getcwd (curdir, DIRNAMESIZE);
#endif /* NO_GETCWD */
	StrAllocCat(startfile, curdir);
#endif /* VMS */
    }

#ifdef VMS
    /*
     * On VMS, a file://localhost/ URL for startfile
     * means a listing for the login directory. - FM
     */
    if(!strcmp(startfile, "file://localhost/"))
	StrAllocCat(startfile, (HTVMS_wwwName(getenv("HOME"))+1));
#endif /* VMS */

    /*
     * If its not a URL then make it one
     */
    if(!is_url(startfile)) {
	    /* rewrite the file as a URL */
	   char *old_startfile=startfile; 

	   startfile = NULL;  /* so StrAllocCopy doesn't free it */
	   StrAllocCopy(startfile,"file://localhost");
	   if(*old_startfile != '/') {
#ifdef VMS
	      /*
	       *  Not a URL pathspec.  Get the full VMS spec and convert it.
	       */
	       char *cp, *cur_dir=NULL, *tmp_dir=NULL;
	       static char start_file[256], file_name[256];
	       int context = 0;
	       $DESCRIPTOR(start_file_dsc, start_file);
	       $DESCRIPTOR(file_name_dsc, file_name);
	       strcpy(start_file, old_startfile);
	       start_file_dsc.dsc$w_length = (short) strlen(old_startfile);
	       if (1&lib$find_file(&start_file_dsc, &file_name_dsc, &context,
    				   0, 0, 0, 0)) {
		  /*
		   *  We found the file.  Convert to a URL pathspec.
		   */
	           if ((cp=strchr(file_name, ';')) != NULL)
		       *cp = '\0';
		   for (cp = file_name; *cp; cp++)
		   	*cp = TOLOWER(*cp);
		   strcpy(start_file, HTVMS_wwwName(file_name));
		   if ((cp=strchr(old_startfile, ';')) != NULL)
		       strcat(start_file, cp);
	       } else if ((cur_dir=getcwd(cur_dir, 256, 0)) &&
	       		  0==chdir(old_startfile)) {
		   /*
		    * Probably a directory.  Try converting that.
		    */
		   tmp_dir = getcwd(tmp_dir, 256, 0);
		   if (tmp_dir) {
		       /*
		        * Yup, we got it!
			*/
		       strcpy(start_file, tmp_dir);
		       free(tmp_dir);
		   } else {
		       /*
		        *  Nope.  Use original pathspec for the
			*  error message that will result.
			*/
		       strcpy(start_file, "/");
		       strcat(start_file, old_startfile);
		   }
	       } else {
	          /*
		   *  Nothing found.  Use original pathspec for the
		   *  error message that will result.
		   */
	           strcpy(start_file, "/");
	           strcat(start_file, old_startfile);
	       }
	       lib$find_file_end(&context);
	       if (cur_dir) {
	           chdir(cur_dir);
		   free(cur_dir);
	       }
	       StrAllocCat(startfile, start_file);
	   } else {
	      /*
	       *  Use the original, URL pathspec.
	       */
	       StrAllocCat(startfile, old_startfile);
	   }
#else /* Unix: */
               	char curdir[DIRNAMESIZE];
#ifdef NO_GETCWD
      		getwd (curdir);
#else
    		getcwd (curdir, DIRNAMESIZE);
#endif /* NO_GETCWD */
		StrAllocCat(startfile,curdir);

		StrAllocCat(startfile,"/");
	   }
	   StrAllocCat(startfile,old_startfile);
#endif /* VMS */
	   if(old_startfile)
	       free(old_startfile);
    }

    /*
     * If homepage is a file URL and the host is defaulted,
     * force in "//localhost".  We need this until all the
     * other Lynx code which performs security checks based
     * on the "localhost" string is changed to assume
     * "//localhost" when a host field is not present in file
     * URLs - FM
     */
    if(homepage && !strncmp(homepage, "file:", 5)) {
	char *temp=NULL;
        if (homepage[5] == '\0') {
            StrAllocCat(homepage, "//localhost");
        } else if(!strcmp(homepage, "file://")) {
            StrAllocCat(homepage, "localhost");
        } else if(!strncmp(homepage, "file:///", 8)) {
	    StrAllocCopy(temp, (homepage+7));
	    StrAllocCopy(homepage, "file://localhost");
	    StrAllocCat(homepage, temp);
	    free(temp);
        } else if (!strncmp(homepage, "file:/", 6) && homepage[6] != '/') {
	    StrAllocCopy(temp, (homepage+5));
	    StrAllocCopy(homepage, "file://localhost");
	    StrAllocCat(homepage, temp);
	    free(temp);
	}
    }

    /*
     * No path in a file://localhost URL for homepage means
     * a directory listing for the current default. - FM
     */
    if(homepage && !strcmp(homepage, "file://localhost")) {
#ifdef VMS
	StrAllocCat(homepage, HTVMS_wwwName(getenv("PATH")));
#else
        char curdir[DIRNAMESIZE];
#ifdef NO_GETCWD
      	getwd (curdir);
#else
    	getcwd (curdir, DIRNAMESIZE);
#endif /* NO_GETCWD */
	StrAllocCat(homepage, curdir);
#endif /* VMS */
    }

#ifdef VMS
    /*
     * On VMS, a file://localhost/ URL for homepage
     * means a listing for the login directory. - FM
     */
    if(homepage && !strcmp(homepage, "file://localhost/"))
	StrAllocCat(homepage, (HTVMS_wwwName(getenv("HOME"))+1));
#endif /* VMS */

    if(homepage && !is_url(homepage)) {
	    /* rewrite the file as a URL */
	   char *old_homepage=homepage; 

	   homepage = NULL;  /* so StrAllocCopy doesn't free it */
	   StrAllocCopy(homepage,"file://localhost");
	   if(*old_homepage != '/') {
#ifdef VMS
	      /*
	       *  Not a URL pathspec.  Get the full VMS spec and convert it.
	       */
	       char *cp, *cur_dir=NULL, *tmp_dir=NULL;
	       static char home_page[256], file_name[256];
	       int context = 0;
	       $DESCRIPTOR(home_page_dsc, home_page);
	       $DESCRIPTOR(file_name_dsc, file_name);
	       strcpy(home_page, old_homepage);
	       home_page_dsc.dsc$w_length = (short) strlen(old_homepage);
	       if (1&lib$find_file(&home_page_dsc, &file_name_dsc, &context,
    				   0, 0, 0, 0)) {
		  /*
		   *  We found the file.  Convert to a URL pathspec.
		   */
	           if ((cp=strchr(file_name, ';')) != NULL)
		       *cp = '\0';
		   for (cp = file_name; *cp; cp++)
		   	*cp = TOLOWER(*cp);
		   strcpy(home_page, HTVMS_wwwName(file_name));
		   if ((cp=strchr(old_homepage, ';')) != NULL)
		       strcat(home_page, cp);
	       } else if ((cur_dir=getcwd(cur_dir, 256, 0)) &&
	       		  0==chdir(old_homepage)) {
		   /*
		    * Probably a directory.  Try converting that.
		    */
		   tmp_dir = getcwd(tmp_dir, 256, 0);
		   if (tmp_dir) {
		       /*
		        * Yup, we got it!
			*/
		       strcpy(home_page, tmp_dir);
		       free(tmp_dir);
		   } else {
		       /*
		        *  Nope.  Use original pathspec for the
			*  error message that will result.
			*/
		       strcpy(home_page, "/");
		       strcat(home_page, old_homepage);
		   }
	       } else {
	          /*
		   *  File not found.  Use original pathspec for the
		   *  error message that will result.
		   */
	           strcpy(home_page, "/");
	           strcat(home_page, old_homepage);
	       }
	       lib$find_file_end(&context);
	       if (cur_dir) {
	           chdir(cur_dir);
		   free(cur_dir);
	       }
	       StrAllocCat(homepage, home_page);
	   } else {
	      /*
	       *  Use the original, URL pathspec.
	       */
	       StrAllocCat(homepage, old_homepage);
	   }
#else /* Unix: */
               	char curdir[256];
#ifdef NO_GETCWD
      		getwd (curdir);
#else
    		getcwd (curdir, DIRNAMESIZE);
#endif /* NO_GETCWD */
		StrAllocCat(homepage,curdir);

		StrAllocCat(homepage,"/");
	   }
	   StrAllocCat(homepage,old_homepage);
#endif /* VMS */
	   if(old_homepage)
	       free(old_homepage);
    }
    if (!homepage)
	homepage = startfile;

    /*
     * anonymous may already be set above by command line options.
     * so this just sets the correct options.
     */
#ifndef VMS
#ifdef NO_CUSERID
    if (STREQ(((char *)getlogin()==NULL ? " " : getlogin()) , ANONYMOUS_USER)) {
#else
    if (STREQ((char *)cuserid((char *) NULL), ANONYMOUS_USER)) {
#endif /* NO_CUSERID */
	if(!restrictions_set)
	    parse_restrictions("default");
    }
#endif /* !VMS */

    if(inlocaldomain()) {
#if defined(NO_UTMP) || defined(VMS) /* not selective */
        telnet_ok = !no_inside_telnet && !no_outside_telnet && telnet_ok;
	news_ok = !no_inside_news && !no_outside_news && news_ok;
	ftp_ok = !no_inside_ftp && !no_outside_ftp && ftp_ok;
	rlogin_ok = !no_inside_rlogin && !no_outside_rlogin && rlogin_ok;
#else
	if(TRACE)
	   fprintf(stderr,"LYMain.c: User in Local domain\n");
        telnet_ok = !no_inside_telnet && telnet_ok;
	news_ok = !no_inside_news && news_ok;
	ftp_ok = !no_inside_ftp && ftp_ok;
	rlogin_ok = !no_inside_rlogin && rlogin_ok;
#endif /* NO_UTMP || VMS */
    } else {
	if(TRACE)
	   fprintf(stderr,"LYMain.c: User in REMOTE domain\n");
        telnet_ok = !no_outside_telnet && telnet_ok;
	news_ok = !no_outside_news && news_ok;
	ftp_ok = !no_outside_ftp && ftp_ok;
	rlogin_ok = !no_outside_rlogin && rlogin_ok;
    }

#ifdef SIGTSTP
    if(no_suspend)
	signal(SIGTSTP,SIG_IGN);
#endif /* SIGTSTP */

    /*
     * here's where we do all the work
     */
    if(dump_output_immediately) {
	mainloop();
        (void) signal (SIGHUP, SIG_IGN);
        (void) signal (SIGTERM, SIG_IGN);
        (void) signal (SIGINT, SIG_IGN);
    } else {
 	if (setup(terminal)) {
	    mainloop();
	    cleanup();
	}
    }
 
    exit(0);
    /* NOTREACHED */
}

/* Called by HTAccessInit to register any protocols supported by lynx.
 * Protocols added by lynx:
 *   lynxcgi
 */
GLOBALREF  HTProtocol LYLynxCGI;
PUBLIC void LYRegisterLynxProtocols NOARGS
{
    HTRegisterProtocol(&LYLynxCGI);
}
 
/* Parse one argument, optionally picking up the next entry in argv (if
 * appropriate).
 */
PRIVATE void parse_arg ARGS3(char **, argv, int *, i, int, argc)
{
    char *cp;
 
    if (strncmp(argv[0], "-anonymous", 10) == 0) {
	if(!restrictions_set)
	    parse_restrictions("default");
	
    } else if(strncmp(argv[0], "-restrictions", 13) == 0) {
	if((cp=strchr(argv[0],'=')) != NULL)
	    parse_restrictions(cp+1);
	else 
	    {
		/* print help */
		printf("\n\
   USAGE: lynx -restrictions=[option][,option][,option]\n\
   List of Options:\n\
   all             restricts all options.\n\
   default         same as commandline option -anonymous.  Disables\n\
                   default services for anonymous users.  Currently set to,\n\
                   all restricted except for: inside_telnet, outside_telnet,\n\
                   inside_news, inside_ftp, outside_ftp, inside_rlogin,\n\
		   outside_rlogin, goto, jump and mail.  Defaults settable\n\
		   within userdefs.h\n");
	        printf("\
   bookmark        disallow changing the location of the bookmark file.\n\
   bookmark_exec   disallow execution links via the bookmark file\n");
#ifdef DIRED_SUPPORT
	        printf("\
   dired_support   disallow local file management\n");
#endif /* DIRED_SUPPORT */
	        printf("\
   disk_save       disallow saving binary files to disk in the download menu\n\
   download        disallow downloaders in the download menu\n\
   editor          disallow editing\n\
   exec            disable execution scripts\n\
   exec_frozen     disallow the user from changing the execution link\n\
   file_url        disallow using G)oto to go to file: URL's\n\
   goto            disable the 'g' (goto) command\n");
#if defined(NO_UTMP) || defined(VMS) /* not selective */
	        printf("\
   inside_ftp      disallow ftps for people coming from inside your\n\
                   domain (utmp required for selectivity)\n\
   inside_news     disallow USENET news posting for people coming from\n\
                   inside your domain (utmp required for selectivity)\n\
   inside_rlogin   disallow rlogins for people coming from inside your\n\
                   domain (utmp required for selectivity)\n\
   inside_telnet   disallow telnets for people coming from inside your\n\
                   domain (utmp required for selectivity)\n");
#else
	        printf("\
   inside_ftp      disallow ftps for people coming from inside your domain\n\
   inside_news     disallow USENET news posting for people coming from inside\n\
                   your domain\n\
   inside_rlogin   disallow rlogins for people coming from inside your domain\n\
   inside_telnet   disallow telnets for people coming from inside your domain\n");
#endif /* NO_UTMP || VMS */
	        printf("\
   jump            disable the 'j' (jump) command\n\
   mail            disallow mail\n\
   news_post       disallow USENET News posting setting in the O)ptions menu\n\
   option_save     disallow saving options in .lynxrc\n");
#if defined(NO_UTMP) || defined(VMS) /* not selective */
	        printf("\
   outside_ftp     disallow ftps for people coming from outside your\n\
                   domain (utmp required for selectivity)\n\
   outside_news    disallow USENET news posting for people coming from\n\
                   outside your domain (utmp required for selectivity)\n\
   outside_rlogin  disallow rlogins for people coming from outside your\n\
                   domain (utmp required for selectivity)\n\
   outside_telnet  disallow telnets for people coming from outside your\n\
                   domain (utmp required for selectivity)\n");
#else
		printf("\
   outside_ftp     disallow ftps for people coming from outside your domain\n\
   outside_news    disallow USENET news posting for people coming from outside\n\
                   your domain\n\
   outside_rlogin  disallow rlogins for people coming from outside your domain\n\
   outside_telnet  disallow telnets for people coming from outside your domain\n");
#endif /* NO_UTMP || VMS */
		printf("\
   print           disallow most print options\n\
   shell           disallow shell escapes, lynxexec, and lynxcgi G)oto's\n\
   suspend         disallow Control-Z suspends with escape to shell\n\
   telnet_port     disallow specifying a port in telnet G)oto's\n");
		exit(1);
	    }

    } else if(strncmp(argv[0], "-homepage", 9) == 0) {
	if((cp=strchr(argv[0],'=')) != NULL)
	    StrAllocCopy(homepage,cp+1);
	else if (argv[1]) {
	    StrAllocCopy(homepage,argv[1]);
	    *i++;
	}
	
    } else if(strncmp(argv[0], "-editor", 7) == 0) {
	if((cp=strchr(argv[0],'=')) != NULL)
	    StrAllocCopy(editor,cp+1);
	else if (argv[1]) {
	    StrAllocCopy(editor,argv[1]);
	    *i++;
	}
	system_editor = TRUE;
	
#ifndef VMS
#ifdef SYSLOG_REQUESTED_URLS
    } else if(strncmp(argv[0], "-syslog", 7) == 0) {
	if((cp=strchr(argv[0],'=')) != NULL)
	    StrAllocCopy(syslog_txt,cp+1);
	else if (argv[1]) {
	    StrAllocCopy(syslog_txt,argv[1]);
	    *i++;
	}
#endif /* SYSLOG_REQUESTED_URLS */
#endif /* !VMS */
	
    } else if(strncmp(argv[0], "-display", 8) == 0) {
	
	char *putenv_command;
	
	if((cp=strchr(argv[0],'=')) != NULL)
	    display = cp+1;
	else if (argv[1]) {
	    display = argv[1];
	    *i++;
	}
	
#ifdef UNIX
	StrAllocCopy(putenv_command,"DISPLAY=");
	StrAllocCopy(putenv_command,display);
	putenv(putenv_command);
#endif /* UNIX */
	
    } else if(strncmp(argv[0], "-index", 6) == 0) {
	if((cp=strchr(argv[0],'=')) != NULL)
	    StrAllocCopy(indexfile, cp+1);
	else if (argv[1]) {
	    StrAllocCopy(indexfile, argv[1]);
	    *i++;
	}
	
    } else if(strncmp(argv[0], "-cfg", 4) == 0) {
	/* already read the alternate configuration file 
	 * so just check whether we need to increment i
	 */
	if((cp=strchr(argv[0],'=')) == NULL)
	    *i++;
	
    } else if(strncmp(argv[0], "-stack_dump", 11) == 0) {
	stack_dump = TRUE;
	
    } else if(strncmp(argv[0], "-cache", 6) == 0) {
	if((cp=strchr(argv[0],'=')) != NULL)
	    HTCacheSize = atoi(cp+1);
	else if (argv[1]) {
	    HTCacheSize= atoi(argv[1]);
	    *i++;
	}
	
	/* limit size */
	if(HTCacheSize < 2) HTCacheSize = 2;
	
    } else if(strncmp(argv[0], "-vikeys", 7) == 0) {
	vi_keys = TRUE;
	
    } else if(strncmp(argv[0], "-emacskeys", 10) == 0) {
	emacs_keys = TRUE;
	
    } else if(strncmp(argv[0], "-version", 8) == 0) {
	printf("\n%s Version %s\n(c)1995 University of Kansas\n<lynx-help@ukanaix.cc.ukans.edu>\n\n",LYNX_NAME, LYNX_VERSION);
	exit(0);
	
    } else if(strncmp(argv[0], "-case", 5) == 0) {
	case_sensitive = TRUE;
	
    } else if(strncmp(argv[0], "-dump", 5) == 0) {
	dump_output_immediately = TRUE;
	LYcols=80;
	
    } else if(strncmp(argv[0], "-source", 7) == 0) {
	dump_output_immediately = TRUE;
	HTOutputFormat = HTAtom_for("www/dump");
	LYcols=999;
	
    } else if(strncmp(argv[0], "-force_html", 11) == 0) {
	LYforce_HTML_mode = TRUE;
	
    } else if (strncmp(argv[0], "-trace", 6) == 0) {
	WWW_TraceFlag = TRUE;
	
    } else if (strncmp(argv[0], "-linknums", 9) == 0) {
	keypad_mode = LINKS_ARE_NUMBERED;
	
    } else if (strncmp(argv[0], "-localhost", 10) == 0) {
	local_host_only = TRUE;
	
    } else if(strncmp(argv[0], "-nobrowse", 9) == 0) {
	HTDirAccess = HT_DIR_FORBID;
	
    } else if(strncmp(argv[0], "-selective", 10) == 0) {
	HTDirAccess = HT_DIR_SELECTIVE;
	
    } else if (strncmp(argv[0], "-noprint", 8) == 0) {
	no_print=TRUE;
	
    } else if (strncmp(argv[0], "-print", 6) == 0) {
	no_print=FALSE;
	
#if defined(EXEC_LINKS) || defined(EXEC_SCRIPTS)
    } else if (strncmp(argv[0], "-exec", 5) == 0) {
#ifndef NEVER_ALLOW_REMOTE_EXEC
	local_exec=TRUE;
#else
	local_exec_on_local_files=TRUE;
#endif /* NEVER_ALLOW_REMOTE_EXEC */
	
    } else if (strncmp(argv[0], "-locexec", 8) == 0) {
	local_exec_on_local_files=TRUE;
	
    } else if (strncmp(argv[0], "-noexec", 7) == 0) {
	local_exec=FALSE;
#endif /* EXEC_LINKS || EXEC_SCRIPTS */
	
    } else if (strncmp(argv[0], "-child", 6) == 0) {
	child_lynx=TRUE;
	
    } else if (strncmp(argv[0], "-nolog", 6) == 0) {
	error_logging=TRUE;
	
    } else if(strncmp(argv[0], "-nostatus", 9) == 0)	{
	no_statusline = TRUE;
	
    } else if(strncmp(argv[0], "-show_cursor", 12) == 0) {
	LYShowCursor = TRUE;
	
    } else if (strncmp(argv[0], "-term", 5) == 0) {
	if((cp=strchr(argv[0],'=')) != NULL)
	    terminal = cp+1;
	else if (argv[1]) {
	    terminal = argv[1];
	    *i++;
	}
	
    } else if (strncmp(argv[0], "-telnet", 7) == 0) {
	telnet_ok=FALSE;
	
    } else if (strncmp(argv[0], "-ftp", 4) == 0) {
	ftp_ok=FALSE;
	
    } else if (strncmp(argv[0], "-rlogin", 7) == 0) {
	rlogin_ok=FALSE;
	
    } else if (strncmp(argv[0], "-fileversions", 13) == 0) {
#ifdef VMS
	HTVMSFileVersions=TRUE;
#else
	return;
#endif /* VMS */
	
    } else if (strcmp(argv[0], "-post_data") == 0 ||
 	       strcmp(argv[0], "-get_data") == 0) { 	/* User data for post
 							   or get form. */
	char **post_data;
	char buf[1024];

        /* -post_data and -get_data conflict with curses when interactive
          * so let's force them to dump.  - CL
          */
 	dump_output_immediately = TRUE;
        LYcols = 80;
        
	if (strcmp(argv[0], "-get_data") == 0) {
	    StrAllocCopy(form_get_data, "?");   /* Prime the pump */
	    post_data = &form_get_data;
	} else {
	    post_data = &form_post_data;
	}
	
	/* Build post data for later. Stop reading when we see a line with
	 * "---" as its first three characters.
	 */
	while(fgets(buf, sizeof(buf), stdin) && strncmp(buf, "---", 3) != 0) {
	    int j;
	    
	    for(j = strlen(buf) - 1; j >= 0 && /* Strip line terminators */
		(buf[j] == CR || buf[j] == LF); j--) {
		buf[j] = '\0';
	    }
	    StrAllocCat(*post_data, buf);
	}
	
    } else if (strcmp(argv[0], "-mime_header") == 0) {/* Return mime headers */
	keep_mime_headers = TRUE;
	dump_output_immediately = TRUE;
	HTOutputFormat = HTAtom_for("www/dump");
	LYcols=999;

    } else if (strncmp(argv[0], "-error_file", 11) == 0) { /* Output return
							      (success/failure)
							      code of an HTTP
							      transaction */
	if((cp=strchr(argv[0],'=')) != NULL) {
	    http_error_file = cp+1;
	} else if (argv[1]) {
	    http_error_file = argv[1];
	    *i++;		/* Let master know we've stolen an argument */
	}	
	
    } else if (strncmp(argv[0], "-auth", 5) == 0) { /* Authentication
						       information for
						       protected forms */
	char *auth_info = NULL;
	
	if((cp=strchr(argv[0],'=')) != NULL) {
	    StrAllocCopy(auth_info, (cp+1));
	    memset(argv[0], ' ', strlen(argv[0]));/* Let's not show too much */
	} else if (argv[1]) {
	    StrAllocCopy(auth_info, argv[1]);
	    memset(argv[1], ' ', strlen(argv[1]));/* Let's not show too much */
	    *i++;		/* Let master know we've stolen an argument */
	}
	if (auth_info != NULL)  {
	    if ((cp = strchr(auth_info, ':')) != NULL) { /* Pw */
		*cp++ = '\0';	/* Terminate ID */
		authentication_info[1] = HTUnEscape(cp);
	    }
	    authentication_info[0] = HTUnEscape(auth_info); /* Id */
	}
	
    } else if (strcmp(argv[0], "-noredir") == 0) { /* Don't follow URL
						      Redirections */
	no_url_redirection = TRUE;
	 
    } else if (strncmp(argv[0], "-", 1) == 0) {
	if(strncmp(argv[0], "-help", 5) != 0) 
#ifdef VMS
	    printf(" LYNX: Invalid Option: %s\n", argv[0]);
	printf("USAGE: lynx [options] [file]\n");
#else
	printf("%s: Invalid Option: %s\n", pgm, argv[0]);
	printf("USAGE: %s [options] [file]\n",pgm);
#endif /* VMS */
	printf("Options are:\n");
	printf("    -anonymous       used to specify the anonymous account\n");
 	printf("    -auth=id:pw      authentication information for protected forms\n");
	printf("    -case            enable case sensitive user searching\n");
	printf("    -cache=NUMBER    NUMBER of documents cached in memory. (default is %d\n",DEFAULT_CACHE_SIZE);
	printf("    -cfg=FILENAME    specifies a lynx.cfg file other than the default.\n");
	printf("    -display=DISPLAY set the display variable for X execed programs\n");
	printf("    -dump            dump the first file to stdout and exit\n");
	printf("    -editor=EDITOR   enable edit mode with specified editor\n");
	printf("    -emacskeys       enable emacs-like key movement\n");
 	printf("    -error_file=file write the HTTP status code here\n");
#if defined(EXEC_LINKS) || defined(EXEC_SCRIPTS)
#ifndef NEVER_ALLOW_REMOTE_EXEC
	printf("    -exec            enable local program execution\n");
#endif /* !NEVER_ALLOW_REMOTE_EXEC */
	printf("    -locexec         enable local program execution from local files only\n");
	printf("    -noexec          disable local program execution (DEFAULT)\n");
#endif /* EXEC_LINKS || EXEC_SCRIPTS */
	printf("    -fileversions    include all versions of files in local VMS directory\n\
                     listings\n");
	printf("    -force_html      forces the first document to be interpreted as HTML\n");
	printf("    -ftp             disable ftp access\n");
 	printf("    -get_data        User data for get forms, read from stdin,\n");
        printf("                     terminated by '---' on a line\n");
	printf("    -help            print this usage message\n");
	printf("    -homepage=URL    set homepage separate from start page\n");
	printf("    -index=URL       set the default index file to URL\n");
	printf("    -localhost       disable URLs that point to remote hosts\n");
 	printf("    -mime_header     Show full mime header\n");
	printf("    -nobrowse        disable directory browsing\n");
	printf("    -noprint         disable print functions\n");
 	printf("    -noredir         Don't follow Location: redirection\n");
	printf("    -nostatus        disable the miscellaneous information messages\n");
 	printf("    -post_data       User data for post forms, read from stdin,\n");
        printf("                     terminated by '---' on a line\n");
	printf("    -print           enable print functions (DEFAULT)\n");
	printf("    -restrictions=[options]  use -restrictions to see list\n");
	printf("    -rlogin          disable rlogins\n");
	printf("    -selective       require .www_browsable files to browse directories\n");
	printf("    -show_cursor     don't hide the curser in the lower right corner\n");
	printf("    -source          dump the source of the first file to stdout and exit\n");
#ifndef VMS
#ifdef SYSLOG_REQUESTED_URLS
	printf("    -syslog=text     information for syslog call\n");
#endif /* SYSLOG_REQUESTED_URLS */
#endif /* !VMS */
	printf("    -telnet          disable telnets\n");
	printf("    -term=TERM       set terminal type to TERM\n");
	printf("    -trace           turns on WWW trace mode\n");
	printf("    -version         print Lynx version information\n");
	printf("    -vikeys          enable vi-like key movement\n");
	exit(0);
    } else {	/* alternate database path */
	
	StrAllocCopy(startfile, argv[0]);
    }
}
#ifndef VMS

static void FatalProblem ARGS1(int,sig)
{
fprintf (stderr, "\r\nSorry, you have encountered a bug in %s Ver. %s\r\n",
	LYNX_NAME, LYNX_VERSION);

fprintf(stderr, "\r\nPlease send a concise mail message to\r\n\
lynx-bug@ukanaix.cc.ukans.edu describing what you were doing,\r\n\
the URL you were looking at or attempting to access,\r\n\
your operating system name with version number,\r\n\
the TCP/IP implementation that your system is using,\r\n\
and any other information you deem relevant.\r\n");

fprintf(stderr, "\r\nDo not mail the core file if one was generated.\r\n");

fprintf(stderr, "\r\nLynx now exiting with signal:  %d\r\n\n", sig);

    /* ignore further interrupts */     /*  mhc: 11/2/91 */
    (void) signal (SIGHUP, SIG_IGN);
    (void) signal (SIGTERM, SIG_IGN);
#ifndef VMS  /* use ttclose() from cleanup() for VMS */
    (void) signal (SIGINT, SIG_IGN);
#endif /* !VMS */
#ifndef __linux__
     (void) signal (SIGBUS, SIG_IGN);
#endif /* !__linux__ */
     (void) signal (SIGSEGV, SIG_IGN);
     (void) signal (SIGILL, SIG_IGN);

  cleanup_sig(0);
#ifndef __linux__
  signal (SIGBUS, 0);
#endif /* !__linux__ */
  signal (SIGSEGV, 0);
  signal (SIGILL, 0);
  abort();  /* exit and dump core */
}
#endif /* !VMS */
