1 line
29 KiB
C
Executable File
1 line
29 KiB
C
Executable File
/* Copyright (c) 2017, Computer History Museum
|
|
All rights reserved.
|
|
Redistribution and use in source and binary forms, with or without modification, are permitted (subject to
|
|
the limitations in the disclaimer below) provided that the following conditions are met:
|
|
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
|
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
|
|
disclaimer in the documentation and/or other materials provided with the distribution.
|
|
* Neither the name of Computer History Museum nor the names of its contributors may be used to endorse or promote products
|
|
derived from this software without specific prior written permission.
|
|
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE
|
|
COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
|
DAMAGE. */
|
|
|
|
#include "ctb.h"
|
|
#define FILE_NUM 9
|
|
#ifdef CTB
|
|
/* Copyright (c) 1990-1992 by the University of Illinois Board of Trustees */
|
|
/************************************************************************
|
|
* functions for i/o over a pseudo-telnet ctb stream
|
|
* these functions are oriented toward CONVENIENCE, not performance
|
|
************************************************************************/
|
|
|
|
#pragma segment CTBTrans
|
|
#include <stdio.h>
|
|
static short CTBErr;
|
|
TransStream gCTBStream;
|
|
|
|
/************************************************************************
|
|
* private functions
|
|
************************************************************************/
|
|
typedef struct
|
|
{
|
|
short pending;
|
|
short errCode;
|
|
CMBufferSizes asyncCount;
|
|
short inUse;
|
|
} AsyncStuff, *AsyncStuffPtr;
|
|
Boolean CTBExists(void);
|
|
short ConfigureCTB(Boolean makeUser);
|
|
short CTBNavigateString(Uptr string);
|
|
short MyCMOpen(ConnHandle cn,long timeout);
|
|
short MyCMClose(ConnHandle cn);
|
|
short MyCMWrite(ConnHandle cn,UPtr buffer,long *size,AsyncStuffPtr callerStuff);
|
|
short MyCMBreak(ConnHandle cn,long howLong);
|
|
short MyCMRead(ConnHandle cn,UPtr buffer,long *size,long timeout);
|
|
typedef pascal void MyCTBCompleteType(ConnHandle cn);
|
|
SIMPLE_UPP(MyCTBComplete,ConnectionCompletion);
|
|
Handle GetNavResource(short id);
|
|
void CheckNavPWRes(Boolean *primary,Boolean *secondary,Handle resH);
|
|
long CTBDataCount(void);
|
|
void CTBAuxConfig(ConnHandle cnH, PStr toolName);
|
|
Boolean SilentCTB=False;
|
|
PStr StripHi(PStr string);
|
|
#define CTBTrouble(err) CTBTR(err,FNAME_STRN+FILE_NUM,__LINE__)
|
|
short CTBTR(short err,short file,short line);
|
|
#define ESC_AUXUSR 1
|
|
#define ESC_AUXUSRERR 2
|
|
#define ESC_AUXPW 4
|
|
#define ESC_USR 8
|
|
#define ESC_PW 16
|
|
short EscapeCopy(PStr to,PStr from,PStr expect,PStr hangup);
|
|
|
|
/************************************************************************
|
|
* InitCTB - initialize the CommToolbox
|
|
************************************************************************/
|
|
Boolean InitCTB(Boolean makeUser)
|
|
{
|
|
static int CTBInitted=0;
|
|
|
|
ASSERT(gCTBStream);
|
|
|
|
CTBInitted = MIN(CTBInitted,4);
|
|
CTBSilenceTrans(gCTBStream,False);
|
|
switch (CTBInitted)
|
|
{
|
|
case 0:
|
|
if (!CTBExists())
|
|
{
|
|
WarnUser(NO_CTB,0);
|
|
return(False);
|
|
}
|
|
CTBInitted++;
|
|
case 1:
|
|
if (CTBErr = InitCTBUtilities())
|
|
{
|
|
WarnUser(NO_CTBU,CTBErr);
|
|
return(False);
|
|
}
|
|
CTBInitted++;
|
|
case 2:
|
|
if (CTBErr = InitCRM())
|
|
{
|
|
WarnUser(NO_CTBRM,CTBErr);
|
|
return(False);
|
|
}
|
|
CTBInitted++;
|
|
case 3:
|
|
if (CTBErr = InitCM())
|
|
{
|
|
WarnUser(NO_CTBCM,CTBErr);
|
|
return(False);
|
|
}
|
|
CTBInitted++;
|
|
case 4:
|
|
if (CTBErr = ConfigureCTB(makeUser))
|
|
return(False);
|
|
CTBInitted++;
|
|
}
|
|
return(True);
|
|
}
|
|
|
|
/************************************************************************
|
|
* CTBExists - is the CTB installed?
|
|
************************************************************************/
|
|
Boolean CTBExists(void)
|
|
{
|
|
#define CTBTrap 0x8b
|
|
#define UnimplTrap 0x9f
|
|
return(NGetTrapAddress(UnimplTrap,OSTrap)!=NGetTrapAddress(CTBTrap,OSTrap));
|
|
}
|
|
|
|
/************************************************************************
|
|
* DialThePhone - create a CTB connection
|
|
************************************************************************/
|
|
short DialThePhone(TransStream stream)
|
|
{
|
|
CMStatFlags flags;
|
|
CMBufferSizes sizes;
|
|
|
|
if (!CnH || CMStatus(CnH,sizes,&flags) || !(flags&cmStatusOpen))
|
|
{
|
|
ProgressR(NoChange,NoChange,0,INIT_CTB,nil);
|
|
|
|
gCTBStream = stream;
|
|
gCTBStream->Opening = True;
|
|
if (!InitCTB(False)) return (CTBErr?CTBErr:cmGenericError);
|
|
|
|
gCTBStream->RcvSpot = -1;
|
|
if (!gCTBStream->RcvBuffer
|
|
&& (gCTBStream->RcvBuffer=NuHandle(GetRLong(RCV_BUFFER_SIZE)))==nil)
|
|
{
|
|
CTBErr=MemError();
|
|
WarnUser(MEM_ERR,CTBErr);
|
|
return(CTBErr);
|
|
}
|
|
ProgressR(NoChange,NoChange,0,MAKE_CONNECT,nil);
|
|
CTBErr = MyCMOpen(CnH,0/* 60*GetRLong(OPEN_TIMEOUT) */);
|
|
gCTBStream->Opening = False;
|
|
if (CTBErr)
|
|
{
|
|
CMDispose(CnH);
|
|
CnH = nil;
|
|
return(CTBErr);
|
|
}
|
|
return(CTBNavigateSTRN(NAVIN));
|
|
}
|
|
return (0);
|
|
}
|
|
|
|
/************************************************************************
|
|
* CTBConnectTrans - connect to the remote host. This version uses the CTB.
|
|
************************************************************************/
|
|
OSErr CTBConnectTrans(TransStream stream, UPtr serverName, short port, Boolean silently)
|
|
{
|
|
#pragma unused (stream)
|
|
#pragma unused (silently)
|
|
Str127 scratch;
|
|
|
|
#ifdef DEBUG
|
|
if (BUG12) port += 10000;
|
|
#endif
|
|
ComposeRString(scratch,TS_CONNECT_FMT,serverName,(uLong) port);
|
|
ProgressMessage(kpMessage,scratch);
|
|
CTBSendTrans(nil,scratch+1,*scratch,nil);
|
|
|
|
return(CTBErr);
|
|
}
|
|
|
|
/************************************************************************
|
|
* CTBSendTrans - send some text to the remote host. This version uses the CTB.
|
|
************************************************************************/
|
|
OSErr CTBSendTrans(TransStream stream, UPtr text,long size, ...)
|
|
{
|
|
#pragma unused (stream)
|
|
long bSize;
|
|
|
|
if (size==0) return(noErr); /* allow vacuous sends */
|
|
CycleBalls();
|
|
|
|
bSize = size;
|
|
if (CTBErr=MyCMWrite(CnH,text,&bSize,nil))
|
|
return(CTBErr);
|
|
{
|
|
Uptr buffer;
|
|
va_list extra_buffers;
|
|
va_start(extra_buffers,size);
|
|
while (buffer = va_arg(extra_buffers,UPtr))
|
|
{
|
|
CycleBalls();
|
|
bSize = va_arg(extra_buffers,int);
|
|
if (CTBErr=CTBSendTrans(nil,buffer,bSize,nil)) break;
|
|
}
|
|
va_end(extra_buffers);
|
|
}
|
|
return(CTBErr);
|
|
}
|
|
|
|
/************************************************************************
|
|
* CTBRecvTrans - get some text from the remote host. This version uses the CTB.
|
|
************************************************************************/
|
|
OSErr CTBRecvTrans(TransStream stream,UPtr line,long *size)
|
|
{
|
|
#pragma unused (stream)
|
|
long gotThis;
|
|
Str31 tmStr;
|
|
short factor = 60;
|
|
UPtr spot = line;
|
|
long want = *size;
|
|
|
|
NumToString(CTBTimeout,tmStr);
|
|
MyCMIdle();
|
|
do
|
|
{
|
|
CTBErr = SpinOn(&CTBHasChars,CTBTimeout*factor,True,False);
|
|
if (CTBErr)
|
|
CTBErr = cmTimeOut;
|
|
else
|
|
{
|
|
factor = 10;
|
|
gotThis = CTBDataCount();
|
|
gotThis = MIN(gotThis,want);
|
|
CTBErr=MyCMRead(CnH,line,&gotThis,0);
|
|
if (!CTBErr) {spot += gotThis; want -= gotThis;}
|
|
}
|
|
}
|
|
while (want && spot==line && !SilentCTB && !CommandPeriod &&
|
|
AlertStr(TIMEOUT_ALRT,Caution,tmStr)==1);
|
|
|
|
*size = spot - line;
|
|
if (!CTBErr && *size==0) CTBErr = cmTimeOut;
|
|
if (!CTBErr && *size) ResetAlrtStage();
|
|
return(CTBErr);
|
|
}
|
|
|
|
/************************************************************************
|
|
*
|
|
************************************************************************/
|
|
void HangUpThePhone()
|
|
{
|
|
ASSERT(gCTBStream);
|
|
|
|
if (CnH)
|
|
{
|
|
(void) CTBNavigateSTRN(NAVOUT);
|
|
ProgressMessageR(kpSubTitle,CTB_CLOSING);
|
|
if (!PrefIsSet(PREF_NO_HANGUP)) (void) MyCMClose(CnH);
|
|
}
|
|
if (CnH)
|
|
{
|
|
CMDispose(CnH);
|
|
CnH = nil;
|
|
}
|
|
if (gCTBStream->RcvBuffer) ZapHandle(gCTBStream->RcvBuffer);
|
|
gCTBStream = 0;
|
|
}
|
|
|
|
/************************************************************************
|
|
* CTBDisTrans - disconnect from the remote host. This version uses the CTB.
|
|
************************************************************************/
|
|
OSErr CTBDisTrans(TransStream stream)
|
|
{
|
|
#pragma unused (stream)
|
|
return(noErr);
|
|
}
|
|
|
|
/************************************************************************
|
|
* CTBDestroyTrans - destory the connection.
|
|
************************************************************************/
|
|
OSErr CTBDestroyTrans(TransStream stream)
|
|
{
|
|
#pragma unused (stream)
|
|
return(noErr);
|
|
}
|
|
|
|
/************************************************************************
|
|
* CTBTransError - report our most recent error
|
|
************************************************************************/
|
|
OSErr CTBTransError(TransStream stream)
|
|
{
|
|
#pragma unused (stream)
|
|
return(CTBErr);
|
|
}
|
|
|
|
/************************************************************************
|
|
* CTBSilenceTrans - turn off error reports from tcp routines
|
|
************************************************************************/
|
|
void CTBSilenceTrans(TransStream stream,Boolean silence)
|
|
{
|
|
#pragma unused (stream)
|
|
SilentCTB = silence;
|
|
}
|
|
|
|
/************************************************************************
|
|
* ConfigureCTB - configure the communications toolbox
|
|
************************************************************************/
|
|
short ConfigureCTB(Boolean makeUser)
|
|
{
|
|
Str63 toolName;
|
|
short procID;
|
|
CMBufferSizes bs;
|
|
Point pt;
|
|
short result;
|
|
Handle cfigH;
|
|
Boolean needConfig = True;
|
|
|
|
CTBErr = 0;
|
|
|
|
/*
|
|
* find the tool to use
|
|
*/
|
|
if (!*GetRStr(toolName,CTB_TOOL_STR)) return(1);
|
|
|
|
if ((procID=CMGetProcID(toolName))<0)
|
|
{
|
|
CRMGetIndToolName(classCM,1,toolName);
|
|
if (!*toolName)
|
|
return(WarnUser(NO_CTB_TOOLS,1));
|
|
else if ((procID=CMGetProcID(toolName))<0)
|
|
return(WarnUser(COULDNT_GET_TOOL,1));
|
|
}
|
|
|
|
/*
|
|
* create a connection record
|
|
*/
|
|
WriteZero(bs,sizeof(bs));
|
|
if (!(CnH = CMNew(procID,
|
|
cmNoMenus|(PrefIsSet(PREF_AUTO_DISMISS)?cmQuiet:0),bs,nil,nil)))
|
|
{
|
|
WarnUser(MEM_ERR,MemError());
|
|
return(1);
|
|
}
|
|
|
|
/*
|
|
* try to load the old configuration
|
|
*/
|
|
if (cfigH = GetNamedResource(CTB_CFIG_TYPE,toolName))
|
|
{
|
|
if (GetPtrSize((*CnH)->config)==GetHandleSize_(cfigH))
|
|
{
|
|
BMD(*cfigH,(*CnH)->config,GetPtrSize((*CnH)->config));
|
|
BMD(*cfigH,(*CnH)->oldConfig,GetPtrSize((*CnH)->config));
|
|
needConfig = CMValidate(CnH);
|
|
}
|
|
ReleaseResource_(cfigH);
|
|
}
|
|
|
|
/*
|
|
* let the user have a look at things
|
|
*/
|
|
if (makeUser || needConfig)
|
|
{
|
|
pt.h = 10; pt.v = GetMBarHeight()+10;
|
|
UseResFile(0); /* make sure no Eudora rsrcs interfere */
|
|
result = CMChoose(&CnH,pt,nil);
|
|
UseResFile(SettingsRefN);
|
|
switch (result)
|
|
{
|
|
case chooseDisaster:
|
|
case chooseFailed:
|
|
case chooseAborted:
|
|
CTBErr = result;
|
|
break;
|
|
case chooseOKMajor:
|
|
case chooseOKMinor:
|
|
/* save the name string */
|
|
CMGetToolName((*CnH)->procID,toolName);
|
|
CTBAuxConfig(CnH,toolName);
|
|
BMD((*CnH)->config,(*CnH)->oldConfig,GetPtrSize((*CnH)->config));
|
|
if (CTBErr = SettingsPtr('STR ',nil,CTB_TOOL_STR,toolName,*toolName+1))
|
|
WarnUser(WRITE_SETTINGS,CTBErr);
|
|
else if (CTBErr = SettingsPtr(CTB_CFIG_TYPE,toolName,CTB_CFIG_ID,
|
|
(*CnH)->config,GetPtrSize((*CnH)->config)))
|
|
WarnUser(WRITE_SETTINGS,CTBErr);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* just configuring?
|
|
*/
|
|
if (CnH)
|
|
if (makeUser) {CMDispose(CnH); CnH = nil;}
|
|
|
|
return(CTBErr);
|
|
}
|
|
|
|
/************************************************************************
|
|
* CTBAuxConfig - allow the user to set extra parameters
|
|
************************************************************************/
|
|
void CTBAuxConfig(ConnHandle cnH, PStr toolName)
|
|
{
|
|
Str255 resName;
|
|
Handle resH = nil;
|
|
long zero = 0;
|
|
|
|
ComposeRString(resName,CTB_SETCONFIG_FMT,toolName);
|
|
|
|
if ((resH = GetNamedResource('TEXT',resName)) ||
|
|
(resH = GetNamedResource('TEXT',GetRString(resName,SETCONFIG))))
|
|
{
|
|
PtrPlusHand_(&zero,resH,1);
|
|
(void) CMSetConfig(cnH,LDRef(resH));
|
|
ReleaseResource_(resH);
|
|
}
|
|
}
|
|
|
|
|
|
/************************************************************************
|
|
* CTBNavigateSTRN - navigate a serial connection by means of an STRN resource
|
|
************************************************************************/
|
|
short CTBNavigateSTRN(short id)
|
|
{
|
|
short count,n;
|
|
Str63 name;
|
|
Uhandle strnH;
|
|
Str255 string;
|
|
ResType theType;
|
|
Boolean oldSilence = SilentCTB;
|
|
short err=noErr;
|
|
|
|
ASSERT(gCTBStream);
|
|
|
|
strnH = GetNavResource(id);
|
|
|
|
if (strnH)
|
|
{
|
|
CTBTimeout = GetRLong(SHORT_TIMEOUT);
|
|
count = (*strnH)[0]*256 + (*strnH)[1];
|
|
GetResInfo(strnH,&id,&theType,name);
|
|
ReleaseResource_(strnH);
|
|
ComposeLogR(LOG_NAV,nil,NAV_BEGIN,name,id,count);
|
|
|
|
CTBSilenceTrans(gCTBStream,True);
|
|
for (n=1; n<=count; n++)
|
|
{
|
|
GetIndString(string,id,n);
|
|
if (err=CTBNavigateString(string)) break;
|
|
}
|
|
CTBSilenceTrans(gCTBStream,oldSilence);
|
|
CTBTimeout = InAThread() ? GetRLong(THREAD_RECV_TIMEOUT) : GetRLong(RECV_TIMEOUT);
|
|
if (err!=cmTimeOut) CTBTrouble(err);
|
|
}
|
|
|
|
return(err==cmTimeOut ? noErr : err);
|
|
}
|
|
|
|
/************************************************************************
|
|
* GetNavResource - get a navigation resource
|
|
************************************************************************/
|
|
Handle GetNavResource(short id)
|
|
{
|
|
Handle strnH;
|
|
Str255 name,string;
|
|
|
|
GetRString(name,id);
|
|
GetRStr(string,CTB_TOOL_STR);
|
|
PCatC(string,' ');
|
|
PCat(string,name);
|
|
strnH = GetNamedResource('STR#',string);
|
|
if (!strnH)
|
|
strnH = GetNamedResource('STR#',name);
|
|
if (!strnH)
|
|
strnH = GetResource_('STR#',id==NAVIN ? CTB_NAV_IN_STRN :
|
|
(id==NAVMID ? CTB_NAV_MID_STRN : CTB_NAV_OUT_STRN));
|
|
return(strnH);
|
|
}
|
|
|
|
/************************************************************************
|
|
* CTBNavigateString - navigate a serial connection by a string
|
|
************************************************************************/
|
|
short CTBNavigateString(Uptr string)
|
|
{
|
|
Str255 data, scratch, expect, hangup;
|
|
long bSize;
|
|
long tics;
|
|
UPtr exSpot,dSpot, hangSpot;
|
|
Boolean found=False,brk=False,wait=False,doHangup=False;
|
|
short escFlags;
|
|
|
|
ASSERT(gCTBStream);
|
|
|
|
escFlags = EscapeCopy(data,string,expect,hangup);
|
|
StripHi(expect);
|
|
StripHi(hangup);
|
|
|
|
/*
|
|
* user might have cancelled when entering password above
|
|
*/
|
|
if (CommandPeriod) return(userCancelled);
|
|
|
|
/*
|
|
* no dialup username?
|
|
*/
|
|
if (escFlags & ESC_AUXUSRERR)
|
|
{
|
|
WarnUser(NO_AUXUSR,0);
|
|
return(userCancelled);
|
|
}
|
|
|
|
/*
|
|
* Progress. If bullet, we hide
|
|
*/
|
|
if (*data && data[1]==bulletChar)
|
|
{
|
|
ProgressMessageR(kpMessage,SECRET);
|
|
BMD(data+2,data+1,*data-1);
|
|
--*data;
|
|
}
|
|
else if (*data && ((brk=data[1]==betaChar) || (wait=data[1]==deltaChar)))
|
|
{
|
|
BMD(data+2,data+1,*data);
|
|
--*data;
|
|
tics = Atoi(data+1);
|
|
if (wait) tics *= 60;
|
|
ProgressMessageR(kpMessage,brk?BREAKING:WAITING);
|
|
}
|
|
else
|
|
{
|
|
ProgressMessage(kpMessage,data);
|
|
}
|
|
|
|
/*
|
|
* log our message
|
|
*/
|
|
CarefulLog(LOG_NAV,LOG_SENT,data+1,*data);
|
|
|
|
/*
|
|
* send a break
|
|
*/
|
|
if (brk)
|
|
{
|
|
if (CTBErr=MyCMBreak(CnH,tics)) return(CTBErr);
|
|
}
|
|
|
|
/*
|
|
* delay
|
|
*/
|
|
else if (wait)
|
|
for (tics+=TickCount();TickCount()<tics;) MiniEvents();
|
|
|
|
/*
|
|
* send some data
|
|
*/
|
|
else if (CTBErr=CTBSendTrans(nil,data+1,*data,nil)) return(CTBErr);
|
|
|
|
/*
|
|
* are we looking for a response?
|
|
*/
|
|
if (*expect)
|
|
{
|
|
CarefulLog(LOG_NAV,LOG_EXPECT,expect+1,*expect);
|
|
tics = TickCount()+(InAThread() ? GetRLong(THREAD_RECV_TIMEOUT) : GetRLong(RECV_TIMEOUT))*60;
|
|
exSpot = expect+1;
|
|
}
|
|
|
|
/*
|
|
* are we looking for something that will make us give up?
|
|
*/
|
|
if (*hangup)
|
|
{
|
|
CarefulLog(LOG_NAV,LOG_HANGUP,hangup+1,*hangup);
|
|
tics = TickCount()+(InAThread() ? GetRLong(THREAD_RECV_TIMEOUT) : GetRLong(RECV_TIMEOUT))*60;
|
|
hangSpot = hangup+1;
|
|
}
|
|
|
|
/*
|
|
* now, look!
|
|
*/
|
|
do
|
|
{
|
|
/*
|
|
* read response
|
|
*/
|
|
bSize = sizeof(data)-1;
|
|
CTBErr = RecvLine(gCTBStream,data+1,&bSize);
|
|
|
|
/*
|
|
* got a response
|
|
*/
|
|
if (bSize)
|
|
{
|
|
data[0] = bSize;
|
|
ProgressMessage(kpMessage,data);
|
|
CarefulLog(LOG_NAV,LOG_GOT,data+1,*data);
|
|
|
|
/*
|
|
* scan for expect or hangup strings
|
|
*/
|
|
if (*expect || *hangup)
|
|
{
|
|
for(dSpot=data+1;dSpot<=data+*data;dSpot++)
|
|
{
|
|
if (*expect)
|
|
if ((*dSpot&0x7f)==*exSpot)
|
|
{
|
|
if (++exSpot>expect+*expect)
|
|
{
|
|
ComposeLogR(LOG_NAV,nil,LOG_FOUND);
|
|
found = True;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
exSpot = expect+1;
|
|
if (*hangup)
|
|
if ((*dSpot&0x7f)==*hangSpot)
|
|
{
|
|
if (++hangSpot>hangup+*hangup)
|
|
{
|
|
ComposeLogR(LOG_NAV,nil,LOG_HANGUP_FOUND);
|
|
doHangup = True;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
hangSpot = hangup+1;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* timeout looking for an expect string
|
|
*/
|
|
if (*expect && TickCount()>tics)
|
|
{
|
|
GetRString(scratch,InAThread() ? THREAD_RECV_TIMEOUT : RECV_TIMEOUT);
|
|
CTBSilenceTrans(gCTBStream,False);
|
|
|
|
/*
|
|
* does the user want us to try some more?
|
|
*/
|
|
if (AlertStr(TIMEOUT_ALRT,Caution,scratch)==1)
|
|
tics = TickCount()+60*((InAThread() ? GetRLong(THREAD_RECV_TIMEOUT) : GetRLong(RECV_TIMEOUT))); /* Yes, try more */
|
|
else
|
|
{
|
|
ComposeLogR(LOG_NAV,nil,LOG_NOTFOUND); /* No, give up now */
|
|
CTBErr = userCancelled;
|
|
}
|
|
CTBSilenceTrans(gCTBStream,True);
|
|
}
|
|
}
|
|
while (!CommandPeriod && (!CTBErr || CTBErr==cmTimeOut&&*expect) && !found && !doHangup);
|
|
|
|
if (CTBErr==cmTimeOut) CTBErr = 0;
|
|
|
|
/*
|
|
* We gave up on an expect string, or hit the hangup string
|
|
*/
|
|
if (*expect && !found || doHangup)
|
|
{
|
|
CTBErr = userCancelled;
|
|
InvalidatePasswords(0==(escFlags&ESC_PW),0==(escFlags&ESC_AUXPW),False);
|
|
}
|
|
return(CTBErr);
|
|
}
|
|
|
|
|
|
/**********************************************************************
|
|
* StripHi - strip the high bits from a string
|
|
**********************************************************************/
|
|
PStr StripHi(PStr string)
|
|
{
|
|
UPtr spot;
|
|
|
|
for (spot=string+*string;spot>string;spot--) *spot &= 0x7f; /* strip parity */
|
|
return(string);
|
|
}
|
|
|
|
/************************************************************************
|
|
* MyCMClose - call CMClose
|
|
************************************************************************/
|
|
short MyCMClose(ConnHandle cn)
|
|
{
|
|
AsyncStuff stuff;
|
|
short err; /* real error */
|
|
|
|
DebugStr11("\pMyCMClose;g");
|
|
(*cn)->refCon = (long) &stuff; /* store address */
|
|
stuff.pending = 1;
|
|
if (PrefIsSet(PREF_SYNCH_CTB))
|
|
err=CMClose(cn,False,nil,-1,True);
|
|
else
|
|
{
|
|
(void) CMIOKill(cn,cmDataIn);
|
|
(void) CMIOKill(cn,cmDataOut);
|
|
if (!(err=CMClose(cn,True,MyCTBCompleteUPP,-1,False)))
|
|
{
|
|
err = SpinOn(&stuff.pending,0,True,True);
|
|
if (!err) err = stuff.errCode;
|
|
}
|
|
}
|
|
CTBTrouble(err);
|
|
return (err); /* error? */
|
|
}
|
|
|
|
/************************************************************************
|
|
* MyCMOpen - call CMOpen
|
|
************************************************************************/
|
|
short MyCMOpen(ConnHandle cn,long timeout)
|
|
{
|
|
AsyncStuff stuff;
|
|
short err; /* real error */
|
|
|
|
DebugStr11("\pMyCMOpen;g");
|
|
(*cn)->refCon = (long) &stuff; /* store address */
|
|
stuff.pending = 1;
|
|
if (PrefIsSet(PREF_SYNCH_CTB))
|
|
err=CMOpen(cn,False,MyCTBCompleteUPP,timeout);
|
|
else
|
|
{
|
|
if (!(err=CMOpen(cn,True,MyCTBCompleteUPP,timeout)))
|
|
{
|
|
err = SpinOn(&stuff.pending,0,True,False);
|
|
if (!err) err = stuff.errCode;
|
|
if (err==userCancelled)
|
|
(void) CMAbort(CnH);
|
|
}
|
|
}
|
|
|
|
CTBTrouble(err);
|
|
return (err);
|
|
}
|
|
|
|
/************************************************************************
|
|
* MyCMRead - call CMRead
|
|
************************************************************************/
|
|
short MyCMRead(ConnHandle cn,UPtr buffer,long *size,long timeout)
|
|
{
|
|
short err; /* real error */
|
|
CMFlags junk;
|
|
|
|
DebugStr11("\pMyCMRead;g");
|
|
#ifdef DEBUG
|
|
if (BUG11) Dprintf("\p%d bytes;g",*size);
|
|
#endif
|
|
|
|
#ifdef APPLE_FIXES_EM_TOOL
|
|
AsyncStuff stuff;
|
|
|
|
(*cn)->refCon = (long)&stuff;
|
|
stuff.pending = 1;
|
|
if (!(err=CMRead(cn,buffer,size,cmData,True,MyCTBCompleteUPP,timeout,&junk)))
|
|
{
|
|
err = SpinOn(&stuff.pending,0,False);
|
|
if (!err) err = stuff.errCode;
|
|
if (err==userCancelled)
|
|
CMIOKill(cn,cmDataIn);
|
|
}
|
|
|
|
if (!err || err==cmTimeOut)
|
|
{
|
|
*size = stuff.asyncCount[cmDataIn];
|
|
if (*size) err = noErr;
|
|
else err = cmTimeOut;
|
|
}
|
|
else
|
|
*size = 0;
|
|
#else
|
|
DebugStr11("\pCMRead call;g");
|
|
err = CMRead(cn,buffer,size,cmData,False,nil,timeout,&junk);
|
|
DebugStr11("\pCMRead return;g");
|
|
#endif
|
|
|
|
|
|
if (*size && LogLevel&LOG_TRANS) CarefulLog(LOG_TRANS,LOG_GOT,buffer,*size);
|
|
if (err!=cmTimeOut) CTBTrouble(err);
|
|
return(err);
|
|
}
|
|
|
|
/************************************************************************
|
|
* MyCMWrite - call CMWrite
|
|
************************************************************************/
|
|
short MyCMWrite(ConnHandle cn,UPtr buffer,long *size, AsyncStuffPtr callerStuff)
|
|
{
|
|
AsyncStuffPtr stuff;
|
|
AsyncStuff localStuff;
|
|
short err; /* real error */
|
|
|
|
DebugStr11("\pMyCMWrite;g");
|
|
stuff = callerStuff ? callerStuff : &localStuff;
|
|
(*cn)->refCon = (long)stuff;
|
|
stuff->pending = 1;
|
|
if (LogLevel&LOG_TRANS) CarefulLog(LOG_TRANS,LOG_SENT,buffer,*size);
|
|
if (!(err=CMWrite(cn,buffer,size,cmData,True,MyCTBCompleteUPP,3600,0)))
|
|
{
|
|
if (callerStuff) return(noErr);
|
|
err = SpinOn(&stuff->pending,0,True,False);
|
|
if (!err) err = stuff->errCode;
|
|
if (err==userCancelled)
|
|
CMIOKill(cn,cmDataOut);
|
|
}
|
|
|
|
if (!err)
|
|
*size = stuff->asyncCount[cmDataOut];
|
|
else
|
|
*size = 0;
|
|
|
|
CTBTrouble(err);
|
|
return(err);
|
|
}
|
|
|
|
/************************************************************************
|
|
* MyCMBreak - call CMBreak
|
|
************************************************************************/
|
|
short MyCMBreak(ConnHandle cn,long howLong)
|
|
{
|
|
AsyncStuff stuff;
|
|
short err; /* real error */
|
|
(*cn)->refCon = (long)&stuff;
|
|
stuff.pending = 1;
|
|
CMBreak(cn,howLong,True,MyCTBCompleteUPP);
|
|
|
|
err = SpinOn(&stuff.pending,0,True,False);
|
|
if (!err) err = stuff.errCode;
|
|
if (err==userCancelled)
|
|
CMIOKill(cn,cmDataOut);
|
|
|
|
CTBTrouble(err);
|
|
return(err);
|
|
}
|
|
|
|
/************************************************************************
|
|
* CTBTR - report a CTB error
|
|
************************************************************************/
|
|
short CTBTR(short err,short file,short line)
|
|
{
|
|
Uhandle strnH;
|
|
|
|
ASSERT(gCTBStream);
|
|
|
|
if (!SilentCTB && err && (!(CommandPeriod || err==userCancelled) || gCTBStream->Opening))
|
|
{
|
|
strnH = GetResource_('STR#',CTB_ERR_STRN);
|
|
if (strnH)
|
|
{
|
|
Str127 errString,debugStr,message;
|
|
if (err+2 > 0 && err+2 <= (*strnH)[0]*256 + (*strnH)[1])
|
|
GetRString(errString,CTB_ERR_STRN+err+2);
|
|
else
|
|
NumToString(err,errString);
|
|
ReleaseResource_(strnH);
|
|
GetRString(message,CTB_PROBLEM);
|
|
ComposeRString(debugStr,FILE_LINE_FMT,file,line);
|
|
MyParamText(message,errString,"",debugStr);
|
|
if (gCTBStream->Opening)
|
|
{
|
|
if (2==ReallyDoAnAlert(OPEN_ERR_ALRT,Caution))
|
|
SetPref(PREF_OFFLINE,YesStr);
|
|
}
|
|
else ReallyDoAnAlert(OK_ALRT,Caution);
|
|
CTBSilenceTrans(gCTBStream,True);
|
|
}
|
|
}
|
|
return(err);
|
|
}
|
|
|
|
/************************************************************************
|
|
* CTBWhoAmI - return the mac's ctb name
|
|
************************************************************************/
|
|
UPtr CTBWhoAmI(TransStream stream,Uptr who)
|
|
{
|
|
#pragma unused (stream)
|
|
return(GetRString(who,CTB_ME));
|
|
}
|
|
|
|
/************************************************************************
|
|
* MyCMIdle - do the things I should do at CMIdle time
|
|
************************************************************************/
|
|
void MyCMIdle(void)
|
|
{
|
|
CMIdle(CnH);
|
|
CTBHasChars = CTBDataCount() ? noErr : inProgress;
|
|
}
|
|
|
|
/************************************************************************
|
|
* CTBDataCount - how much data do we have?
|
|
************************************************************************/
|
|
long CTBDataCount(void)
|
|
{
|
|
CMStatFlags flags;
|
|
CMBufferSizes sizes;
|
|
|
|
CMStatus(CnH,sizes,&flags);
|
|
return(flags&cmStatusDataAvail ? sizes[cmDataIn] : 0);
|
|
}
|
|
|
|
/************************************************************************
|
|
* GetSecondPass - get the user's secondary password
|
|
************************************************************************/
|
|
short GetSecondPass(UPtr pass)
|
|
{
|
|
Str31 save;
|
|
short err;
|
|
Str31 dialup;
|
|
|
|
if (!*(*CurPers)->secondPass)
|
|
{
|
|
PCopy(save,(*CurPers)->password);
|
|
*(*CurPers)->password = 0;
|
|
GetRString(dialup,DIALUP);
|
|
if (!(err=GetPassword(dialup,pass,32,ENTER)))
|
|
{
|
|
PCopy((*CurPers)->secondPass,pass);
|
|
if (PrefIsSet(PREF_SAVE_PASSWORD) && *(*CurPers)->secondPass)
|
|
{
|
|
PCopy(dialup,(*CurPers)->secondPass);
|
|
SetPref(PREF_AUXPW,dialup);
|
|
MyUpdateResFile(SettingsRefN);
|
|
}
|
|
}
|
|
PCopy((*CurPers)->password,save);
|
|
return(err);
|
|
}
|
|
else
|
|
{
|
|
PCopy(pass,(*CurPers)->secondPass);
|
|
return(noErr);
|
|
}
|
|
}
|
|
|
|
|
|
/************************************************************************
|
|
* CheckNavPW - see if the nav strings need passwords
|
|
************************************************************************/
|
|
void CheckNavPW(Boolean *primary,Boolean *secondary)
|
|
{
|
|
CheckNavPWRes(primary,secondary,GetNavResource(NAVIN));
|
|
CheckNavPWRes(primary,secondary,GetNavResource(NAVOUT));
|
|
CheckNavPWRes(primary,secondary,GetNavResource(NAVMID));
|
|
}
|
|
|
|
|
|
/************************************************************************
|
|
* CheckNavPWRes - see if a particular resource needs passwords
|
|
************************************************************************/
|
|
void CheckNavPWRes(Boolean *primary,Boolean *secondary,Handle strnH)
|
|
{
|
|
short n;
|
|
Str255 s;
|
|
short id;
|
|
OSType theType;
|
|
UPtr spot;
|
|
|
|
if (!strnH) return;
|
|
GetResInfo(strnH,&id,&theType,s);
|
|
n = CountStrn(id);
|
|
while (n && (!*primary || !*secondary))
|
|
{
|
|
GetIndString(s,id,n--);
|
|
if (spot=PPtrFindSub("\p\\p",s+1,*s))
|
|
{
|
|
if (spot[1]=='p') *primary = True;
|
|
else *secondary = True;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#pragma segment Transport
|
|
/************************************************************************
|
|
* EscapeCopy - copy a string, expanding escapes
|
|
************************************************************************/
|
|
short EscapeCopy(PStr to,PStr from,PStr expect,PStr hangup)
|
|
{
|
|
UPtr end = from+*from;
|
|
UPtr spot = to+1;
|
|
Boolean esc;
|
|
Str127 scratch1, scratch2;
|
|
short returnVal=0;
|
|
Str63 prompt;
|
|
UPtr slash;
|
|
|
|
GetRString(prompt,ANSWER_RESPONSE);
|
|
|
|
*expect = *hangup = 0;
|
|
from++;
|
|
for (esc=false; from<=end; from++)
|
|
{
|
|
if (esc)
|
|
{
|
|
esc = False;
|
|
switch (*from)
|
|
{
|
|
case 'U':
|
|
GetPref(scratch1,PREF_AUXUSR);
|
|
BMD(scratch1+1,spot,*scratch1);
|
|
spot += *scratch1;
|
|
returnVal |= ESC_AUXUSR;
|
|
if (!*scratch1) returnVal |= ESC_AUXUSRERR;
|
|
break;
|
|
case 'P':
|
|
if (GetSecondPass(scratch1))
|
|
{
|
|
CommandPeriod = True;
|
|
if (ProgressIsOpen()) PressStop();
|
|
break;
|
|
}
|
|
BMD(scratch1+1,spot,*scratch1);
|
|
spot += *scratch1;
|
|
returnVal |= ESC_AUXPW;
|
|
break;
|
|
case 'u':
|
|
GetPOPInfo(scratch1,scratch2);
|
|
BMD(scratch1+1,spot,*scratch1);
|
|
spot += *scratch1;
|
|
returnVal |= ESC_USR;
|
|
break;
|
|
case 'h':
|
|
GetPOPInfo(scratch1,scratch2);
|
|
BMD(scratch2+1,spot,*scratch2);
|
|
spot += *scratch2;
|
|
break;
|
|
case 's':
|
|
GetSMTPInfo(scratch1);
|
|
BMD(scratch1+1,spot,*scratch1);
|
|
spot += *scratch1;
|
|
break;
|
|
case '^':
|
|
for (slash=from+1;slash<end;slash++)
|
|
if (*slash==92 && slash[1]!=92) break;
|
|
MakePStr(prompt,from+1,slash-from-1);
|
|
from = slash-1;
|
|
break;
|
|
case 'a':
|
|
if (adlOk==GetAnswer(prompt,scratch1))
|
|
{
|
|
BMD(scratch1+1,spot,*scratch1);
|
|
spot += *scratch1;
|
|
}
|
|
else
|
|
{
|
|
CommandPeriod = True;
|
|
if (ProgressIsOpen()) PressStop();
|
|
}
|
|
break;
|
|
case 'e': /* switch to 'expect' string */
|
|
*to = spot-to-1;
|
|
to[*to+1] = 0;
|
|
to = expect;
|
|
spot=to+1;
|
|
break;
|
|
case 'c': /* switch to 'hangup' string */
|
|
*to = spot-to-1;
|
|
to[*to+1] = 0;
|
|
to = hangup;
|
|
spot=to+1;
|
|
break;
|
|
case 'p':
|
|
BMD((*CurPers)->password+1,spot,*(*CurPers)->password);
|
|
spot += *(*CurPers)->password;
|
|
returnVal |= ESC_PW;
|
|
break;
|
|
case 'n': *spot++ = '\012'; break;
|
|
case 'r': *spot++ = '\015'; break;
|
|
case 'b': *spot++ = bulletChar; break;
|
|
case 'B': *spot++ = betaChar; break;
|
|
case 'D': *spot++ = deltaChar; break;
|
|
default: *spot++ = *from; break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
esc = *from=='\\';
|
|
if (!esc) *spot++ = *from;
|
|
}
|
|
}
|
|
*to = spot-to-1;
|
|
to[*to+1] = 0; /* null terminate, just for fun */
|
|
return(returnVal);
|
|
}
|
|
|
|
#pragma segment Main
|
|
|
|
/************************************************************************
|
|
* MyCTBComplete - completion routine
|
|
************************************************************************/
|
|
pascal void MyCTBComplete(ConnHandle cn)
|
|
{
|
|
AsyncStuffPtr stuffP = (AsyncStuffPtr)(*cn)->refCon;
|
|
uLong *fp, *tp, *ep;
|
|
|
|
//DebugStr11("\pComplete!;g"); // Ok, this was stupid. Can't look at
|
|
//ASSERT(!BugFlags); // globals here, because no A5
|
|
stuffP->errCode = (*cn)->errCode;
|
|
fp=(uLong*)(*cn)->asyncCount;
|
|
tp=(uLong*)stuffP->asyncCount;
|
|
ep=tp+sizeof(CMBufferSizes)/sizeof(uLong);
|
|
while (tp<ep) *tp++ = *fp++;
|
|
stuffP->pending = 0;
|
|
}
|
|
#endif
|