/***************************************************************************/
/***************************************************************************/
/*                                                                         */
/*   (c) 1995-1999.  The Regents of the University of California.  All     */
/*   rights reserved.                                                      */
/*                                                                         */
/*   This work was produced at the University of California, Lawrence      */
/*   Livermore National Laboratory (UC LLNL) under contract no.            */
/*   W-7405-ENG-48 (Contract 48) between the U.S. Department of Energy     */
/*   (DOE) and The Regents of the University of California (University)    */
/*   for the operation of UC LLNL.  Copyright is reserved to the           */
/*   University for purposes of controlled dissemination,                  */
/*   commercialization through formal licensing, or other disposition      */
/*   under terms of Contract 48; DOE policies, regulations and orders;     */
/*   and U.S. statutes.  The rights of the Federal Government are          */
/*   reserved under Contract 48 subject to the restrictions agreed upon    */
/*   by the DOE and University.                                            */
/*                                                                         */
/*                                                                         */
/*                              DISCLAIMER                                 */
/*                                                                         */
/*   This software was prepared as an account of work sponsored by an      */
/*   agency of the United States Government.  Neither the United States    */
/*   Government nor the University of California nor any of their          */
/*   employees, makes any warranty, express or implied, or assumes any     */
/*   liability or responsibility for the accuracy, completeness, or        */
/*   usefulness of any information, apparatus, product, or process         */
/*   disclosed, or represents that its specific commercial products,       */
/*   process, or service by trade name, trademark, manufacturer, or        */
/*   otherwise, does not necessarily constitute or imply its               */
/*   endorsement, recommendation, or favoring by the United States         */
/*   Government or the University of California. The views and opinions    */
/*   of the authors expressed herein do not necessarily state or reflect   */
/*   those of the United States Government or the University of            */
/*   California, and shall not be used for advertising or product          */
/*   endorsement purposes.                                                 */
/*                                                                         */
/*   Permission to use, copy, modify and distribute this software and its  */
/*   documentation for any non-commercial purpose, without fee, is         */
/*   hereby granted, provided that the above copyright notice and this     */
/*   permission notice appear in all copies of the software and            */
/*   supporting documentation, and that all UC LLNL identification in      */
/*   the user interface remain unchanged.  The title to copyright LLNL     */
/*   XDIR shall at all times remain with The Regents of the University     */
/*   of California and users agree to preserve same. Users seeking the     */
/*   right to make derivative works with LLNL XDIR for commercial          */
/*   purposes may obtain a license from the Lawrence Livermore National    */
/*   Laboratory's Technology Transfer Office, P.O. Box 808, L-795,         */
/*   Livermore, CA 94550.                                                  */
/*                                                                         */
/***************************************************************************/
/***************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <Xm/Xm.h>
#include "xdir.h"

#ifndef SIGCLD
#define SIGCLD SIGCHLD
#endif

struct st_host_info hinfo[MAXHOSTS];
Widget w_toplev;
XtAppContext app;
Display *display;
int screen;
int depth;
Visual *visual;
Window root_window;
int xfer_mode;
int child_to_parent_pipe[2];

void cb_msg_from_child_process();
void cb_diag_close();
void fatal_error();
int cb_create_dialogs();
int create_gprefs_window();
int create_vprefs_window();
void reapchild();
char *merge_paths();

static int (*dialog_creation_fns[])() = {
	create_gprefs_window,
	create_vprefs_window,
	NULL
};

static void (*saved_sigcld_handler)();
String *get_fallbacks();

extern int initial_xfer_mode;
extern struct dirwin_st *launch_dirwin;


/*
 * main - Initialize and run.
 */
