home *** CD-ROM | disk | FTP | other *** search
/ PC go! 1995 July / Image.iso / pcgo / programm / share / basics / telixw / tfw.5 / WINHOST.SLT < prev   
Encoding:
Text File  |  1995-02-01  |  40.6 KB  |  1,399 lines

  1. //
  2. //   W I N H O S T . S L T
  3. //
  4. //   Copyright (C) 1988-1994 deltaComm Development.
  5. //
  6. //   - Written by Colin Sampaleanu.
  7. //   - Modifications by Jeff Woods, Feb '91, to add help function and support
  8. //     for locked modems.
  9. //   - Modifications by Dan Horn, Nov '92, fixed 'floating' timer bug.
  10. //   - Thanks to Jon Fleming for his help in porting this to Windows.
  11. //   - Modifications for hot keys and logins, fixes for chat mode and
  12. //     <=9600 baud remote dos shells in Dec '94 by Sean Palmer
  13. //   - Modifications to Connect baud parsing Jan '95 by Sean Palmer
  14. //
  15. //   This is a Host Mode for Telix, written as a script file.
  16. //   To configure Host Mode parameters such as passwords, run the 'WCONFIG'
  17. //   script. That script is run automatically if the Host Mode configuration
  18. //   file 'WINHOST.CNF' is missing.
  19. //
  20. //   This script will only work with Hayes compatible modems, but may be
  21. //   modified for operation with other modems.
  22. //
  23. //////////////////////////////////////////////////////////////////////////////
  24.  
  25.  
  26. // Parameters which are configured from the WinHost configuration file
  27.  
  28. str host_downloads[64],         // Default where users may download from
  29.     host_uploads[64];           // Default where uploaded files go
  30.  
  31. int direct_connect = 0,         // 0 = using a modem
  32.     modem_lock = 0,
  33.     closed_sys = 0;             // 0 = users may sign up on line if not
  34.                                 //  found in the config file
  35.  
  36. // Various global variables
  37.  
  38. str current_caller[31],         // storage of current caller's name
  39.     our_dir[64];                // Winhost directory (either Telix's
  40.                                 //  scripts directory or the contents
  41.                                 //  of the HOST2DIR environment variable
  42.                                 //  if it exists)
  43.  
  44.  
  45. int finished_caller,            // set to TRUE when must return to top
  46.     local_mode,                 // set to TRUE when local test mode
  47.     access_level,               // access level of current caller
  48.     carrier_counts = 1,         // TRUE if should watch Carrier signal
  49.     already_connected = 0,
  50.     exit_requested = 0,         // set to TRUE if Sysop has pressed Esc
  51.     connection_lost = 0,        // set to TRUE when carrier lost
  52.     kill_user = 0,              // set to TRUE when user must be purged
  53.     min_user_name = 5,          // Minimum length of user's name
  54.     user_has_own_dir;           // Flag to restrict the user to one dir
  55.  
  56. int old_scr_chk_key,            // storage for some system variables
  57.     old_cisb_auto,              // which we have to modify and put
  58.     old_zmod_auto,              // back to what they were when done
  59.     old_sound;
  60.  
  61. str old_down_dir[64],
  62.     old_up_dir[64],
  63.     tfw_down_dir[64],
  64.     tfw_up_dir[64],
  65.     old_usage_fname[64];
  66.  
  67. #INCLUDE "WHUTILS.SLT"          // Functions which are shared with the
  68.                                 //  configuration managements script
  69.  
  70. //////////////////////////////////////////////////////////////////////////////
  71. //////////////////////////////////////////////////////////////////////////////
  72.  
  73. main() {
  74.  
  75.   int c;
  76.   str s[80];
  77.  
  78.   tfw_up_dir = _up_dir;
  79.   tfw_down_dir = _down_dir;
  80.   clear_scr;
  81.  
  82.   get_our_dir;
  83.  
  84.   if (read_host_config_file == -1) {
  85.      prints("Unable to read WINHOST.CNF...");
  86.      prints("Running WCONFIG, the Host Mode configuration script.^M^J");
  87.      s = our_dir;
  88.      strcat (s, "WCONFIG");
  89.      calld(s);
  90.      if (read_host_config_file() == -1) {
  91.         prints("Still unable to read WINHOST.CNF. Aborting Host Mode.^M^J");
  92.         return -1;
  93.      }
  94.   }
  95.  
  96.   prints ("Checking existence of download and upload directories ...");
  97.   if (!(check_directory(host_downloads) && check_directory(host_uploads))) {
  98.     prints("Aborting Host Mode.");
  99.     return -1;
  100.   }
  101.  
  102.   old_scr_chk_key = _scr_chk_key;
  103.   _scr_chk_key = 0;
  104.   old_cisb_auto = _cisb_auto;
  105.   _cisb_auto = 0;
  106.   old_zmod_auto = _zmod_auto;
  107.   _zmod_auto = 0;
  108.   old_sound = _sound_on;
  109.   _sound_on = 0;
  110.   old_down_dir = _down_dir;
  111.   old_usage_fname = _usage_fname;
  112.  
  113.   s = our_dir;
  114.   strcat (s, "HOST2.LOG");
  115.   usagelog (s);
  116.  
  117.   carrier_counts = !direct_connect;
  118.   already_connected = (carrier_counts && carrier());
  119.  
  120.   while (1) {
  121.     _down_dir = host_uploads;   // these are reversed because we are the Host
  122.     old_up_dir = _up_dir;
  123.     _up_dir = host_downloads;   // these are reversed because we are the Host
  124.     user_has_own_dir = 0;
  125.     if (!direct_connect && !already_connected) {
  126.       if (!modem_lock)
  127.         set_cparams(modem_lock, 0, 8, 1);
  128.       delay_scr(3);
  129.       prints("Sending Modem Init string...");
  130.       cputs_tr(_mdm_init_str);
  131.       delay_scr(20);
  132.       prints("Sending Auto-Answer string...");
  133.       cputs_tr(_auto_ans_str);
  134.       delay_scr(10);
  135.     }
  136.  
  137.     finished_caller = kill_user = 0;
  138.  
  139.     if (direct_connect)
  140.       carrier_counts = 0;
  141.     else {
  142.       carrier_counts = 1;
  143.       local_mode = 0;
  144.       prints("^M^JHost Mode: Waiting for call...");
  145.       prints("(Press Esc to exit, or 'L' for local test mode).^M^J");
  146.  
  147.       do {
  148.         if (carrier()) break;
  149.  
  150.         if ((c = inkey())==27) {
  151.           exit_requested = 1;
  152.           break;
  153.         }
  154.         else if (toupper(c) == 'L') {             // local test mode
  155.           prints("Local test mode entered");
  156.           local_mode = 1;
  157.           carrier_counts = 0;
  158.           break;
  159.         }
  160.       } while (1);
  161.     }
  162.  
  163.     if (!exit_requested) {
  164.       prints("Incoming call. Sysop: press Esc to exit, or END to terminate user.");
  165.  
  166.       do_one_caller();
  167.       if ((connection_lost || kill_user) && carrier_counts && carrier())
  168.         hangup();             // make sure nobody sneaks in
  169.     }
  170.     already_connected = 0;
  171.     if (exit_requested) {
  172.       if (!carrier() && !direct_connect) {
  173.         prints("Sending Modem Init string...");
  174.         cputs_tr(_mdm_init_str);
  175.       }
  176.       _scr_chk_key = old_scr_chk_key;
  177.       _cisb_auto = old_cisb_auto;
  178.       _zmod_auto = old_zmod_auto;
  179.       _sound_on = old_sound;
  180.       _down_dir = tfw_down_dir;
  181.       _up_dir = tfw_up_dir;
  182.       prints("^M^JHost mode script finished.");
  183.       usagelog("*CLOSE*");
  184.       _usage_fname = old_usage_fname;
  185.       return 1;
  186.     }
  187.   }
  188. }
  189.  
  190. //////////////////////////////////////////////////////////////////////////////
  191.  
  192. host_help (str mode, str option) {
  193.  
  194.   str fname[64];
  195.  
  196.   fname = our_dir;
  197.   strcat (fname, mode);
  198.   strcat (fname, "_HELP_");
  199.   StrCat (fname, option);
  200.   StrCat (fname, ".TXT");
  201.  
  202.   if (FileFind (fname, 0)) {
  203.     type_our_file (fname);
  204.     return (1);
  205.   }
  206.   else {
  207.     printsc ("^MCan't find help file ");
  208.     prints (fname);
  209.     return (0);
  210.   }
  211. }
  212.  
  213. //////////////////////////////////////////////////////////////////////////////
  214.  
  215. do_one_caller() {
  216.  
  217.   str strn[80], fname[64],  s[80], temporary[1], num[10];
  218.   int option, status, c, i, i2, f, len;
  219.  
  220.   access_level = 1;
  221.  
  222. //  flushbuf();
  223.  
  224.   if (already_connected)
  225.     prints("Already connected, or modem Carrier Detect switch improperly set!");
  226.   else if (carrier_counts)
  227.     determine_baud();
  228.  
  229.   if (!local_mode) delay_scr(20);
  230.   type_our_file("LOGO.MSG");
  231.  
  232.   flushbuf();
  233.  
  234.   if (!get_user_name()) {
  235.     ustamp("Failed logon attempt", 1, 0);
  236.     return;
  237.     }
  238.  
  239.   access_level = setup_user(3);
  240.  
  241.   if (access_level) {
  242.     ustamp("Logon by ", 1, 0);
  243.     ustamp(current_caller, 0, 1);
  244.   }
  245.   else {
  246.     ustamp("Failed logon attempt by ", 1, 0);
  247.     ustamp(current_caller, 0, 1);
  248.     send_goodbye();
  249.     if (carrier_counts) {
  250.       delay_scr(10);
  251.       hangup();
  252.     }
  253.     return;
  254.   }
  255.  
  256.   type_our_file("WELCOME.MSG");
  257.  
  258.   while (1) {
  259.     if (finished_caller)
  260.     return;
  261.  
  262.     if (access_level == 3) {
  263.       if (type_our_file("MMENU3.TXT") == -1)
  264.         host_send("^M^JFiles  Type  Upload  Download  Shell  Chat  Help  Goodbye ? ");
  265.     }
  266.     else {
  267.       if (type_our_file ("MMENU.TXT") == -1)
  268.           host_send("^M^JFiles  Type  Upload  Download  Chat  Help  Goodbye ? ");
  269.     }
  270.  
  271.     host_send ("^M^JCommand: ");
  272.     host_input_strn(strn, 1, 1);
  273.     option = toupper(subchr(strn, 0));
  274.     host_send("^M^J");
  275.  
  276.     if (option == 'H') {               // Help
  277.       host_send("^M^JWhich item above do you wish help on? ");
  278.       host_input_strn(strn, 1, 1);
  279.       substr (strn, 0, 1, strn);
  280.       strupper (strn);
  281.       Host_send("^M^J");
  282.       host_help( "H", strn);
  283.     }
  284.  
  285.     if (option == 'F') {               // Files directory
  286.       if (access_level >= 2) {
  287.         host_send("Enter 'filespec' or press Return for *.*,^M^J: ");
  288.         host_input_strn(fname, 64, 1);
  289.         host_send("^M^J");
  290.         ustamp ("Requested file listing of ", 1, 0);
  291.         ustamp (fname, 0, 1);
  292.  
  293.         if (strcmpi (fname, "") == 0) {
  294.           fname = "*.*";
  295.         }
  296.  
  297.         if (just_filename(fname)) {
  298.           strn = _down_dir;
  299.           strcat(strn, fname);
  300.         }
  301.         else if (user_has_own_dir == 1) {
  302.           host_send ("^M^JAccess outside ");
  303.           host_send (_down_dir);
  304.           host_send (" not allowed^M^J");
  305.           strn = _down_dir;
  306.           strcat(strn, "*.*");
  307.         }
  308.         else {
  309.           len = strlen (fname);
  310.           substr (fname, len - 1, 1, temporary);
  311.           if (strcmpi (temporary, "\") == 0) {
  312.             strn = fname;
  313.             strcat (strn, "*.*");
  314.           }
  315.           else strn = fname;
  316.         }
  317.       }
  318.       else {
  319.         strn = _down_dir;
  320.         strcat(strn, "*.*");
  321.         ustamp ("Requested listing of files", 1, 1);
  322.       }
  323.  
  324.       host_show_directory(strn);
  325.       ustamp ("Displayed ", 1, 0);
  326.       ustamp (strn, 0, 1);
  327.     }
  328.  
  329.     else if (option == 'T') {          // Type a file
  330.       host_send("Type what file? ");
  331.       host_input_strn(strn, 64, 1);
  332.       host_send("^M^J");
  333.       ustamp ("Requested to type ", 1, 0);
  334.       ustamp (strn, 0, 1);
  335.  
  336.       if ((access_level == 1) || (user_has_own_dir == 1))
  337.         fnstrip(strn, 3, fname);
  338.       else
  339.         fname = strn;
  340.  
  341.       if (just_filename(fname)) {
  342.         strn = _down_dir;
  343.         strcat(strn, fname);
  344.         fname = strn;
  345.       }
  346.  
  347.       if (!filefind(fname, 0, strn)) {
  348.         host_send("Unable to find ");
  349.         host_send(fname);
  350.         continue;
  351.       }
  352.  
  353.       get_extension(fname, strn);
  354.       if (strcmpi(strn,"ZIP")==0 ||
  355.           strcmpi(strn,"ARJ")==0)
  356.       {
  357.         host_send("Unable to type ");
  358.         host_send(fname);
  359.         continue;
  360.       }
  361.  
  362.       type_file(fname);
  363.       ustamp ("Typed ", 1, 0);
  364.       ustamp (fname, 0, 1);
  365.     }
  366.  
  367.     else if (option == 'G') {          // Goodbye (Hang-up)
  368.       send_goodbye ();
  369.       ustamp("User logged off.", 1, 1);
  370.       if (carrier_counts) {
  371.         delay_scr(10);
  372.         hangup();
  373.       }
  374.       return;
  375.     }
  376.  
  377.     else if (option == 'C') {          // Chat mode
  378.       prints("Sysop: Press Space to chat, any other key not to.^M^J");
  379.       c = 0;
  380.       _sound_on = 1;
  381.       for (i = 8; i && !c; --i) {
  382.         host_send (".");
  383.         if (carrier_counts && !carrier()) {
  384.           prints("^M^JConnection has been lost, call terminated.^M^J");
  385.           connection_lost = 1;
  386.           finished_caller = 1;
  387.           break;
  388.         }
  389.         cputc('^G');
  390.         tone(523, 20);
  391.         tone(659, 20);
  392.         tone(523, 20);
  393.         tone(659, 20);
  394.         tone(523, 20);
  395.         tone(659, 20);
  396.         delay(9);
  397.         c = inkey();
  398.       }
  399.       _sound_on = 0;
  400.       host_send ("^M^J");
  401.       if (finished_caller)
  402.         continue;
  403.       if (c != ' ') {
  404.         host_send("Sorry, the Sysop is unavailable^M^J");
  405.         continue;
  406.       }
  407.       host_send("The sysop is here!^M^J");
  408.       chatmode(1,1); //start chat
  409.       status_wind("Press Ctrl-X to terminate chat",30);
  410.       while (1) {
  411.         if (waitfor("^X",1)) break;
  412.       }
  413.       chatmode(1,0); //end chat
  414.     }
  415.  
  416.     else if (option == 'U') {          // User upload
  417.       option = host_get_prot();
  418.       if (!option)
  419.         continue;
  420.  
  421.       ustamp ("Upload ", 1, 0);
  422.       status = 1;
  423.       if (option == 'Y' || option == 'Z' || option == 'E') {
  424.         ustamp ("with name-transferrring protocol ", 0, 1);
  425.         send_transfer_msg();
  426.         status = receive(option, "");
  427.       }
  428.       else {
  429.         host_send("Upload what file? ");
  430.         host_input_strn(strn, 48, 1);
  431.         host_send("^M^J");
  432.           if (!strn)
  433.             continue;
  434.           ustamp (strn, 0, 1);
  435.           if ((access_level == 1) || (user_has_own_dir == 1)) // if access 1, name and ext only
  436.             fnstrip(strn, 3, fname);
  437.           else
  438.             fname = strn;
  439.  
  440.           if (just_filename(fname)) {
  441.             strn = _up_dir;
  442.             strcat(strn, fname);
  443.             fname = strn;
  444.           }
  445.  
  446.           if (filefind(fname, 23, strn)) {
  447.             host_send("File already exists!^M^J");
  448.             ustamp ("File already exists", 1, 1);
  449.           }
  450.           else {
  451.             send_transfer_msg();
  452.             status = receive(option, fname);
  453.           }
  454.         }
  455.  
  456.         if (status == -2) {                      // Carrier lost
  457.           connection_lost = finished_caller = 1;
  458.           ustamp ("Lost carrier", 1, 1);
  459.         }
  460.         else if (status == -1) {
  461.           host_send("^M^J^M^J^GOne or more files not received!^M^J");
  462.           ustamp ("One or more files not received", 1, 1);
  463.         }
  464.         else {
  465.           ustamp ("Transfer complete", 1, 1);
  466.         }
  467.       }
  468.  
  469.     else if (option == 'D') {          // User download
  470.       option = host_get_prot();
  471.       if (!option)
  472.         continue;
  473.       host_send("Download what file(s)? ");
  474.       host_input_strn(strn, 48, 1);
  475.       host_send("^M^J");
  476.       if (!strn)
  477.         continue;
  478.       ustamp ("Attempt to download ", 1, 0);
  479.       ustamp (strn, 0, 1);
  480.       if ((access_level == 1) || (user_has_own_dir == 1)) // if not level 2, keep only name & ext
  481.         fnstrip(strn, 3, fname);
  482.       else
  483.         fname = strn;
  484.       if (just_filename(fname)) {
  485.         strn = _down_dir;
  486.         strcat(strn, fname);
  487.         fname = strn;
  488.       }
  489.  
  490.       if (!filefind(fname, 0, strn)) {
  491.         host_send("Unable to find any matching file(s)!^M^J");
  492.         ustamp ("No such file", 1, 1);
  493.         continue;
  494.       }
  495.  
  496.       status = 1;
  497.       send_transfer_msg();
  498.       status = send(option, fname);
  499.       if (status == -2) {                      // Carrier lost
  500.         connection_lost = finished_caller = 1;
  501.         ustamp ("Lost carrier", 1, 1);
  502.       }
  503.       else if (status == -1) {
  504.         host_send("^M^J^M^J^GOne or more files not sent!^M^J");
  505.         ustamp ("One or more files not sent", 1, 1);
  506.       }
  507.       else {
  508.         ustamp ("Transfer complete", 1, 1);
  509.       }
  510.     }
  511.  
  512.     else if (option == 'S') {          // Remote shell
  513.       ustamp ("Attempted shell", 1, 1);
  514.       if (access_level == 3) {
  515.         host_send("Type EXIT and then press Enter to come back.^M^J");
  516.         if (get_baud() == 300)
  517.           delay_scr(10);
  518.         if (local_mode)
  519.           dos("", 0);
  520.              // See if user has prepared a custom file for shell operation
  521.              // and call that if it exists
  522.         else {
  523.           if (filefind("RSHELL.BAT", 0, strn))
  524.             do_remote_shell("RSHELL.BAT");
  525.           else {  // otherwise make our own temporary batch file for redirection
  526.             if (get_port() != 1 && get_port() != 2) {
  527.               host_send("Remote Shell not supported on this comm port due to DOS limits!^M^J");
  528.             }
  529.             else {
  530.              // now want to make a temporary batch file which will be
  531.              // called to redirect DOS input and output, then shell to
  532.              // another copy of the command interpreter
  533.               f = fopen("HOSTTEMP.BAT", "w");
  534.               if (f) {
  535.                 if (get_baud()>9600) {
  536.                   status_wind("Attempting to shell to dos at over 9600 baud",50);
  537.                   ustamp("DOS shell baud > 9600",0,1);
  538.                   }
  539.                 fputs("MODE ", f);    // this command informs dos of the port rate
  540.                 strn = "COMx";
  541.                 setchr(strn, 3, get_port() + '0'); // get right name to redirect
  542.                 fputs(strn, f);                    // save strn for later
  543.                 fputc(" baud=", f);
  544.                 itos(get_baud(), num);
  545.                 fputs(num, f);
  546.                 fputs(" parity=", f);
  547.                 switch (get_parity()) {
  548.                   case 1:  fputc('E', f);
  549.                   case 2:  fputc('O', f);
  550.                   case 3:  fputc('M', f);
  551.                   case 4:  fputc('S', f);
  552.                   default: fputc('N', f);
  553.                 }
  554.                 fputs(" data=", f);
  555.                 itos(get_dataB(), num);
  556.                 fputs(num, f);
  557.                 fputs(" stop=", f);
  558.                 itos(get_stopB(), num);
  559.                 fputs(num, f);
  560.                 fputs("^M^J", f);
  561.  
  562.                 fputs("CTTY ", f);           // write to batch file
  563.                 fputs(strn, f);              // this command actually makes the shell work
  564.                 fputs("^M^J", f);
  565.                 if (getenv ("COMSPEC", s) == 0)
  566.                   s = "COMMAND.COM";
  567.  
  568.                 fputs (s, f);
  569.                 fputs("^M^J", f);
  570.                 fputs("CTTY CON^M^J", f);
  571.                 fputs("EXIT^M^J", f);
  572.  
  573.                 fclose(f);                   // close the file
  574.  
  575.                 if (!local_mode)             // call batch file
  576.                   do_remote_shell("HOSTTEMP.BAT");
  577.               }
  578.               else
  579.                 host_send("Can't open temporary batch file!^M^J");
  580.             }
  581.           }
  582.         }
  583.       }
  584.       else ustamp ("Request denied", 1, 1);
  585.     }
  586.  
  587.     else if (option == '^Z') {          // Shut down Host Mode
  588.       if (access_level == 3) {
  589.         host_send("Shutting down Host mode. ");
  590.         ustamp("User shut down Host Mode.", 1, 1);
  591.         send_goodbye ();
  592.         ustamp("User logged off.", 1, 1);
  593.         if (carrier_counts)
  594.           hangup();
  595.         finished_caller = 1;
  596.         exit_requested = 1;
  597.       }
  598.     }
  599.   }
  600. }
  601.  
  602. //////////////////////////////////////////////////////////////////////////////
  603.  
  604. do_remote_shell(str batfile) {
  605.   str savedConn[80];                   //holds saved connect device's name
  606.  
  607.   //here we make a new connect device with a port of 0 which causes the
  608.   //device to not be attached to any specific port. Useful to
  609.   //keep Telix from using any ports temporarily.
  610.   if (makeConnectDevice("__NULL__","2400bps Generic",0,0,0))
  611.   {
  612.     connectDeviceName(0,savedConn);      //get current device name
  613.     if (set_ConnectDevice("__NULL__",2)) //selecting a port 0 device won't
  614.     {                                    //disturb the current device's connection
  615.       dos(batfile);
  616.       set_ConnectDevice(savedConn,1);  //restore previous connect device
  617.     }                                  //without sending init string
  618.     killConnectDevice("__NULL__");
  619.   }
  620. }
  621.  
  622. //////////////////////////////////////////////////////////////////////////////
  623.  
  624. host_get_prot() {
  625.  
  626.   str prot[1], strn[1], s[64];
  627.  
  628.   int Option;
  629.  
  630.   prot = "H";
  631.  
  632.   while (strcmpi (prot, "H") == 0) {
  633.  
  634.     if (type_our_file ("PMENU.TXT") == -1) {
  635.       host_send("^M^JXmodem  1k-Xmodem  G-1k-Xmodem  Ymodem  YmodEm-g  Zmodem^M^J");
  636.       host_send("Help Cancel^M^J");
  637.     }
  638.  
  639.     host_send("Which protocol, or H for help ? ");
  640.     host_input_strn(prot, 1, 1);
  641.     strupper (prot);
  642.     host_send("^M^J");
  643.  
  644.     if (strcmpi (prot, "H") == 0) {
  645.       host_send ("^M^JHelp on which protocol, or ^"A^" for ALL? ");
  646.       host_input_strn (strn, 1, 1);
  647.       substr (strn, 0, 1, strn);
  648.       strupper (strn);
  649.       Host_send("^M^J");
  650.       host_help( "P", strn);
  651.     }
  652.  
  653.     if (strposi("X1GYEZH", prot, 0) == -1)    // if illegal prot or cancel
  654.       prot = "";                              // return 0
  655.   }
  656.  
  657.   return (toupper(subchr(prot, 0)));
  658.  
  659. }
  660.  
  661. //////////////////////////////////////////////////////////////////////////////
  662.  
  663. send_transfer_msg() {
  664.  
  665.   host_send("Ready to transfer file(s)... Press Ctrl-X at least twice to abort^M^J");
  666. }
  667.  
  668. //////////////////////////////////////////////////////////////////////////////
  669. // Determine the baud rate once a Carrier Detect Signal has been detected
  670. // Since no characters were read, the 'CONNECT' string should still be
  671. // in the receive buffer.
  672.  
  673. determine_baud() {
  674.  
  675.   int tconnect;
  676.   int tmark, stat, c;
  677.   int new_baud = 0;
  678.  
  679.   str cstring[20];
  680.  
  681.   printsc("Determining baud... ");
  682.  
  683.   track_free(0);                // clear all existing tracks
  684.  
  685.   tconnect = track(_connect_str, 0);  // check for connect string
  686.  
  687.   tmark = timer_start(30);      // wait up to 3 seconds for string
  688.  
  689.   while (!time_up(tmark)) {
  690.     if (!carrier()) {
  691.       track_free(0);            // clear all existing tracks
  692.       timer_free(tmark);        // free existing timer
  693.       return 0;
  694.     }
  695.  
  696.     if (cinp_cnt()) {
  697.       printc_trm(c=cGetC);      // does tracks too
  698. //      printc(c=cGetC);
  699. //      track_addChr(c);
  700.       }
  701.  
  702.     if (track_hit(0) != tConnect) continue;
  703.  
  704.     while (1) {
  705.       while (!cinp_cnt()) ;
  706.       if ((c=cgetc)>' ') break;
  707.       printc(c);
  708.       }
  709.     while(1) {
  710.       printc(c);
  711.       if ((c>='0') && (c<='9'))
  712.         new_baud = new_baud * 10 + c - '0';
  713.       else break;
  714.       while (!cinp_cnt) ;
  715.       c=cgetc();
  716.     }
  717.     printc(c);
  718.  
  719.     if (!new_baud) new_baud = 300;
  720.  
  721.     break;                      // have baud rate, get out
  722.   }
  723.  
  724.   track_free(0);                // clear all existing tracks
  725.   timer_free(tmark);            // free existing timer
  726.  
  727.   if (!new_baud) {              // time-up without CONNECT string
  728.     prints("Failed!");
  729.     return 0;
  730.   }
  731.  
  732. //  printn(new_baud);
  733. //  newLine();
  734.   setDCERate(new_baud);         // Let TFW know
  735.   return 1;                     // indicate success
  736.  
  737. }
  738.  
  739.  
  740. //////////////////////////////////////////////////////////////////////////////
  741.  
  742. type_our_file(str fname) {
  743.   int f;
  744.   str s[144];
  745.  
  746.   if ((f=type_file(fname)) == -1) {
  747.     s=our_dir;
  748.     strcat(s,fname);
  749.     f=type_file(s);
  750.     }
  751.   return f;
  752. }
  753.  
  754. //////////////////////////////////////////////////////////////////////////////
  755.  
  756. type_file(str fname) {
  757.  
  758.   int f;
  759.   str s[80], buf[100];
  760.   int ichar, lines_sent = 0;
  761.  
  762.   f = fopen(fname, "r");
  763.   if (!f)
  764.     return -1;
  765.  
  766.   host_send("^M^J");
  767.  
  768.   while (1) {
  769.     if (carrier_counts)
  770.     if (!carrier()) {
  771.       connection_lost = 1;
  772.       finished_caller = 1;
  773.       fclose(f);
  774.       return 0;
  775.     }
  776.  
  777.     if (fgets(buf, 80, f) == -1) {
  778.       fclose(f);
  779.       return 1;
  780.     }
  781.  
  782.     host_send(buf);
  783.     host_send("^M^J");
  784.     ++lines_sent;
  785.  
  786.     if (lines_sent >= 22) {
  787.       lines_sent = 0;
  788.       host_send("[More]");
  789.       host_input(1);
  790.  
  791.       if (finished_caller) {       // if user inactivity
  792.         fclose(f);
  793.         return 0;
  794.       }
  795.  
  796.       host_send("^H ^H^H ^H^H ^H^H ^H^H ^H^H ^H^H ^H");
  797.     }
  798.  
  799.     while (cinp_cnt()) {
  800.       ichar = cgetc();
  801.       if (ichar == '^C' || ichar == '^K') {
  802.         host_send("^M^J");
  803.         fclose(f);
  804.         return 1;
  805.       }
  806.     }
  807.   }
  808. }
  809.  
  810. //////////////////////////////////////////////////////////////////////////////
  811.  
  812. host_send(str outstr) {
  813.  
  814.   printsc(outstr);
  815.   if (!local_mode)
  816.     cputs(outstr);
  817.  
  818. }
  819.  
  820. //////////////////////////////////////////////////////////////////////////////
  821.  
  822. host_send_c(int chr) {
  823.  
  824.   printc(chr);
  825.   if (!local_mode)
  826.     cputc(chr);
  827.  
  828. }
  829.  
  830. //////////////////////////////////////////////////////////////////////////////
  831.  
  832. host_input_strn(str buf, int maximum, int echoable) {
  833.  
  834.   int i = 0, key;
  835.  
  836.   while (1) {
  837.     key = host_input(echoable);
  838.     if (!key) {               // timeout or user disconnect
  839.       setchr(buf, 0, 0);      // set string to empty
  840.       return 0;               // indicate there is a problem
  841.     }
  842.  
  843.     if (key == '^M') {
  844. //      if (!echoable) host_send("^H ");
  845.       break;
  846.       }
  847.     if (key == 127 || key == 8) {
  848.       if (i) {
  849.         --i;
  850.         host_send_c(key);
  851.       }
  852.       continue;
  853.     }
  854.     if (i < maximum)
  855.       setchr(buf, i, key);
  856.     ++i;
  857.     if (maximum<=1) break;  //hotkeys if buffer only holds one
  858.   }
  859.  
  860.   if (i > maximum)
  861.     i = maximum;
  862.  
  863.   setchr(buf, i, '^0');
  864.  
  865.   if (subchr(buf, 0))
  866.     return 1;
  867.   else
  868.     return 0;
  869.  
  870. }
  871.  
  872. //////////////////////////////////////////////////////////////////////////////
  873.  
  874. host_input(int echoable) {
  875.  
  876.   int c, t;
  877.  
  878.   t = timer_start(2400);         // 4 minutes inactivity allowed
  879.  
  880.   while (1) {
  881.     if (time_up(t) && !direct_connect) {
  882.       host_send("^M^J^M^JInactivity period too long. Connection terminated!^M^J");
  883.       if (carrier_counts)
  884.         hangup();
  885.       finished_caller = 1;
  886.       kill_user = 1;
  887.       break;
  888.     }
  889.  
  890.     if (carrier_counts)
  891.       if (!carrier()) {
  892.         prints("^M^JConnection has been lost, call terminated.^M^J");
  893.         connection_lost = 1;
  894.         finished_caller = 1;
  895.         break;
  896.       }
  897.     if ((c = inkey()) != 0) {
  898.       if (c == 27) {             // ESC key, sysop wants to exit
  899.         finished_caller = 1;
  900.           exit_requested = 1;
  901.           break;
  902.       }
  903.       else if (c == 0x4f00) {    // END key, terminate user
  904.         prints("^M^JUser terminated!");
  905.         ustamp("User terminated!", 1, 1);
  906.         if (carrier_counts)
  907.           hangup();
  908.  
  909.         finished_caller = 1;
  910.         kill_user = 1;
  911.         access_level = 0;
  912.         break;
  913.       }
  914.  
  915.       else if (c <= 255) {
  916.         if (c != 8 && c != 127)
  917.           if ((!echoable)&& c != 13)
  918.             host_send_c('*');
  919.           else
  920.             host_send_c(c);
  921.         break;
  922.       }
  923.     }
  924.  
  925.     if (!local_mode)
  926.       if (cinp_cnt())  {
  927.         c = cgetc();
  928.         if (c != 8 && c != 127)
  929.           if ((!echoable)&& c != 13)
  930.             host_send_c('*');
  931.           else
  932.             host_send_c(c);
  933.         break;
  934.       }
  935.   }
  936.  
  937.   timer_free(t);                 // free existing timer
  938.   if (finished_caller)
  939.     return 0;                    // return 0 - no character
  940.  
  941.   return c;                      // return received/pressed character
  942. }
  943.  
  944. //////////////////////////////////////////////////////////////////////////////
  945.  
  946.  
  947. //  This routine maintains an ASCII file in the Telix files directory called
  948. //    WHPASS.TXT.  The format for each line is:
  949.  
  950. //    name;password;working_dir;access_level  (optional comment)
  951.  
  952. //    The name, password, working_dir, and access_level fields MUST be
  953. //    separated by semicolons
  954.  
  955. //    The working_dir field is optional (but the semicolons before and after
  956. //    it are _NOT_).  If there's no working_dir field, the default host
  957. //    upload and download direcories are used.
  958.  
  959. //  The routine searches the file for a line on which the "name" field
  960. //    matches the global variable "current_caller"  (not case sensitive).
  961.  
  962. //  If a match is found, and the user can type a password that matches
  963. //    the "password" field (not case sensitive), the routine returns
  964. //    the integer "access_level".
  965.  
  966. //  If no match is found, the user is given an opportunity to register
  967. //    (at access level 1).
  968.  
  969. //  If the user registers, the file is updated with the new user name,
  970. //    password, and access level (1), and the routine returns 1.
  971.  
  972. //  If the user does not register, or if the user cannot match the password
  973. //    in the file in "maxtries",  or if the user registers and cannot match
  974. //    the password he/she chose in "maxtries", the routine returns 0.
  975.  
  976. setup_user (int maxtries) {
  977.   str password_file[64], line_from_file[127], password_from_file[16],
  978.       name_from_file[31], temporary[16], typed_password[16],
  979.       working_dir[64], last_char[1];
  980.  
  981.   int password_file_handle, field_length, field_start,
  982.       found_password = 0, access_from_file, counter = 0,
  983.       file_ends_in_control_z = 0, line_number = 0, length;
  984.   password_file = our_dir;
  985.   strcat (password_file, "WHPASS.TXT");
  986.  
  987.   for (counter = 1; counter <= maxtries; counter = counter + 1) {
  988.                       // Try to open password file
  989.     if (password_file_handle = fopen (password_file, "r")) {
  990.                         // Read next line from file.
  991.       while (fgets (line_from_file, 64, password_file_handle) != -1) {
  992.                         // Check for ^Z termination
  993.         if (line_from_file == "^Z") {
  994.           file_ends_in_control_z = 1;
  995.           break;
  996.         }
  997.         line_number = line_number + 1;
  998.                       // allow for empty or comment lines
  999.                       // comment lines begin with ';'
  1000.         if (!strlen(line_from_file) || strchr(line_from_file, 0, ';')) {
  1001.                       // If line is long enough . . .
  1002.           if (strlen (line_from_file) >= min_user_name+4) {
  1003.                       // Get length of name
  1004.             if ( (field_length = strchr (line_from_file, 0, ';')) > 0) {
  1005.                       // Get name
  1006.               substr (line_from_file, 0, field_length, name_from_file);
  1007.                       // If name matches . . . .
  1008.               if (strcmpi (name_from_file, current_caller) == 0) {
  1009.                       // Get password
  1010.                 field_start = field_length + 1;
  1011.                 if ( (field_length = strchr (line_from_file, field_start, ';') - field_start) > 0) {
  1012.                   substr (line_from_file, field_start, field_length, password_from_file);
  1013.                       // Get working directory
  1014.                   field_start = field_start + field_length + 1;
  1015.                   if ( (field_length = strchr (line_from_file, field_start, ';') - field_start) >= 0) {
  1016.                     substr (line_from_file, field_start, field_length, working_dir);
  1017.                       // Get access level
  1018.                     field_start = field_start + field_length + 1;
  1019.                     substr (line_from_file, field_start, 1, temporary);
  1020.                     access_from_file = stoi (temporary);
  1021.                       // Set flag that we got an old user
  1022.                     found_password = 1;
  1023.                     break;
  1024.                   }
  1025.                   else password_file_error (line_number, line_from_file, "no third semicolon");
  1026.                 }
  1027.                 else password_file_error (line_number, line_from_file, "no second semicolon");
  1028.               }
  1029.             }
  1030.             else password_file_error (line_number, line_from_file, "no first semicolon");
  1031.           }
  1032.           else password_file_error (line_number, line_from_file, "line too short");
  1033.         }
  1034.       }
  1035.       fclose (password_file_handle);
  1036.     }
  1037.     else if (password_file_handle = fopen(password_file, 'W')) {  // no password file. Make one.
  1038.       fputs(";WHPASS.TXT - WinHost user data file^M^J", password_file_handle);
  1039.       fputs(";format: <NAME>;<PASSWORD>;<WORK_DIR>;<ACCESS> <COMMENT>^M^J", password_file_handle);
  1040.       fclose(password_file_handle);
  1041.     }
  1042.  
  1043.     if (found_password)
  1044.       break;
  1045.     else {
  1046.       host_send ("^M^JNo user ^"");
  1047.       host_send (current_caller);
  1048.       host_send ("^" on file; ");
  1049.       host_send ("Re-type name? (y/n): ");
  1050.       host_input_strn (temporary, 1, 1);
  1051.       host_send ("^M^J");
  1052.  
  1053.       if (strcmpi(temporary, "y"))
  1054.         break;
  1055.       else
  1056.         get_user_name();
  1057.     }
  1058.   }
  1059.  
  1060.   if (found_password) {
  1061.                       // Password is on file; ask for it
  1062.     host_send ("Password: ");
  1063.     for (counter = 1; counter <= maxtries; ++counter) {
  1064.       host_input_strn (typed_password, 16, 0);
  1065.                       // If a match
  1066.       if (!strcmpi (typed_password, password_from_file)) {
  1067.         host_send ("^M^J");
  1068.           // If the user has a working directory ...
  1069.         if (strlen(working_dir)) {
  1070.             // Check for a "\" on the end and add it if necessary
  1071.           length = strlen(working_dir);
  1072.           substr (working_dir, length - 1, 1, last_char);
  1073.           if (strcmpi (last_char, "\"))
  1074.             strcat (working_dir, "\");
  1075.             // Establish download & upload directories
  1076.           strupper (working_dir);
  1077.           if (check_directory (working_dir)) {
  1078.             _down_dir = working_dir;
  1079.             _up_dir = working_dir;
  1080.             user_has_own_dir = 1;
  1081.           }
  1082.           else {
  1083.             prints ("Using defaults");
  1084.             ustamp (working_dir, 1, 0);
  1085.             ustamp (" does not exist, using default", 0, 1);
  1086.           }
  1087.         }
  1088.           // Return the user's access level
  1089.         return (access_from_file);
  1090.       }
  1091.       if (counter < maxtries) {
  1092.         host_send ("^M^JDoes not match password on file!");
  1093.         host_send ("^M^JRe-type name? (y/N): ");
  1094.         host_input_strn (temporary, 1, 1);
  1095.         host_send ("^M^J^J");
  1096.  
  1097.         if (!strcmpi (temporary, "y")) {
  1098.           get_user_name();
  1099.           host_send("Password: ");
  1100.           }
  1101.         else host_send("Re-type password: ");
  1102.       }
  1103.       else
  1104.         host_send ("^M^JMaximum number of tries exceeded!^M^J");
  1105.  
  1106.     }
  1107.   }
  1108.                       // Password is not on file
  1109.   else if (!closed_sys) {
  1110.                       // Offer chance to register
  1111. //    host_send ("No user  ^"");
  1112. //    host_send (current_caller);
  1113. //    host_send ("^"  found in user file.^M^J");
  1114.     host_send ("Do you want to register? (y/N): ");
  1115.     host_input_strn (temporary, 1, 1);
  1116.     host_send ("^M^J");
  1117.                       // If user doesn't want to register
  1118.     if (not ((temporary == "Y") || (temporary == "y")))
  1119.       return (0);
  1120.                       // If user wants to register
  1121.     host_send ("Pick a password (16 characters maximum): ");
  1122.     host_input_strn (password_from_file, 16, 0);
  1123.                       // Make sure password is right
  1124.     host_send ("^M^JRe-enter your password to verify: ");
  1125.     for (counter = 1; counter <= maxtries; counter = counter + 1) {
  1126.       host_input_strn (typed_password, 16, 0);
  1127.                       // If all is ok
  1128.       if (strcmpi (typed_password, password_from_file) == 0) {
  1129.                       // Build new line for password file
  1130.         line_from_file = current_caller;
  1131.         strcat (line_from_file, ";");
  1132.         strcat (line_from_file, password_from_file);
  1133.         strcat (line_from_file, ";;1 **NEW USER** ");
  1134.         date (curtime(), temporary);
  1135.         strcat (line_from_file, temporary);
  1136.                       // Open password file for appending
  1137.         password_file_handle = fopen(password_file, 'a');
  1138.         if (file_ends_in_control_z)
  1139.           fseek (password_file_handle, -1, 2);
  1140.                       // Now we can write the line
  1141.         fwrite (line_from_file, strlen (line_from_file), password_file_handle);
  1142.         fwrite ("^M^J", 2, password_file_handle);
  1143.         fclose (password_file_handle);
  1144.         host_send ("^M^J");
  1145.         return (1);   // Return access level
  1146.       }
  1147.       if (counter < maxtries)
  1148.         host_send ("^M^JDoes not match!  Please try again: ");
  1149.       else
  1150.         host_send ("^M^JMaximum number of tries exceeded!^M^J");
  1151.     }
  1152.   }
  1153.   return (0);
  1154. }
  1155.  
  1156. //////////////////////////////////////////////////////////////////////////////
  1157. // A routine to print an error message to the local screen when something
  1158. //    is wrong with the password file
  1159.  
  1160. password_file_error (int line_number, str line, str error_specifier) {
  1161.  
  1162.   str line_number_string[4];
  1163.  
  1164.   itos (line_number, line_number_string);
  1165.  
  1166.   prints ("");
  1167.   printsc ("Bad line ");
  1168.   printsc (line_number_string);
  1169.   prints (" in password file:");
  1170.   printsc ("   ^"");
  1171.   printsc (line);
  1172.   prints ("^"");
  1173.   prints (error_specifier);
  1174.  
  1175.   return (1);
  1176. }
  1177.  
  1178. //////////////////////////////////////////////////////////////////////////////
  1179. // returns TRUE if passed filespec is just a filename. Also handles the
  1180. // forward slash as a path separator.
  1181.  
  1182. just_filename(str filespec) {
  1183.  
  1184.   int slash, space;
  1185.  
  1186.   if (strpos(filespec, ":", 0) != -1)
  1187.     return 0;
  1188.   if (strpos(filespec, "\", 0) != -1)
  1189.     return 0;
  1190.   if ((slash = strpos(filespec, "/")) == -1)
  1191.     return 1;
  1192.  
  1193.   space = strpos(filespec, " ");
  1194.   if (space == -1)
  1195.     return 0;
  1196.   if (space < slash)
  1197.     return 1;
  1198.  
  1199.   return 0;
  1200.  
  1201. }
  1202.  
  1203. //////////////////////////////////////////////////////////////////////////////
  1204.  
  1205. host_show_directory (str dir_spec) {
  1206.   str file_name[13], f_name_ext[12], f_size_str[20], f_date_str[20],
  1207.       f_time_str[20], buffer[80], path[67], full_name[80],
  1208.       temp[26], hours_str[2], minutes_str[2], seconds_str[2];
  1209.  
  1210.   int file_exists, fsize, ftime, lines, dot_pos, bps, seconds,
  1211.       minutes, hours;
  1212.  
  1213.   bps = get_baud (1);
  1214.  
  1215.   fnstrip (dir_spec, 12, path);
  1216.  
  1217.   file_exists = FileFind (dir_spec, 0, file_name);
  1218.  
  1219.   if (!file_exists) {
  1220.     host_send ("^M^JNo matching file found.^M^J");
  1221.   }
  1222.   else {
  1223.     lines = 2;
  1224.     host_send ("        Name          Size      Date     Time^M^J");
  1225.   }
  1226.  
  1227.   while (file_exists) {
  1228.  
  1229.     // Get the file size, as a string, with commas where appropriate
  1230.     fsize = FileSize ("");
  1231.     ItoS (fsize, temp);
  1232.     insert_commas (temp, f_size_str);
  1233.  
  1234.     // Get the file date and time as a string
  1235.     ftime = FileTime ("");
  1236.     Date (ftime, f_date_str);
  1237.     Time (ftime, f_time_str);
  1238.  
  1239.     // Estimate how long it'll take to transfer the file with Zmodem
  1240.     seconds = (fsize*10)/bps;
  1241.     // Guess at about 95% efficiency
  1242.     seconds = seconds + seconds/20;
  1243.     if (seconds == 0) {
  1244.       seconds = 1;
  1245.     }
  1246.     minutes = seconds/60;
  1247.     seconds = seconds - minutes*60;
  1248.     hours = minutes/60;
  1249.     minutes = minutes - hours*60;
  1250.  
  1251.     // Convert the transfer time to a string
  1252.     if (seconds < 10) {
  1253.       ItoS (seconds, temp);
  1254.       seconds_str = "0";
  1255.       strcat (seconds_str, temp);
  1256.     }
  1257.     else {
  1258.       ItoS (seconds, seconds_str);
  1259.     }
  1260.     if (minutes < 10) {
  1261.       ItoS (minutes, temp);
  1262.       minutes_str = "0";
  1263.       strcat (minutes_str, temp);
  1264.     }
  1265.     else {
  1266.       ItoS (minutes, minutes_str);
  1267.     }
  1268.     ItoS (hours, hours_str);
  1269.  
  1270.     // Stuff the buffer with just enough spaces so the periods in the
  1271.     //  file names line up
  1272.     dot_pos = strpos (file_name, ".", 0);
  1273.     if (dot_pos > 0) {
  1274.       substr ("        ", 0, 8 - dot_pos, buffer);
  1275.     }
  1276.     else {
  1277.       substr ("        ", 0, 8 - strlen (file_name), buffer);
  1278.     }
  1279.  
  1280.     // Put the file name into the buffer
  1281.     strcat (buffer, file_name);
  1282.  
  1283.     // Append just enough spaces to the buffer to make the right sides of
  1284.     //  the file sizes line up
  1285.     substr ("              ", 0, 26 - strlen (buffer) - strlen (f_size_str), temp);
  1286.     strcat (buffer, temp);
  1287.  
  1288.     // Put the file size into the buffer
  1289.     strcat (buffer, f_size_str);
  1290.  
  1291.     // Put the file date and time into the buffer
  1292.     strcat (buffer, "  ");
  1293.     strcat (buffer, f_date_str);
  1294.     strcat (buffer, " ");
  1295.     strcat (buffer, f_time_str);
  1296.  
  1297.     // Put the transfer time into the buffer
  1298. //  if (hours < 10) {
  1299. //    strcat (buffer, "   ");
  1300. //  }
  1301. //  else {
  1302. //    strcat (buffer, "  ");
  1303. //  }
  1304. //  strcat (buffer, hours_str);
  1305. //  strcat (buffer, ":");
  1306. //  strcat (buffer, minutes_str);
  1307. //  strcat (buffer, ":");
  1308. //  strcat (buffer, seconds_str);
  1309.  
  1310.     // See if we've filled a screen yet ...
  1311.     if (lines > 23) {
  1312.       host_send ("[More]");
  1313.       host_input (1);
  1314.       lines = 0;
  1315.     }
  1316.     else {
  1317.       lines = lines + 1;
  1318.     }
  1319.  
  1320.     // Send the line
  1321.     host_send (buffer);
  1322.     host_send ("^M^J");
  1323.  
  1324.     file_exists = FileFind ("", 0, file_name);
  1325.   }
  1326.  
  1327. }
  1328.  
  1329. //////////////////////////////////////////////////////////////////////////////
  1330.  
  1331. get_extension(str file_name, str result) {
  1332.    int dot_pos;
  1333.    dot_pos = strpos (file_name, ".", 0);
  1334.    result = "";
  1335.    if (dot_pos > 0) {
  1336.      substr(file_name, dot_pos+1, 3, result);
  1337.    }
  1338. }
  1339.  
  1340. // Insert commas into a string representation of an integer, up to
  1341. //  999,999,999,999 (the largest SALT integer is 2,147,483,647)
  1342.  
  1343. insert_commas (str input, str output) {
  1344.  
  1345.   str tmp1[15], tmp2[15];
  1346.   int len, delta;
  1347.  
  1348.   output = input;
  1349.  
  1350.   for (delta = 3; delta <= 11; delta = delta + 4) {
  1351.     if ((len = strlen (output)) > delta) {
  1352.       substr (output, 0, len - delta, tmp1);
  1353.       substr (output, len - delta, 15, tmp2);
  1354.       output = tmp1;
  1355.       strcat (output, ",");
  1356.       strcat (output, tmp2);
  1357.     }
  1358.     else {
  1359.       break;
  1360.     }
  1361.   }
  1362. }
  1363.  
  1364. //////////////////////////////////////////////////////////////////////////////
  1365.  
  1366. send_goodbye () {
  1367.   str s[80];
  1368.  
  1369.   if (type_our_file("GOODBYE.MSG") == -1)
  1370.     host_send ("^M^JGoodbye^M^J");
  1371.  
  1372.   delay_scr(20);
  1373. }
  1374.  
  1375. //////////////////////////////////////////////////////////////////////////////
  1376.  
  1377. get_user_name() {
  1378.   int tries=5;
  1379.   str temporary[1];
  1380.  
  1381.   while (tries) {
  1382.     host_send("Please enter your full name: ");
  1383.     host_input_strn(current_caller, 30, 1);
  1384.     host_send("^M^J");
  1385.  
  1386.     if (finished_caller) {
  1387.       access_level = 0;
  1388.       return 0;
  1389.     }
  1390.  
  1391.     if (strlen(current_caller) >= min_user_name)
  1392.       break;
  1393.     else
  1394.       host_send ("Name too short!^M^J");
  1395.     --tries;
  1396.   }
  1397.   return (tries>0);
  1398. }
  1399.