home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Computerworld 1996 March
/
Computerworld_1996-03_cd.bin
/
idg_cd3
/
aplikace
/
komunika
/
telixwin
/
tfw.5
/
WINHOST.SLT
< prev
Wrap
Text File
|
1995-07-28
|
52KB
|
1,856 lines
//
// W I N H O S T . S L T
//
// Copyright (C) 1988-1995 deltaComm Development.
//
// - Written by Colin Sampaleanu.
// - Modifications by Jeff Woods, Feb '91, to add help function and support
// for locked modems.
// - Modifications by Dan Horn, Nov '92, fixed 'floating' timer bug.
// - Thanks to Jon Fleming for his help in porting this to Windows.
// - Modifications for hot keys and logins, fixes for chat mode and
// <=9600 baud remote dos shells in Dec '94 by Sean Palmer
// - Modifications to Connect baud parsing Jan '95 by Sean Palmer
// - Modifications to allow ANSI and RIP displays Feb '95 by Jeff Smith
// - Message system added March '95 by Jeff Smith
//
// This is a Host Mode for Telix, written as a script file.
// To configure Host Mode parameters such as passwords, run the 'WCONFIG'
// script. That script is run automatically if the Host Mode configuration
// file 'WINHOST.CNF' is missing.
//
// This script will only work with Hayes compatible modems, but may be
// modified for operation with other modems.
//
//////////////////////////////////////////////////////////////////////////////
#stack 1536 // Increased stack size
// Parameters which are configured from the WinHost configuration file
str host_downloads[64], // Default where users may download from
host_uploads[64], // Default where uploaded files go
host_message[64]; // Default used by message system
int direct_connect = 0, // 0 = using a modem
modem_lock = 0,
closed_sys = 0; // 0 = users may sign up on line if not
// found in the config file
// Various global variables
str current_caller[31], // storage of current caller's name
our_dir[64]; // Winhost directory (either Telix's
// scripts directory or the contents
// of the HOST2DIR environment variable
// if it exists)
int finished_caller, // set to TRUE when must return to top
local_mode, // set to TRUE when local test mode
access_level, // access level of current caller
carrier_counts = 1, // TRUE if should watch Carrier signal
already_connected = 0,
exit_requested = 0, // set to TRUE if Sysop has pressed Esc
connection_lost = 0, // set to TRUE when carrier lost
kill_user = 0, // set to TRUE when user must be purged
min_user_name = 5, // Minimum length of user's name
user_has_own_dir; // Flag to restrict the user to one dir
int old_scr_chk_key, // storage for some system variables
old_cisb_auto, // which we have to modify and put
old_zmod_auto, // back to what they were when done
old_sound,
RIP_On, ANSI_On; // Flag ANSI and RIP capability
str old_down_dir[64],
old_up_dir[64],
tfw_down_dir[64],
tfw_up_dir[64],
old_usage_fname[64];
int ndx_fil, mssg_num, // Message system variables
mssg_time, mssg_priv; // used by the index file
str mssg_to[30], mssg_from[30], // "message.ndx"
mssg_subj[30];
#INCLUDE "WHUTILS.SLT" // Functions which are shared with the
// configuration managements script
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
main() {
int c;
str s[80], filnam[64];
tfw_up_dir = _up_dir;
tfw_down_dir = _down_dir;
clear_scr;
get_our_dir;
if (read_host_config_file == -1) {
prints("Unable to read WINHOST.CNF...");
prints("Running WCONFIG, the Host Mode configuration script.^M^J");
s = our_dir;
strcat (s, "WCONFIG");
calld(s);
if (read_host_config_file() == -1) {
prints("Still unable to read WINHOST.CNF. Aborting Host Mode.^M^J");
return -1;
}
}
prints ("Checking existence of directories ...");
if (!(check_directory(host_downloads)
&& check_directory(host_uploads)
&& check_directory(host_message))) {
prints("Aborting Host Mode.");
return -1;
}
old_scr_chk_key = _scr_chk_key;
_scr_chk_key = 0;
old_cisb_auto = _cisb_auto;
_cisb_auto = 0;
old_zmod_auto = _zmod_auto;
_zmod_auto = 0;
old_sound = _sound_on;
_sound_on = 0;
old_down_dir = _down_dir;
old_usage_fname = _usage_fname;
s = our_dir;
strcat (s, "HOST2.LOG");
usagelog (s);
carrier_counts = !direct_connect;
already_connected = (carrier_counts && carrier());
filnam=host_message;
strcat(filnam, "message.ndx");
if (filefind(filnam, 0)) {
ndx_fil=fopen(filnam, "r+");
if (ndx_fil)
update_ndx_file(); // scan index file for msgs more than
// a certain age, & delete them
}
else { // Create the index file
ndx_fil=fopen(filnam, "w+");
mssg_from="Internal";
mssg_to="Internal";
mssg_priv=1;
mssg_time=curtime();
mssg_subj="Time Index";
ndx_write(0);
}
while (1) {
_down_dir = host_uploads; // these are reversed because we are the Host
old_up_dir = _up_dir;
_up_dir = host_downloads; // these are reversed because we are the Host
user_has_own_dir = 0;
if (!direct_connect && !already_connected) {
if (!modem_lock)
set_cparams(modem_lock, 0, 8, 1);
delay_scr(3);
prints("Sending Modem Init string...");
cputs_tr(_mdm_init_str);
delay_scr(20);
prints("Sending Auto-Answer string...");
cputs_tr(_auto_ans_str);
delay_scr(10);
}
finished_caller = kill_user = 0;
if (direct_connect)
carrier_counts = 0;
else {
carrier_counts = 1;
local_mode = 0;
prints("^M^JHost Mode: Waiting for call...");
prints("(Press Esc to exit, or 'L' for local test mode).^M^J");
do {
if (carrier()) break;
if ((c = inkey())==27) {
exit_requested = 1;
break;
}
else if (c==' ') { cputs("ata^m"); c=0; }
else if (toupper(c) == 'L') { // local test mode
prints("Local test mode entered");
local_mode = 1;
carrier_counts = 0;
break;
}
} while (1);
}
if (!exit_requested) {
prints("Incoming call. Sysop: press Esc to exit, or END to terminate user.");
do_one_caller();
if ((connection_lost || kill_user) && carrier_counts && carrier())
hangup(); // make sure nobody sneaks in
}
already_connected = 0;
if (exit_requested) {
if (!carrier() && !direct_connect) {
prints("Sending Modem Init string...");
cputs_tr(_mdm_init_str);
}
_scr_chk_key = old_scr_chk_key;
_cisb_auto = old_cisb_auto;
_zmod_auto = old_zmod_auto;
_sound_on = old_sound;
_down_dir = tfw_down_dir;
_up_dir = tfw_up_dir;
prints("^M^JHost mode script finished.");
usagelog("*CLOSE*");
_usage_fname = old_usage_fname;
return 1;
}
}
}
//////////////////////////////////////////////////////////////////////////////
host_help (str mode, str option) {
str fname[64];
fname = our_dir;
strcat (fname, mode);
strcat (fname, "_HELP_");
StrCat (fname, option);
StrCat (fname, ".TXT");
if (FileFind (fname, 0)) {
type_our_file (fname);
return (1);
}
else {
printsc ("^MCan't find help file ");
prints (fname);
return (0);
}
}
//////////////////////////////////////////////////////////////////////////////
do_one_caller() {
str strn[80], fname[64], s[80], temporary[1],
num[10], CHKSTR[20];
int option, status, c, i, i2, f, len, TIMR;
access_level = 1;
// flushbuf();
if (already_connected)
prints("Already connected, or modem Carrier Detect switch improperly set!");
else if (carrier_counts)
determine_baud();
if (!local_mode) delay_scr(20);
flushbuf();
if (local_mode) {
ansi_on=rip_on=0;
s=gety(); //detect local ansi
host_send("^[[2A");
if ((s-gety())==2) {
ansi_on=1;
host_send("^[[2B");
host_send("^A|H"); //detect local rip
if (gety()==0) {
rip_on=1;
}
else host_send("^H^H^H ^H^H^H");
}
else host_send("^H^H^H ^H^H^H");
gotoxy(1, s); //fix cursor
}
else {
Ansi_On=0;
Rip_On=0;
chkstr="";
cputs("^M^[[6n^H^H^H^H ^H^H^H^H");
timr=timer_start(10);
do {
if (cinp_cnt()) {
s=cgetc();
strcat(chkstr, s);
}
}
while (!time_up(timr));
timer_free(timr);
if ((strpos(chkstr, "^[[", 0)>=0) && (strpos(chkstr, "R", 1)>=0))
{
ANSI_On=1;
chkstr="";
cputs("^M^[[!^H^H^H ^H^H^H");
timr=timer_start(10);
do
{
if (cinp_cnt()) {
s=cgetc();
strcat(chkstr, s);
}
}
while (!time_up(timr));
timer_free(timr);
RIP_On = (strpos(chkstr, "RIPSCRIP", 0) >= 0);
}
}
type_our_file("LOGO");
if (!get_user_name()) {
ustamp("Failed logon attempt", 1, 0);
return;
}
access_level = setup_user(3);
if (access_level) {
ustamp("Logon by ", 1, 0);
ustamp(current_caller, 0, 1);
}
else {
ustamp("Failed logon attempt by ", 1, 0);
ustamp(current_caller, 0, 1);
send_goodbye();
if (carrier_counts) {
delay_scr(10);
hangup();
}
return;
}
type_our_file("WELCOME");
while (1) {
if (finished_caller)
return;
if (access_level == 3) {
if (type_our_file("MMENU3") == -1)
host_send("^M^JFiles Type Upload Download Shell Chat Help Message Goodbye ? ");
}
else {
if (type_our_file ("MMENU") == -1)
host_send("^M^JFiles Type Upload Download Chat Help Message Goodbye ? ");
}
host_send ("^M^JCommand: ");
host_input_strn(strn, 1, 1);
option = toupper(subchr(strn, 0));
host_send("^M^J");
if (option == 'H') { // Help
host_send("^M^JWhich item above do you wish help on? ");
host_input_strn(strn, 1, 1);
substr (strn, 0, 1, strn);
strupper (strn);
Host_send("^M^J");
host_help( "H", strn);
}
if (option == 'F') { // Files directory
if (access_level >= 2) {
host_send("Enter 'filespec' or press Return for *.*,^M^J: ");
host_input_strn(fname, 64, 1);
host_send("^M^J");
ustamp ("Requested file listing of ", 1, 0);
ustamp (fname, 0, 1);
if (strcmpi (fname, "") == 0) {
fname = "*.*";
}
if (just_filename(fname)) {
strn = _down_dir;
strcat(strn, fname);
}
else if (user_has_own_dir == 1) {
host_send ("^M^JAccess outside ");
host_send (_down_dir);
host_send (" not allowed^M^J");
strn = _down_dir;
strcat(strn, "*.*");
}
else {
len = strlen (fname);
substr (fname, len - 1, 1, temporary);
if (strcmpi (temporary, "\") == 0) {
strn = fname;
strcat (strn, "*.*");
}
else strn = fname;
}
}
else {
strn = _down_dir;
strcat(strn, "*.*");
ustamp ("Requested listing of files", 1, 1);
}
host_show_directory(strn);
ustamp ("Displayed ", 1, 0);
ustamp (strn, 0, 1);
}
else if (option == 'T') { // Type a file
host_send("Type what file? ");
host_input_strn(strn, 64, 1);
host_send("^M^J");
ustamp ("Requested to type ", 1, 0);
ustamp (strn, 0, 1);
if ((access_level == 1) || (user_has_own_dir == 1))
fnstrip(strn, 3, fname);
else
fname = strn;
if (just_filename(fname)) {
strn = _down_dir;
strcat(strn, fname);
fname = strn;
}
if (!filefind(fname, 0, strn)) {
host_send("Unable to find ");
host_send(fname);
continue;
}
get_extension(fname, strn);
if (strcmpi(strn,"ZIP")==0 ||
strcmpi(strn,"ARJ")==0)
{
host_send("Unable to type ");
host_send(fname);
continue;
}
type_file(fname);
ustamp ("Typed ", 1, 0);
ustamp (fname, 0, 1);
}
else if (option == 'M') { // Message system
do {
if (type_our_file("mssgmenu")==-1)
host_send("Read Write Quit ?");
i=host_input(1);
i=toupper(i);
if (i=="R") read_mssg();
else if (i=="W") write_mssg();
}
while (i!='Q');
}
else if (option == 'G') { // Goodbye (Hang-up)
send_goodbye ();
ustamp("User logged off.", 1, 1);
if (carrier_counts) {
delay_scr(10);
hangup();
}
return;
}
else if (option == 'C') { // Chat mode
prints("Sysop: Press Space to chat, any other key not to.^M^J");
c = 0;
_sound_on = 1;
for (i = 8; i && !c; --i) {
host_send (".");
if (carrier_counts && !carrier()) {
prints("^M^JConnection has been lost, call terminated.^M^J");
connection_lost = 1;
finished_caller = 1;
break;
}
cputc('^G');
tone(523, 20);
tone(659, 20);
tone(523, 20);
tone(659, 20);
tone(523, 20);
tone(659, 20);
delay(9);
c = inkey();
}
_sound_on = 0;
host_send ("^M^J");
if (finished_caller)
continue;
if (c != ' ') {
host_send("Sorry, the Sysop is unavailable^M^J");
continue;
}
host_send("The sysop is here!^M^J");
chatmode(!local_mode,1); //start chat, no echo if local
status_wind("Press Ctrl-X to terminate chat",30);
while (1) {
if (waitfor("^X",1)) break;
}
chatmode(!local_mode,0); //end chat
}
else if (option == 'U') { // User upload
option = host_get_prot();
if (!option)
continue;
ustamp ("Upload ", 1, 0);
status = 1;
if (option == 'Y' || option == 'Z' || option == 'E') {
ustamp ("with name-transferrring protocol ", 0, 1);
send_transfer_msg();
status = receive(option, "");
}
else {
host_send("Upload what file? ");
host_input_strn(strn, 48, 1);
host_send("^M^J");
if (!strn)
continue;
ustamp (strn, 0, 1);
if ((access_level == 1) || (user_has_own_dir == 1)) // if access 1, name and ext only
fnstrip(strn, 3, fname);
else
fname = strn;
if (just_filename(fname)) {
strn = _up_dir;
strcat(strn, fname);
fname = strn;
}
if (filefind(fname, 23, strn)) {
host_send("File already exists!^M^J");
ustamp ("File already exists", 1, 1);
}
else {
send_transfer_msg();
status = receive(option, fname);
}
}
if (status == -2) { // Carrier lost
connection_lost = finished_caller = 1;
ustamp ("Lost carrier", 1, 1);
}
else if (status == -1) {
host_send("^M^J^M^J^GOne or more files not received!^M^J");
ustamp ("One or more files not received", 1, 1);
}
else {
ustamp ("Transfer complete", 1, 1);
}
}
else if (option == 'D') { // User download
option = host_get_prot();
if (!option)
continue;
host_send("Download what file(s)? ");
host_input_strn(strn, 48, 1);
host_send("^M^J");
if (!strn)
continue;
ustamp ("Attempt to download ", 1, 0);
ustamp (strn, 0, 1);
if ((access_level == 1) || (user_has_own_dir == 1)) // if not level 2, keep only name & ext
fnstrip(strn, 3, fname);
else
fname = strn;
if (just_filename(fname)) {
strn = _down_dir;
strcat(strn, fname);
fname = strn;
}
if (!filefind(fname, 0, strn)) {
host_send("Unable to find any matching file(s)!^M^J");
ustamp ("No such file", 1, 1);
continue;
}
status = 1;
send_transfer_msg();
status = send(option, fname);
if (status == -2) { // Carrier lost
connection_lost = finished_caller = 1;
ustamp ("Lost carrier", 1, 1);
}
else if (status == -1) {
host_send("^M^J^M^J^GOne or more files not sent!^M^J");
ustamp ("One or more files not sent", 1, 1);
}
else {
ustamp ("Transfer complete", 1, 1);
}
}
else if (option == 'S') { // Remote shell
ustamp ("Attempted shell", 1, 1);
if (access_level == 3) {
host_send("Type EXIT and then press Enter to come back.^M^J");
if (get_baud() == 300)
delay_scr(10);
if (local_mode)
dos("", 0);
// See if user has prepared a custom file for shell operation
// and call that if it exists
else {
if (filefind("RSHELL.BAT", 0, strn))
do_remote_shell("RSHELL.BAT");
else { // otherwise make our own temporary batch file for redirection
if (get_port() != 1 && get_port() != 2) {
host_send("Remote Shell not supported on this comm port due to DOS limits!^M^J");
}
else {
// now want to make a temporary batch file which will be
// called to redirect DOS input and output, then shell to
// another copy of the command interpreter
f = fopen("HOSTTEMP.BAT", "w");
if (f) {
if (get_baud()>9600) {
status_wind("Attempting to shell to dos at over 9600 baud",50);
ustamp("DOS shell baud > 9600",0,1);
}
fputs("MODE ", f); // this command informs dos of the port rate
strn = "COMx";
setchr(strn, 3, get_port() + '0'); // get right name to redirect
fputs(strn, f); // save strn for later
fputc(" baud=", f);
itos(get_baud(), num);
fputs(num, f);
fputs(" parity=", f);
switch (get_parity()) {
case 1: fputc('E', f);
case 2: fputc('O', f);
case 3: fputc('M', f);
case 4: fputc('S', f);
default: fputc('N', f);
}
fputs(" data=", f);
itos(get_dataB(), num);
fputs(num, f);
fputs(" stop=", f);
itos(get_stopB(), num);
fputs(num, f);
fputs("^M^J", f);
fputs("CTTY ", f); // write to batch file
fputs(strn, f); // this command actually makes the shell work
fputs("^M^J", f);
if (getenv ("COMSPEC", s) == 0)
s = "COMMAND.COM";
fputs (s, f);
fputs("^M^J", f);
fputs("CTTY CON^M^J", f);
fputs("EXIT^M^J", f);
fclose(f); // close the file
if (!local_mode) // call batch file
do_remote_shell("HOSTTEMP.BAT");
}
else
host_send("Can't open temporary batch file!^M^J");
}
}
}
}
else ustamp ("Request denied", 1, 1);
}
else if (option == '^Z') { // Shut down Host Mode
if (access_level == 3) {
host_send("Shutting down Host mode. ");
ustamp("User shut down Host Mode.", 1, 1);
send_goodbye ();
ustamp("User logged off.", 1, 1);
if (carrier_counts)
hangup();
finished_caller = 1;
exit_requested = 1;
}
}
}
}
//////////////////////////////////////////////////////////////////////////////
do_remote_shell(str batfile) {
str savedConn[80]; //holds saved connect device's name
//here we make a new connect device with a port of 0 which causes the
//device to not be attached to any specific port. Useful to
//keep Telix from using any ports temporarily.
if (makeConnectDevice("__NULL__","2400bps Generic",0,0,0))
{
connectDeviceName(0,savedConn); //get current device name
if (set_ConnectDevice("__NULL__",2)) //selecting a port 0 device won't
{ //disturb the current device's connection
dos(batfile);
set_ConnectDevice(savedConn,1); //restore previous connect device
} //without sending init string
killConnectDevice("__NULL__");
}
}
//////////////////////////////////////////////////////////////////////////////
host_get_prot() {
str prot[1], strn[1], s[64];
int Option;
prot = "H";
while (strcmpi (prot, "H") == 0) {
if (type_our_file ("PMENU") == -1) {
host_send("^M^JXmodem xmodem-Crc xmodem-1k xmodem-1k-G Ymodem ymodEm-g Zmodem Kermit^M^J");
host_send("Help Cancel^M^J");
}
host_send("Which protocol, or H for help ? ");
host_input_strn(prot, 1, 1);
strupper (prot);
host_send("^M^J");
if (strcmpi (prot, "H") == 0) {
host_send ("^M^JHelp on which protocol, or ^"A^" for ALL? ");
host_input_strn (strn, 1, 1);
substr (strn, 0, 1, strn);
strupper (strn);
Host_send("^M^J");
host_help( "P", strn);
}
if (strposi("XC1GYEZKH", prot, 0) == -1) // if illegal prot or cancel
prot = ""; // return 0
}
return (toupper(subchr(prot, 0)));
}
//////////////////////////////////////////////////////////////////////////////
send_transfer_msg() {
host_send("Ready to transfer file(s)... Press Ctrl-X at least twice to abort^M^J");
}
//////////////////////////////////////////////////////////////////////////////
// Determine the baud rate once a Carrier Detect Signal has been detected
// Since no characters were read, the 'CONNECT' string should still be
// in the receive buffer.
determine_baud() {
int tconnect;
int tmark, stat, c;
int new_baud = 0;
str cstring[20];
printsc("Determining baud... ");
track_free(0); // clear all existing tracks
tconnect = track(_connect_str, 0); // check for connect string
tmark = timer_start(30); // wait up to 3 seconds for string
while (!time_up(tmark)) {
if (!carrier()) {
track_free(0); // clear all existing tracks
timer_free(tmark); // free existing timer
return 0;
}
if (cinp_cnt()) {
printc_trm(c=cGetC); // does tracks too
// printc(c=cGetC);
// track_addChr(c);
}
if (track_hit(0) != tConnect) continue;
while (1) {
while (!cinp_cnt()) ;
if ((c=cgetc)>' ') break;
printc(c);
}
while(1) {
printc(c);
if ((c>='0') && (c<='9'))
new_baud = new_baud * 10 + c - '0';
else break;
while (!cinp_cnt) ;
c=cgetc();
}
printc(c);
if (!new_baud) new_baud = 300;
break; // have baud rate, get out
}
track_free(0); // clear all existing tracks
timer_free(tmark); // free existing timer
if (!new_baud) { // time-up without CONNECT string
prints("Failed!");
return 0;
}
// printn(new_baud);
// newLine();
setDCERate(new_baud); // Let TFW know
return 1; // indicate success
}
//////////////////////////////////////////////////////////////////////////////
// Allow user to read messages
read_mssg()
{
str read_fil[64], buf[64];
int mcode, rflag, position, i;
mcode=0;
host_send("^M^J Read all public mail (y/n): ");
i=toupper(host_input(1));
if (i=='Y') mcode=2;
else
{
host_send("^M^J Read mail to 'All' (y/n): ");
i=toupper(host_input(1));
if (i=='Y') mcode=1;
}
host_send("^M^J");
fseek(ndx_fil, 0, 0);
while (ndx_read()) {
rflag=0;
if ((strcmpi(mssg_to, current_caller)==0)
and (mssg_priv < 2)) rflag=1;
else
if ((strcmpi(mssg_to, "ALL")==0) and (mcode>0)
and (mssg_priv == 0)) rflag=1;
else
if ((mssg_priv==0) and (mcode==2)) rflag=1;
if (rflag)
{
host_send("^M^J From: ");
host_send(mssg_from);
host_send(" To: ");
if (mssg_to==0) host_send("All");
else host_send(mssg_to);
host_send(" ");
date(mssg_time, read_fil);
host_send(read_fil);
host_send("^M^J Subject: ");
host_send(mssg_subj);
host_send("^M^J^M^J Read Message (y/n)");
i=host_input(1);
i=toupper(i);
host_send("^M^J");
if (i=='Y')
{
itos(mssg_num, buf);
read_fil=host_message;
strcat(read_fil, "M");
strcat(read_fil, buf);
strcat(read_fil, ".MSG");
type_file(read_fil);
host_send("^M^J");
}
if (strcmpi(mssg_to, current_caller)==0)
{
host_send(" Delete Message (y/n)");
i=host_input(1);
i=toupper(i);
if (i=='Y') delete_mssg(mssg_num);
host_send("^M^J");
}
}
}
}
// Allow user to write messages
write_mssg()
{
str ans[85], fn[64], wrd[80];
int cnt, i, mssgdone, f;
f=fopen("edit.msg", 'w');
host_send("^M^J^M^J");
host_send(" Private message (y/n)");
do
i=toupper(host_input(1));
while ((i!='Y') and (i!='N'));
if (i=='Y') mssg_priv=1;
else mssg_priv=0;
host_send("^M^J To: ");
host_input_strn(mssg_to, 30, 1);
host_send("^M^J Subject: ");
host_input_strn(mssg_subj, 30, 1);
host_send("^M^J");
host_send(" Enter message:^M^J");
ANS=wrd=""; CNT=1;
MSSGDONE=0;
do
{
i=host_input(1);
++CNT;
if (i==13)
{
strcat(ans, wrd);
wrd="";
host_send("^M^J");
IF (ANS=="") MSSGDONE=1;
strcat(ans, "^m");
fputs(ans, f);
ANS="";
CNT=1;
}
else
if (i==8)
{
CNT=CNT-2;
IF (CNT<0) CNT=0;
ELSE {
if (strlen(wrd)>0)
substr(wrd, 0, strlen(wrd)-1, wrd);
else
substr(ans, 0, strlen(ans)-1, ans);
host_send_c(i);
}
}
ELSE
{
strcat(wrd, i);
if ((i==' ') && (cnt<80)) {
strcat(ans, wrd);
wrd="";
}
IF (CNT>=80)
{
cnt=strlen(wrd);
do {
cnt=cnt-1;
host_send_c(8);
}
while (cnt>0);
cnt=strlen(wrd);
do {
cnt=cnt-1;
host_send_c(' ');
}
while (cnt>0);
host_send("^M^J");
strcat(ans, "^m");
fputs(ans, f);
host_send(wrd);
ANS=wrd;
wrd="";
CNT=strlen(ans)+1;
}
}
}
while (MSSGDONE==0);
host_send("^M^J");
fclose(f);
host_send(" Send Message? Y/n: ");
i='a';
do
i=toupper(host_input(1));
while ((i!='Y') and (i!='N'));
host_send("^M^J^M^J");
IF (i=='Y')
{
mssg_from=current_caller;
ans="";
do
{
ans=host_message;
strcat(ans, "M");
mssg_num=random(10000)*100+random(100);
itos(mssg_num, fn);
strcat(ans, fn);
strcat(ans, ".msg");
if (filefind(ans, 0)) ans="";
}
while (ans=="");
frename("edit.msg", ans);
fseek(ndx_fil, 0, 2);
mssg_time=curtime();
ndx_write(0);;
}
else
{
fdelete("edit.msg");
}
}
// Mark message record for deletion and delete message file
delete_mssg(int m_num)
{
int position;
str filnam[64], buf[64];
position=ftell(ndx_fil);
if (position==0) position=filesize(ndx_fil);
position=position-110;
do
{
fseek(ndx_fil, position, 0);
ndx_read();
if (mssg_num==m_num)
{
mssg_priv=2;
fseek(ndx_fil, position, 0);
ndx_write(0);;
// delete message file
itos(mssg_num, filnam);
filnam=strcat("M", filnam);
buf=host_message;
filnam=strcat(buf, filnam);
strcat(filnam, ".msg");
fdelete(filnam);
return;
}
position=position-110;
}
while (position > 0);
}
// Delete old and marked messages
update_ndx_file()
{
str filnam[80]; //the new temp ndx filename
str buf[80]; //general purpose & old ndx filename
int f, tim;
prints("Updating Message Index File");
filnam = host_message;
strCat(filnam, "temp.ndx");
f=fopen(filnam, "w");
fseek(ndx_fil, 0, 0);
ndx_read();
mssg_time=tim=curtime();
ndx_write(f);
mssg_time=0;
do {
if (!ndx_read())
{
mssg_time=tim;
mssg_priv=2;
}
else
if ((tim-mssg_time) > 684800)
{
// delete Old files
buf="M";
itos(mssg_num, filnam);
filnam=strcat(buf, filnam);
buf=host_message;
filnam=strcat(buf, filnam);
strcat(filnam, ".msg");
fdelete(filnam);
}
} while ((tim-mssg_time) > 684800); // one week
do {
if (mssg_priv < 2) ndx_write(f);
} while (ndx_read());
fclose(f);
fclose(ndx_fil);
filnam=host_message;
strcat(filnam, "temp.ndx");
buf=host_message;
strcat(buf, "message.ndx");
fdelete(buf);
frename(filnam, buf);
ndx_fil=fopen(buf, "r+");
}
ndx_read() {
str buf[110], buf2[10];
int n;
if (feof(ndx_fil)) return 0;
fread(buf, 110, ndx_fil);
substr(buf, 0, 9, buf2);
mssg_num=stoi(buf2);
substr(buf, 9, 1, buf2);
mssg_priv=stoi(buf2);
substr(buf, 10, 31, mssg_to);
do {
substr(mssg_to, 0, strlen(mssg_to)-1, mssg_to);
} while (subchr(mssg_to, strlen(mssg_to)-1)==' ');
substr(buf, 40 , 31, mssg_from);
do {
substr(mssg_from, 0, strlen(mssg_from)-1, mssg_from);
} while (subchr(mssg_from, strlen(mssg_from)-1)==' ');
substr(buf, 70, 10, buf2);
mssg_time=stoi(buf2);
substr(buf, 80, 30, mssg_subj);
return 1;
}
ndx_write(int fl)
{
str buf[30];
int hold_ndx;
if (fl!=0)
{
hold_ndx=ndx_fil;
ndx_fil=fl;
}
itos(mssg_num, buf);
if (strlen(buf)<9)
do
strcat(buf, " ");
while (strlen(buf) < 9);
fwrite(buf, 9, ndx_fil);
itos(mssg_priv, buf);
fwrite(buf, 1, ndx_fil);
buf=mssg_to;
if (strlen(buf) < 30)
do
strcat(buf, " ");
while (strlen(buf) < 30);
fwrite(buf, 30, ndx_fil);
buf=mssg_from;
if (strlen(buf) < 30)
do
strcat(buf, " ");
while (strlen(buf) < 30);
fwrite(buf, 30, ndx_fil);
itos(mssg_time, buf);
if (strlen(buf)<10)
do
strcat(buf, " ");
while (strlen(buf) < 10);
fwrite(buf, 10, ndx_fil);
if (strlen(mssg_subj)<30)
do
strcat(mssg_subj, " ");
while (strlen(mssg_subj) < 30);
fwrite(mssg_subj, 30, ndx_fil);
if (fl!=0) ndx_fil=hold_ndx;
}
//////////////////////////////////////////////////////////////////////////////
type_our_file(str fname) {
int f;
str s[144];
if ((f=type_file(fname)) == -1) {
s=our_dir;
strcat(s,fname);
f=type_file(s);
}
return f;
}
//////////////////////////////////////////////////////////////////////////////
type_file(str fname) {
int f, r_a_fl;
str s[80];
str buf[255], fname_b[80], fname_x[80];
int cnt, ichar;
int lines_sent = 0;
r_a_fl=0;
// fname_x = our_dir;
strCat(fname_x, fname);
if (strposi(fname, "." )==-1)
{
r_a_fl=2;
fname_b=fname_x;
strcat(fname_b, ".rip");
if ((rip_on) and (filefind(fname_b, 0) != 0)) {}
else
{
r_a_fl=1;
fname_b=fname_x;
strcat(fname_b, ".ans");
if ((ansi_on) and (filefind(fname_b, 0) != 0)) {}
else
{
r_a_fl=0;
fname_b=fname_x;
strcat(fname_b, ".txt");
}
}
fname=fname_b;
}
f = fopen(fname, "r");
if (!f)
return -1;
host_send("^M^J^J");
while (1) {
if (carrier_counts)
if (!carrier()) {
connection_lost = 1;
finished_caller = 1;
fclose(f);
return 0;
}
if (R_A_Fl > 0) {
if ((cnt=fread(buf, strMaxLen(buf), f)) <= 0) {
fclose(f);
return 1;
}
setchr(buf, cnt, 0);
}
else {
if (fgets(buf, 80, f) == -1) {
fclose(f);
return 1;
}
}
host_send(buf);
if (r_a_fl==0) {
host_send("^M^J");
++lines_sent;
if (lines_sent >= 22) {
lines_sent = 0;
host_send("[More]");
host_input(1);
if (finished_caller) { // if user inactivity
fclose(f);
return 0;
}
host_send("^H ^H^H ^H^H ^H^H ^H^H ^H^H ^H^H ^H");
}
}
while (cinp_cnt()) {
ichar = cgetc();
if (ichar == '^C' || ichar == '^K') {
host_send("^M^J");
fclose(f);
return 1;
}
}
}
}
//////////////////////////////////////////////////////////////////////////////
host_send(str outstr) {
printsc_trm(outstr);
if (!local_mode)
cputs(outstr);
}
//////////////////////////////////////////////////////////////////////////////
host_send_c(int chr) {
printc(chr);
if (!local_mode)
cputc(chr);
}
//////////////////////////////////////////////////////////////////////////////
host_input_strn(str buf, int maximum, int echoable) {
int i = 0, key;
while (1) {
key = host_input(echoable);
if (!key) { // timeout or user disconnect
setchr(buf, 0, 0); // set string to empty
return 0; // indicate there is a problem
}
if (key == '^M') {
// if (!echoable) host_send("^H ");
break;
}
if (key == 127 || key == 8) {
if (i) {
--i;
host_send_c(key);
}
continue;
}
if (i < maximum)
setchr(buf, i, key);
++i;
if (maximum<=1) break; //hotkeys if buffer only holds one
}
if (i > maximum)
i = maximum;
setchr(buf, i, '^0');
if (subchr(buf, 0))
return 1;
else
return 0;
}
//////////////////////////////////////////////////////////////////////////////
host_input(int echoable) {
int c, t;
t = timer_start(2400); // 4 minutes inactivity allowed
while (1) {
if (time_up(t) && !direct_connect) {
host_send("^M^J^M^JInactivity period too long. Connection terminated!^M^J");
if (carrier_counts)
hangup();
finished_caller = 1;
kill_user = 1;
break;
}
if (carrier_counts)
if (!carrier()) {
prints("^M^JConnection has been lost, call terminated.^M^J");
connection_lost = 1;
finished_caller = 1;
break;
}
if ((c = inkey()) != 0) {
if (c == 27) { // ESC key, sysop wants to exit
finished_caller = 1;
exit_requested = 1;
break;
}
else if (c == 0x4f00) { // END key, terminate user
prints("^M^JUser terminated!");
ustamp("User terminated!", 1, 1);
if (carrier_counts)
hangup();
finished_caller = 1;
kill_user = 1;
access_level = 0;
break;
}
else if (c <= 255) {
if (c != 8 && c != 127)
if ((!echoable)&& c != 13)
host_send_c('*');
else
host_send_c(c);
break;
}
}
if (!local_mode)
if (cinp_cnt()) {
c = cgetc();
if (c != 8 && c != 127)
if ((!echoable)&& c != 13)
host_send_c('*');
else
host_send_c(c);
break;
}
}
timer_free(t); // free existing timer
if (finished_caller)
return 0; // return 0 - no character
return c; // return received/pressed character
}
//////////////////////////////////////////////////////////////////////////////
// This routine maintains an ASCII file in the Telix files directory called
// WHPASS.TXT. The format for each line is:
// name;password;working_dir;access_level (optional comment)
// The name, password, working_dir, and access_level fields MUST be
// separated by semicolons
// The working_dir field is optional (but the semicolons before and after
// it are _NOT_). If there's no working_dir field, the default host
// upload and download direcories are used.
// The routine searches the file for a line on which the "name" field
// matches the global variable "current_caller" (not case sensitive).
// If a match is found, and the user can type a password that matches
// the "password" field (not case sensitive), the routine returns
// the integer "access_level".
// If no match is found, the user is given an opportunity to register
// (at access level 1).
// If the user registers, the file is updated with the new user name,
// password, and access level (1), and the routine returns 1.
// If the user does not register, or if the user cannot match the password
// in the file in "maxtries", or if the user registers and cannot match
// the password he/she chose in "maxtries", the routine returns 0.
setup_user (int maxtries) {
str password_file[64], line_from_file[127], password_from_file[16],
name_from_file[31], temporary[16], typed_password[16],
working_dir[64], last_char[1];
int password_file_handle, field_length, field_start,
found_password = 0, access_from_file, counter = 0,
file_ends_in_control_z = 0, line_number = 0, length;
password_file = our_dir;
strcat (password_file, "WHPASS.TXT");
for (counter = 1; counter <= maxtries; counter = counter + 1) {
// Try to open password file
if (password_file_handle = fopen (password_file, "r")) {
// Read next line from file.
while (fgets (line_from_file, 64, password_file_handle) != -1) {
// Check for ^Z termination
if (line_from_file == "^Z") {
file_ends_in_control_z = 1;
break;
}
line_number = line_number + 1;
// allow for empty or comment lines
// comment lines begin with ';'
if (!strlen(line_from_file) || strchr(line_from_file, 0, ';')) {
// If line is long enough . . .
if (strlen (line_from_file) >= min_user_name+4) {
// Get length of name
if ( (field_length = strchr (line_from_file, 0, ';')) > 0) {
// Get name
substr (line_from_file, 0, field_length, name_from_file);
// If name matches . . . .
if (strcmpi (name_from_file, current_caller) == 0) {
// Get password
field_start = field_length + 1;
if ( (field_length = strchr (line_from_file, field_start, ';') - field_start) > 0) {
substr (line_from_file, field_start, field_length, password_from_file);
// Get working directory
field_start = field_start + field_length + 1;
if ( (field_length = strchr (line_from_file, field_start, ';') - field_start) >= 0) {
substr (line_from_file, field_start, field_length, working_dir);
// Get access level
field_start = field_start + field_length + 1;
substr (line_from_file, field_start, 1, temporary);
access_from_file = stoi (temporary);
// Set flag that we got an old user
found_password = 1;
break;
}
else password_file_error (line_number, line_from_file, "no third semicolon");
}
else password_file_error (line_number, line_from_file, "no second semicolon");
}
}
else password_file_error (line_number, line_from_file, "no first semicolon");
}
else password_file_error (line_number, line_from_file, "line too short");
}
}
fclose (password_file_handle);
}
else if (password_file_handle = fopen(password_file, 'W')) { // no password file. Make one.
fputs(";WHPASS.TXT - WinHost user data file^M^J", password_file_handle);
fputs(";format: <NAME>;<PASSWORD>;<WORK_DIR>;<ACCESS> <COMMENT>^M^J", password_file_handle);
fclose(password_file_handle);
}
if (found_password)
break;
else {
host_send ("^M^JNo user ^"");
host_send (current_caller);
host_send ("^" on file; ");
host_send ("Re-type name? (y/n): ");
host_input_strn (temporary, 1, 1);
host_send ("^M^J");
if (strcmpi(temporary, "y"))
break;
else
get_user_name();
}
}
if (found_password) {
// Password is on file; ask for it
host_send ("Password: ");
for (counter = 1; counter <= maxtries; ++counter) {
host_input_strn (typed_password, 16, 0);
// If a match
if (!strcmpi (typed_password, password_from_file)) {
host_send ("^M^J");
// If the user has a working directory ...
if (strlen(working_dir)) {
// Check for a "\" on the end and add it if necessary
length = strlen(working_dir);
substr (working_dir, length - 1, 1, last_char);
if (strcmpi (last_char, "\"))
strcat (working_dir, "\");
// Establish download & upload directories
strupper (working_dir);
if (check_directory (working_dir)) {
_down_dir = working_dir;
_up_dir = working_dir;
user_has_own_dir = 1;
}
else {
prints ("Using defaults");
ustamp (working_dir, 1, 0);
ustamp (" does not exist, using default", 0, 1);
}
}
// Return the user's access level
return (access_from_file);
}
if (counter < maxtries) {
host_send ("^M^JDoes not match password on file!");
host_send ("^M^JRe-type name? (y/N): ");
host_input_strn (temporary, 1, 1);
host_send ("^M^J^J");
if (!strcmpi (temporary, "y")) {
get_user_name();
host_send("Password: ");
}
else host_send("Re-type password: ");
}
else
host_send ("^M^JMaximum number of tries exceeded!^M^J");
}
}
// Password is not on file
else if (!closed_sys) {
// Offer chance to register
// host_send ("No user ^"");
// host_send (current_caller);
// host_send ("^" found in user file.^M^J");
host_send ("Do you want to register? (y/N): ");
host_input_strn (temporary, 1, 1);
host_send ("^M^J");
// If user doesn't want to register
if (not ((temporary == "Y") || (temporary == "y")))
return (0);
// If user wants to register
host_send ("Pick a password (16 characters maximum): ");
host_input_strn (password_from_file, 16, 0);
// Make sure password is right
host_send ("^M^JRe-enter your password to verify: ");
for (counter = 1; counter <= maxtries; counter = counter + 1) {
host_input_strn (typed_password, 16, 0);
// If all is ok
if (strcmpi (typed_password, password_from_file) == 0) {
// Build new line for password file
line_from_file = current_caller;
strcat (line_from_file, ";");
strcat (line_from_file, password_from_file);
strcat (line_from_file, ";;1 **NEW USER** ");
date (curtime(), temporary);
strcat (line_from_file, temporary);
// Open password file for appending
password_file_handle = fopen(password_file, 'a');
if (file_ends_in_control_z)
fseek (password_file_handle, -1, 2);
// Now we can write the line
fwrite (line_from_file, strlen (line_from_file), password_file_handle);
fwrite ("^M^J", 2, password_file_handle);
fclose (password_file_handle);
host_send ("^M^J");
return (1); // Return access level
}
if (counter < maxtries)
host_send ("^M^JDoes not match! Please try again: ");
else
host_send ("^M^JMaximum number of tries exceeded!^M^J");
}
}
return (0);
}
//////////////////////////////////////////////////////////////////////////////
// A routine to print an error message to the local screen when something
// is wrong with the password file
password_file_error (int line_number, str line, str error_specifier) {
str line_number_string[4];
itos (line_number, line_number_string);
prints ("");
printsc ("Bad line ");
printsc (line_number_string);
prints (" in password file:");
printsc (" ^"");
printsc (line);
prints ("^"");
prints (error_specifier);
return (1);
}
//////////////////////////////////////////////////////////////////////////////
// returns TRUE if passed filespec is just a filename. Also handles the
// forward slash as a path separator.
just_filename(str filespec) {
int slash, space;
if (strpos(filespec, ":", 0) != -1)
return 0;
if (strpos(filespec, "\", 0) != -1)
return 0;
if ((slash = strpos(filespec, "/")) == -1)
return 1;
space = strpos(filespec, " ");
if (space == -1)
return 0;
if (space < slash)
return 1;
return 0;
}
//////////////////////////////////////////////////////////////////////////////
host_show_directory (str dir_spec) {
str file_name[13], f_name_ext[12], f_size_str[20], f_date_str[20],
f_time_str[20], buffer[80], path[67], full_name[80],
temp[26], hours_str[2], minutes_str[2], seconds_str[2];
int file_exists, fsize, ftime, lines, dot_pos, bps, seconds,
minutes, hours;
bps = get_baud (1);
fnstrip (dir_spec, 12, path);
file_exists = FileFind (dir_spec, 0, file_name);
if (!file_exists) {
host_send ("^M^JNo matching file found.^M^J");
}
else {
lines = 2;
host_send (" Name Size Date Time^M^J");
}
while (file_exists) {
// Get the file size, as a string, with commas where appropriate
fsize = FileSize ("");
ItoS (fsize, temp);
insert_commas (temp, f_size_str);
// Get the file date and time as a string
ftime = FileTime ("");
Date (ftime, f_date_str);
Time (ftime, f_time_str);
// Estimate how long it'll take to transfer the file with Zmodem
seconds = (fsize*10)/bps;
// Guess at about 95% efficiency
seconds = seconds + seconds/20;
if (seconds == 0) {
seconds = 1;
}
minutes = seconds/60;
seconds = seconds - minutes*60;
hours = minutes/60;
minutes = minutes - hours*60;
// Convert the transfer time to a string
if (seconds < 10) {
ItoS (seconds, temp);
seconds_str = "0";
strcat (seconds_str, temp);
}
else {
ItoS (seconds, seconds_str);
}
if (minutes < 10) {
ItoS (minutes, temp);
minutes_str = "0";
strcat (minutes_str, temp);
}
else {
ItoS (minutes, minutes_str);
}
ItoS (hours, hours_str);
// Stuff the buffer with just enough spaces so the periods in the
// file names line up
dot_pos = strpos (file_name, ".", 0);
if (dot_pos > 0) {
substr (" ", 0, 8 - dot_pos, buffer);
}
else {
substr (" ", 0, 8 - strlen (file_name), buffer);
}
// Put the file name into the buffer
strcat (buffer, file_name);
// Append just enough spaces to the buffer to make the right sides of
// the file sizes line up
substr (" ", 0, 26 - strlen (buffer) - strlen (f_size_str), temp);
strcat (buffer, temp);
// Put the file size into the buffer
strcat (buffer, f_size_str);
// Put the file date and time into the buffer
strcat (buffer, " ");
strcat (buffer, f_date_str);
strcat (buffer, " ");
strcat (buffer, f_time_str);
// Put the transfer time into the buffer
// if (hours < 10) {
// strcat (buffer, " ");
// }
// else {
// strcat (buffer, " ");
// }
// strcat (buffer, hours_str);
// strcat (buffer, ":");
// strcat (buffer, minutes_str);
// strcat (buffer, ":");
// strcat (buffer, seconds_str);
// See if we've filled a screen yet ...
if (lines > 23) {
host_send ("[More]");
host_input (1);
lines = 0;
}
else {
lines = lines + 1;
}
// Send the line
host_send (buffer);
host_send ("^M^J");
file_exists = FileFind ("", 0, file_name);
}
}
//////////////////////////////////////////////////////////////////////////////
get_extension(str file_name, str result) {
int dot_pos;
dot_pos = strpos (file_name, ".", 0);
result = "";
if (dot_pos > 0) {
substr(file_name, dot_pos+1, 3, result);
}
}
// Insert commas into a string representation of an integer, up to
// 999,999,999,999 (the largest SALT integer is 2,147,483,647)
insert_commas (str input, str output) {
str tmp1[15], tmp2[15];
int len, delta;
output = input;
for (delta = 3; delta <= 11; delta = delta + 4) {
if ((len = strlen (output)) > delta) {
substr (output, 0, len - delta, tmp1);
substr (output, len - delta, 15, tmp2);
output = tmp1;
strcat (output, ",");
strcat (output, tmp2);
}
else {
break;
}
}
}
//////////////////////////////////////////////////////////////////////////////
send_goodbye () {
str s[80];
if (type_our_file("GOODBYE") == -1)
host_send ("^M^JGoodbye^M^J");
delay_scr(20);
}
//////////////////////////////////////////////////////////////////////////////
get_user_name() {
int tries=5;
str temporary[1];
while (tries) {
host_send("Please enter your full name: ");
host_input_strn(current_caller, 30, 1);
host_send("^M^J");
if (finished_caller) {
access_level = 0;
return 0;
}
if (strlen(current_caller) >= min_user_name)
break;
else
host_send ("Name too short!^M^J");
--tries;
}
return (tries>0);
}