/*
* Modifications Copyright 1996, 1999, 2000, 2001, 2002, 2004 by Paul Mattes.
* Copyright October 1995 by Dick Altenbern.
* Based in part on code Copyright 1993, 1994, 1995 by Paul Mattes.
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation.
*
* x3270, c3270, s3270 and tcl3270 are distributed in the hope that they will
* be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the file LICENSE
* for more details.
*/
/*
* ft.c
* This module handles the file transfer dialogs.
*/
#include "globals.h"
#if defined(X3270_FT) /*[*/
#if defined(X3270_DISPLAY) /*[*/
#include <X11/StringDefs.h>
#include <X11/Xaw/Toggle.h>
#include <X11/Xaw/Command.h>
#include <X11/Xaw/Form.h>
#include <X11/Shell.h>
#include <X11/Xaw/AsciiText.h>
#include <X11/Xaw/TextSrc.h>
#include <X11/Xaw/TextSink.h>
#include <X11/Xaw/AsciiSrc.h>
#include <X11/Xaw/AsciiSink.h>
#endif /*]*/
#include <errno.h>
#include "appres.h"
#include "actionsc.h"
#include "ft_cutc.h"
#include "ft_dftc.h"
#include "ftc.h"
#include "dialogc.h"
#include "hostc.h"
#include "kybdc.h"
#include "macrosc.h"
#include "objects.h"
#include "popupsc.h"
#include "tablesc.h"
#include "telnetc.h"
#include "utilc.h"
/* Macros. */
#define eos(s) strchr((s), '\0')
#if defined(X3270_DISPLAY) /*[*/
#define FILE_WIDTH 300 /* width of file name widgets */
#define MARGIN 3 /* distance from margins to widgets */
#define CLOSE_VGAP 0 /* distance between paired toggles */
#define FAR_VGAP 10 /* distance between single toggles and groups */
#define BUTTON_GAP 5 /* horizontal distance between buttons */
#define COLUMN_GAP 40 /* distance between columns */
#endif /*]*/
#define BN (Boolean *)NULL
/* Externals. */
#if defined(X3270_DISPLAY) && defined(X3270_MENUS) /*[*/
extern Pixmap diamond;
extern Pixmap no_diamond;
extern Pixmap null;
extern Pixmap dot;
extern Pixmap no_dot;
#endif /*]*/
/* Globals. */
enum ft_state ft_state = FT_NONE; /* File transfer state */
char *ft_local_filename; /* Local file to transfer to/from */
FILE *ft_local_file = (FILE *)NULL; /* File descriptor for local file */
Boolean ft_last_cr = False; /* CR was last char in local file */
Boolean ascii_flag = True; /* Convert to ascii */
Boolean cr_flag = True; /* Add crlf to each line */
Boolean remap_flag = True; /* Remap ASCII<->EBCDIC */
unsigned long ft_length = 0; /* Length of transfer */
/* Statics. */
#if defined(X3270_DISPLAY) && defined(X3270_MENUS) /*[*/
static Widget ft_dialog, ft_shell, local_file, host_file;
static Widget lrecl_widget, blksize_widget;
static Widget primspace_widget, secspace_widget;
static Widget send_toggle, receive_toggle;
static Widget vm_toggle, tso_toggle;
static Widget ascii_toggle, binary_toggle;
static Widget cr_widget;
static Widget remap_widget;
static Widget buffersize_widget;
#endif /*]*/
static char *ft_host_filename; /* Host file to transfer to/from */
static Boolean receive_flag = True; /* Current transfer is receive */
static Boolean append_flag = False; /* Append transfer */
static Boolean vm_flag = False; /* VM Transfer flag */
#if defined(X3270_DISPLAY) && defined(X3270_MENUS) /*[*/
static Widget recfm_options[5];
static Widget units_options[5];
static struct toggle_list recfm_toggles = { recfm_options };
static struct toggle_list units_toggles = { units_options };
#endif /*]*/
static enum recfm {
DEFAULT_RECFM, FIXED, VARIABLE, UNDEFINED
} recfm = DEFAULT_RECFM;
#if defined(X3270_DISPLAY) && defined(X3270_MENUS) /*[*/
static Boolean recfm_default = True;
static enum recfm r_default_recfm = DEFAULT_RECFM;
static enum recfm r_fixed = FIXED;
static enum recfm r_variable = VARIABLE;
static enum recfm r_undefined = UNDEFINED;
#endif /*]*/
static enum units {
DEFAULT_UNITS, TRACKS, CYLINDERS, AVBLOCK
} units = DEFAULT_UNITS;
#if defined(X3270_DISPLAY) && defined(X3270_MENUS) /*[*/
static Boolean units_default = True;
static enum units u_default_units = DEFAULT_UNITS;
static enum units u_tracks = TRACKS;
static enum units u_cylinders = CYLINDERS;
static enum units u_avblock = AVBLOCK;
#endif /*]*/
static Boolean allow_overwrite = False;
#if defined(X3270_DISPLAY) && defined(X3270_MENUS) /*[*/
static sr_t *ft_sr = (sr_t *)NULL;
static Widget progress_shell, from_file, to_file;
static Widget ft_status, waiting, aborting;
static String status_string;
#endif /*]*/
static struct timeval t0; /* Starting time */
static Boolean ft_is_cut; /* File transfer is CUT-style */
#if defined(X3270_DISPLAY) && defined(X3270_MENUS) /*[*/
static Widget overwrite_shell;
#endif /*]*/
static Boolean ft_is_action;
#if defined(X3270_DISPLAY) && defined(X3270_MENUS) /*[*/
static void ft_cancel(Widget w, XtPointer client_data, XtPointer call_data);
static void ft_popup_callback(Widget w, XtPointer client_data,
XtPointer call_data);
static void ft_popup_init(void);
static int ft_start(void);
static void ft_start_callback(Widget w, XtPointer call_parms,
XtPointer call_data);
static void overwrite_cancel_callback(Widget w, XtPointer client_data,
XtPointer call_data);
static void overwrite_okay_callback(Widget w, XtPointer client_data,
XtPointer call_data);
static void overwrite_popdown(Widget w, XtPointer client_data,
XtPointer call_data);
static void overwrite_popup_init(void);
static void popup_overwrite(void);
static void popup_progress(void);
static void progress_cancel_callback(Widget w, XtPointer client_data,
XtPointer call_data);
static void progress_popup_callback(Widget w, XtPointer client_data,
XtPointer call_data);
static void progress_popup_init(void);
static void recfm_callback(Widget w, XtPointer user_data, XtPointer call_data);
static void toggle_append(Widget w, XtPointer client_data, XtPointer call_data);
static void toggle_ascii(Widget w, XtPointer client_data, XtPointer call_data);
static void toggle_cr(Widget w, XtPointer client_data, XtPointer call_data);
static void toggle_remap(Widget w, XtPointer client_data, XtPointer call_data);
static void toggle_receive(Widget w, XtPointer client_data,
XtPointer call_data);
static void toggle_vm(Widget w, XtPointer client_data, XtPointer call_data);
static void units_callback(Widget w, XtPointer user_data, XtPointer call_data);
#endif /*]*/
static void ft_connected(Boolean ignored);
static void ft_in3270(Boolean ignored);
/* Main external entry point. */
#if !defined(X3270_DISPLAY) || !defined(X3270_MENUS) /*[*/
void
ft_init(void)
{
/* Register for state changes. */
register_schange(ST_CONNECT, ft_connected);
register_schange(ST_3270_MODE, ft_in3270);
}
#endif /*]*/
#if defined(X3270_DISPLAY) && defined(X3270_MENUS) /*[*/
/* "File Transfer" dialog. */
/*
* Pop up the "Transfer" menu.
* Called back from the "File Transfer" option on the File menu.
*/
void
popup_ft(Widget w unused, XtPointer call_parms unused,
XtPointer call_data unused)
{
/* Initialize it. */
if (ft_shell == (Widget)NULL)
ft_popup_init();
/* Pop it up. */
dialog_set(&ft_sr, ft_dialog);
popup_popup(ft_shell, XtGrabNone);
}
/* Initialize the transfer pop-up. */
static void
ft_popup_init(void)
{
Widget w;
Widget cancel_button;
Widget local_label, host_label;
Widget append_widget;
Widget lrecl_label, blksize_label, primspace_label, secspace_label;
Widget h_ref = (Widget)NULL;
Dimension d1;
Dimension maxw = 0;
Widget recfm_label, units_label;
Widget buffersize_label;
Widget start_button;
char buflen_buf[128];
/* Register for state changes. */
register_schange(ST_CONNECT, ft_connected);
register_schange(ST_3270_MODE, ft_in3270);
/* Prep the dialog functions. */
dialog_set(&ft_sr, ft_dialog);
/* Create the menu shell. */
ft_shell = XtVaCreatePopupShell(
"ftPopup", transientShellWidgetClass, toplevel,
NULL);
XtAddCallback(ft_shell, XtNpopupCallback, place_popup,
(XtPointer)CenterP);
XtAddCallback(ft_shell, XtNpopupCallback, ft_popup_callback,
(XtPointer)NULL);
/* Create the form within the shell. */
ft_dialog = XtVaCreateManagedWidget(
ObjDialog, formWidgetClass, ft_shell,
NULL);
/* Create the file name widgets. */
local_label = XtVaCreateManagedWidget(
"local", labelWidgetClass, ft_dialog,
XtNvertDistance, FAR_VGAP,
XtNhorizDistance, MARGIN,
XtNborderWidth, 0,
NULL);
local_file = XtVaCreateManagedWidget(
"value", asciiTextWidgetClass, ft_dialog,
XtNeditType, XawtextEdit,
XtNwidth, FILE_WIDTH,
XtNvertDistance, FAR_VGAP,
XtNfromHoriz, local_label,
XtNhorizDistance, 0,
NULL);
dialog_match_dimension(local_label, local_file, XtNheight);
w = XawTextGetSource(local_file);
if (w == NULL)
XtWarning("Cannot find text source in dialog");
else
XtAddCallback(w, XtNcallback, dialog_text_callback,
(XtPointer)&t_unixfile);
dialog_register_sensitivity(local_file,
BN, False,
BN, False,
BN, False);
host_label = XtVaCreateManagedWidget(
"host", labelWidgetClass, ft_dialog,
XtNfromVert, local_label,
XtNvertDistance, 3,
XtNhorizDistance, MARGIN,
XtNborderWidth, 0,
NULL);
host_file = XtVaCreateManagedWidget(
"value", asciiTextWidgetClass, ft_dialog,
XtNeditType, XawtextEdit,
XtNwidth, FILE_WIDTH,
XtNdisplayCaret, False,
XtNfromVert, local_label,
XtNvertDistance, 3,
XtNfromHoriz, host_label,
XtNhorizDistance, 0,
NULL);
dialog_match_dimension(host_label, host_file, XtNheight);
dialog_match_dimension(local_label, host_label, XtNwidth);
w = XawTextGetSource(host_file);
if (w == NULL)
XtWarning("Cannot find text source in dialog");
else
XtAddCallback(w, XtNcallback, dialog_text_callback,
(XtPointer)&t_hostfile);
dialog_register_sensitivity(host_file,
BN, False,
BN, False,
BN, False);
/* Create the left column. */
/* Create send/receive toggles. */
send_toggle = XtVaCreateManagedWidget(
"send", commandWidgetClass, ft_dialog,
XtNfromVert, host_label,
XtNvertDistance, FAR_VGAP,
XtNhorizDistance, MARGIN,
XtNborderWidth, 0,
NULL);
dialog_apply_bitmap(send_toggle, receive_flag ? no_diamond : diamond);
XtAddCallback(send_toggle, XtNcallback, toggle_receive,
(XtPointer)&s_false);
receive_toggle = XtVaCreateManagedWidget(
"receive", commandWidgetClass, ft_dialog,
XtNfromVert, send_toggle,
XtNvertDistance, CLOSE_VGAP,
XtNhorizDistance, MARGIN,
XtNborderWidth, 0,
NULL);
dialog_apply_bitmap(receive_toggle, receive_flag ? diamond : no_diamond);
XtAddCallback(receive_toggle, XtNcallback, toggle_receive,
(XtPointer)&s_true);
/* Create ASCII/binary toggles. */
ascii_toggle = XtVaCreateManagedWidget(
"ascii", commandWidgetClass, ft_dialog,
XtNfromVert, receive_toggle,
XtNvertDistance, FAR_VGAP,
XtNhorizDistance, MARGIN,
XtNborderWidth, 0,
NULL);
dialog_apply_bitmap(ascii_toggle, ascii_flag ? diamond : no_diamond);
XtAddCallback(ascii_toggle, XtNcallback, toggle_ascii,
(XtPointer)&s_true);
binary_toggle = XtVaCreateManagedWidget(
"binary", commandWidgetClass, ft_dialog,
XtNfromVert, ascii_toggle,
XtNvertDistance, CLOSE_VGAP,
XtNhorizDistance, MARGIN,
XtNborderWidth, 0,
NULL);
dialog_apply_bitmap(binary_toggle, ascii_flag ? no_diamond : diamond);
XtAddCallback(binary_toggle, XtNcallback, toggle_ascii,
(XtPointer)&s_false);
/* Create append toggle. */
append_widget = XtVaCreateManagedWidget(
"append", commandWidgetClass, ft_dialog,
XtNfromVert, binary_toggle,
XtNvertDistance, FAR_VGAP,
XtNhorizDistance, MARGIN,
XtNborderWidth, 0,
NULL);
dialog_apply_bitmap(append_widget, append_flag ? dot : no_dot);
XtAddCallback(append_widget, XtNcallback, toggle_append, NULL);
/* Set up the recfm group. */
recfm_label = XtVaCreateManagedWidget(
"file", labelWidgetClass, ft_dialog,
XtNfromVert, append_widget,
XtNvertDistance, FAR_VGAP,
XtNhorizDistance, MARGIN,
XtNborderWidth, 0,
NULL);
dialog_register_sensitivity(recfm_label,
&receive_flag, False,
BN, False,
BN, False);
recfm_options[0] = XtVaCreateManagedWidget(
"recfmDefault", commandWidgetClass, ft_dialog,
XtNfromVert, recfm_label,
XtNvertDistance, 3,
XtNhorizDistance, MARGIN,
XtNborderWidth, 0,
NULL);
dialog_apply_bitmap(recfm_options[0],
(recfm == DEFAULT_RECFM) ? diamond : no_diamond);
XtAddCallback(recfm_options[0], XtNcallback, recfm_callback,
(XtPointer)&r_default_recfm);
dialog_register_sensitivity(recfm_options[0],
&receive_flag, False,
BN, False,
BN, False);
recfm_options[1] = XtVaCreateManagedWidget(
"fixed", commandWidgetClass, ft_dialog,
XtNfromVert, recfm_options[0],
XtNvertDistance, CLOSE_VGAP,
XtNhorizDistance, MARGIN,
XtNborderWidth, 0,
NULL);
dialog_apply_bitmap(recfm_options[1],
(recfm == FIXED) ? diamond : no_diamond);
XtAddCallback(recfm_options[1], XtNcallback, recfm_callback,
(XtPointer)&r_fixed);
dialog_register_sensitivity(recfm_options[1],
&receive_flag, False,
BN, False,
BN, False);
recfm_options[2] = XtVaCreateManagedWidget(
"variable", commandWidgetClass, ft_dialog,
XtNfromVert, recfm_options[1],
XtNvertDistance, CLOSE_VGAP,
XtNhorizDistance, MARGIN,
XtNborderWidth, 0,
NULL);
dialog_apply_bitmap(recfm_options[2],
(recfm == VARIABLE) ? diamond : no_diamond);
XtAddCallback(recfm_options[2], XtNcallback, recfm_callback,
(XtPointer)&r_variable);
dialog_register_sensitivity(recfm_options[2],
&receive_flag, False,
BN, False,
BN, False);
recfm_options[3] = XtVaCreateManagedWidget(
"undefined", commandWidgetClass, ft_dialog,
XtNfromVert, recfm_options[2],
XtNvertDistance, CLOSE_VGAP,
XtNhorizDistance, MARGIN,
XtNborderWidth, 0,
NULL);
dialog_apply_bitmap(recfm_options[3],
(recfm == UNDEFINED) ? diamond : no_diamond);
XtAddCallback(recfm_options[3], XtNcallback, recfm_callback,
(XtPointer)&r_undefined);
dialog_register_sensitivity(recfm_options[3],
&receive_flag, False,
&vm_flag, False,
BN, False);
lrecl_label = XtVaCreateManagedWidget(
"lrecl", labelWidgetClass, ft_dialog,
XtNfromVert, recfm_options[3],
XtNvertDistance, 3,
XtNhorizDistance, MARGIN,
XtNborderWidth, 0,
NULL);
dialog_register_sensitivity(lrecl_label,
&receive_flag, False,
&recfm_default, False,
BN, False);
lrecl_widget = XtVaCreateManagedWidget(
"value", asciiTextWidgetClass, ft_dialog,
XtNfromVert, recfm_options[3],
XtNvertDistance, 3,
XtNfromHoriz, lrecl_label,
XtNhorizDistance, MARGIN,
XtNwidth, 100,
XtNeditType, XawtextEdit,
XtNdisplayCaret, False,
NULL);
dialog_match_dimension(lrecl_label, lrecl_widget, XtNheight);
w = XawTextGetSource(lrecl_widget);
if (w == NULL)
XtWarning("Cannot find text source in dialog");
else
XtAddCallback(w, XtNcallback, dialog_text_callback,
(XtPointer)&t_numeric);
dialog_register_sensitivity(lrecl_widget,
&receive_flag, False,
&recfm_default, False,
BN, False);
blksize_label = XtVaCreateManagedWidget(
"blksize", labelWidgetClass, ft_dialog,
XtNfromVert, lrecl_widget,
XtNvertDistance, 3,
XtNhorizDistance, MARGIN,
XtNborderWidth, 0,
NULL);
dialog_match_dimension(blksize_label, lrecl_label, XtNwidth);
dialog_register_sensitivity(blksize_label,
&receive_flag, False,
&recfm_default, False,
BN, False);
blksize_widget = XtVaCreateManagedWidget(
"value", asciiTextWidgetClass, ft_dialog,
XtNfromVert, lrecl_widget,
XtNvertDistance, 3,
XtNfromHoriz, blksize_label,
XtNhorizDistance, MARGIN,
XtNwidth, 100,
XtNeditType, XawtextEdit,
XtNdisplayCaret, False,
NULL);
dialog_match_dimension(blksize_label, blksize_widget, XtNheight);
w = XawTextGetSource(blksize_widget);
if (w == NULL)
XtWarning("Cannot find text source in dialog");
else
XtAddCallback(w, XtNcallback, dialog_text_callback,
(XtPointer)&t_numeric);
dialog_register_sensitivity(blksize_widget,
&receive_flag, False,
&recfm_default, False,
BN, False);
/* Find the widest widget in the left column. */
XtVaGetValues(send_toggle, XtNwidth, &maxw, NULL);
h_ref = send_toggle;
#define REMAX(w) { \
XtVaGetValues((w), XtNwidth, &d1, NULL); \
if (d1 > maxw) { \
maxw = d1; \
h_ref = (w); \
} \
}
REMAX(receive_toggle);
REMAX(ascii_toggle);
REMAX(binary_toggle);
REMAX(append_widget);
#undef REMAX
/* Create the right column buttons. */
/* Create VM/TSO toggle. */
vm_toggle = XtVaCreateManagedWidget(
"vm", commandWidgetClass, ft_dialog,
XtNfromVert, host_label,
XtNvertDistance, FAR_VGAP,
XtNfromHoriz, h_ref,
XtNhorizDistance, COLUMN_GAP,
XtNborderWidth, 0,
NULL);
dialog_apply_bitmap(vm_toggle, vm_flag ? diamond : no_diamond);
XtAddCallback(vm_toggle, XtNcallback, toggle_vm, (XtPointer)&s_true);
tso_toggle = XtVaCreateManagedWidget(
"tso", commandWidgetClass, ft_dialog,
XtNfromVert, vm_toggle,
XtNvertDistance, CLOSE_VGAP,
XtNfromHoriz, h_ref,
XtNhorizDistance, COLUMN_GAP,
XtNborderWidth, 0,
NULL);
dialog_apply_bitmap(tso_toggle, vm_flag ? no_diamond : diamond);
XtAddCallback(tso_toggle, XtNcallback, toggle_vm, (XtPointer)&s_false);
/* Create CR toggle. */
cr_widget = XtVaCreateManagedWidget(
"cr", commandWidgetClass, ft_dialog,
XtNfromVert, tso_toggle,
XtNvertDistance, FAR_VGAP,
XtNfromHoriz, h_ref,
XtNhorizDistance, COLUMN_GAP,
XtNborderWidth, 0,
NULL);
dialog_apply_bitmap(cr_widget, cr_flag ? dot : no_dot);
XtAddCallback(cr_widget, XtNcallback, toggle_cr, 0);
dialog_register_sensitivity(cr_widget,
BN, False,
BN, False,
BN, False);
/* Create remap toggle. */
remap_widget = XtVaCreateManagedWidget(
"remap", commandWidgetClass, ft_dialog,
XtNfromVert, cr_widget,
XtNfromHoriz, h_ref,
XtNvertDistance, CLOSE_VGAP,
XtNhorizDistance, COLUMN_GAP,
XtNborderWidth, 0,
NULL);
dialog_apply_bitmap(remap_widget, remap_flag ? dot : no_dot);
XtAddCallback(remap_widget, XtNcallback, toggle_remap, NULL);
dialog_register_sensitivity(remap_widget,
&ascii_flag, True,
BN, False,
BN, False);
/* Set up the Units group. */
units_label = XtVaCreateManagedWidget(
"units", labelWidgetClass, ft_dialog,
XtNfromVert, append_widget,
XtNvertDistance, FAR_VGAP,
XtNfromHoriz, h_ref,
XtNhorizDistance, COLUMN_GAP,
XtNborderWidth, 0,
NULL);
dialog_register_sensitivity(units_label,
&receive_flag, False,
&vm_flag, False,
BN, False);
units_options[0] = XtVaCreateManagedWidget(
"spaceDefault", commandWidgetClass, ft_dialog,
XtNfromVert, units_label,
XtNvertDistance, 3,
XtNfromHoriz, h_ref,
XtNhorizDistance, COLUMN_GAP,
XtNborderWidth, 0,
NULL);
dialog_apply_bitmap(units_options[0],
(units == DEFAULT_UNITS) ? diamond : no_diamond);
XtAddCallback(units_options[0], XtNcallback,
units_callback, (XtPointer)&u_default_units);
dialog_register_sensitivity(units_options[0],
&receive_flag, False,
&vm_flag, False,
BN, False);
units_options[1] = XtVaCreateManagedWidget(
"tracks", commandWidgetClass, ft_dialog,
XtNfromVert, units_options[0],
XtNvertDistance, CLOSE_VGAP,
XtNfromHoriz, h_ref,
XtNhorizDistance, COLUMN_GAP,
XtNborderWidth, 0,
NULL);
dialog_apply_bitmap(units_options[1],
(units == TRACKS) ? diamond : no_diamond);
XtAddCallback(units_options[1], XtNcallback,
units_callback, (XtPointer)&u_tracks);
dialog_register_sensitivity(units_options[1],
&receive_flag, False,
&vm_flag, False,
BN, False);
units_options[2] = XtVaCreateManagedWidget(
"cylinders", commandWidgetClass, ft_dialog,
XtNfromVert, units_options[1],
XtNvertDistance, CLOSE_VGAP,
XtNfromHoriz, h_ref,
XtNhorizDistance, COLUMN_GAP,
XtNborderWidth, 0,
NULL);
dialog_apply_bitmap(units_options[2],
(units == CYLINDERS) ? diamond : no_diamond);
XtAddCallback(units_options[2], XtNcallback,
units_callback, (XtPointer)&u_cylinders);
dialog_register_sensitivity(units_options[2],
&receive_flag, False,
&vm_flag, False,
BN, False);
units_options[3] = XtVaCreateManagedWidget(
"avblock", commandWidgetClass, ft_dialog,
XtNfromVert, units_options[2],
XtNvertDistance, CLOSE_VGAP,
XtNfromHoriz, h_ref,
XtNhorizDistance, COLUMN_GAP,
XtNborderWidth, 0,
NULL);
dialog_apply_bitmap(units_options[3],
(units == AVBLOCK) ? diamond : no_diamond);
XtAddCallback(units_options[3], XtNcallback,
units_callback, (XtPointer)&u_avblock);
dialog_register_sensitivity(units_options[3],
&receive_flag, False,
&vm_flag, False,
BN, False);
primspace_label = XtVaCreateManagedWidget(
"primspace", labelWidgetClass, ft_dialog,
XtNfromVert, units_options[3],
XtNvertDistance, 3,
XtNfromHoriz, h_ref,
XtNhorizDistance, COLUMN_GAP,
XtNborderWidth, 0,
NULL);
dialog_register_sensitivity(primspace_label,
&receive_flag, False,
&vm_flag, False,
&units_default, False);
primspace_widget = XtVaCreateManagedWidget(
"value", asciiTextWidgetClass, ft_dialog,
XtNfromVert, units_options[3],
XtNvertDistance, 3,
XtNfromHoriz, primspace_label,
XtNhorizDistance, 0,
XtNwidth, 100,
XtNeditType, XawtextEdit,
XtNdisplayCaret, False,
NULL);
dialog_match_dimension(primspace_label, primspace_widget, XtNheight);
w = XawTextGetSource(primspace_widget);
if (w == NULL)
XtWarning("Cannot find text source in dialog");
else
XtAddCallback(w, XtNcallback, dialog_text_callback,
(XtPointer)&t_numeric);
dialog_register_sensitivity(primspace_widget,
&receive_flag, False,
&vm_flag, False,
&units_default, False);
secspace_label = XtVaCreateManagedWidget(
"secspace", labelWidgetClass, ft_dialog,
XtNfromVert, primspace_widget,
XtNvertDistance, 3,
XtNfromHoriz, h_ref,
XtNhorizDistance, COLUMN_GAP,
XtNborderWidth, 0,
NULL);
dialog_match_dimension(primspace_label, secspace_label, XtNwidth);
dialog_register_sensitivity(secspace_label,
&receive_flag, False,
&vm_flag, False,
&units_default, False);
secspace_widget = XtVaCreateManagedWidget(
"value", asciiTextWidgetClass, ft_dialog,
XtNfromVert, primspace_widget,
XtNvertDistance, 3,
XtNfromHoriz, secspace_label,
XtNhorizDistance, 0,
XtNwidth, 100,
XtNeditType, XawtextEdit,
XtNdisplayCaret, False,
NULL);
dialog_match_dimension(secspace_label, secspace_widget, XtNheight);
w = XawTextGetSource(secspace_widget);
if (w == NULL)
XtWarning("Cannot find text source in dialog");
else
XtAddCallback(w, XtNcallback, dialog_text_callback,
(XtPointer)&t_numeric);
dialog_register_sensitivity(secspace_widget,
&receive_flag, False,
&vm_flag, False,
&units_default, False);
/* Set up the DFT buffer size. */
buffersize_label = XtVaCreateManagedWidget(
"buffersize", labelWidgetClass, ft_dialog,
XtNfromVert, blksize_label,
XtNvertDistance, FAR_VGAP,
XtNhorizDistance, MARGIN,
XtNborderWidth, 0,
NULL);
buffersize_widget = XtVaCreateManagedWidget(
"value", asciiTextWidgetClass, ft_dialog,
XtNfromVert, blksize_label,
XtNvertDistance, FAR_VGAP,
XtNfromHoriz, buffersize_label,
XtNhorizDistance, 0,
XtNwidth, 100,
XtNeditType, XawtextEdit,
XtNdisplayCaret, False,
NULL);
dialog_match_dimension(buffersize_label, buffersize_widget, XtNheight);
w = XawTextGetSource(buffersize_widget);
if (w == NULL)
XtWarning("Cannot find text source in dialog");
else
XtAddCallback(w, XtNcallback, dialog_text_callback,
(XtPointer)&t_numeric);
dialog_register_sensitivity(buffersize_widget,
BN, False,
BN, False,
BN, False);
set_dft_buffersize();
(void) sprintf(buflen_buf, "%d", dft_buffersize);
XtVaSetValues(buffersize_widget, XtNstring, buflen_buf, NULL);
/* Set up the buttons at the bottom. */
start_button = XtVaCreateManagedWidget(
ObjConfirmButton, commandWidgetClass, ft_dialog,
XtNfromVert, buffersize_label,
XtNvertDistance, FAR_VGAP,
XtNhorizDistance, MARGIN,
NULL);
XtAddCallback(start_button, XtNcallback, ft_start_callback,
(XtPointer)NULL);
cancel_button = XtVaCreateManagedWidget(
ObjCancelButton, commandWidgetClass, ft_dialog,
XtNfromVert, buffersize_label,
XtNvertDistance, FAR_VGAP,
XtNfromHoriz, start_button,
XtNhorizDistance, BUTTON_GAP,
NULL);
XtAddCallback(cancel_button, XtNcallback, ft_cancel, 0);
}
/* Callbacks for all the transfer widgets. */
/* Transfer pop-up popping up. */
static void
ft_popup_callback(Widget w unused, XtPointer client_data unused,
XtPointer call_data unused)
{
/* Set the focus to the local file widget. */
PA_dialog_focus_action(local_file, (XEvent *)NULL, (String *)NULL,
(Cardinal *)NULL);
/* Disallow overwrites. */
allow_overwrite = False;
}
/* Cancel button pushed. */
static void
ft_cancel(Widget w unused, XtPointer client_data unused,
XtPointer call_data unused)
{
XtPopdown(ft_shell);
}
/* recfm options. */
static void
recfm_callback(Widget w, XtPointer user_data, XtPointer call_data unused)
{
recfm = *(enum recfm *)user_data;
recfm_default = (recfm == DEFAULT_RECFM);
dialog_check_sensitivity(&recfm_default);
dialog_flip_toggles(&recfm_toggles, w);
}
/* Units options. */
static void
units_callback(Widget w, XtPointer user_data, XtPointer call_data unused)
{
units = *(enum units *)user_data;
units_default = (units == DEFAULT_UNITS);
dialog_check_sensitivity(&units_default);
dialog_flip_toggles(&units_toggles, w);
}
/* OK button pushed. */
static void
ft_start_callback(Widget w unused, XtPointer call_parms unused,
XtPointer call_data unused)
{
if (ft_start()) {
XtPopdown(ft_shell);
popup_progress();
}
}
/* Send/receive options. */
static void
toggle_receive(Widget w unused, XtPointer client_data,
XtPointer call_data unused)
{
/* Toggle the flag */
receive_flag = *(Boolean *)client_data;
/* Change the widget states. */
dialog_mark_toggle(receive_toggle, receive_flag ? diamond : no_diamond);
dialog_mark_toggle(send_toggle, receive_flag ? no_diamond : diamond);
dialog_check_sensitivity(&receive_flag);
}
/* Ascii/binary options. */
static void
toggle_ascii(Widget w unused, XtPointer client_data, XtPointer call_data unused)
{
/* Toggle the flag. */
ascii_flag = *(Boolean *)client_data;
/* Change the widget states. */
dialog_mark_toggle(ascii_toggle, ascii_flag ? diamond : no_diamond);
dialog_mark_toggle(binary_toggle, ascii_flag ? no_diamond : diamond);
cr_flag = ascii_flag;
remap_flag = ascii_flag;
dialog_mark_toggle(cr_widget, cr_flag ? dot : no_dot);
dialog_mark_toggle(remap_widget, remap_flag ? dot : no_dot);
dialog_check_sensitivity(&ascii_flag);
}
/* CR option. */
static void
toggle_cr(Widget w, XtPointer client_data unused, XtPointer call_data unused)
{
/* Toggle the cr flag */
cr_flag = !cr_flag;
dialog_mark_toggle(w, cr_flag ? dot : no_dot);
}
/* Append option. */
static void
toggle_append(Widget w, XtPointer client_data unused,
XtPointer call_data unused)
{
/* Toggle Append Flag */
append_flag = !append_flag;
dialog_mark_toggle(w, append_flag ? dot : no_dot);
}
/* Remap option. */
static void
toggle_remap(Widget w, XtPointer client_data unused,
XtPointer call_data unused)
{
/* Toggle Remap Flag */
remap_flag = !remap_flag;
dialog_mark_toggle(w, remap_flag ? dot : no_dot);
}
/* TSO/VM option. */
static void
toggle_vm(Widget w unused, XtPointer client_data unused,
XtPointer call_data unused)
{
/* Toggle the flag. */
vm_flag = *(Boolean *)client_data;
/* Change the widget states. */
dialog_mark_toggle(vm_toggle, vm_flag ? diamond : no_diamond);
dialog_mark_toggle(tso_toggle, vm_flag ? no_diamond : diamond);
if (vm_flag) {
if (recfm == UNDEFINED) {
recfm = DEFAULT_RECFM;
recfm_default = True;
dialog_flip_toggles(&recfm_toggles,
recfm_toggles.widgets[0]);
}
}
dialog_check_sensitivity(&vm_flag);
}
/*
* Begin the transfer.
* Returns 1 if the transfer has started, 0 otherwise.
*/
static int
ft_start(void)
{
char opts[80];
char *op = opts + 1;
char *cmd;
String buffersize, lrecl, blksize, primspace, secspace;
char updated_buffersize[128];
unsigned flen;
char *ft_command;
ft_is_action = False;
/* Get the DFT buffer size. */
XtVaGetValues(buffersize_widget, XtNstring, &buffersize, NULL);
if (*buffersize)
dft_buffersize = atoi(buffersize);
else
dft_buffersize = 0;
set_dft_buffersize();
(void) sprintf(updated_buffersize, "%d", dft_buffersize);
XtVaSetValues(buffersize_widget, XtNstring, updated_buffersize, NULL);
/* Get the host file from its widget */
XtVaGetValues(host_file, XtNstring, &ft_host_filename, NULL);
if (!*ft_host_filename)
return 0;
/* XXX: probably more validation to do here */
/* Get the local file from it widget */
XtVaGetValues(local_file, XtNstring, &ft_local_filename, NULL);
if (!*ft_local_filename)
return 0;
/* See if the local file can be overwritten. */
if (receive_flag && !append_flag && !allow_overwrite) {
ft_local_file = fopen(ft_local_filename, "r");
if (ft_local_file != (FILE *)NULL) {
(void) fclose(ft_local_file);
ft_local_file = (FILE *)NULL;
popup_overwrite();
return 0;
}
}
/* Open the local file. */
ft_local_file = fopen(ft_local_filename,
receive_flag ?
(append_flag ? "a" : "w" ) :
"r");
if (ft_local_file == (FILE *)NULL) {
allow_overwrite = False;
popup_an_errno(errno, "Open(%s)", ft_local_filename);
return 0;
}
/* Build the ind$file command */
op[0] = '\0';
if (ascii_flag)
strcat(op, " ascii");
if (cr_flag)
strcat(op, " crlf");
if (append_flag && !receive_flag)
strcat(op, " append");
if (!receive_flag) {
if (!vm_flag) {
if (recfm != DEFAULT_RECFM) {
/* RECFM Entered, process */
strcat(op, " recfm(");
switch (recfm) {
case FIXED:
strcat(op, "f");
break;
case VARIABLE:
strcat(op, "v");
break;
case UNDEFINED:
strcat(op, "u");
break;
default:
break;
};
strcat(op, ")");
XtVaGetValues(lrecl_widget,
XtNstring, &lrecl,
NULL);
if (strlen(lrecl) > 0)
sprintf(eos(op), " lrecl(%s)", lrecl);
XtVaGetValues(blksize_widget,
XtNstring, &blksize,
NULL);
if (strlen(blksize) > 0)
sprintf(eos(op), " blksize(%s)",
blksize);
}
if (units != DEFAULT_UNITS) {
/* Space Entered, processs it */
switch (units) {
case TRACKS:
strcat(op, " tracks");
break;
case CYLINDERS:
strcat(op, " cylinders");
break;
case AVBLOCK:
strcat(op, " avblock");
break;
default:
break;
};
XtVaGetValues(primspace_widget, XtNstring,
&primspace, NULL);
if (strlen(primspace) > 0) {
sprintf(eos(op), " space(%s",
primspace);
XtVaGetValues(secspace_widget,
XtNstring, &secspace,
NULL);
if (strlen(secspace) > 0)
sprintf(eos(op), ",%s",
secspace);
strcat(op, ")");
}
}
} else {
if (recfm != DEFAULT_RECFM) {
strcat(op, " recfm ");
switch (recfm) {
case FIXED:
strcat(op, "f");
break;
case VARIABLE:
strcat(op, "v");
break;
default:
break;
};
XtVaGetValues(lrecl_widget,
XtNstring, &lrecl,
NULL);
if (strlen(lrecl) > 0)
sprintf(eos(op), " lrecl %s", lrecl);
}
}
}
/* Insert the '(' for VM options. */
if (strlen(op) > 0 && vm_flag) {
opts[0] = ' ';
opts[1] = '(';
op = opts;
}
/*
* Unless the user specified a particular file transfer command,
* translate 'ind$file' so that it will have the proper EBCDIC value,
* regardless of the local character set.
*/
if (appres.ft_command != CN) {
ft_command = appres.ft_command;
} else {
char *s = "ind$file";
char *t;
unsigned char c;
ft_command = Malloc(strlen(s) + 1);
t = ft_command;
while ((c = *s++)) {
*t++ = ebc2asc[asc2ebc0[c & 0xff]];
}
*t = '\0';
}
/* Build the whole command. */
cmd = xs_buffer("%s %s %s%s\\n",
ft_command,
receive_flag ? "get" : "put", ft_host_filename, op);
if (appres.ft_command == CN)
Free(ft_command);
/* Erase the line and enter the command. */
flen = kybd_prime();
if (!flen || flen < strlen(cmd) - 1) {
XtFree(cmd);
popup_an_error(get_message("ftUnable"));
allow_overwrite = False;
return 0;
}
(void) emulate_input(cmd, strlen(cmd), False);
XtFree(cmd);
/* Get this thing started. */
ft_state = FT_AWAIT_ACK;
ft_is_cut = False;
ft_last_cr = False;
return 1;
}
/* "Transfer in Progress" pop-up. */
/* Pop up the "in progress" pop-up. */
static void
popup_progress(void)
{
/* Initialize it. */
if (progress_shell == (Widget)NULL)
progress_popup_init();
/* Pop it up. */
popup_popup(progress_shell, XtGrabNone);
}
/* Initialize the "in progress" pop-up. */
static void
progress_popup_init(void)
{
Widget progress_pop, from_label, to_label, cancel_button;
/* Create the shell. */
progress_shell = XtVaCreatePopupShell(
"ftProgressPopup", transientShellWidgetClass, toplevel,
NULL);
XtAddCallback(progress_shell, XtNpopupCallback, place_popup,
(XtPointer)CenterP);
XtAddCallback(progress_shell, XtNpopupCallback,
progress_popup_callback, (XtPointer)NULL);
/* Create a form structure to contain the other stuff */
progress_pop = XtVaCreateManagedWidget(
ObjDialog, formWidgetClass, progress_shell,
NULL);
/* Create the widgets. */
from_label = XtVaCreateManagedWidget(
"fromLabel", labelWidgetClass, progress_pop,
XtNvertDistance, FAR_VGAP,
XtNhorizDistance, MARGIN,
XtNborderWidth, 0,
NULL);
from_file = XtVaCreateManagedWidget(
"filename", labelWidgetClass, progress_pop,
XtNwidth, FILE_WIDTH,
XtNvertDistance, FAR_VGAP,
XtNfromHoriz, from_label,
XtNhorizDistance, 0,
NULL);
dialog_match_dimension(from_label, from_file, XtNheight);
to_label = XtVaCreateManagedWidget(
"toLabel", labelWidgetClass, progress_pop,
XtNfromVert, from_label,
XtNvertDistance, FAR_VGAP,
XtNhorizDistance, MARGIN,
XtNborderWidth, 0,
NULL);
to_file = XtVaCreateManagedWidget(
"filename", labelWidgetClass, progress_pop,
XtNwidth, FILE_WIDTH,
XtNfromVert, from_label,
XtNvertDistance, FAR_VGAP,
XtNfromHoriz, to_label,
XtNhorizDistance, 0,
NULL);
dialog_match_dimension(to_label, to_file, XtNheight);
dialog_match_dimension(from_label, to_label, XtNwidth);
waiting = XtVaCreateManagedWidget(
"waiting", labelWidgetClass, progress_pop,
XtNfromVert, to_label,
XtNvertDistance, FAR_VGAP,
XtNhorizDistance, MARGIN,
XtNborderWidth, 0,
XtNmappedWhenManaged, False,
NULL);
ft_status = XtVaCreateManagedWidget(
"status", labelWidgetClass, progress_pop,
XtNfromVert, to_label,
XtNvertDistance, FAR_VGAP,
XtNhorizDistance, MARGIN,
XtNborderWidth, 0,
XtNresizable, True,
XtNmappedWhenManaged, False,
NULL);
XtVaGetValues(ft_status, XtNlabel, &status_string, NULL);
status_string = XtNewString(status_string);
aborting = XtVaCreateManagedWidget(
"aborting", labelWidgetClass, progress_pop,
XtNfromVert, to_label,
XtNvertDistance, FAR_VGAP,
XtNhorizDistance, MARGIN,
XtNborderWidth, 0,
XtNmappedWhenManaged, False,
NULL);
cancel_button = XtVaCreateManagedWidget(
ObjCancelButton, commandWidgetClass, progress_pop,
XtNfromVert, ft_status,
XtNvertDistance, FAR_VGAP,
XtNhorizDistance, MARGIN,
NULL);
XtAddCallback(cancel_button, XtNcallback, progress_cancel_callback,
NULL);
}
/* Callbacks for the "in progress" pop-up. */
/* In-progress pop-up popped up. */
static void
progress_popup_callback(Widget w unused, XtPointer client_data unused,
XtPointer call_data unused)
{
XtVaSetValues(from_file, XtNlabel,
receive_flag ? ft_host_filename : ft_local_filename, NULL);
XtVaSetValues(to_file, XtNlabel,
receive_flag ? ft_local_filename : ft_host_filename, NULL);
switch (ft_state) {
case FT_AWAIT_ACK:
XtUnmapWidget(ft_status);
XtUnmapWidget(aborting);
XtMapWidget(waiting);
break;
case FT_RUNNING:
XtUnmapWidget(waiting);
XtUnmapWidget(aborting);
XtMapWidget(ft_status);
break;
case FT_ABORT_WAIT:
case FT_ABORT_SENT:
XtUnmapWidget(waiting);
XtUnmapWidget(ft_status);
XtMapWidget(aborting);
break;
default:
break;
}
}
/* In-progress "cancel" button. */
static void
progress_cancel_callback(Widget w unused, XtPointer client_data unused,
XtPointer call_data unused)
{
if (ft_state == FT_RUNNING) {
ft_state = FT_ABORT_WAIT;
XtUnmapWidget(waiting);
XtUnmapWidget(ft_status);
XtMapWidget(aborting);
} else {
/* Impatient user or hung host -- just clean up. */
ft_complete(get_message("ftUserCancel"));
}
}
/* "Overwrite existing?" pop-up. */
/* Pop up the "overwrite" pop-up. */
static void
popup_overwrite(void)
{
/* Initialize it. */
if (overwrite_shell == (Widget)NULL)
overwrite_popup_init();
/* Pop it up. */
popup_popup(overwrite_shell, XtGrabExclusive);
}
/* Initialize the "overwrite" pop-up. */
static void
overwrite_popup_init(void)
{
Widget overwrite_pop, overwrite_name, okay_button, cancel_button;
String overwrite_string, label, lf;
Dimension d;
/* Create the shell. */
overwrite_shell = XtVaCreatePopupShell(
"ftOverwritePopup", transientShellWidgetClass, toplevel,
NULL);
XtAddCallback(overwrite_shell, XtNpopupCallback, place_popup,
(XtPointer)CenterP);
XtAddCallback(overwrite_shell, XtNpopdownCallback, overwrite_popdown,
(XtPointer)NULL);
/* Create a form structure to contain the other stuff */
overwrite_pop = XtVaCreateManagedWidget(
ObjDialog, formWidgetClass, overwrite_shell,
NULL);
/* Create the widgets. */
overwrite_name = XtVaCreateManagedWidget(
"overwriteName", labelWidgetClass, overwrite_pop,
XtNvertDistance, MARGIN,
XtNhorizDistance, MARGIN,
XtNborderWidth, 0,
XtNresizable, True,
NULL);
XtVaGetValues(overwrite_name, XtNlabel, &overwrite_string, NULL);
XtVaGetValues(local_file, XtNstring, &lf, NULL);
label = xs_buffer(overwrite_string, lf);
XtVaSetValues(overwrite_name, XtNlabel, label, NULL);
XtFree(label);
XtVaGetValues(overwrite_name, XtNwidth, &d, NULL);
if ((Dimension)(d + 20) < 400)
d = 400;
else
d += 20;
XtVaSetValues(overwrite_name, XtNwidth, d, NULL);
XtVaGetValues(overwrite_name, XtNheight, &d, NULL);
XtVaSetValues(overwrite_name, XtNheight, d + 20, NULL);
okay_button = XtVaCreateManagedWidget(
ObjConfirmButton, commandWidgetClass, overwrite_pop,
XtNfromVert, overwrite_name,
XtNvertDistance, FAR_VGAP,
XtNhorizDistance, MARGIN,
NULL);
XtAddCallback(okay_button, XtNcallback, overwrite_okay_callback,
NULL);
cancel_button = XtVaCreateManagedWidget(
ObjCancelButton, commandWidgetClass, overwrite_pop,
XtNfromVert, overwrite_name,
XtNvertDistance, FAR_VGAP,
XtNfromHoriz, okay_button,
XtNhorizDistance, BUTTON_GAP,
NULL);
XtAddCallback(cancel_button, XtNcallback, overwrite_cancel_callback,
NULL);
}
/* Overwrite "okay" button. */
static void
overwrite_okay_callback(Widget w unused, XtPointer client_data unused,
XtPointer call_data unused)
{
XtPopdown(overwrite_shell);
allow_overwrite = True;
if (ft_start()) {
XtPopdown(ft_shell);
popup_progress();
}
}
/* Overwrite "cancel" button. */
static void
overwrite_cancel_callback(Widget w unused, XtPointer client_data unused,
XtPointer call_data unused)
{
XtPopdown(overwrite_shell);
}
/* Overwrite pop-up popped down. */
static void
overwrite_popdown(Widget w unused, XtPointer client_data unused,
XtPointer call_data unused)
{
XtDestroyWidget(overwrite_shell);
overwrite_shell = (Widget)NULL;
}
#endif /*]*/
/* External entry points called by ft_dft and ft_cut. */
/* Pop up a message, end the transfer. */
void
ft_complete(const char *errmsg)
{
/* Close the local file. */
if (ft_local_file != (FILE *)NULL && fclose(ft_local_file) < 0)
popup_an_errno(errno, "close(%s)", ft_local_filename);
ft_local_file = (FILE *)NULL;
/* Clean up the state. */
ft_state = FT_NONE;
#if defined(X3270_DISPLAY) && defined(X3270_MENUS) /*[*/
/* Pop down the in-progress shell. */
if (!ft_is_action)
XtPopdown(progress_shell);
#endif /*]*/
/* Pop up the text. */
if (errmsg != CN) {
char *msg_copy = NewString(errmsg);
/* Make sure the error message will fit on the display. */
if (strlen(msg_copy) > 50 && strchr(msg_copy, '\n') == CN) {
char *s = msg_copy + 50;
while (s > msg_copy && *s != ' ')
s--;
if (s > msg_copy)
*s = '\n'; /* yikes! */
}
popup_an_error(msg_copy);
Free(msg_copy);
} else {
struct timeval t1;
double kbytes_sec;
char *buf;
(void) gettimeofday(&t1, (struct timezone *)NULL);
kbytes_sec = (double)ft_length / 1024.0 /
((double)(t1.tv_sec - t0.tv_sec) +
(double)(t1.tv_usec - t0.tv_usec) / 1.0e6);
buf = Malloc(256);
(void) sprintf(buf, get_message("ftComplete"), ft_length,
kbytes_sec, ft_is_cut ? "CUT" : "DFT");
if (ft_is_action) {
sms_info("%s", buf);
sms_continue();
}
#if defined(X3270_DISPLAY) && defined(X3270_MENUS) /*[*/
else
popup_an_info(buf);
#endif /*]*/
Free(buf);
}
}
/* Update the bytes-transferred count on the progress pop-up. */
void
ft_update_length(void)
{
#if defined(X3270_DISPLAY) && defined(X3270_MENUS) /*[*/
char text_string[80];
/* Format the message */
if (!ft_is_action) {
sprintf(text_string, status_string, ft_length);
XtVaSetValues(ft_status, XtNlabel, text_string, NULL);
}
#endif /*]*/
}
/* Process a transfer acknowledgement. */
void
ft_running(Boolean is_cut)
{
if (ft_state == FT_AWAIT_ACK)
ft_state = FT_RUNNING;
ft_is_cut = is_cut;
(void) gettimeofday(&t0, (struct timezone *)NULL);
ft_length = 0;
#if defined(X3270_DISPLAY) && defined(X3270_MENUS) /*[*/
if (!ft_is_action) {
XtUnmapWidget(waiting);
ft_update_length();
XtMapWidget(ft_status);
}
#endif /*]*/
}
/* Process a protocol-generated abort. */
void
ft_aborting(void)
{
if (ft_state == FT_RUNNING || ft_state == FT_ABORT_WAIT) {
ft_state = FT_ABORT_SENT;
#if defined(X3270_DISPLAY) && defined(X3270_MENUS) /*[*/
if (!ft_is_action) {
XtUnmapWidget(waiting);
XtUnmapWidget(ft_status);
XtMapWidget(aborting);
}
#endif /*]*/
}
}
/* Process a disconnect abort. */
static void
ft_connected(Boolean ignored unused)
{
if (!CONNECTED && ft_state != FT_NONE)
ft_complete(get_message("ftDisconnected"));
}
/* Process an abort from no longer being in 3270 mode. */
static void
ft_in3270(Boolean ignored unused)
{
if (!IN_3270 && ft_state != FT_NONE)
ft_complete(get_message("ftNot3270"));
}
/*
* Script/macro action for file transfer.
* Transfer(option=value[,...])
* Options are:
* Direction=send|receive default receive
* HostFile=name required
* LocalFile=name required
* Host=[tso|vm] default tso
* Mode=[ascii|binary] default ascii
* Cr=[add|remove|keep] default add/remove
* Exist=[keep|replace|append] default keep
* Recfm=[default|fixed|variable|undefined] default default
* Lrecl=n no default
* Blksize=n no default
* Allocation=[default|tracks|cylinders|avblock] default default
* PrimarySpace=n no default
* SecondarySpace=n no default
*/
static struct {
const char *name;
char *value;
const char *keyword[4];
} tp[] = {
{ "Direction", CN, { "receive", "send" } },
{ "HostFile" },
{ "LocalFile" },
{ "Host", CN, { "tso", "vm" } },
{ "Mode", CN, { "ascii", "binary" } },
{ "Cr", CN, { "auto", "remove", "add", "keep" } },
{ "Exist", CN, { "keep", "replace", "append" } },
{ "Recfm", CN, { "default", "fixed", "variable",
"undefined" } },
{ "Lrecl" },
{ "Blksize" },
{ "Allocation", CN, { "default", "tracks", "cylinders",
"avblock" } },
{ "PrimarySpace" },
{ "SecondarySpace" },
{ "BufferSize" },
{ CN }
};
enum ft_parm_name {
PARM_DIRECTION,
PARM_HOST_FILE,
PARM_LOCAL_FILE,
PARM_HOST,
PARM_MODE,
PARM_CR,
PARM_EXIST,
PARM_RECFM,
PARM_LRECL,
PARM_BLKSIZE,
PARM_ALLOCATION,
PARM_PRIMARY_SPACE,
PARM_SECONDARY_SPACE,
PARM_BUFFER_SIZE,
N_PARMS
};
void
Transfer_action(Widget w unused, XEvent *event, String *params,
Cardinal *num_params)
{
int i, k;
Cardinal j;
long l;
char *ptr;
char *ft_command = CN;
char opts[80];
char *op = opts + 1;
char *cmd;
unsigned flen;
action_debug(Transfer_action, event, params, num_params);
ft_is_action = True;
/* Make sure we're connected. */
if (!IN_3270) {
popup_an_error("Not connected");
return;
}
/* Set everything to the default. */
for (i = 0; i < N_PARMS; i++) {
Free(tp[i].value);
if (tp[i].keyword[0] != CN)
tp[i].value =
NewString(tp[i].keyword[0]);
else
tp[i].value = CN;
}
/* See what they specified. */
for (j = 0; j < *num_params; j++) {
for (i = 0; i < N_PARMS; i++) {
char *eq;
int kwlen;
eq = strchr(params[j], '=');
if (eq == CN || eq == params[j] || !*(eq + 1)) {
popup_an_error("Invalid option syntax: '%s'",
params[j]);
return;
}
kwlen = eq - params[j];
if (!strncasecmp(params[j], tp[i].name, kwlen)
&& !tp[i].name[kwlen]) {
if (tp[i].keyword[0]) {
for (k = 0;
tp[i].keyword[k] != CN && k < 4;
k++) {
if (!strcasecmp(eq + 1,
tp[i].keyword[k])) {
break;
}
}
if (k >= 4 ||
tp[i].keyword[k] == CN) {
popup_an_error("Invalid option "
"value: '%s'", eq + 1);
return;
}
} else switch (i) {
case PARM_LRECL:
case PARM_BLKSIZE:
case PARM_PRIMARY_SPACE:
case PARM_SECONDARY_SPACE:
case PARM_BUFFER_SIZE:
l = strtol(eq + 1, &ptr, 10);
if (ptr == eq + 1 || *ptr) {
popup_an_error("Invalid option "
"value: '%s'", eq + 1);
return;
}
break;
default:
break;
}
tp[i].value = NewString(eq + 1);
break;
}
}
if (i >= N_PARMS) {
popup_an_error("Unknown option: %s", params[j]);
return;
}
}
/* Check for required values. */
if (tp[PARM_HOST_FILE].value == CN) {
popup_an_error("Missing 'HostFile' option");
return;
}
if (tp[PARM_LOCAL_FILE].value == CN) {
popup_an_error("Missing 'LocalFile' option");
return;
}
/*
* Start the transfer. Much of this is duplicated from ft_start()
* and should be made common.
*/
if (tp[PARM_BUFFER_SIZE].value != CN)
dft_buffersize = atoi(tp[PARM_BUFFER_SIZE].value);
else
dft_buffersize = 0;
set_dft_buffersize();
receive_flag = !strcasecmp(tp[PARM_DIRECTION].value, "receive");
append_flag = !strcasecmp(tp[PARM_EXIST].value, "append");
allow_overwrite = !strcasecmp(tp[PARM_EXIST].value, "replace");
ascii_flag = !strcasecmp(tp[PARM_MODE].value, "ascii");
if (!strcasecmp(tp[PARM_CR].value, "auto")) {
cr_flag = ascii_flag;
} else {
cr_flag = !strcasecmp(tp[PARM_CR].value, "remove") ||
!strcasecmp(tp[PARM_CR].value, "add");
}
vm_flag = !strcasecmp(tp[PARM_HOST].value, "vm");
recfm = DEFAULT_RECFM;
for (k = 0; tp[PARM_RECFM].keyword[k] != CN && k < 4; k++) {
if (!strcasecmp(tp[PARM_RECFM].value,
tp[PARM_RECFM].keyword[k])) {
recfm = (enum recfm)k;
break;
}
}
units = DEFAULT_UNITS;
for (k = 0; tp[PARM_ALLOCATION].keyword[k] != CN && k < 4; k++) {
if (!strcasecmp(tp[PARM_ALLOCATION].value,
tp[PARM_ALLOCATION].keyword[k])) {
units = (enum units)k;
break;
}
}
ft_host_filename = tp[PARM_HOST_FILE].value;
ft_local_filename = tp[PARM_LOCAL_FILE].value;
/* See if the local file can be overwritten. */
if (receive_flag && !append_flag && !allow_overwrite) {
ft_local_file = fopen(ft_local_filename, "r");
if (ft_local_file != (FILE *)NULL) {
(void) fclose(ft_local_file);
popup_an_error("File exists");
return;
}
}
/* Open the local file. */
ft_local_file = fopen(ft_local_filename,
receive_flag ?
(append_flag ? "a" : "w" ) :
"r");
if (ft_local_file == (FILE *)NULL) {
popup_an_errno(errno, "Open(%s)", ft_local_filename);
return;
}
/* Build the ind$file command */
op[0] = '\0';
if (ascii_flag)
strcat(op, " ascii");
if (cr_flag)
strcat(op, " crlf");
if (append_flag && !receive_flag)
strcat(op, " append");
if (!receive_flag) {
if (!vm_flag) {
if (recfm != DEFAULT_RECFM) {
/* RECFM Entered, process */
strcat(op, " recfm(");
switch (recfm) {
case FIXED:
strcat(op, "f");
break;
case VARIABLE:
strcat(op, "v");
break;
case UNDEFINED:
strcat(op, "u");
break;
default:
break;
};
strcat(op, ")");
if (tp[PARM_LRECL].value != CN)
sprintf(eos(op), " lrecl(%s)",
tp[PARM_LRECL].value);
if (tp[PARM_BLKSIZE].value != CN)
sprintf(eos(op), " blksize(%s)",
tp[PARM_BLKSIZE].value);
}
if (units != DEFAULT_UNITS) {
/* Space Entered, processs it */
switch (units) {
case TRACKS:
strcat(op, " tracks");
break;
case CYLINDERS:
strcat(op, " cylinders");
break;
case AVBLOCK:
strcat(op, " avblock");
break;
default:
break;
};
if (tp[PARM_PRIMARY_SPACE].value != CN) {
sprintf(eos(op), " space(%s",
tp[PARM_PRIMARY_SPACE].value);
if (tp[PARM_SECONDARY_SPACE].value)
sprintf(eos(op), ",%s",
tp[PARM_SECONDARY_SPACE].value);
strcat(op, ")");
}
}
} else {
if (recfm != DEFAULT_RECFM) {
strcat(op, " recfm ");
switch (recfm) {
case FIXED:
strcat(op, "f");
break;
case VARIABLE:
strcat(op, "v");
break;
default:
break;
};
if (tp[PARM_LRECL].value)
sprintf(eos(op), " lrecl %s",
tp[PARM_LRECL].value);
}
}
}
/* Insert the '(' for VM options. */
if (strlen(op) > 0 && vm_flag) {
opts[0] = ' ';
opts[1] = '(';
op = opts;
}
/*
* Unless the user specified a particular file transfer command,
* translate 'ind$file' so that it will have the proper EBCDIC value,
* regardless of the local character set.
*/
if (appres.ft_command != CN) {
ft_command = appres.ft_command;
} else {
char *s = "ind$file";
char *t;
unsigned char c;
ft_command = Malloc(strlen(s) + 1);
t = ft_command;
while ((c = *s++)) {
*t++ = ebc2asc[asc2ebc0[c & 0xff]];
}
*t = '\0';
}
/* Build the whole command. */
cmd = xs_buffer("%s %s %s%s\\n",
ft_command,
receive_flag ? "get" : "put", ft_host_filename, op);
if (appres.ft_command == CN)
Free(ft_command);
/* Erase the line and enter the command. */
flen = kybd_prime();
if (!flen || flen < strlen(cmd) - 1) {
Free(cmd);
popup_an_error(get_message("ftUnable"));
return;
}
(void) emulate_input(cmd, strlen(cmd), False);
Free(cmd);
/* Get this thing started. */
ft_state = FT_AWAIT_ACK;
ft_is_cut = False;
}
#endif /*]*/
syntax highlighted by Code2HTML, v. 0.9.1