/* Program Name            : FILEREXE.C                                 */
/*   Original Author       : C. K. Hung					*/
/*   Date                  : 3-AUG-1990					*/
/*   Program Description   :                                            */
/*                         :                                            */
/* References                                                           */
/*   Files open for Input  :                                            */
/*   Files open for Output :                                            */
/*   Modules Referenced    :                                            */
/* Revision History follows                                             */
 
#include "global.h"
#include "dx.h"
#include "filerexe.h"
#include "fileropt.h"
#include "inquire.h"
#include <signal.h>
 
 

/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      to be specified
**
**--
**/
int	filer_vms_gateway()
{
    int status;
 
    status = vms_gateway();
    if (status == DX__NORMAL && cntrl_info_block.user_pref.auto_update)
    {
	signal_err("Updating directory...", silence);
	filer_update();
	check_OK(smg$unpaste_virtual_display (
		  &cntrl_info_block.status_display.id,
		  &cntrl_info_block.pasteboard_id))
    }
 
    return status;
}
 
 

/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      VMS_GATEWAY() spawns a child process and execute at DCL level.
**
**--
**/
int	vms_gateway()
{
    char devnm[MAXFILESPEC+1];
    $DESCRIPTOR (devnm_descriptor, devnm);
 
    char errmsg[MAXFILESPEC+1];
 
    unsigned long status;
    int subpid;	/**  Sub-process  **/
    char str[128];
    $DESCRIPTOR (str_descrip, str);
    unsigned long int display_id;
    char dirbuf[MAXFILESPEC+1];
 
    /*
    **	Set default directory so that the subprocess will have
    **	correct SYS$DISK definition
    **/
 
    setddir(DX_CURRENT_DIRECTORY.cur_dir, errmsg);
 
    /*
    **	Spawn an new process
    **/
 
    check_OK(smg$save_physical_screen (
		&cntrl_info_block.pasteboard_id,
		&display_id,
		0,
		0))
 
    check_OK(smg$set_physical_cursor (
	      &cntrl_info_block.pasteboard_id,
	      &cntrl_info_block.pasteboard_rows,
	      &1))
 
    check_OK(smg$disable_broadcast_trapping (
                 &cntrl_info_block.pasteboard_id))
 
    printf("TYPE LOGOUT TO RETURN TO DX");
 
    status = lib$spawn (
		    0,
		    0,
		    0,
		    0,
		    0,
		    &subpid,
		    0,
		    0,
		    0,
		    0,
		    $DESCR ("1$ "),
		    0);
 
    /*
    **	Restore old states
    **/
 
    check_OK(smg$set_broadcast_trapping (
                 &cntrl_info_block.pasteboard_id,
                 broadcast_routine,
                 0))
 
    setddir(DX_CURRENT_DIRECTORY.cur_dir, errmsg);
 
    check_OK(smg$restore_physical_screen (
	      &cntrl_info_block.pasteboard_id,
	      &display_id))
 
    if (status & 1)
	return DX__NORMAL;
    else
    {
	signal_err("Error spawning a child process", bell);
	return DX__ERROR;
    }
}
 
 

/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      to be specified
**
**--
**/
int	filer_vms_command()
{
    int status;
    char errmsg[255];
 
    strcpy(errmsg, "Error executing command");
    get_userinput_and_execute(
	vms_command,
	"DCL Command",
	"Command: ",
	"",
	errmsg,
	"");
    if (cntrl_info_block.user_pref.auto_update)
    {
	signal_err("Updating directory...", silence);
	filer_update();
	check_OK(smg$unpaste_virtual_display (
		  &cntrl_info_block.status_display.id,
		  &cntrl_info_block.pasteboard_id))
    }
    return DX__NORMAL;
}
 
 