main(argc, argv)
int argc;
char **argv;
{
	int i;
	int j;
	int retval;
	int use_color = False;
	String *fallbacks;
	char *requested_wd;
	char *current_wd;

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

    /* Verify that environment variable HOME is set */
    if (getenv("HOME") == NULL)
        fatal_error("Environment variable HOME not set");

	/* Initialize preferences from .xdirrc */
	construct_prefs_filename();
	read_prefs_from_file();

	/* Initialize the file transfer and recursive copy mode */
	xfer_mode = initial_xfer_mode;

	/* Initialize caches from .xdircache */
	construct_history_filename();
	read_history_from_file();

	/* Should fallback resources contain color information? */
	for (i=0; i<argc; i++)
		if (!strcmp(argv[i], "-color")) {
			use_color = True;
			for (j=i+1; j<argc; j++)
				argv[j-1] = argv[j];
			argc--;
			break;
		}
	fallbacks = get_fallbacks(use_color);

    /* Initialize the toolkit and create the toplevel shell */
    w_toplev = XtVaAppInitialize(&app, "XDir", NULL, 0,
#if XtSpecificationRelease > 4
        (int *)&argc,
#else
        (Cardinal *)&argc,
#endif
        argv,
		fallbacks,
		XmNmappedWhenManaged,	False,
		NULL
	);

	/* Get application resources */
	get_application_resources();

    /* Get the display and screen characteristics */
    display = XtDisplay(w_toplev);
    screen = XDefaultScreen(display);
    depth = XDefaultDepth(display, screen);
    visual = XDefaultVisual(display, screen);
    root_window = XRootWindowOfScreen(XtScreen(w_toplev));

	/* Create custom Xdir icon for window manager */
	create_wm_icon();

	/* Add callback for the WM_DELETE_WINDOW protocol */
	add_wm_delete_window_cb(w_toplev, cb_diag_close, NULL, True);

	/* Display startup window */
	display_startup_dialog();

    /* Create diagnostics window */
    create_diagnostics_window();

	/* Get rid of startup window */
	close_startup_dialog();

	/* Remember current working directory */
	if (local_pwd(&current_wd) < 0)
		fatal_error("Unable to get working directory");

	/* Initialize local host */
	init_local_host();

    /* Make widgets "real" */
    XtRealizeWidget(w_toplev);

	/* Ignore signals from broken pipes (and sockets) */
	signal(SIGPIPE, SIG_IGN);

    /* Connect to local host */
	if (argc > 1) {
		if (argv[argc-1][0] == '/')
			requested_wd = XtNewString(argv[argc-1]);
		else
			requested_wd = merge_paths(SYS_UNIX, current_wd, argv[argc-1]);
		retval = display_dir(LOCAL, NULL, requested_wd, True, True, False,
			False);
		XtFree(requested_wd);
		if (retval < 0) {
		    if (connect_to_local(NULL) < 0)
				fatal_error("Unable to connect to local host.");
		}
	} else if (connect_to_local(NULL) < 0)
		fatal_error("Unable to connect to local host.");

	/* No longer need to remember current working directory */
	XtFree(current_wd);

	/* Create often-used dialogs in background */
	XtAppAddWorkProc(app, (XtWorkProc)cb_create_dialogs, NULL);

	/* Will need to reap children */
	signal(SIGCLD, reapchild);

	/* Create mechanism for receiving messages from child process */
	if (pipe(child_to_parent_pipe) == -1)
		fatal_error("Unable to create child to parent pipe");
	XtAppAddInput(app, child_to_parent_pipe[0], (XtPointer)XtInputReadMask,
		(XtInputCallbackProc)cb_msg_from_child_process, NULL);

	/* Display copyright notice */
	write_copyright();

    /* Turn over control */
    XtAppMainLoop(app);
}


/*
 * fatal_error - Writes string "msg" to standard error and then terminates.
 */
void
fatal_error(msg)
char *msg;
{
    fprintf(stderr, "*** FATAL ERROR: %s\n", msg);
    exit(-1);
}


/*
 * cb_create_dialogs - Work procedure to create often-used dialogs in
 *                     the background.
 */
cb_create_dialogs()
{
	static int indx = 0;

	if (dialog_creation_fns[indx]) {
		dialog_creation_fns[indx]();
		indx++;
		return False;
	} else
		return True;
}


/*
 * reapchild - Reap the child file viewer process in order to free up the
 *             temporary directory and file(s).
 */
void
reapchild(signo)
int signo;
{
	int pid = iwait(NULL);

	if (pid != -1)
		mark_viewdir_for_removal(pid);

	/* Reset signal handler for AIX, IRIX, etc. */
	signal(SIGCLD, reapchild);
	
}


/*
 * save_sigcld_handler - Save current signal handler for SIGCLD.
 */
void
save_sigcld_handler()
{
	saved_sigcld_handler = signal(SIGCLD, SIG_DFL);
}


/*
 * restore_sigcld_handler - Restore signal handler for SIGCLD that was
 *                          saved by save_sigcld_handler().
 */
void
restore_sigcld_handler()
{
	signal(SIGCLD, saved_sigcld_handler);
}


/*
 * cb_msg_from_child_process - Callback to process error message from child
 *                             process.  Message ends with a bell character.
 */
void
cb_msg_from_child_process(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
	int nbytes;
	char buf[2];
	char *msg = XtNewString("");
	char *temp;

	/* Read entire message from child */
	while (1) {
		nbytes = iread(child_to_parent_pipe[0], buf, 1);
		if (nbytes < 0)
			fatal_error("Trouble in cb_msg_from_child_process()");
		buf[nbytes] = '\0';
		temp = XtMalloc(strlen(msg)+nbytes+1);
		strcpy(temp, msg);
		strcat(temp, buf);
		XtFree(msg);
		msg = temp;
		if (msg[strlen(msg)-1] == '\007') {
			warn(msg, launch_dirwin->w_shell);
			XtFree(msg);
			return;
		}
	}
}



syntax highlighted by Code2HTML, v. 0.9.1