home *** CD-ROM | disk | FTP | other *** search
/ Boston 2 / boston-2.iso / DOS / HILFEN / MODEM / TELIX / QDHOST.SLT < prev    next >
Text File  |  1993-12-01  |  29KB  |  1,097 lines

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. //   Q D H O S T . S L T
  4. //
  5. //   Copyright (C) 1988-1992 deltaComm Development.
  6. //
  7. //   - Written by Colin Sampaleanu.
  8. //   - Modifications by Jeff Woods, Feb '91, to add help function and support
  9. //     for locked modems.
  10. //   - Modifications by Dan Horn, Nov '92, fixed 'floating' timer bug.
  11. //
  12. //
  13. //   This is a Host Mode for Telix, written as a script file.
  14. //   To configure Host Mode parameters such as passwords, run the 'QDCONFIG'
  15. //   script. That script is run automatically if the Host Mode configuration
  16. //   file 'QDHOST.CNF' is missing.
  17. //
  18. //   This script will only work with Hayes compatible modems, but may be
  19. //   modified for operation with other modems.
  20. //
  21. //////////////////////////////////////////////////////////////////////////////
  22.  
  23. // Parameters which can be configured
  24.  
  25. str pass1[8] = "pass1",                 // The level 1 pass
  26.     pass2[8] = "pass2",                 // The level 2 (Sysop) pass
  27.     shellpass[8] = "shell",             // the pass to enter the Remote Shell
  28.     shutpass[8] = "shut",               // the pass to shut down the Host Mode
  29.     host_downloads[64],                 // where users may download from
  30.     host_uploads[64];                   // where uploaded files go
  31. int direct_connect = 0,
  32.     modem_lock = 0;
  33.  
  34. str current_caller[31],                 // storage of current caller's name
  35.     conn300[] = "CONNECT^M",            // modem result messages for bauds
  36.     conn1200[] = "CONNECT 1200",
  37.     conn2400[] = "CONNECT 2400",
  38.     conn9600[] = "CONNECT 9600",
  39.     conn19200[] = "CONNECT 19200";
  40.  
  41. int finished_caller,                    // set to TRUE when must return to top
  42.     local_mode,                         // set to TRUE when local test mode
  43.     access_level,                       // access level of current caller
  44.     carrier_counts = 1,                 // TRUE if should watch Carrier signal
  45.     already_connected = 0,
  46.     exit_requested = 0,                 // set to TRUE if Sysop has pressed Esc
  47.     connection_lost = 0,                // set to TRUE when carrier lost
  48.     kill_user = 0;                      // set to TRUE when user must be purged
  49.  
  50. int old_scr_chk_key,                    // storage for some system variables
  51.     old_cisb_auto,                      // which we have to modify and put
  52.     old_zmod_auto,                      // back to what they were when done
  53.     old_sound;
  54. str old_down_dir[64],
  55.     old_up_dir[64];
  56.  
  57. //////////////////////////////////////////////////////////////////////////////
  58. //////////////////////////////////////////////////////////////////////////////
  59.  
  60. main()
  61.  
  62. {
  63.  int c;
  64.  
  65.  clear_scr();
  66.  
  67.  if (read_host_config_file() == -1)
  68.   {
  69.    prints("Unable to read QDHOST.CNF...");
  70.    prints("Running QDCONFIG, the Host Mode configuration script.^M^J");
  71.    call("QDCONFIG");
  72.    if (read_host_config_file() == -1)
  73.     {
  74.      prints("Still unable to read QDHOST.CNF. Aborting Host Mode.^M^J");
  75.      return -1;
  76.     }
  77.   }
  78.  
  79.  if (!check_directories())
  80.   {
  81.    prints("Either the upload or download directory as defined in the QDHOST.CNF file");
  82.    prints("doesn't exist. Either create the missing directory with the DOS 'MKDIR'");
  83.    prints("command, or run the QDCONFIG script to redefine what directories to use.");
  84.    prints("Aborting Host Mode.");
  85.    return -1;
  86.   }
  87.  
  88.  old_scr_chk_key = _scr_chk_key;
  89.  _scr_chk_key = 0;
  90.  old_cisb_auto = _cisb_auto;
  91.  _cisb_auto = 0;
  92.  old_zmod_auto = _zmod_auto;
  93.  _zmod_auto = 0;
  94.  old_sound = _sound_on;
  95.  _sound_on = 0;
  96.  old_down_dir = _down_dir;
  97.  _down_dir = host_uploads;   // these are reversed because we are now the Host
  98.  old_up_dir = _up_dir;
  99.  _up_dir = host_downloads;   // these are reversed because we are now the Host
  100.  
  101.  usagelog("QDHOST.LOG");
  102.  
  103.  if (direct_connect)
  104.   carrier_counts = 0;
  105.  else
  106.   carrier_counts = 1;
  107.  
  108.  if (!direct_connect && carrier())
  109.   already_connected = 1;
  110.  
  111.  
  112.  while (1)
  113.   {
  114.    if (!direct_connect && !already_connected)
  115.     {
  116.      if (!modem_lock)
  117.         set_cparams(modem_lock, 0, 8, 1);
  118.      delay(3);
  119.      prints("Sending Modem Init string...");
  120.      cputs_tr(_mdm_init_str);
  121.      delay(10);
  122.      prints("Sending Auto-Answer string...");
  123.      cputs_tr(_auto_ans_str);
  124.     }
  125.  
  126.    finished_caller = kill_user = 0;
  127.  
  128.    if (direct_connect)
  129.     carrier_counts = 0;
  130.    else
  131.     carrier_counts = 1;
  132.  
  133.    if (!direct_connect)
  134.     {
  135.      prints("^M^JQDHost Mode: Waiting for call...");
  136.      prints("(Press Esc to exit, or 'L' for local test mode).^M^J");
  137.  
  138.      do
  139.       {
  140.        if (carrier())
  141.         {
  142.          local_mode = 0;
  143.          break;
  144.         }
  145.  
  146.        c = inkey();
  147.        if (c)
  148.         {
  149.          if (c == 27)
  150.           {
  151.            exit_requested = 1;
  152.            break;
  153.           }
  154.          else if (c == 'l' || c == 'L')               // local teswt mode
  155.           {
  156.            prints("Local test mode entered");
  157.            local_mode = 1;
  158.            carrier_counts = 0;
  159.           }
  160.         }
  161.       }
  162.      while (toupper(c) != 'L');
  163.     }
  164.  
  165.    if (!exit_requested)
  166.     {
  167.      prints("Incoming call. Sysop: press Esc to exit, or END to terminate user.");
  168.  
  169.      do_one_caller();
  170.      if ((connection_lost || kill_user) && carrier_counts && carrier())
  171.       hangup();             // make sure nobody sneaks in
  172.     }
  173.    already_connected = 0;
  174.    if (exit_requested)
  175.     {
  176.      if (!carrier() && !direct_connect)
  177.       {
  178.        prints("Sending Modem Init string...");
  179.        cputs_tr(_mdm_init_str);
  180.       }
  181.      _scr_chk_key = old_scr_chk_key;
  182.      _cisb_auto = old_cisb_auto;
  183.      _zmod_auto = old_zmod_auto;
  184.      _sound_on = old_sound;
  185.      _down_dir = old_down_dir;
  186.      _up_dir = old_up_dir;
  187.      prints("^M^JQDHost mode script finished.");
  188.      usagelog("*CLOSE*");
  189.      return 1;
  190.     }
  191.   }
  192. }
  193.  
  194. //////////////////////////////////////////////////////////////////////////////
  195.  
  196. HelpOn(int option)
  197.  
  198. {
  199.    if (option == 'H')
  200.     {
  201.      host_send("^M^JHelp on Help^M^J");
  202.      host_send("^M^JTo use the help, simply type the first letter of one of the following:");
  203.      host_send("^M^J^M^J<H>elp <F>iles <T>ype <U>pload <D>ownload <S>hell <C>hat <G>oodbye");
  204.      Host_send("^M^J");
  205.     }
  206.    if (option == 'F')
  207.     {
  208.      host_send("^M^JHelp on Files^M^J");
  209.      host_send("^M^JThe 'Files' option allows the caller to list the files in the");
  210.      host_send("^M^Jcurrent disk directory. The caller must press a key after each");
  211.      host_send("^M^Jscreen. The output is not echoed on the local screen. If the");
  212.      host_send("^M^Jcaller has access level two s/he is prompted for a filespec,");
  213.      host_send("^M^Jwhich may include the * and ? wildcard characters (see your");
  214.      host_send("^M^JDOS manual), so that the contents of other directories than");
  215.      host_send("^M^Jthe 'Host download dir' may be listed.");
  216.      Host_send("^M^J");
  217.     }
  218.    if (option == 'T')
  219.     {
  220.      host_send("^M^JHelp on Type^M^J");
  221.      host_send("^M^JThe 'Type' option allows the caller to view any ASCII file in");
  222.      host_send("^M^Jthe Host Download Directory, or in any directory for access");
  223.      host_send("^M^JLevel 2 callers.   Simply give the name (or full path and name)");
  224.      host_send("^M^Jof the system file you wish to view:    ie. C:\TELIX\TELIX.IMG");
  225.      Host_send("^M^J");
  226.     }
  227.    if (option == 'U')
  228.     {
  229.      host_send("^M^JHelp on Uploading^M^J");
  230.      host_send("^M^JThe 'Upload' option allows the caller to send a file to the");
  231.      host_send("^M^Jhost. The caller is shown the a menu of protocols.   He/she");
  232.      host_send("^M^Jshould select the appropriate protocol by its first letter");
  233.      host_send("^M^J(or 'E' for Ymodem-g). If appropriate the caller is also asked");
  234.      host_send("^M^Jfor the filename.  The transfer is then initiated by QDHOST.  The");
  235.      host_send("^M^Jcaller must then initiate the upload on THEIR side by giving");
  236.      host_send("^M^Jtheir comm program an upload instruction, choosing the same");
  237.      host_send("^M^Jprotocol as they told host, and giving the filename again,");
  238.      host_send("^M^Jwithin 60 seconds of telling QDHOST the same information.");
  239.      Host_send("^M^J");
  240.     }
  241.    if (option == 'D')
  242.     {
  243.      host_send("^M^JHelp on Downloading^M^J");
  244.      host_send("^M^JThe 'Download' command allows a caller to receive a file from");
  245.      host_send("^M^Jthe host. The caller must select the protocol after giving the");
  246.      host_send("^M^Jdownload command to QDHOST, and then must tell QDHOST what files");
  247.      host_send("^M^Jto send.    Some protocols like ZModem will start automatically");
  248.      host_send("^M^Jafter this.   Others, like XModem, require the caller to start");
  249.      host_send("^M^Ja download in their comm program at this point (usually Pg-Dn)");
  250.      host_send("^M^Jand will be asked by the comm program for a file name again.  The");
  251.      host_send("^M^Jtransfer is then initiated.");
  252.      Host_send("^M^J");
  253.     }
  254.    if (option == 'S')
  255.     {
  256.      host_send("^M^JHelp on Shelling^M^J");
  257.      host_send("^M^JThe 'Shell' command is a very powerful but also very dangerous");
  258.      host_send("^M^Jcommand. It allows the caller to run a DOS shell on the sys-");
  259.      host_send("^M^Jtem, except that the caller receives the output, and the");
  260.      host_send("^M^Jcaller enters the keystrokes.   The caller has complete control");
  261.      host_send("^M^Jof the HOST system at the DOS level.   Shell is a password");
  262.      host_send("^M^Jprotected feature of QDHOST.  The caller sees program output only");
  263.      host_send("^M^Jif the programs use standard DOS output. Programs that write");
  264.      host_send("^M^Jdirectly to the video screen will work, but will not be seen");
  265.      host_send("^M^Jby the remote caller. As well, programs that use non-DOS meth-");
  266.      host_send("^M^Jods of getting keystrokes will not receive the callers");
  267.      host_send("^M^Jkeystrokes. Finally, under some systems, if the caller presses");
  268.      host_send("^M^JBackspace at the DOS prompt when the current line is empty,");
  269.      host_send("^M^JDOS will hang on the Host machine. As these are functions of");
  270.      host_send("^M^JDOS, there is nothing that can be done about these limits.");
  271.      Host_send("^M^J");
  272.     }
  273.    if (option == 'C')
  274.     {
  275.      host_send("^M^JHelp on Chatting^M^J");
  276.      host_send("^M^JThe 'Chat' command allows the caller to chat with the host op-");
  277.      host_send("^M^Jerator. When the caller presses 'C' the host operator is paged");
  278.      host_send("^M^Jfor 20 seconds.    If the host operator responds, you will see");
  279.      host_send("^M^Jhim/her typing on your screen.    If you can, place yourself in");
  280.      host_send("^M^JChat Mode, by using your comm program's chat mode (Telix's is");
  281.      host_send("^M^JAlt-Y).   You will then see what you type on half of the screen");
  282.      host_send("^M^Jand the operator's words on the other half.");
  283.      Host_send("^M^J");
  284.     }
  285.    if (option == 'G')
  286.     {
  287.      host_send("^M^JHelp on Goodbye^M^J");
  288.      host_send("^M^JThe 'Goodbye' command allows the caller to log off the host");
  289.      Host_send("^M^J");
  290.     }
  291. }
  292.  
  293. //////////////////////////////////////////////////////////////////////////////
  294.  
  295. do_one_caller()
  296.  
  297. {
  298.  str strn[80],
  299.      fname[64];
  300.  int option,
  301.      status,
  302.      c, i, i2, f;
  303.  
  304.  access_level = 1;
  305.  
  306.  if (already_connected)
  307.   prints("Already connected, or modem Carrier Detect switch improperly set!");
  308.  else if (carrier_counts)
  309.   {
  310.    if (!modem_lock)
  311.     if (!determine_baud())
  312.     ;                          // do something else here if this is a problem
  313.   }
  314.  
  315.  delay(10);
  316.  type_file("LOGO.MSG");
  317.  
  318.  flushbuf();
  319.  while (1)
  320.   {
  321.    host_send("Please enter your full name: ");
  322.    host_input_strn(current_caller, 30, 1);
  323.    host_send("^M^J");
  324.  
  325.    if (finished_caller)
  326.     return;
  327.  
  328.    if (strlen(current_caller) >= 5)
  329.     break;
  330.   }
  331.  
  332.  access_level = ask_for_pass(3, pass1, pass2);
  333.  
  334.  if (access_level)
  335.   ustamp("Logon by ", 1, 0);
  336.  else
  337.   ustamp("Failed logon attempt by ", 1, 0);
  338.  ustamp(current_caller, 0, 1);
  339.  
  340.  if (!access_level)
  341.   {
  342.    host_send("Goodbye!^M^J");
  343.    if (carrier_counts)
  344.     {
  345.      delay(10);
  346.      hangup();
  347.     }
  348.    return;
  349.   }
  350.  
  351.  type_file("WELCOME.MSG");
  352.  
  353.  while (1)
  354.   {
  355.    if (finished_caller)
  356.     return;
  357.  
  358.    host_send("^M^JCommand: Help  Files  Type  Upload  Download  Shell  Chat  Goodbye ? ");
  359.    host_input_strn(strn, 1, 1);
  360.    option = toupper(subchr(strn, 0));
  361.    host_send("^M^J");
  362.  
  363.    if (option == 'H')
  364.     {
  365.      host_send("^M^J^M^JWhich item above do you wish help on? ");
  366.      host_input_strn(strn, 1, 1);
  367.      Option = toupper(subchr(strn, 0));
  368.      Host_send("^M^J");
  369.      HelpOn(Option);
  370.      Option = 'H';
  371.     }
  372.    if (option == 'F')                 // Files directory
  373.     {
  374.      if (access_level == 2)
  375.       {
  376.        host_send("Enter 'filespec' or press Return for *.*,^M^J: ");
  377.        host_input_strn(fname, 64, 1);
  378.        host_send("^M^J");
  379.  
  380.        if (just_filename(fname))
  381.         {
  382.          strn = host_downloads;
  383.          strcat(strn, fname);
  384.         }
  385.        else
  386.         strn = fname;
  387.       }
  388.      else
  389.       {
  390.        strn = host_downloads;
  391.        strcat(strn, "*.*");
  392.       }
  393.        
  394.      if (local_mode)
  395.       show_directory(strn, 0, carrier_counts);
  396.      else
  397.       show_directory(strn, 1, carrier_counts);
  398.      host_send("^M^J");
  399.     }
  400.    else if (option == 'T')            // Type a file
  401.     {
  402.      host_send("Type what file? ");
  403.      host_input_strn(strn, 64, 1);
  404.      host_send("^M^J");
  405.      if (access_level != 2)             // if access 1, name and ext only
  406.       fnstrip(strn, 3, fname);
  407.      else
  408.       fname = strn;
  409.  
  410.      if (just_filename(fname))
  411.       {
  412.        strn = host_downloads;
  413.        strcat(strn, fname);
  414.        fname = strn;
  415.       }
  416.  
  417.      if (!filefind(fname, 0, strn))
  418.       {
  419.        host_send("Unable to find ");
  420.        host_send(fname);
  421.        continue;
  422.       }
  423.  
  424.      type_file(fname);
  425.     }
  426.    else if (option == 'G')            // Goodbye (Hang-up)
  427.     {
  428.      host_send("^M^JGoodbye!^M^J");
  429.      ustamp("User logged off.", 1, 1);
  430.      if (carrier_counts)
  431.       {
  432.        delay(10);
  433.        hangup();
  434.       }
  435.      return;
  436.     }
  437.    else if (option == 'C')            // Chat mode
  438.     {
  439.      prints("Sysop: Press Space to chat, any other key not to.^M^J");
  440.      c = 0;
  441.      _sound_on = 1;
  442.      for (i = 8; i && !c; --i)
  443.       {
  444.        if (carrier_counts && !carrier())
  445.         {
  446.          prints("^M^JConnection has been lost, call terminated.^M^J");
  447.          connection_lost = 1;
  448.          finished_caller = 1;
  449.          break;
  450.         }
  451.        cputc('^G');
  452.        tone(523, 20);
  453.        tone(659, 20);
  454.        tone(523, 20);
  455.        tone(659, 20);
  456.        tone(523, 20);
  457.        tone(659, 20);
  458.        for (i2 = 30; i2 && (c = inkey()) == 0; --i2)
  459.         delay(1);
  460.       }
  461.      _sound_on = 0;
  462.      if (finished_caller)
  463.       continue;
  464.      if (c != ' ' || !c)
  465.       {
  466.        host_send("Sorry, the Sysop is unavailable^M^J");
  467.        continue;
  468.       }
  469.      host_send("The sysop is here!^M^J");
  470.      chatmode(1);
  471.     }
  472.    else if (option == 'U')            // User upload
  473.     {
  474.      option = host_get_prot();
  475.      if (!option)
  476.       continue;
  477.  
  478.      status = 1;
  479.      if (option == 'T' || option == 'M' || option == 'S' ||
  480.          option == 'Y' || option == 'Z' || option == 'E')
  481.       {
  482.        send_transfer_msg();
  483.        status = receive(option, "");
  484.       }
  485.      else
  486.       {
  487.        host_send("Upload what file? ");
  488.        host_input_strn(strn, 48, 1);
  489.        host_send("^M^J");
  490.        if (!strn)
  491.         continue;
  492.        if (access_level != 2)             // if access 1, name and ext only
  493.         fnstrip(strn, 3, fname);
  494.        else
  495.         fname = strn;
  496.  
  497.        if (just_filename(fname))
  498.         {
  499.          strn = host_uploads;
  500.          strcat(strn, fname);
  501.          fname = strn;
  502.         }
  503.  
  504.        if (filefind(fname, 23, strn))
  505.         host_send("File already exists!^M^J");
  506.        else
  507.         {
  508.          send_transfer_msg();
  509.          status = receive(option, fname);
  510.         }
  511.       }
  512.      if (status == -2)                        // Carrier lost
  513.       connection_lost = finished_caller = 1;
  514.      else if (status == -1)
  515.       host_send("^GOne or more files not received!^M^J");
  516.     }
  517.    else if (option == 'D')            // User download
  518.     {
  519.      option = host_get_prot();
  520.      if (!option)
  521.       continue;
  522.      host_send("Download what file(s)? ");
  523.      host_input_strn(strn, 48, 1);
  524.      host_send("^M^J");
  525.      if (!strn)
  526.       continue;
  527.      if (access_level != 2)      // if not level 2, keep only name & ext
  528.       fnstrip(strn, 3, fname);
  529.      else
  530.       fname = strn;
  531.  
  532.      if (just_filename(fname))
  533.       {
  534.        strn = host_downloads;
  535.        strcat(strn, fname);
  536.        fname = strn;
  537.       }
  538.  
  539.      if (!filefind(fname, 0, strn))
  540.       {
  541.        host_send("Unable to find any matching file(s)!^M^J");
  542.        continue;
  543.       }
  544.  
  545.      status = 1;
  546.      send_transfer_msg();
  547.      status = send(option, fname);
  548.      if (status == -2)                        // Carrier lost
  549.       connection_lost = finished_caller = 1;
  550.      else if (status == -1)
  551.       host_send("^GOne or more files not received!^M^J");
  552.     }
  553.    else if (option == 'S')            // Remote shell
  554.     {
  555.      if (ask_for_pass(3, shellpass, shellpass) != 0)
  556.       {
  557.        host_send("Type EXIT and then press Enter to come back.^M^J");
  558.        if (get_baud() == 300)
  559.         delay(10);
  560.        if (local_mode)
  561.         dos("", 0);
  562.                  // See if user has prepared a custom file for shell operation
  563.                  // and call that if it exists
  564.        else if (filefind("RSHELL.BAT", 0, strn))
  565.         dos("RSHELL.BAT", 0);
  566.        else   // otherwise make our own temporary batch file for redirection
  567.         {
  568.          // now want to make a temporary batch file which will be called
  569.          // to redirect DOS input and output, then shell to another copy
  570.          // of COMMAND.COM
  571.          f = fopen("HOSTTEMP.BAT", "w");
  572.          if (f)
  573.           {
  574.            if (get_port() != 1 && get_port() != 2)
  575.             {
  576.              host_send("Remote Shell not supported on this comm port due to DOS limits!^M^J");
  577.              continue;
  578.             }
  579.  
  580.            strn = "COMx";
  581.            setchr(strn, 3, get_port() + '0'); // get right name to redirect
  582.  
  583.            fputs("CTTY ", f);           // write to batch file
  584.            fputs(strn, f);
  585.            fputs("^M^JCOMMAND^M^J", f);
  586.            fputs("CTTY CON^M^J", f);
  587.            fputs("EXIT^M^J", f);
  588.  
  589.            fclose(f);                   // close the file
  590.  
  591.            if (!local_mode)             // call batch file
  592.             dos("HOSTTEMP.BAT", 0);
  593.           }
  594.          else
  595.           host_send("Can't open temporary batch file!^M^J");
  596.         }
  597.       }
  598.     }
  599.    else if (option == '^Z')            // Shut down Host Mode
  600.     {
  601.      host_send("Shut down QDHost mode. ");
  602.      if (!ask_for_pass(3, shutpass, shutpass))
  603.       continue;
  604.      host_send("Goodbye!^M^J");
  605.      if (carrier_counts)
  606.       hangup();
  607.      ustamp("User shut down QDHost Mode.", 1, 1);
  608.      finished_caller = 1;
  609.      exit_requested = 1;
  610.     }
  611.   }
  612. }
  613.  
  614. //////////////////////////////////////////////////////////////////////////////
  615.  
  616. host_get_prot()
  617.  
  618. {
  619.  str prot[1];
  620.  
  621.  host_send("^M^JModem7  SEAlink  Xmodem  1k-Xmodem  G-1k-Xmodem  Ymodem  YmodEm-g  Zmodem^M^J");
  622.  host_send("Which protocol? ");
  623.  host_input_strn(prot, 1, 1);
  624.  host_send("^M^J");
  625.  
  626.  if (strposi("MSX1GYEZ", prot, 0) == -1)     // if illegal prot
  627.   prot = "";                                 // return 0
  628.  
  629.  return (toupper(subchr(prot, 0)));
  630.  
  631. }
  632.  
  633. //////////////////////////////////////////////////////////////////////////////
  634.  
  635. send_transfer_msg()
  636.  
  637. {
  638.  host_send("Ready to transfer file(s)... Press Ctrl-X at least twice to abort^M^J");
  639. }
  640.  
  641. //////////////////////////////////////////////////////////////////////////////
  642. // Determine the baud rate once a Carrier Detect Signal has been detected
  643. // Since no characters were read, the 'CONNECT' string should still be
  644. // in the receive buffer.
  645.  
  646. determine_baud()
  647.  
  648. {
  649.  int t3, t12, t24, t96, t192;
  650.  int tmark, stat;
  651.  int new_baud = 0;
  652.  
  653.  printsc("Determining baud... ");
  654.  
  655.  track_free(0);                // clear all existing tracks
  656.  
  657.  t3 = track(conn300, 0);       // check for connect strings
  658.  t12 = track(conn1200, 0);
  659.  t24 = track(conn2400, 0);
  660.  t96 = track(conn9600, 0);
  661.  t192 = track(conn19200, 0);
  662.  
  663.  tmark = timer_start(30);      // wait up to 3 seconds for string
  664.                              
  665.  while (!time_up(tmark))
  666.   {
  667.    if (!carrier())
  668.     {
  669.      track_free(0);            // clear all existing tracks
  670.      timer_free(tmark);        // free existing timer
  671.      return 0;
  672.     }
  673.  
  674.    if (cinp_cnt())
  675.     track_addchr(cgetc());
  676.  
  677.    stat = track_hit(0);
  678.    if (stat == 0)
  679.     continue;
  680.  
  681.    if (stat == t3)
  682.     new_baud = 300;
  683.    else if (stat == t24)
  684.     new_baud = 2400;
  685.    else if (stat == t96)
  686.     new_baud = 9600;
  687.    else if (stat == t192)
  688.     new_baud = 19200;
  689.    else
  690.     new_baud = 1200;
  691.  
  692.    break;                      // have baud rate, get out
  693.   }
  694.  
  695.  track_free(0);                // clear all existing tracks
  696.  timer_free(tmark);            // free existing timer
  697.  
  698.  if (!new_baud)                // time-up without CONNECT string
  699.   {
  700.    prints("Failed!");
  701.    return 0;     
  702.   }
  703.  
  704.  printn(new_baud);
  705.  prints("");
  706.  set_cparams(new_baud, get_parity(), get_datab(), get_stopb());
  707.  
  708.  return 1;                     // indicate success
  709.  
  710. }
  711.  
  712. //////////////////////////////////////////////////////////////////////////////
  713.  
  714. type_file(str fname)
  715.  
  716. {
  717.  int f;
  718.  str buf[100];
  719.  int ichar, lines_sent = 0;
  720.  
  721.  f = fopen(fname, "r");
  722.  if (!f)
  723.   return -1;
  724.  
  725.  host_send("^M^J");
  726.  
  727.  while (1)
  728.   {
  729.    if (carrier_counts)
  730.     if (!carrier())
  731.      {
  732.       connection_lost = 1;
  733.       finished_caller = 1;
  734.       fclose(f);
  735.       return 0;
  736.      }
  737.  
  738.    if (fgets(buf, 80, f) == -1)
  739.     {
  740.      fclose(f);
  741.      return 1;
  742.     }
  743.  
  744.    host_send(buf);
  745.    host_send("^M^J");
  746.    ++lines_sent;
  747.  
  748.    if (lines_sent >= 22)
  749.     {
  750.      lines_sent = 0;
  751.      host_send("[More]");
  752.      host_input(1);
  753.  
  754.      if (finished_caller)         // if user inactivity
  755.       {
  756.        fclose(f);
  757.        return 0;
  758.       }
  759.  
  760.      host_send("^H ^H^H ^H^H ^H^H ^H^H ^H^H ^H^H ^H");
  761.     }
  762.  
  763.    while (cinp_cnt())
  764.     {
  765.      ichar = cgetc();
  766.      if (ichar == '^C' || ichar == '^K')
  767.       {
  768.        host_send("^M^J");
  769.        fclose(f);
  770.        return 1;
  771.       }
  772.     }
  773.   }
  774. }
  775.  
  776. //////////////////////////////////////////////////////////////////////////////
  777.  
  778. host_send(str outstr)
  779.  
  780. {
  781.  
  782.  printsc(outstr);
  783.  if (!local_mode)
  784.   cputs(outstr);
  785.  
  786. }
  787.  
  788. //////////////////////////////////////////////////////////////////////////////
  789.  
  790. host_send_c(int chr)
  791.  
  792. {
  793.  
  794.  printc(chr);
  795.  if (!local_mode)
  796.   cputc(chr);
  797.  
  798. }
  799.  
  800. //////////////////////////////////////////////////////////////////////////////
  801.  
  802. host_input_strn(str buf, int maximum, int echoable)
  803.  
  804. {
  805.  int i = 0, key;
  806.  
  807.  while (1)
  808.   {
  809.    key = host_input(echoable);
  810.    if (!key)                 // timeout or user disconnect
  811.     {
  812.      setchr(buf, 0, 0);      // set string to empty
  813.      return 0;               // indicate there is a problem
  814.     }
  815.  
  816.    if (key == '^M')
  817.     break;
  818.    if (key == 127 || key == 8)
  819.     {
  820.      if (i)
  821.       {
  822.        --i;
  823.          host_send_c(key);
  824.       }
  825.      continue;
  826.     }
  827.    if (i < maximum)
  828.     {
  829.      setchr(buf, i, key);
  830.      i = i + 1;
  831.     }
  832.    else
  833.     i = i + 1;
  834.   }
  835.  
  836.  if (i > maximum)
  837.   i = maximum;
  838.  
  839.  setchr(buf, i, '^0');
  840.  
  841.  if (subchr(buf, 0))
  842.   return 1;
  843.  else
  844.   return 0;
  845.  
  846. }
  847.  
  848. //////////////////////////////////////////////////////////////////////////////
  849.  
  850. host_input(int echoable)
  851.  
  852. {
  853.  int c;
  854.  int t;
  855.  
  856.  t = timer_start(2400);         // 4 minutes inactivity allowed
  857.  
  858.  while (1)
  859.   {
  860.    if (time_up(t) && !direct_connect)
  861.     {
  862.      host_send("^M^J^M^JInactivity period too long. Connection terminated!^M^J");
  863.      if (carrier_counts)
  864.       hangup();
  865.      finished_caller = 1;
  866.      kill_user = 1;
  867.      break;
  868.     }
  869.  
  870.    if (carrier_counts)
  871.     if (!carrier())
  872.       {
  873.        prints("^M^JConnection has been lost, call terminated.^M^J");
  874.        connection_lost = 1;
  875.        finished_caller = 1;
  876.        break;
  877.       }
  878.  
  879.    if ((c = inkey()) != 0)
  880.     {
  881.      if (c == 27)               // ESC key, sysop wants to exit
  882.       {
  883.        finished_caller = 1;
  884.        exit_requested = 1;
  885.        break;
  886.       }
  887.      else if (c == 0x4f00)      // END key, temrinate user
  888.       {
  889.        prints("^M^JUser terminated!");
  890.        ustamp("User terminated!", 1, 1);
  891.        if (carrier_counts)
  892.         hangup();
  893.  
  894.        finished_caller = 1;
  895.        kill_user = 1;
  896.        break;
  897.       }
  898.  
  899.      else if (c <= 255)
  900.       {
  901.        if (c != 8 && c != 127)   
  902.         if (!echoable)
  903.          host_send_c('*');
  904.         else
  905.          host_send_c(c);
  906.        break;
  907.       }
  908.     }
  909.  
  910.    if (!local_mode)
  911.     if (cinp_cnt())
  912.      {
  913.       c = cgetc();
  914.       if (c != 8 && c != 127)
  915.        if (!echoable)
  916.         host_send_c('*');
  917.        else
  918.         host_send_c(c);
  919.       break;
  920.      }
  921.   }
  922.  
  923.  timer_free(t);                 // free existing timer
  924.  if (finished_caller)
  925.    return 0;                    // return 0 - no character
  926.  
  927.  return c;                      // return received/pressed character
  928. }
  929.  
  930. //////////////////////////////////////////////////////////////////////////////
  931.  
  932. ask_for_pass(int maxtries, str pass1, str pass2)
  933.  
  934. {
  935.  int i;
  936.  str strn[8];
  937.  
  938.  for (i = 0; i < maxtries; ++i)
  939.   {
  940.    if (i)
  941.     host_send("Wrong! Try again.^M^J");
  942.    host_send("Password: ");
  943.    host_input_strn(strn, 8, 0);
  944.    host_send("^M^J");
  945.  
  946.    if (finished_caller)
  947.     return 0;
  948.  
  949.    if (!strcmpi(strn, pass1))
  950.     return 1;
  951.  
  952.    if (!strcmpi(strn, pass2))
  953.     return 2;
  954.   }
  955.  
  956.  host_send("No more chances. Access denied.^M^J");
  957.  
  958.  return 0;
  959.  
  960. }
  961.  
  962. //////////////////////////////////////////////////////////////////////////////
  963.  
  964. read_host_config_file()
  965.  
  966. {
  967.  str s[80];
  968.  int f, stat;
  969.  
  970.  s = _telix_dir;
  971.  strcat(s, "QDHOST.CNF");
  972.  
  973.  f = fopen(s, "r");
  974.  if (!f)
  975.   {
  976.    printsc("Can't open ");
  977.    prints(s);
  978.    return -1;
  979.   }
  980.  
  981.  stat = fgets(s, 80, f);
  982.  if (stat == -1)
  983.   goto got_error;
  984.  pass1 = s;
  985.  
  986.  stat = fgets(s, 80, f);
  987.  if (stat == -1)
  988.   goto got_error;
  989.  pass2 = s;
  990.  
  991.  stat = fgets(s, 80, f);
  992.  if (stat == -1)
  993.   goto got_error;
  994.  shellpass = s;
  995.  
  996.  stat = fgets(s, 80, f);
  997.  if (stat == -1)
  998.   goto got_error;
  999.  shutpass = s;
  1000.  
  1001.  stat = fgets(s, 80, f);
  1002.  if (stat == -1)
  1003.   goto got_error;
  1004.  host_downloads = s;
  1005.  
  1006.  stat = fgets(s, 80, f);
  1007.  if (stat == -1)
  1008.   goto got_error;
  1009.  host_uploads = s;
  1010.  
  1011.  stat = fgets(s, 80, f);
  1012.  if (stat == -1)
  1013.   goto got_error;
  1014.  direct_connect = (toupper(subchr(s, 0)) == 'D');
  1015.  
  1016.  stat = fgets(s, 80, f);
  1017.  if (stat == -1)
  1018.   goto got_error;
  1019.  modem_lock = stoi(s);
  1020.  
  1021.  fclose(f);
  1022.  return 1;
  1023.  
  1024. // jump here if error
  1025.  
  1026.  got_error:
  1027.   fclose(f);
  1028.   return -1;
  1029.  
  1030. }
  1031.  
  1032. //////////////////////////////////////////////////////////////////////////////
  1033.  
  1034. check_directories()
  1035.  
  1036. {
  1037.  str s[80];
  1038.  int i, a;
  1039.  
  1040.  // first remove trailing slashes
  1041.  
  1042.  s = host_uploads;
  1043.  i = strlen(s);
  1044.  if (i > 0)
  1045.   if (subchr(s, i - 1) == '\' || subchr(s, i - 1) == '/')
  1046.    setchr(s, i - 1, 0);
  1047.  if (s && !(strlen(s) == 2 && subchr(s, 1) == ':'))
  1048.   {
  1049.    a = fileattr(s);
  1050.    if (a == -1 || !(a & 16))
  1051.     return 0;                  // not a directory or doesn't exist
  1052.   }
  1053.  
  1054.  s = host_downloads;
  1055.  i = strlen(s);
  1056.  if (i > 0)
  1057.   if (subchr(s, i - 1) == '\' || subchr(s, i - 1) == '/')
  1058.    setchr(s, i - 1, 0);
  1059.  if (s && !(strlen(s) == 2 && subchr(s, 1) == ':'))
  1060.   {
  1061.    a = fileattr(s);
  1062.    if (a == -1 || !(a & 16))
  1063.     return 0;                  // not a directory or doesn't exist
  1064.   }
  1065.  
  1066.  return 1;
  1067.  
  1068. }
  1069.  
  1070. //////////////////////////////////////////////////////////////////////////////
  1071. // returns TRUE if passed filespec is just a filename. Also handles the
  1072. // forward slash as a path separator.
  1073.  
  1074. just_filename(str filespec)
  1075.  
  1076. {
  1077.  int slash, space;
  1078.  
  1079.  if (strpos(filespec, ":", 0) != -1)
  1080.   return 0;
  1081.  if (strpos(filespec, "\", 0) != -1)
  1082.   return 0;
  1083.  if ((slash = strpos(filespec, "/")) == -1)
  1084.   return 1;
  1085.  
  1086.  space = strpos(filespec, " ");
  1087.  if (space == -1)
  1088.   return 0;
  1089.  if (space < slash)
  1090.   return 1;
  1091.  
  1092.  return 0;
  1093.  
  1094. }
  1095.  
  1096. //////////////////////////////////////////////////////////////////////////////
  1097.