/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      VMS_COMMAND() spawns a child process and execute a command.
**
**--
**/
int	vms_command(result_string, dummy, errmsg)
char *result_string;
char *dummy;
char *errmsg;
{
    /**  Subprocess display id and AST arguments  **/
    static unsigned long int display_id = 0;
 
    /**  Current working directory  **/
    static char cwd[MAXFILESPEC+1] = "";
 
    /**  COMMAND STRING  **/
    char command_string[255];
    $DESCRIPTOR (command_string_descrip, command_string);
 
    int cur_row;
    unsigned long status;
    unsigned long prompt_display_id;
    unsigned short int word_terminator_code;
    int p;
 
    /*
    **	Set the signal back to system default so that it won't
    **	interfere with I/O used by the subprocess.
    **/
 
    alarm(0);
    signal(SIGALRM, SIG_DFL);
 
    if (display_id == 0)
    {	    /**  This is the first time called, create a subprocess  **/
        check_OK(smg$create_virtual_display (
                     &cntrl_info_block.pasteboard_rows,
                     &cntrl_info_block.pasteboard_width,
                     &display_id,
                     0,
                     0,
                     0))
        check_OK(smg$create_subprocess (
                     &display_id,
                     0,
                     0))
    }
 
    /*
    **	Set default directory so that the subprocess will have
    **	the correct SYS$DISK definition.
    **/
 
    if (strcmp (cwd, DX_CURRENT_DIRECTORY.cur_dir))
    {
        if (strcmp (cwd, ""))
        {
            cur_row = smg$cursor_row (
                          &display_id);
	    sprintf(command_string, "$ SET DEFAULT %s",
		    DX_CURRENT_DIRECTORY.cur_dir);
	    LENGTH(command_string_descrip) = strlen(command_string);
	    check_OK(smg$execute_command (
			 &display_id,
			 &command_string_descrip,
			 0,
			 &status))
            if (!(status &1))
            {
                sprintf(errmsg, "Error changing default directory to %s",
			DX_CURRENT_DIRECTORY.cur_dir);
		return DX__NORMAL;
            }
            check_OK(smg$erase_display (
                         &display_id,
                         &cur_row,
                         &1,
                         0,
                         0))
            check_OK(smg$set_cursor_abs (
                         &display_id,
                         &cur_row,
                         &1))
        }
        strcpy (cwd, DX_CURRENT_DIRECTORY.cur_dir);
    }
 
    /*
    **	Paste the subprocess display
    **/
 
    check_OK(smg$paste_virtual_display (
                 &display_id,
                 &cntrl_info_block.pasteboard_id,
                 &1,
                 &1,
                 0))
 
    /*
    **	Execute the DCL command
    **/
 
    sprintf(command_string, "$ %s", result_string);
    LENGTH(command_string_descrip) = strlen(command_string);
    check_OK(smg$execute_command (
		 &display_id,
		 &command_string_descrip,
		 0,
		 &status))
 
    cur_row = smg$cursor_row (
	     &display_id);
 
    /*
    **	Scroll until two blank lines are at the bottom of the
    **	screen and wait for user response.
    **/
 
    for (p = cur_row; p > cntrl_info_block.pasteboard_rows-2; p--)
    {
	check_OK(smg$scroll_display_area (
		     &display_id,
		     0,
		     0,
		     0,
		     0,
		     0,
		     0))
	cur_row--;
	check_OK(smg$set_cursor_abs (
		     &display_id,
		     &cur_row,
		     0))
    }
 
    /*
    **  Create a display to get user's response.  No I/O operation
    **  is allowed in subprocess's display.
    **/
 
    check_OK(smg$create_virtual_display (
		 &1,
		 &cntrl_info_block.pasteboard_width,
		 &prompt_display_id,
		 0,
		 0,
		 0))
    check_OK(smg$paste_virtual_display (
		 &prompt_display_id,
		 &cntrl_info_block.pasteboard_id,
		 &cntrl_info_block.pasteboard_rows,
		 &1,
		 0))
    smg$read_keystroke (
		 &cntrl_info_block.keyboard_id,
		 &word_terminator_code,
		 $DESCR ("Press any key to continue ... "),
		 0,
		 &prompt_display_id,
		 0,
		 0);
    check_OK(smg$delete_virtual_display (
		 &prompt_display_id))
 
    /*
    **	Restore to old states
    **/
 
    check_OK(smg$unpaste_virtual_display (
		 &display_id,
		 &cntrl_info_block.pasteboard_id))
 
    return (status & 1) ? DX__NORMAL : DX__ERROR;
}
