home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / bbs / re_mote / remote.bts
Encoding:
Text File  |  1992-12-11  |  21.4 KB  |  788 lines

  1.   -----------------------------------------------------------------------
  2.    //                                   // September 9, 1991
  3.   //      R E M O T E . B T S          //
  4.  //                                   //
  5. -----------------------------------------------------------------------
  6.  
  7. --  REMOTE.BTS, STalker™ "Remote Mode" script.
  8. --
  9. --  Copyright © 1991, Strata Software, All Rights Reserved.
  10. --  Exclusive worldwide marketing and distributing by Gribnif Software.
  11. --
  12. --  This file is for the exclusive use of registered STalker™ owners
  13. --  and may not be distributed, in whole or in part, without the express
  14. --  written permission of Strata Software.
  15. --
  16. --  Permission has been granted by Strata Software to distribute
  17. --  this file on bulletin boards, paid access networks, and public
  18. --  domain and shareware disks, provided:
  19. --
  20. --          That this header remains intact, and
  21. --        All modifications are mentioned in the header before
  22. --        redistribution.
  23. --
  24. --  Modified by Scott Dowdle (L.DOWDLE1) in the spring of 1992 to
  25. --  show the remote user their location in the system at all times
  26. --  (i.e. C:\TELECOMM\)
  27. --
  28. --  Modified by Bob Morrow (R.MORROW10) on 12/10/92 to delete the
  29. --  requirement for using a password to enter remote mode when in
  30. --  local echo.  Being in local isn't any different from quitting
  31. --  the program and doing damage that way.  To exit from local
  32. --  mode, you're forced to put up with a message "Quitting from
  33. --  local mode" after you've decided to.  Sorry, it was the only
  34. --  way to deal with exiting once I had removed the password
  35. --  requirement in local.  However, it's a simple [return] that
  36. --  exits you for good.  There isn't a "yes/no" option; that caused
  37. --  a lot of problems.  This does not affect half or full echo
  38. --  operations.
  39.  
  40. include "stalker.bth"
  41.  
  42. int   carrier_at_start; -- TRUE/FALSE based on DCD state when we begin
  43.       //  Set these based on the duplex mode so we don't have to keep
  44.       //  checking.  One of these three is TRUE, the others are false.
  45. int   mode_echo;      -- Are we in ECHO (half-duplex) mode?
  46. int   mode_full;      -- Are we in FULL mode?
  47. int   mode_local;     -- Are we in LOCAL mode?
  48. string  newline;      -- Holds CR/LF, something we use often.
  49. int   output_blocked;   -- TRUE if user has typed ^S.  ^Q resets.
  50. int   saved_key;      -- Room to hold one saved keypress.
  51. int   whatnow;        -- Asks for user input when reading files.
  52.  
  53. function  get_key     returns int;
  54. function  get_string    returns int;
  55. function  keyboard_check;
  56. function  output_char;
  57. function  output_string;
  58. function  parse_filename;
  59. function  remote_loop   returns int;
  60. function  run_cli;
  61. function  show_files;
  62. function  upload_file;
  63.  
  64.  
  65.  ------------------------------
  66. //    carrier_dropped   //
  67. -----------------------------
  68. function carrier_dropped() returns int
  69.   if carrier_at_start then
  70.     return not port_carrier();
  71.   else
  72.     return FALSE;
  73.   endif
  74. endfunction
  75.  
  76.  ------------------------------
  77. //    change_dir      //
  78. -----------------------------
  79. function change_dir()
  80.   string  dir[128];
  81.  
  82.   dir[0] = file_get_drive();
  83.   dir[1] = ':';
  84.   file_get_dir(0, dir + 2);
  85.   output_string("\r\nCurrent location is:\r\n   ");
  86.   output_string(dir);
  87.   output_string("\r\n\nNew location: ");
  88.  
  89.   if get_string(dir, sizeof(dir), FALSE) > 0 then
  90.     file_change_dir(dir);
  91.   endif
  92. endfunction
  93.  
  94.  
  95.  ------------------------------
  96. //    check_key     //
  97. -----------------------------
  98. function check_key() returns int
  99.   int   ch;
  100.  
  101.   keyboard_check();
  102.  
  103.   ch = 0;
  104.  
  105.   if mode_local then
  106.     if saved_key then
  107.       ch = saved_key;
  108.       saved_key = 0;
  109.     endif
  110.   else
  111.     if port_instat() then
  112.       ch = port_getchar();
  113.     endif
  114.   endif
  115.  
  116.   return ch;
  117. endfunction
  118.  
  119.  
  120.  ------------------------------
  121. //    check_local     //
  122. -----------------------------
  123.  function check_local() returns int
  124.   if mode_local then
  125.     output_string("\nInvalid operation in LOCAL mode.\r\n");
  126.     return TRUE;
  127.   endif
  128.   return FALSE;
  129. endfunction
  130.  
  131.  
  132.  ------------------------------
  133. //    display_file    //
  134. -----------------------------
  135. function display_file()
  136.   int   count;
  137.   int   file_handle;
  138.   string  input[128];
  139.   string  message[128];
  140.  
  141.   output_string("File to show: ");
  142.   if get_string(input, sizeof(input), FALSE) > 0 then
  143.     output_string(newline);
  144.     printf("Ctrl-S stops, Ctrl-Q continues\r\n");
  145.     wait(12);
  146.   endif
  147.     if (file_handle = file_open(input, FO_READ)) < 0 then
  148.       sprintf(message, "File '%.80s' couldn't be opened (error %d).\r\n",
  149.           input, file_handle);
  150.       output_string(message);
  151.    endif
  152.       while (count = file_gets(input, sizeof(input), file_handle)) > 0  and
  153.           not (check_key() == 3  or  carrier_dropped()) do
  154.    output_string(input);
  155.       endwhile
  156.    endfunction
  157.  
  158.  ------------------------------
  159. //    download_file   //
  160. -----------------------------
  161. function download_file()
  162.   int   choice;
  163.   string  filename[128];
  164.   string  fullname[128];
  165.   string  input[128];
  166.   int   old_protocol;
  167.   int   success;
  168.  
  169.   if check_local() then
  170.     return;   ------------------------------------------------------>
  171.   endif
  172.  
  173.   old_protocol = get_protocol();
  174.  
  175.   output_string("\nProtocols Available:\r\n[A]SCII, [X]Modem, XModem-1[K], [Y]Modem, [Z]Modem\r\n\nYour choice: ");
  176.   choice = toupper(get_key(TRUE));
  177.   output_string(newline);
  178.  
  179.   if strchr("AXKYZ", choice) == NULL then
  180.     choice = 0;
  181.   else
  182.     if choice == 'X' then
  183.       set_protocol(PROTO_XMODEM);
  184.     endif
  185.  
  186.     if choice == 'K' then
  187.       set_protocol(PROTO_XMODEM1K);
  188.     endif
  189.  
  190.     if choice == 'Y' then
  191.       set_protocol(PROTO_YMODEM);
  192.     endif
  193.  
  194.     if choice == 'Z' then
  195.       set_protocol(PROTO_ZMODEM);
  196.     endif
  197.   endif
  198.  
  199.   if choice then
  200.     output_string("File to download: ");
  201.     if get_string(input, sizeof(input), FALSE) > 0 then
  202.       parse_filename(input, fullname, filename);
  203.       output_string("Begin downloading now...\r\n");
  204.  
  205.       if choice == 'A' then
  206.         success = ascii_send(fullname);
  207.       else
  208.         success = upload(fullname);
  209.       endif
  210.       if not success then
  211.         output_string("\r\nThe download was not completed successfully.");
  212.       endif
  213.     endif
  214.   endif
  215.  
  216.   set_protocol(old_protocol);
  217.  
  218.   output_char('\n');
  219. endfunction
  220.  
  221.  
  222.  ------------------------------
  223. //    get_key       //
  224. -----------------------------
  225. function get_key(
  226.   int   echo_it
  227.   ) returns int
  228.   int   ch;
  229.  
  230.   while not ((ch = check_key()) or carrier_dropped()) do
  231.     ; -- Wait for a key
  232.   endwhile
  233.  
  234.   if echo_it and ch then
  235.     output_char(ch);
  236.   endif
  237.  
  238.   return ch;
  239. endfunction
  240.  
  241.  
  242.  ------------------------------
  243. //    get_password    //
  244. -----------------------------
  245. -- Returns TRUE if the password is typed correctly, FALSE otherwise
  246. function get_password() returns int
  247.   int   attempts;
  248.   string  entered_password[10];
  249.   string  password[10];
  250.  
  251.   get_string_param(REMOTE_PARAM, REMOTE_PASSWORD, password, sizeof(password));
  252.  
  253.   if !password[0] then
  254.     return TRUE;
  255.   endif
  256.  
  257.   if mode_local then
  258.      output_char('\n');
  259.     return TRUE;
  260.   else
  261.  
  262.   show_message("validating password", FALSE);
  263.  
  264.   attempts = 0;
  265.   repeat
  266.     output_string("\r\nWelcome to the Conehead BBS!!!\r\n");
  267.     output_string("About 30MB online.\r\n\n");
  268.     output_string("Password: ");
  269.     get_string(entered_password, sizeof(entered_password), TRUE);
  270.     if carrier_dropped() then
  271.       return FALSE;
  272.     endif
  273.     if !strcmp(entered_password, password) then
  274.       output_char('\n');
  275.       return TRUE;
  276.     else
  277.       output_string("Incorrect password\n");
  278.     endif
  279.   until (attempts = attempts + 1) >= 3;
  280.  
  281.   output_string("\r\nSlamming the door now-see ya!\r\n");
  282.  
  283.   return FALSE;
  284.   endif
  285. endfunction
  286.  
  287.  
  288.  ------------------------------
  289. //    get_string      //
  290. -----------------------------
  291. --  Allows the user to type and edit a string.  The number of characters
  292. --  read is returned, or -1 if the operation is aborted due to ^C or a
  293. --  carrier drop.
  294. function get_string(
  295.   string  buffer,     -- Where to store the characters read
  296.   int   buffer_size,  -- Max # chars we can put in 'buffer'
  297.   int   echo_stars    -- Should we echo characters as '*'?
  298.   ) returns int     -- Returns:  the # of chars read; -1 on error.
  299.  
  300.   string  blot;
  301.   int   ch;
  302.   int   done;
  303.   int   i;
  304.  
  305.   blot = "\b \b";
  306.  
  307.   if buffer_size <= 0 then
  308.     return -1;  ------------------------------------------------------>
  309.   endif
  310.  
  311.   buffer_size = buffer_size -1; -- Leave room for a null byte.
  312.  
  313.   done = FALSE;
  314.   i = 0;
  315.   while i < buffer_size  and  not done do
  316.     ch = get_key(FALSE);
  317.     if carrier_dropped() then
  318.       return -1;  -------------------------------------------------->
  319.     endif
  320.     if ch == '\r'  or  ch == '\n' then
  321.       done = TRUE;
  322.     else
  323.       if ch == 3 then   -- ^C
  324.         return -1;  ---------------------------------------------->
  325.       endif
  326.       if ch == '\b'  or  ch == 127 then -- Backspace or Delete
  327.         if i then
  328.           output_string(blot);
  329.           i = i -1;
  330.         endif
  331.       else
  332.         if ch == 24 then  -- ^X
  333.           if i then
  334.             repeat
  335.               output_string(blot);
  336.             until (i = i - 1) == 0;
  337.           endif
  338.         else
  339.           if ch then  -- Make sure it's non-zero
  340.             buffer[i] = ch;
  341.             i = i + 1;
  342.             if echo_stars then
  343.               ch = '*';
  344.             endif
  345.             output_char(ch);
  346.           endif
  347.         endif
  348.       endif
  349.     endif
  350.   endwhile
  351.  
  352.   buffer[i] = 0;
  353.   output_string(newline);
  354.   return i;
  355. endfunction
  356.  
  357.  
  358.  ------------------------------
  359. //    keyboard_check    //
  360. -----------------------------
  361. function keyboard_check()
  362.   int   ch;
  363.  
  364.   if instat() then
  365.     if (ch = getchar()) == 19 then  -- 19 is ^S, or XOFF
  366.       output_blocked = TRUE;
  367.     else
  368.       if ch == 17 then      -- 17 is ^Q, or XON
  369.         output_blocked = FALSE;
  370.       else
  371.         saved_key = ch;
  372.       endif
  373.     endif
  374.   endif
  375. endfunction
  376.  
  377.  
  378.  ------------------------------
  379. //    main        //
  380. -----------------------------
  381. -- This is the top-level routine for the remote mode script.  If
  382. -- it returns a value of 0, STalker will hang-up and prepare for the
  383. -- next caller.  A non-zero return value tells STalker to hang-up and
  384. -- then terminate remote mode.
  385. function main() returns int
  386.   int   duplex;
  387.  
  388.   carrier_at_start = port_carrier();
  389.  
  390.   -- Set up the 'mode_' variables.
  391.   duplex = get_duplex();
  392.   mode_echo  = (duplex == DUPLEX_ECHO);
  393.   mode_full  = (duplex == DUPLEX_FULL);
  394.   mode_local = (duplex == DUPLEX_LOCAL);
  395.  
  396.   newline = "\r\n";
  397.  
  398.   -- Set the file transfer parameters to be the way we want them
  399.   set_string_param(XFER_PARAM, ASCII_BLANK_EXPAND, "");
  400.   set_string_param(XFER_PARAM, ASCII_HOST_PROMPT, "");
  401.   set_int_param(XFER_PARAM, ASCII_ADD_LF      , TRUE);
  402.   set_int_param(XFER_PARAM, ASCII_LINE_WAIT   , 0);
  403.   set_int_param(XFER_PARAM, ASCII_STRIP_LF    , FALSE);
  404.   set_int_param(XFER_PARAM, ASCII_USE_CTRL_Z  , FALSE);
  405.   set_int_param(XFER_PARAM, ZMODEM_RCV_OPTION , ZOPT_NONE);
  406.   set_int_param(XFER_PARAM, ZMODEM_RCV_MODE   , ZCONV_AUTO);
  407.   set_int_param(XFER_PARAM, ZMODEM_SEND_OPTION, ZOPT_NONE);
  408.   set_int_param(XFER_PARAM, ZMODEM_SEND_MODE  , ZCONV_AUTO);
  409.  
  410.   if !get_password() then
  411.     -- They didn't type the right password, but we still return
  412.     -- a value of 0 since we don't want remote mode to be aborted.
  413.     return 0;
  414.   endif
  415.  
  416.   return remote_loop();
  417. endfunction
  418.  
  419.  
  420.  ------------------------------
  421. //    output_char     //
  422. -----------------------------
  423. function output_char(
  424.   int   ch
  425.   )
  426.   string  str[2];
  427.  
  428.   str[0] = ch;
  429.   str[1] = 0;
  430.   output_string(str);
  431. endfunction
  432.  
  433.  
  434.  ------------------------------
  435. //    output_string   //
  436. -----------------------------
  437. --  Outputs the passed string to the remote system, or the terminal
  438. --  window, or both, depending on the mode.
  439. function output_string(
  440.   string  str
  441.   )
  442.   int   ch;
  443.  
  444.   keyboard_check(); -- Pick up any keypresses waiting for us
  445.  
  446.   if mode_local then
  447.     while output_blocked do
  448.       keyboard_check();
  449.     endwhile
  450.   endif
  451.  
  452.   if not mode_full then
  453.     puts(str);  -- Show the string in the terminal window
  454.   endif
  455.  
  456.   if not mode_local then
  457.     while (ch = str[0]) do
  458.       str = str + 1;
  459.       while !port_outstat() do
  460.         if carrier_dropped() then
  461.           return; -- Carrier dropped, let's get outta here.
  462.         endif
  463.       endwhile
  464.       port_putchar(ch);
  465.     endwhile
  466.   endif
  467. endfunction
  468.  
  469.  
  470.  ------------------------------
  471. //    parse_filename    //
  472. -----------------------------
  473. function parse_filename(
  474.   string  name, -- Input:  Something like \DIR\FILENAME.EXT
  475.   string  full, -- Output: C:\DIR\FILENAME.EXT
  476.   string  file  -- Output: FILENAME.EXT
  477.   )
  478.   -- See if name[] has a drive specifier
  479.   if name[1] == ':' then
  480.     full[0] = toupper(name[0]);
  481.     full[1] = name[1];
  482.     name = name + 2;
  483.   else
  484.     full[0] = file_get_drive();
  485.     full[1] = ':';
  486.   endif
  487.   full[2] = 0;
  488.  
  489.   -- Make sure the drive letter is legit, in case something
  490.   -- like 1:\file.txt is passed in.
  491.   if not isalpha(full[0]) then
  492.     full[0] = 'A';
  493.   endif
  494.  
  495.   -- See if name[] has an explicit directory spec.
  496.   if name[0] != '\\' then
  497.     file_get_dir(full[0] - 0x40, full + 2);
  498.     strcat(full, "\\");
  499.   endif
  500.   strcat(full, name);
  501.  
  502.   -- Now parse out the filename.ext
  503.   strcpy(file, strrchr(full, '\\') + 1);
  504. endfunction
  505.  
  506.  
  507.  ------------------------------
  508. //    remote_loop     //
  509. -----------------------------
  510. -- Return a value of 0 unless you want STalker to exit remote mode.
  511. function remote_loop() returns int  -- Returns an exit status.
  512.   int   command;
  513.   int   duplex;
  514.   string  dir[128];
  515.  
  516.   while TRUE do
  517.     if carrier_dropped() then
  518.       return 0;
  519.     endif
  520.  
  521.     show_message("waiting for a command", FALSE);
  522.  
  523.     output_string("\r\n[B]rief file listing  [C]hange directory   [D]ownload a file\r\n");
  524.     output_string("[F]ull file listing   [G]oodbye            [R]un shell program\r\n");
  525.     output_string("[S]how text file      [T]alk to SysOp      [U]pload a file\r\n");
  526.  
  527.     dir[0] = file_get_drive();
  528.     dir[1] = ':';
  529.     file_get_dir(0, dir + 2);
  530.     output_string("\r\nCurrent location ---> ");
  531.     output_string(dir);
  532.  
  533.     output_string("\r\n\nCommand? ");
  534.     command = toupper(get_key(TRUE));
  535.     output_string(newline);
  536.  
  537.     if strchr("BCDFGRSTU", command) == NULL then
  538.       output_string("\r\nInvalid Command - Please try again!\r\n\n");
  539.       while check_key() do
  540.         -- Get rid of any extra input in case it was a burst of line
  541.         -- noise that caused the invalid command in the first place.
  542.         ;
  543.       endwhile
  544.     else
  545.       if command == 'B' then
  546.         show_files(FALSE);
  547.       endif
  548.  
  549.       if command == 'C' then
  550.         change_dir();
  551.       endif
  552.  
  553.       if command == 'D' then
  554.         download_file();
  555.       endif
  556.  
  557.       if command == 'F' then
  558.         show_files(TRUE);
  559.       endif
  560.  
  561.       if command == 'G' then
  562.          if mode_local then
  563.            mode_local = alert("[0][Quitting remote mode  ][Ok]");
  564.            if mode_local == 1 then
  565.            exit(1);
  566.            endif          
  567.          else
  568.         output_string("\r\n\nGoodbye, and thanks for calling.\r\n");
  569.         return 0;
  570.      endif
  571.      endif
  572.      
  573.       if command == 'R' then
  574.         run_cli();
  575.       endif
  576.  
  577.       if command == 'S' then
  578.         display_file();
  579.       endif
  580.  
  581.       if command == 'T' then
  582.         if !check_local() then
  583.           output_string("Type ^C when done.\r\n");
  584.           show_message("in TALK mode.  Type UNDO to end", FALSE);
  585.           play_sound(SOUND_SECRET);
  586.           chat_mode();
  587.         endif
  588.       endif
  589.  
  590.       if command == 'U' then
  591.         upload_file();
  592.       endif
  593.     endif
  594.   endwhile
  595. endfunction
  596.  
  597.  
  598.  ------------------------------
  599. //    run_program     //
  600. -----------------------------
  601. function run_cli()
  602.   string  cli_name[128];
  603.   string  cli_password[10];
  604.   string  entered_password[10];
  605.   int   error;
  606.  
  607.   cli_name[0] = 0;
  608.   get_string_param(REMOTE_PARAM, REMOTE_CLI_NAME, cli_name, sizeof(cli_name));
  609.  
  610.   if !cli_name[0] then
  611.     output_string("No CLI specified in my remote settings.\r\n");
  612.     return; // No CLI specified -------------------------------------->
  613.   endif
  614.  
  615.   if !file_exists(cli_name) then
  616.     output_string("The specified CLI (");
  617.     output_string(cli_name);
  618.     output_string(") does not exist.\r\n");
  619.     return; ---------------------------------------------------------->
  620.   endif
  621.  
  622.   get_string_param(REMOTE_PARAM, REMOTE_CLI_PASSWORD, cli_password, sizeof(cli_password));
  623.  
  624.   if cli_password[0] then
  625.     output_string("\r\nCLI password: ");
  626.     if get_string(entered_password, sizeof(entered_password), TRUE) <= 0 then
  627.       return; ------------------------------------------------------>
  628.     endif
  629.     if strcmp(entered_password, cli_password) then
  630.       output_string("Wrong password\r\n");
  631.       return; ------------------------------------------------------>
  632.     endif
  633.   endif
  634.  
  635.   output_char('\n');
  636.  
  637.   show_message("Running the CLI program", FALSE);
  638.  
  639.   if (error = run_program(cli_name, "", !mode_local)) then
  640.     if error == -1 then
  641.       output_string("\r\nI'm unable to redirect program output to the current port.\r\n");
  642.     else
  643.       output_string("\r\nThere's been an error in running the CLI program.\r\n");
  644.     endif
  645.   endif
  646. endfunction
  647.  
  648.  
  649.  ------------------------------
  650. //    show_files      //
  651. -----------------------------
  652. function show_files(int   full_listing)
  653.   int   count;
  654.   string  dir_buf[24];
  655.   int   error;
  656.   int   is_dir;
  657.   string  name[16];
  658.   string  output[128];
  659.   string  time_string[80];
  660.  
  661.   output_string("File search pattern [*.*] ?");
  662.   count = get_string(output, sizeof(output), FALSE);
  663.   if count < 0 then
  664.     return;
  665.   endif
  666.   if count == 0 then
  667.     strcpy(output, "*.*");
  668.   endif
  669.  
  670.   output_char('\n');
  671.  
  672.   count = 0;
  673.  
  674.   error = file_dir_first(output, 0x3F, dir_buf);
  675.   while error do
  676.     is_dir = dir_buf[0] & 0x10;
  677.     if full_listing then
  678.       strftime(time_string, sizeof(time_string), "%c",
  679.            (dir_buf[3] << 24) + (dir_buf[4] << 16) + (dir_buf[1] <<  8) + dir_buf[2]);
  680.       sprintf(output, "%-14.14s  %.30s  %8d", dir_buf + 9,
  681.           time_string,
  682.           (dir_buf[5] << 24) + (dir_buf[6] << 16) + (dir_buf[7] << 8) + dir_buf[8]);
  683.       if is_dir then
  684.         strcat(output, " <DIR>");
  685.       endif
  686.       strcat(output, newline);
  687.     else
  688.       if is_dir then
  689.         sprintf(name, "[%s]", dir_buf + 9);
  690.       else
  691.         strcpy(name, dir_buf + 9);
  692.       endif
  693.       sprintf(output, "%-15.15s", name);
  694.       if (count = count + 1) >= 5 then
  695.         strcat(output, newline);
  696.         count = 0;
  697.       endif
  698.     endif
  699.  
  700.     output_string(output);
  701.     if check_key() == 3  or  carrier_dropped() then
  702.       error = FALSE;  -- Force an exit from the loop
  703.     else
  704.       error = file_dir_next(dir_buf);
  705.     endif
  706.   endwhile
  707.  
  708.   output_char('\n');
  709. endfunction
  710.  
  711.  
  712.  ------------------------------
  713. //    upload_file     //
  714. -----------------------------
  715. function upload_file()
  716.   string  filename[32];
  717.   string  fullname[128];
  718.   string  input[128];
  719.   string  letters;
  720.   int   overwrite;
  721.   int   protocol;
  722.   int   success;
  723.   string  s;
  724.  
  725.   if check_local() then
  726.     return; ---------------------------------------------------------->
  727.   endif
  728.  
  729.   letters = "AXKYGZ";
  730.  
  731.     output_string("\nProtocols Available:\r\n[A]SCII, [X]Modem, XModem-1[K], [Y]Modem, YModem-[G], [Z]Modem\r\n\nYour choice: ");
  732.   protocol = toupper(get_key(TRUE));
  733.   output_string(newline);
  734.  
  735.   if (s = strchr(letters, protocol)) != NULL then
  736.     if protocol != 'A' then
  737.       -- 's' points into the string 'letters'.  Take advantage of the fact
  738.       -- that the order of the letters matches the protocol numbers, but
  739.       -- subtract one since 'letters' starts with 'A' rather than 'X'.
  740.       set_protocol(s - letters - 1);
  741.     endif
  742.  
  743.     if s >= letters + 3 then
  744.       -- It's Y, G, or Z; batch protocols.
  745.       strcpy(input, "RECEIVED.FIL");
  746.     else
  747.       output_string("File to upload: ");
  748.       if get_string(input, sizeof(input), FALSE) <= 0 then
  749.         input[0] = 0;
  750.       endif
  751.     endif
  752.  
  753.     if input[0] then
  754.       parse_filename(input, fullname, filename);
  755.       overwrite = TRUE;
  756.       if file_exists(fullname) then
  757.         output_string("File exists!  Overwrite it [Y/N] ? ");
  758.         overwrite = toupper(get_key(TRUE)) == 'Y';
  759.         output_string(newline);
  760.       endif
  761.       if overwrite then
  762.         success = FALSE;
  763.         if protocol == 'A' then
  764.           output_string("Type ^C when done.\r\n");
  765.           if (success = ascii_receive(fullname, FALSE)) then
  766.             -- STalker automatically aborts an operation in progress when
  767.             -- the remote user types ^C in REMOTE mode, just as if the
  768.             -- UNDO key had been pressed.  We just need to sit and wait
  769.             -- until they do so.  Note that this doesn't work if you
  770.             -- invoke the script the normal way, since STalker won't be
  771.             -- in REMOTE mode.
  772.             wait_until(2000, 1, 1, 0, 0, 0);
  773.             success = ascii_receive(NULL);
  774.           endif
  775.         else
  776.           output_string("Begin uploading now...\r\n");
  777.           success = download(fullname);
  778.         endif
  779.         if !success then
  780.           output_string("\r\nThe upload was not completed successfully.");
  781.         endif
  782.       endif
  783.     endif
  784.   endif
  785.  
  786.   output_char('\n');
  787. endfunction
  788.