/* * 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 #include #include #include #include #include #include #include #include #include #endif /*]*/ #include #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 /*]*/