home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The AGA Experience 2
/
agavol2.iso
/
software
/
utilities
/
comms
/
term
/
extras
/
hydracom
/
hydracom-source.lha
/
amiga.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-08-18
|
56KB
|
2,598 lines
/*
** Amiga support module for HYDRA protocol sample implementation.
**
** Written by Olaf Barthel
** Brabeckstrasse 35
** D-30559 Hannover
**
** eMail: olsen@sourcery.han.de
**
** Freely distributable.
*/
/* System includes. */
#include <intuition/intuitionbase.h>
#include <libraries/gadtools.h>
#include <libraries/locale.h>
#include <libraries/asl.h>
#include <graphics/gfxbase.h>
#include <utility/date.h>
#include <devices/conunit.h>
#include <devices/serial.h>
#include <devices/timer.h>
#include <hardware/cia.h>
#include <dos/dosextens.h>
#include <dos/filehandler.h>
#include <dos/dostags.h>
#include <dos/dosasl.h>
#include <exec/memory.h>
/* Correct a nasty bug in the prototypes. */
#define CheckIO foo21234
#include <clib/intuition_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/graphics_protos.h>
#include <clib/utility_protos.h>
#include <clib/locale_protos.h>
#include <clib/timer_protos.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/asl_protos.h>
#include <clib/macros.h>
#include <errno.h>
//#define DB(x) x
#define DB(x)
void __stdargs kprintf(STRPTR,...);
/* Get the CheckIO prototype right. */
#undef CheckIO
struct IORequest *CheckIO(struct IORequest *);
#include "Rendezvous.h"
#include "hydracom.h"
/* Difference between UTC and Amiga time. */
#define UTC_OFFSET 252482400
/* Minimum of lines to reserve for local input. */
#define MIN_LINES 3
/* Serial buffer size. */
#define BUFFER_SIZE 8192
/* A handy macro. */
#define ClrSignal(s) SetSignal(0,s)
/* Signal masks. */
#define SIG_SERREAD (1UL << ReadPort -> mp_SigBit)
#define SIG_SERWRITE (1UL << WritePort -> mp_SigBit)
#define SIG_CONREAD (1UL << ConsoleReadPort -> mp_SigBit)
#define SIG_TIMER (1UL << TimePort -> mp_SigBit)
#define SIG_WINDOW (1UL << WindowPort -> mp_SigBit)
#define SIG_HANDSHAKE SIGF_SINGLE
#define SIG_KILL SIGBREAKF_CTRL_C
/* A serial buffer structure. */
struct SerialBuffer
{
struct IOExtSer *SerialRequest;
UBYTE *SerialBuffer,
*SerialIndex,
*SerialTop;
LONG SerialSize,
SerialFilled;
BOOL IsClone,
IsBusy;
};
/* Special rendezvous data. */
STATIC struct RendezvousData *RendezvousData;
STATIC struct RendezvousSemaphore *RendezvousSemaphore;
/* Library bases. */
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct LocaleBase *LocaleBase;
struct Library *GadToolsBase,
*UtilityBase,
*TimerBase,
*AslBase;
/* Timer data. */
struct MsgPort *TimePort;
struct timerequest *TimeRequest;
/* Serial data. */
struct MsgPort *ReadPort,
*WritePort;
struct SerialBuffer *ThisBuffer,
*NextBuffer,
*ReadBuffer;
/* Console data. */
struct MsgPort *WindowPort;
struct Window *FileWindow,
*RemoteWindow,
*LocalWindow,
*LogWindow;
struct MsgPort *ConsoleWritePort,
*ConsoleReadPort;
struct IOStdReq *ConsoleReadRequest;
UBYTE ConsoleChar;
BOOL ConsoleReady = FALSE,
WindowReady = FALSE;
struct IOStdReq *FileRequest,
*RemoteRequest,
*LocalRequest,
*LogRequest;
/* DOS Data. */
struct Process *ThisProcess;
APTR OldPtr;
LONG OldPri;
struct AnchorPath *Anchor;
BOOL AnchorUsed = FALSE;
/* File requester data. */
struct Process *FileRequesterProcess;
struct MsgPort *FileRequesterPort;
/* Screen data. */
struct Screen *PublicScreen,
*Screen;
/* Menu data. */
APTR VisualInfo;
struct Menu *Menu;
struct NewMenu MenuTemplate[] =
{
{ NM_TITLE, "Project", 0 , 0, 0, (APTR)0},
{ NM_ITEM, "Toggle chat", "C", 0, 0, (APTR)Alt_C},
{ NM_ITEM, NM_BARLABEL, 0 , 0, 0, (APTR)0},
{ NM_ITEM, "Hang up", "H", 0, 0, (APTR)Alt_H},
{ NM_ITEM, "Toggle duplex", "E", 0, 0, (APTR)Alt_E},
{ NM_ITEM, "Toggle 7 bits/8 bits", "B", 0, 0, (APTR)Alt_B},
{ NM_ITEM, NM_BARLABEL, 0 , 0, 0, (APTR)0},
{ NM_ITEM, "Start upload", "U", 0, 0, (APTR)PgUp},
{ NM_ITEM, "Start download", "D", 0, 0, (APTR)PgDn},
{ NM_ITEM, NM_BARLABEL, 0 , 0, 0, (APTR)0},
{ NM_ITEM, "Abort Hydra session", ".", 0, 0, (APTR)Esc},
{ NM_ITEM, NM_BARLABEL, 0 , 0, 0, (APTR)0},
{ NM_ITEM, "Exit HydraCom", "Q", 0, 0, (APTR)Alt_X},
{ NM_END, 0, 0 , 0, 0, (APTR)0}
};
/* Time data. */
LONG GMT_Offset = UTC_OFFSET;
/* Version ID. */
STRPTR VersionTag = "$VER: hydracom 1.0r7 (18.08.95)\r\n";
/* CloseWindowSafely(struct Window *Window):
*
* Close a window sharing its UserPort with other
* windows.
*/
STATIC VOID
CloseWindowSafely(struct Window *Window)
{
struct IntuiMessage *IntuiMessage;
struct Node *Successor;
Forbid();
if(Window -> UserPort)
{
IntuiMessage = (struct IntuiMessage *)Window -> UserPort -> mp_MsgList . lh_Head;
while(Successor = IntuiMessage -> ExecMessage . mn_Node . ln_Succ)
{
if(IntuiMessage -> IDCMPWindow == Window)
{
Remove((struct Node *)IntuiMessage);
ReplyMsg((struct Message *)IntuiMessage);
}
IntuiMessage = (struct IntuiMessage *)Successor;
}
Window -> UserPort = NULL;
}
ModifyIDCMP(Window,NULL);
Permit();
CloseWindow(Window);
}
/* UpdateTime(struct timeval *Now):
*
* Get the current time and/or update the current
* time offset data.
*/
STATIC VOID
UpdateTime(struct timeval *Now)
{
if(Now)
Now -> tv_secs = Now -> tv_micro = 0;
if(TimePort = CreateMsgPort())
{
if(TimeRequest = (struct timerequest *)CreateIORequest(TimePort,sizeof(struct timerequest)))
{
if(!OpenDevice(TIMERNAME,UNIT_VBLANK,TimeRequest,NULL))
{
TimerBase = (struct Library *)TimeRequest -> tr_node . io_Device;
if(LocaleBase = (struct LocaleBase *)OpenLibrary("locale.library",38))
{
struct Locale *Locale;
if(Locale = OpenLocale(NULL))
{
GMT_Offset = 60 * Locale -> loc_GMTOffset + UTC_OFFSET;
CloseLocale(Locale);
}
CloseLibrary(LocaleBase);
LocaleBase = NULL;
}
if(Now)
GetSysTime(Now);
TimerBase = NULL;
CloseDevice(TimeRequest);
}
DeleteIORequest(TimeRequest);
TimeRequest = NULL;
}
DeleteMsgPort(TimePort);
TimePort = NULL;
}
}
/* FileRequestEntry(VOID):
*
* Asynchronous file request process entry.
*/
STATIC VOID
FileRequestEntry(VOID)
{
struct FileRequester *FileRequester;
geta4();
if(FileRequester = (struct FileRequester *)AllocAslRequestTags(ASL_FileRequest,
ASLFR_TitleText, "Select file(s) to upload",
ASLFR_InitialPattern, "#?",
ASLFR_Flags1, FRF_PRIVATEIDCMP | FRF_DOMULTISELECT | FRF_DOPATTERNS,
TAG_DONE))
{
if(FileRequesterPort = CreateMsgPort())
{
struct Message *Message;
ULONG Signals;
BOOL Done = FALSE;
FileRequesterProcess = (struct Process *)FindTask(NULL);
Signal(ThisProcess,SIG_HANDSHAKE);
do
{
Signals = Wait((1L << FileRequesterPort -> mp_SigBit) | SIG_KILL);
if(Signals & (1L << FileRequesterPort -> mp_SigBit))
{
LONG MaxLen;
while(Message = GetMsg(FileRequesterPort))
{
MaxLen = (LONG)Message -> mn_Node . ln_Name;
if(AslRequestTags(FileRequester,
ASLFR_Window, LocalWindow,
ASLFR_SleepWindow, TRUE,
TAG_DONE))
{
if(FileRequester -> fr_NumArgs > 0)
{
UBYTE LocalBuffer[256];
char *String;
LONG Len,Count,i;
for(i = Len = 0 ; i < FileRequester -> fr_NumArgs ; i++)
{
if(FileRequester -> fr_ArgList[i] . wa_Lock)
{
if(NameFromLock(FileRequester -> fr_ArgList[i] . wa_Lock,LocalBuffer,256))
Len += strlen(LocalBuffer) + 1;
}
else
Len += strlen(FileRequester -> fr_Drawer) + 1;
Len += strlen(FileRequester -> fr_ArgList[i] . wa_Name) + 1 + 2;
}
Len++;
if(String = AllocVec(Len,MEMF_ANY))
{
*String = 0;
for(i = Count = 0 ; Count < MaxLen && i < FileRequester -> fr_NumArgs ; i++)
{
if(FileRequester -> fr_ArgList[i] . wa_Lock)
{
if(NameFromLock(FileRequester -> fr_ArgList[i] . wa_Lock,LocalBuffer,256))
{
if(AddPart(LocalBuffer,FileRequester -> fr_ArgList[i] . wa_Name,256))
{
if(Count + strlen(LocalBuffer) + 2 < MaxLen)
{
strcat(String,"\"");
strcat(String,LocalBuffer);
strcat(String,"\"");
Count += strlen(LocalBuffer) + 2;
}
else
break;
}
}
}
else
{
strcpy(LocalBuffer,FileRequester -> fr_Drawer);
if(AddPart(LocalBuffer,FileRequester -> fr_ArgList[i] . wa_Name,256))
{
if(Count + strlen(LocalBuffer) + 2 < MaxLen)
{
strcat(String,"\"");
strcat(String,LocalBuffer);
strcat(String,"\"");
Count += strlen(LocalBuffer) + 2;
}
else
break;
}
}
if(i != FileRequester -> fr_NumArgs - 1)
{
strcat(String," ");
Count++;
}
}
Message -> mn_Node . ln_Name = String;
ReplyMsg(Message);
Message = NULL;
}
}
else
{
if(FileRequester -> fr_File[0])
{
LONG Len;
Len = strlen(FileRequester -> fr_Drawer) + strlen(FileRequester -> fr_File) + 2 + 2;
if(Len <= MaxLen)
{
char *String;
if(String = AllocVec(Len,MEMF_ANY))
{
strcpy(String + 1,FileRequester -> fr_Drawer);
if(AddPart(String + 1,FileRequester -> fr_File,Len))
{
String[0] = '\"';
strcat(String,"\"");
Message -> mn_Node . ln_Name = String;
ReplyMsg(Message);
Message = NULL;
}
else
FreeVec(String);
}
}
}
}
}
if(Message)
{
Message -> mn_Node . ln_Name = NULL;
ReplyMsg(Message);
}
}
}
if(Signals & SIG_KILL)
Done = TRUE;
}
while(!Done);
while(Message = GetMsg(FileRequesterPort))
{
Message -> mn_Node . ln_Name = NULL;
ReplyMsg(Message);
}
DeleteMsgPort(FileRequesterPort);
}
FreeAslRequest(FileRequester);
}
Forbid();
FileRequesterProcess = NULL;
Signal(ThisProcess,SIG_HANDSHAKE);
}
/* GetFiles(char *Buffer,int MaxLen):
*
* Get a list of file names, asynchronously please.
*/
char *
GetFiles(char *Buffer,int MaxLen)
{
struct MsgPort *ReplyPort;
char *Result = NULL;
if(ReplyPort = CreateMsgPort())
{
struct Message *Message;
if(Message = AllocVec(sizeof(struct Message),MEMF_ANY | MEMF_CLEAR))
{
Message -> mn_Length = sizeof(struct Message);
Message -> mn_ReplyPort = ReplyPort;
Message -> mn_Node . ln_Name = (STRPTR)MaxLen;
PutMsg(FileRequesterPort,Message);
FOREVER
{
if(SetSignal(0,(1L << ReplyPort -> mp_SigBit)) & (1L << ReplyPort -> mp_SigBit))
{
GetMsg(ReplyPort);
break;
}
sys_idle();
}
if(Message -> mn_Node . ln_Name)
{
strcpy(Buffer,Message -> mn_Node . ln_Name);
FreeVec(Message -> mn_Node . ln_Name);
Result = Buffer;
}
FreeVec(Message);
}
DeleteMsgPort(ReplyPort);
}
return(Result);
}
/* OpenConsole():
*
* Open a console window.
*/
STATIC BOOL
OpenConsole(struct Screen *Screen,LONG Top,LONG Height,STRPTR Title,BOOL Resize,struct Window **WindowPtr,struct IOStdReq **ConsolePtr)
{
struct Window *Window;
if(Window = OpenWindowTags(NULL,
WA_Left, 0,
WA_Top, Top,
WA_Width, Screen -> Width,
WA_Height, Height,
WA_Title, Title,
WA_SimpleRefresh, TRUE,
WA_DepthGadget, TRUE,
WA_DragBar, TRUE,
WA_SizeGadget, Resize,
WA_SizeBRight, TRUE,
WA_CustomScreen, Screen,
WA_NewLookMenus, TRUE,
TAG_DONE))
{
Window -> UserPort = WindowPort;
SetMenuStrip(Window,Menu);
if(ModifyIDCMP(Window,IDCMP_MENUPICK))
{
struct IOStdReq *ConsoleRequest;
if(Window -> RPort -> Font -> tf_Flags & FPF_PROPORTIONAL)
SetFont(Window -> RPort,GfxBase -> DefaultFont);
if(ConsoleRequest = (struct IOStdReq *)CreateIORequest(ConsoleWritePort,sizeof(struct IOStdReq)))
{
ConsoleRequest -> io_Data = Window;
if(!OpenDevice("console.device",CONU_CHARMAP,ConsoleRequest,CONFLAG_DEFAULT))
{
WindowLimits(Window,Window -> BorderLeft + 10 * Window -> RPort -> Font -> tf_XSize * 10 + Window -> BorderRight,Window -> BorderTop + 2 * Window -> RPort -> Font -> tf_YSize + Window -> BorderBottom,Screen -> Width,Screen -> Height);
/* Turn off the cursor. */
ConPrintf(ConsoleRequest,"\033[0 p");
*WindowPtr = Window;
*ConsolePtr = ConsoleRequest;
return(TRUE);
}
DeleteIORequest(ConsoleRequest);
}
}
ClearMenuStrip(Window);
CloseWindowSafely(Window);
}
return(FALSE);
}
/* CloseConsole():
*
* Close a console window.
*/
STATIC VOID
CloseConsole(struct Window **WindowPtr,struct IOStdReq **ConsolePtr)
{
if(*ConsolePtr)
{
CloseDevice(*ConsolePtr);
DeleteIORequest(*ConsolePtr);
*ConsolePtr = NULL;
}
if(*WindowPtr)
{
ClearMenuStrip(*WindowPtr);
CloseWindowSafely(*WindowPtr);
*WindowPtr = NULL;
}
}
/* CloneSerialBuffer():
*
* Clone a SerialBuffer structure.
*/
STATIC struct SerialBuffer *
CloneSerialBuffer(struct SerialBuffer *Source,struct MsgPort *MsgPort)
{
struct SerialBuffer *Buffer;
if(Buffer = (struct SerialBuffer *)AllocVec(sizeof(struct SerialBuffer) + Source -> SerialSize,MEMF_ANY | MEMF_PUBLIC))
{
Buffer -> SerialBuffer = Buffer -> SerialIndex = (UBYTE *)(Buffer + 1);
Buffer -> SerialFilled = 0;
Buffer -> SerialTop = Buffer -> SerialBuffer + Source -> SerialSize;
Buffer -> SerialSize = Source -> SerialSize;
Buffer -> IsClone = TRUE;
Buffer -> IsBusy = FALSE;
if(Buffer -> SerialRequest = (struct IOExtSer *)AllocVec(sizeof(struct IOExtSer),MEMF_ANY | MEMF_PUBLIC))
{
CopyMem(Source -> SerialRequest,Buffer -> SerialRequest,sizeof(struct IOExtSer));
Buffer -> SerialRequest -> IOSer . io_Message . mn_ReplyPort = MsgPort;
return(Buffer);
}
else
cprint("Could not create serial request\n");
FreeVec(Buffer);
}
else
cprint("Could not create serial buffer\n");
return(NULL);
}
/* DeleteSerialBuffer():
*
* Delete a SerialBuffer structure.
*/
STATIC VOID
DeleteSerialBuffer(struct SerialBuffer *Buffer)
{
if(Buffer)
{
if(Buffer -> IsBusy)
{
if(!CheckIO(Buffer -> SerialRequest))
AbortIO(Buffer -> SerialRequest);
WaitIO(Buffer -> SerialRequest);
}
if(Buffer -> IsClone)
FreeVec(Buffer -> SerialRequest);
else
{
CloseDevice(Buffer -> SerialRequest);
DeleteIORequest(Buffer -> SerialRequest);
}
FreeVec(Buffer);
}
}
/* CreateSerialBuffer():
*
* Create a serial buffer structure.
*/
STATIC struct SerialBuffer *
CreateSerialBuffer(STRPTR Device,LONG Unit,LONG Size,struct MsgPort *MsgPort)
{
struct SerialBuffer *Buffer;
if(Buffer = (struct SerialBuffer *)AllocVec(sizeof(struct SerialBuffer) + Size,MEMF_ANY | MEMF_PUBLIC))
{
Buffer -> SerialBuffer = Buffer -> SerialIndex = (UBYTE *)(Buffer + 1);
Buffer -> SerialFilled = 0;
Buffer -> SerialTop = Buffer -> SerialBuffer + Size;
Buffer -> SerialSize = Size;
Buffer -> IsClone = FALSE;
Buffer -> IsBusy = FALSE;
if(Buffer -> SerialRequest = (struct IOExtSer *)CreateIORequest(MsgPort,sizeof(struct IOExtSer)))
{
Buffer -> SerialRequest -> io_SerFlags = SERF_SHARED;
if(!OpenDevice(Device,Unit,Buffer -> SerialRequest,NULL))
return(Buffer);
else
{
cprint("Could not open \"%s\", unit %d\n",Device,Unit);
DeleteIORequest(Buffer -> SerialRequest);
}
}
else
cprint("Could not create serial request\n");
FreeVec(Buffer);
}
else
cprint("Could not create serial buffer\n");
return(NULL);
}
/* OpenAll():
*
* Allocate all the resources required.
*/
STATIC BOOL
OpenAll(STRPTR Device,LONG Unit)
{
LONG Top,Lines,BorderSize,FontSize,ExtraLines,RemainingLines,TotalHeight;
UWORD Pens = (UWORD)~0;
ThisProcess = (struct Process *)FindTask(NULL);
if(pri != 1000)
{
if(pri < -128)
pri = 128;
else
{
if(pri > 127)
pri = 127;
}
OldPri = SetTaskPri(ThisProcess,pri);
}
if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",37)))
{
cprint("Could not open intuition.library v37\n");
return(FALSE);
}
if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",37)))
{
cprint("Could not open graphics.library v37\n");
return(FALSE);
}
if(!(GadToolsBase = OpenLibrary("gadtools.library",37)))
{
cprint("Could not open gadtools.library v37\n");
return(FALSE);
}
if(!(UtilityBase = OpenLibrary("utility.library",37)))
{
cprint("Could not open utility.library v37\n");
return(FALSE);
}
if(!(AslBase = OpenLibrary("asl.library",37)))
{
cprint("Could not open asl.library v37\n");
return(FALSE);
}
if(LocaleBase = (struct LocaleBase *)OpenLibrary("locale.library",38))
{
struct Locale *Locale;
if(Locale = OpenLocale(NULL))
{
GMT_Offset = 60 * Locale -> loc_GMTOffset + UTC_OFFSET;
CloseLocale(Locale);
}
CloseLibrary(LocaleBase);
}
Forbid();
if(CreateNewProcTags(
NP_Name, "HydraCom Filerequester Process",
NP_WindowPtr, -1,
NP_Entry, FileRequestEntry,
TAG_DONE))
{
ClrSignal(SIG_HANDSHAKE);
Wait(SIG_HANDSHAKE);
}
Permit();
if(!FileRequesterProcess)
{
cprint("Could not create file requester process\n");
return(FALSE);
}
if(!(TimePort = CreateMsgPort()))
{
cprint("Could not create timer port\n");
return(FALSE);
}
if(!(TimeRequest = (struct timerequest *)CreateIORequest(TimePort,sizeof(struct timerequest))))
{
cprint("Could not create timer request\n");
return(FALSE);
}
if(OpenDevice(TIMERNAME,UNIT_VBLANK,TimeRequest,NULL))
{
cprint("Could not open timer\n");
return(FALSE);
}
TimerBase = (struct Library *)TimeRequest -> tr_node . io_Device;
if(!(Anchor = (struct AnchorPath *)AllocVec(sizeof(struct AnchorPath) + 512,MEMF_ANY | MEMF_CLEAR)))
{
cprint("Could not allocate pattern matching buffe\n");
return(FALSE);
}
Anchor -> ap_Strlen = 512;
if(!(ReadPort = CreateMsgPort()))
{
cprint("Could not create serial read port\n");
return(FALSE);
}
if(!(WritePort = CreateMsgPort()))
{
cprint("Could not create serial write port\n");
return(FALSE);
}
Forbid();
if(RendezvousSemaphore = (struct RendezvousSemaphore *)FindSemaphore(Device))
{
ObtainSemaphore(RendezvousSemaphore);
if(!(RendezvousData = (*RendezvousSemaphore -> rs_Login)(ReadPort,WritePort,NULL)))
{
Permit();
ReleaseSemaphore(RendezvousSemaphore);
RendezvousSemaphore = NULL;
cprint("Could not link to `term' port \"%s\"\n",Device);
return(FALSE);
}
}
Permit();
if(!(ConsoleReadPort = CreateMsgPort()))
{
cprint("Could not create console read port\n");
return(FALSE);
}
if(!(ConsoleWritePort = CreateMsgPort()))
{
cprint("Could not create console write port\n");
return(FALSE);
}
if(!(ConsoleReadRequest = (struct IOStdReq *)AllocVec(sizeof(struct IOStdReq),MEMF_ANY | MEMF_PUBLIC | MEMF_CLEAR)))
{
cprint("Could not create console read request\n");
return(FALSE);
}
if(!RendezvousData)
{
if(!(ReadBuffer = CreateSerialBuffer(Device,Unit,BUFFER_SIZE,ReadPort)))
return(FALSE);
}
else
{
if(ReadBuffer = (struct SerialBuffer *)AllocVec(sizeof(struct SerialBuffer) + BUFFER_SIZE,MEMF_ANY | MEMF_PUBLIC))
{
ReadBuffer -> SerialBuffer = ReadBuffer -> SerialIndex = (UBYTE *)(ReadBuffer + 1);
ReadBuffer -> SerialFilled = 0;
ReadBuffer -> SerialTop = ReadBuffer -> SerialBuffer + BUFFER_SIZE;
ReadBuffer -> SerialSize = BUFFER_SIZE;
ReadBuffer -> IsClone = TRUE;
ReadBuffer -> IsBusy = FALSE;
ReadBuffer -> SerialRequest = &RendezvousData -> rd_ReadRequest;
}
else
{
cprint("Could not create serial ReadBuffer\n");
return(FALSE);
}
}
if(!(ThisBuffer = CloneSerialBuffer(ReadBuffer,WritePort)))
return(FALSE);
if(!(NextBuffer = CloneSerialBuffer(ReadBuffer,WritePort)))
return(FALSE);
if(!(PublicScreen = LockPubScreen(NULL)))
{
cprint("Could not find default public screen\n");
return(FALSE);
}
if(RendezvousData)
{
if(!(Screen = RendezvousData -> rd_Screen))
Screen = PublicScreen;
}
else
{
if(!(Screen = OpenScreenTags(NULL,
SA_DisplayID, GetVPModeID(&PublicScreen -> ViewPort),
SA_Overscan, OSCAN_TEXT,
SA_Depth, 2,
SA_Title, PRGNAME " " VERSION " " HC_OS " Amiga rev 6, ported by Olaf `Olsen' Barthel",
SA_Behind, TRUE,
SA_SysFont, 1,
SA_Pens, &Pens,
SA_Interleaved, TRUE,
TAG_DONE)))
{
cprint("Could not open screen\n");
return(FALSE);
}
}
if(!(VisualInfo = GetVisualInfo(Screen,TAG_DONE)))
{
cprint("Could not obtain screen visual info\n");
return(FALSE);
}
if(!(Menu = CreateMenus(MenuTemplate,TAG_DONE)))
{
cprint("Could not create menus\n");
return(FALSE);
}
if(!LayoutMenus(Menu,VisualInfo,
GTMN_TextAttr, Screen -> Font,
GTMN_NewLookMenus, TRUE,
TAG_DONE))
{
cprint("Could not layout menus\n");
return(FALSE);
}
Top = Screen -> BarHeight + 1;
BorderSize = Screen -> WBorTop + Screen -> Font -> ta_YSize + 1 + Screen -> WBorBottom;
FontSize = GfxBase -> DefaultFont -> tf_YSize;
TotalHeight = Screen -> Height - Top;
Lines = (TotalHeight - 3 - 4 * BorderSize) / FontSize;
ExtraLines = Lines > MIN_LINES ? (Lines - MIN_LINES) / 3 : 0;
RemainingLines = Lines > MIN_LINES + ExtraLines * 3 ? Lines - (MIN_LINES + ExtraLines * 3) : 0;
if(Lines < MIN_LINES)
{
cprint("Screen size too small (need at least %d text lines, can get only %d)\n",MIN_LINES,Lines);
return(FALSE);
}
if(!(WindowPort = CreateMsgPort()))
{
cprint("Could not create window port\n");
return(FALSE);
}
if(!OpenConsole(Screen,Top,BorderSize + (6 + ExtraLines) * FontSize,"Log",TRUE,&LogWindow,&LogRequest))
{
cprint("Could not open console window #1\n");
return(FALSE);
}
TotalHeight -= LogWindow -> Height + 1;
Top += LogWindow -> Height + 1;
if(!OpenConsole(Screen,Top,BorderSize + 2 * FontSize,"File",FALSE,&FileWindow,&FileRequest))
{
cprint("Could not open console window #2\n");
return(FALSE);
}
ConPrintf(FileRequest,"\033[?7l");
TotalHeight -= FileWindow -> Height + 1;
Top += FileWindow -> Height + 1;
if(!OpenConsole(Screen,Top,BorderSize + (8 + RemainingLines) * FontSize,"Remote",TRUE,&RemoteWindow,&RemoteRequest))
{
cprint("Could not open console window #3\n");
return(FALSE);
}
TotalHeight -= RemoteWindow -> Height + 1;
Top += RemoteWindow -> Height + 1;
if(!OpenConsole(Screen,Top,TotalHeight,"Local (Press [Amiga+C] to start/end chat mode, [Esc] to abort Hydra session)",TRUE,&LocalWindow,&LocalRequest))
{
cprint("Could not open console window #4\n");
return(FALSE);
}
CopyMem(LocalRequest,ConsoleReadRequest,sizeof(struct IOStdReq));
ConsoleReadRequest -> io_Message . mn_ReplyPort = ConsoleReadPort;
/* Turn the cursors back on. */
ConPrintf(LocalRequest,"\33[ p");
ConPrintf(RemoteRequest,"\33[ p");
ConsoleReadRequest -> io_Command = CMD_READ;
ConsoleReadRequest -> io_Data = &ConsoleChar;
ConsoleReadRequest -> io_Length = 1;
ClrSignal(SIG_CONREAD);
SendIO(ConsoleReadRequest);
OldPtr = ThisProcess -> pr_WindowPtr;
ThisProcess -> pr_WindowPtr = (APTR)LocalWindow;
if(!quiet)
{
ScreenToFront(Screen);
ActivateWindow(LocalWindow);
}
UnlockPubScreen(NULL,PublicScreen);
PublicScreen = NULL;
if(!RendezvousData)
com_flow(flowflags);
return(TRUE);
}
/* CloseAll():
*
* Close all the resources.
*/
STATIC VOID
CloseAll(VOID)
{
if(FileRequesterProcess)
{
Forbid();
ClrSignal(SIG_HANDSHAKE);
Signal(FileRequesterProcess,SIG_KILL);
Wait(SIG_HANDSHAKE);
Permit();
}
if(LocalWindow)
ClearMenuStrip(LocalWindow);
if(Menu)
FreeMenus(Menu);
if(VisualInfo)
FreeVisualInfo(VisualInfo);
if(AnchorUsed)
MatchEnd(Anchor);
if(Anchor)
FreeVec(Anchor);
if(ThisProcess)
ThisProcess -> pr_WindowPtr = OldPtr;
if(ConsoleReadRequest)
{
if(ConsoleReadRequest -> io_Device)
{
if(!CheckIO(ConsoleReadRequest))
AbortIO(ConsoleReadRequest);
WaitIO(ConsoleReadRequest);
}
FreeVec(ConsoleReadRequest);
}
CloseConsole(&LocalWindow,&LocalRequest);
CloseConsole(&RemoteWindow,&RemoteRequest);
CloseConsole(&FileWindow,&FileRequest);
CloseConsole(&LogWindow,&LogRequest);
if(WindowPort)
DeleteMsgPort(WindowPort);
if(!RendezvousData && Screen)
CloseScreen(Screen);
if(PublicScreen)
UnlockPubScreen(NULL,PublicScreen);
DeleteSerialBuffer(NextBuffer);
DeleteSerialBuffer(ThisBuffer);
if(RendezvousData)
{
if(ReadBuffer -> IsBusy)
{
if(!CheckIO(ReadBuffer -> SerialRequest))
AbortIO(ReadBuffer -> SerialRequest);
WaitIO(ReadBuffer -> SerialRequest);
}
FreeVec(ReadBuffer);
}
else
DeleteSerialBuffer(ReadBuffer);
if(ConsoleWritePort)
DeleteMsgPort(ConsoleWritePort);
if(ConsoleReadPort)
DeleteMsgPort(ConsoleReadPort);
if(WritePort)
DeleteMsgPort(WritePort);
if(ReadPort)
DeleteMsgPort(ReadPort);
if(TimeRequest)
{
if(TimeRequest -> tr_node . io_Device)
CloseDevice(TimeRequest);
DeleteIORequest(TimeRequest);
}
if(TimePort)
DeleteMsgPort(TimePort);
if(UtilityBase)
CloseLibrary(UtilityBase);
if(AslBase)
CloseLibrary(AslBase);
if(GadToolsBase)
CloseLibrary(GadToolsBase);
if(GfxBase)
CloseLibrary(GfxBase);
if(IntuitionBase)
CloseLibrary(IntuitionBase);
if(RendezvousData)
{
(*RendezvousSemaphore -> rs_Logoff)(RendezvousData);
RendezvousData = NULL;
}
if(RendezvousSemaphore)
{
ReleaseSemaphore(RendezvousSemaphore);
RendezvousSemaphore = NULL;
}
if(pri != 1000)
OldPri = SetTaskPri(ThisProcess,OldPri);
}
/* ConPutc():
*
* Output a single character.
*/
VOID __stdargs
ConPutc(struct IOStdReq *Request,UBYTE Char)
{
Request -> io_Command = CMD_WRITE;
Request -> io_Data = &Char;
Request -> io_Length = 1;
DoIO(Request);
}
/* ConPuts():
*
* Output a string.
*/
VOID
ConPuts(struct IOStdReq *Request,STRPTR String)
{
Request -> io_Command = CMD_WRITE;
Request -> io_Data = String;
Request -> io_Length = strlen(String);
DoIO(Request);
}
/* ConPrintf():
*
* Formatted console output.
*/
VOID __stdargs
ConPrintf(struct IOStdReq *Request,STRPTR Format,...)
{
STATIC UBYTE Buffer[512];
va_list VarArgs;
LONG Len;
va_start(VarArgs,Format);
vsprintf(Buffer,Format,VarArgs);
va_end(VarArgs);
Len = strlen(Buffer);
if(Buffer[0] != '\033' && Request == FileRequest)
{
struct ConUnit *Unit = (struct ConUnit *)Request -> io_Unit;
if(Unit -> cu_XCCP + Len > Unit -> cu_XMax)
{
if((Len = Unit -> cu_XMax - Unit -> cu_XCCP) < 1)
return;
}
}
Request -> io_Command = CMD_WRITE;
Request -> io_Data = Buffer;
Request -> io_Length = Len;
DoIO(Request);
}
/* ConMove():
*
* Move the cursor to a new position.
*/
VOID
ConMove(struct IOStdReq *Request,LONG x,LONG y)
{
ConPrintf(Request,"\33[%ld;%ldH",y,x);
}
/* ConClear():
*
* Clear the console window.
*/
VOID
ConClear(struct IOStdReq *Request)
{
struct ConUnit *ConUnit = (struct ConUnit *)Request -> io_Device;
LONG x,y;
x = ConUnit -> cu_XCCP;
y = ConUnit -> cu_YCCP;
ConPrintf(Request,"\033[2J\33[%ld;%ldH",y,x);
}
/* ConGetKey():
*
* Read a character from a console window.
*/
int
ConGetKey()
{
if(ConsoleReady)
{
int Result = ConsoleChar;
ConsoleReady = FALSE;
ConsoleReadRequest -> io_Command = CMD_READ;
ConsoleReadRequest -> io_Data = &ConsoleChar;
ConsoleReadRequest -> io_Length = 1;
ClrSignal(SIG_CONREAD);
SendIO(ConsoleReadRequest);
return(Result);
}
else
{
int Result = 0;
if(WindowReady)
{
struct IntuiMessage *IntuiMessage;
ULONG MsgClass;
UWORD MsgCode;
while(IntuiMessage = (struct IntuiMessage *)GetMsg(LocalWindow -> UserPort))
{
MsgClass = IntuiMessage -> Class;
MsgCode = IntuiMessage -> Code;
ReplyMsg(IntuiMessage);
if(MsgClass == IDCMP_MENUPICK)
{
struct MenuItem *Item;
while(MsgCode != MENUNULL)
{
if(Item = ItemAddress(Menu,MsgCode))
{
if(MENU_USERDATA(Item))
{
if(!Result)
Result = (int)MENU_USERDATA(Item);
}
MsgCode = Item -> NextSelect;
}
else
break;
}
}
}
WindowReady = FALSE;
}
return(Result);
}
}
/* ConScanKey():
*
* Check for a keyboard event.
*/
int
ConScanKey()
{
if(ConsoleReady || WindowReady)
return(1);
else
{
int Result = 0;
if(CheckSignal(SIG_WINDOW))
{
WindowReady = TRUE;
Result = 1;
}
if(CheckIO(ConsoleReadRequest))
{
if(!WaitIO(ConsoleReadRequest))
{
ConsoleReady = TRUE;
return(1);
}
else
{
ConsoleReadRequest -> io_Command = CMD_READ;
ConsoleReadRequest -> io_Data = &ConsoleChar;
ConsoleReadRequest -> io_Length = 1;
ClrSignal(SIG_CONREAD);
SendIO(ConsoleReadRequest);
}
}
return(Result);
}
return(0);
}
/* dtr_out(byte flag):
*
* If flag == 0 -> drop DTR signal, else set it.
*/
VOID
dtr_out(byte flag)
{
if(!flag && !RendezvousData)
{
if(ThisBuffer -> IsBusy)
{
WaitIO(ThisBuffer -> SerialRequest);
ThisBuffer -> IsBusy = FALSE;
ThisBuffer -> SerialIndex = ThisBuffer -> SerialBuffer;
}
if(ReadBuffer -> IsBusy)
{
if(!CheckIO(ReadBuffer -> SerialRequest))
AbortIO(ReadBuffer -> SerialRequest);
WaitIO(ReadBuffer -> SerialRequest);
ReadBuffer -> IsBusy = FALSE;
ReadBuffer -> SerialFilled = ReadBuffer -> SerialRequest -> IOSer . io_Actual;
ReadBuffer -> SerialIndex = ReadBuffer -> SerialBuffer;
ReadBuffer -> SerialRequest -> IOSer . io_Command = SDCMD_QUERY;
DoIO(ReadBuffer -> SerialRequest);
if(ReadBuffer -> SerialRequest -> IOSer . io_Actual)
{
LONG Size = ReadBuffer -> SerialSize - ReadBuffer -> SerialFilled;
if(Size > 0)
{
if(Size > ReadBuffer -> SerialRequest -> IOSer . io_Actual)
Size = ReadBuffer -> SerialRequest -> IOSer . io_Actual;
ReadBuffer -> SerialRequest -> IOSer . io_Command = CMD_READ;
ReadBuffer -> SerialRequest -> IOSer . io_Data = ReadBuffer -> SerialBuffer + ReadBuffer -> SerialFilled;
ReadBuffer -> SerialRequest -> IOSer . io_Length = Size;
DoIO(ReadBuffer -> SerialRequest);
ReadBuffer -> SerialFilled += ReadBuffer -> SerialRequest -> IOSer . io_Actual;
}
}
}
CloseDevice(ReadBuffer -> SerialRequest);
TimeRequest -> tr_node . io_Command = TR_ADDREQUEST;
TimeRequest -> tr_time . tv_secs = 1;
TimeRequest -> tr_time . tv_micro = 0;
DoIO(TimeRequest);
if(OpenDevice(device,port,ReadBuffer -> SerialRequest,NULL))
{
CloseAll();
exit(10);
}
else
{
ReadBuffer -> SerialRequest -> io_Baud = ThisBuffer -> SerialRequest -> io_Baud;
ReadBuffer -> SerialRequest -> io_ReadLen = ThisBuffer -> SerialRequest -> io_ReadLen;
ReadBuffer -> SerialRequest -> io_WriteLen = ThisBuffer -> SerialRequest -> io_WriteLen;
ReadBuffer -> SerialRequest -> io_SerFlags = ThisBuffer -> SerialRequest -> io_SerFlags;
ReadBuffer -> SerialRequest -> IOSer . io_Command = SDCMD_SETPARAMS;
DoIO(ReadBuffer -> SerialRequest);
CopyMem(ReadBuffer -> SerialRequest,ThisBuffer -> SerialRequest,sizeof(struct IOExtSer));
ThisBuffer -> SerialRequest -> IOSer . io_Message . mn_ReplyPort = WritePort;
CopyMem(ReadBuffer -> SerialRequest,NextBuffer -> SerialRequest,sizeof(struct IOExtSer));
NextBuffer -> SerialRequest -> IOSer . io_Message . mn_ReplyPort = WritePort;
}
}
}
/* com_flow(byte flags):
*
* The bit mask `flags' determines the style(s) of
* handshaking:
*
* if (flags & 9) -> enable xON/xOFF software handshaking,
* if (flags & 2) -> enable RTS/CTS hardware handshaking
*/
VOID
com_flow(byte flags)
{
if(ThisBuffer -> IsBusy)
{
WaitIO(ThisBuffer -> SerialRequest);
ThisBuffer -> IsBusy = FALSE;
ThisBuffer -> SerialIndex = ThisBuffer -> SerialBuffer;
}
if(ReadBuffer -> IsBusy)
{
if(!CheckIO(ReadBuffer -> SerialRequest))
AbortIO(ReadBuffer -> SerialRequest);
WaitIO(ReadBuffer -> SerialRequest);
ReadBuffer -> IsBusy = FALSE;
ReadBuffer -> SerialFilled = ReadBuffer -> SerialRequest -> IOSer . io_Actual;
ReadBuffer -> SerialIndex = ReadBuffer -> SerialBuffer;
ReadBuffer -> SerialRequest -> IOSer . io_Command = SDCMD_QUERY;
DoIO(ReadBuffer -> SerialRequest);
if(ReadBuffer -> SerialRequest -> IOSer . io_Actual)
{
LONG Size = ReadBuffer -> SerialSize - ReadBuffer -> SerialFilled;
if(Size > 0)
{
if(Size > ReadBuffer -> SerialRequest -> IOSer . io_Actual)
Size = ReadBuffer -> SerialRequest -> IOSer . io_Actual;
ReadBuffer -> SerialRequest -> IOSer . io_Command = CMD_READ;
ReadBuffer -> SerialRequest -> IOSer . io_Data = ReadBuffer -> SerialBuffer + ReadBuffer -> SerialFilled;
ReadBuffer -> SerialRequest -> IOSer . io_Length = Size;
DoIO(ReadBuffer -> SerialRequest);
ReadBuffer -> SerialFilled += ReadBuffer -> SerialRequest -> IOSer . io_Actual;
}
}
}
if(flags & 2)
ReadBuffer -> SerialRequest -> io_SerFlags |= SERF_7WIRE;
else
ReadBuffer -> SerialRequest -> io_SerFlags &= ~SERF_7WIRE;
if(flags & 9)
ReadBuffer -> SerialRequest -> io_SerFlags &= ~SERF_XDISABLED;
else
ReadBuffer -> SerialRequest -> io_SerFlags |= SERF_XDISABLED;
ReadBuffer -> SerialRequest -> IOSer . io_Command = SDCMD_SETPARAMS;
DoIO(ReadBuffer -> SerialRequest);
ThisBuffer -> SerialRequest -> io_SerFlags = ReadBuffer -> SerialRequest -> io_SerFlags;
NextBuffer -> SerialRequest -> io_SerFlags = ReadBuffer -> SerialRequest -> io_SerFlags;
}
/* com_setspeed(word speed):
*
* Set the transfer speed (in bits/second).
*/
VOID
com_setspeed(word speed)
{
if(ThisBuffer -> IsBusy)
{
WaitIO(ThisBuffer -> SerialRequest);
ThisBuffer -> IsBusy = FALSE;
ThisBuffer -> SerialIndex = ThisBuffer -> SerialBuffer;
}
if(ReadBuffer -> IsBusy)
{
if(!CheckIO(ReadBuffer -> SerialRequest))
AbortIO(ReadBuffer -> SerialRequest);
WaitIO(ReadBuffer -> SerialRequest);
ReadBuffer -> IsBusy = FALSE;
ReadBuffer -> SerialFilled = ReadBuffer -> SerialRequest -> IOSer . io_Actual;
ReadBuffer -> SerialIndex = ReadBuffer -> SerialBuffer;
ReadBuffer -> SerialRequest -> IOSer . io_Command = SDCMD_QUERY;
DoIO(ReadBuffer -> SerialRequest);
if(ReadBuffer -> SerialRequest -> IOSer . io_Actual)
{
LONG Size = ReadBuffer -> SerialSize - ReadBuffer -> SerialFilled;
if(Size > 0)
{
if(Size > ReadBuffer -> SerialRequest -> IOSer . io_Actual)
Size = ReadBuffer -> SerialRequest -> IOSer . io_Actual;
ReadBuffer -> SerialRequest -> IOSer . io_Command = CMD_READ;
ReadBuffer -> SerialRequest -> IOSer . io_Data = ReadBuffer -> SerialBuffer + ReadBuffer -> SerialFilled;
ReadBuffer -> SerialRequest -> IOSer . io_Length = Size;
DoIO(ReadBuffer -> SerialRequest);
ReadBuffer -> SerialFilled += ReadBuffer -> SerialRequest -> IOSer . io_Actual;
}
}
}
ReadBuffer -> SerialRequest -> io_Baud = speed;
if(parity)
{
ReadBuffer -> SerialRequest -> io_ReadLen = ReadBuffer -> SerialRequest -> io_WriteLen = 7;
ReadBuffer -> SerialRequest -> io_SerFlags |= SERF_PARTY_ON;
}
else
{
ReadBuffer -> SerialRequest -> io_ReadLen = ReadBuffer -> SerialRequest -> io_WriteLen = 8;
ReadBuffer -> SerialRequest -> io_SerFlags &= ~SERF_PARTY_ON;
}
ReadBuffer -> SerialRequest -> IOSer . io_Command = SDCMD_SETPARAMS;
DoIO(ReadBuffer -> SerialRequest);
ThisBuffer -> SerialRequest -> io_Baud = ReadBuffer -> SerialRequest -> io_Baud;
ThisBuffer -> SerialRequest -> io_ReadLen = ReadBuffer -> SerialRequest -> io_ReadLen;
ThisBuffer -> SerialRequest -> io_WriteLen = ReadBuffer -> SerialRequest -> io_WriteLen;
ThisBuffer -> SerialRequest -> io_SerFlags = ReadBuffer -> SerialRequest -> io_SerFlags;
NextBuffer -> SerialRequest -> io_Baud = ReadBuffer -> SerialRequest -> io_Baud;
NextBuffer -> SerialRequest -> io_ReadLen = ReadBuffer -> SerialRequest -> io_ReadLen;
NextBuffer -> SerialRequest -> io_WriteLen = ReadBuffer -> SerialRequest -> io_WriteLen;
NextBuffer -> SerialRequest -> io_SerFlags = ReadBuffer -> SerialRequest -> io_SerFlags;
}
/* com_putblock(byte *s,word len):
*
* Send a data block asynchronously.
*/
VOID
com_putblock(byte *s,word len)
{
struct SerialBuffer *Swap = ThisBuffer;
if(ThisBuffer -> IsBusy)
WaitIO(ThisBuffer -> SerialRequest);
else
{
if(ThisBuffer -> SerialIndex > ThisBuffer -> SerialBuffer)
{
ThisBuffer -> SerialRequest -> IOSer . io_Command = CMD_WRITE;
ThisBuffer -> SerialRequest -> IOSer . io_Data = ThisBuffer -> SerialBuffer;
ThisBuffer -> SerialRequest -> IOSer . io_Length = ThisBuffer -> SerialIndex - ThisBuffer -> SerialBuffer;
DoIO(ThisBuffer -> SerialRequest);
}
}
ThisBuffer -> IsBusy = FALSE;
ThisBuffer -> SerialIndex = ThisBuffer -> SerialBuffer;
ThisBuffer = NextBuffer;
NextBuffer = Swap;
if(ThisBuffer -> SerialIndex > ThisBuffer -> SerialBuffer)
{
ThisBuffer -> SerialRequest -> IOSer . io_Command = CMD_WRITE;
ThisBuffer -> SerialRequest -> IOSer . io_Data = ThisBuffer -> SerialBuffer;
ThisBuffer -> SerialRequest -> IOSer . io_Length = ThisBuffer -> SerialIndex - ThisBuffer -> SerialBuffer;
DoIO(ThisBuffer -> SerialRequest);
}
ThisBuffer -> IsBusy = FALSE;
ThisBuffer -> SerialIndex = ThisBuffer -> SerialBuffer;
while(len > 2 * ThisBuffer -> SerialSize)
{
ThisBuffer -> SerialRequest -> IOSer . io_Command = CMD_WRITE;
ThisBuffer -> SerialRequest -> IOSer . io_Data = s;
ThisBuffer -> SerialRequest -> IOSer . io_Length = ThisBuffer -> SerialSize;
s += ThisBuffer -> SerialSize;
len -= ThisBuffer -> SerialSize;
DoIO(ThisBuffer -> SerialRequest);
}
CopyMem(s,ThisBuffer -> SerialBuffer,MIN(len,ThisBuffer -> SerialSize));
ThisBuffer -> IsBusy = TRUE;
ThisBuffer -> SerialIndex = ThisBuffer -> SerialBuffer + MIN(len,ThisBuffer -> SerialSize);
ThisBuffer -> SerialRequest -> IOSer . io_Command = CMD_WRITE;
ThisBuffer -> SerialRequest -> IOSer . io_Data = ThisBuffer -> SerialBuffer;
ThisBuffer -> SerialRequest -> IOSer . io_Length = MIN(len,ThisBuffer -> SerialSize);
len -= ThisBuffer -> SerialRequest -> IOSer . io_Length;
s += ThisBuffer -> SerialRequest -> IOSer . io_Length;
ClrSignal(SIG_SERWRITE);
SendIO(ThisBuffer -> SerialRequest);
if(len > 0)
{
CopyMem(s,NextBuffer -> SerialBuffer,len);
NextBuffer -> SerialIndex = NextBuffer -> SerialBuffer + len;
}
}
/* breakfunc():
*
* Cleanup routine for SAS/C.
*/
static int
breakfunc(void)
{
CloseAll();
return(1);
}
/* sys_init(VOID):
*
* Initialize this driver implementation.
*/
VOID
sys_init(VOID)
{
if(!OpenAll(device,port))
{
CloseAll();
endprog(2);
}
onbreak(breakfunc);
}
/* sys_reset(VOID):
*
* Perform cleanup for this driver implementation.
*/
VOID
sys_reset(VOID)
{
CloseAll();
}
/* sys_idle(VOID):
*
* This routine gets called when the system is idle.
* That's a nice one. We are supposed to call the
* system scheduler, etc.
*/
VOID
sys_idle(VOID)
{
ULONG Signals;
if(ReadBuffer -> SerialFilled <= 0 && !ReadBuffer -> IsBusy)
{
ReadBuffer -> IsBusy = TRUE;
ReadBuffer -> SerialIndex = ReadBuffer -> SerialBuffer;
ReadBuffer -> SerialRequest -> IOSer . io_Command = CMD_READ;
ReadBuffer -> SerialRequest -> IOSer . io_Data = ReadBuffer -> SerialBuffer;
ReadBuffer -> SerialRequest -> IOSer . io_Length = 1;
ClrSignal(SIG_SERREAD);
SendIO(ReadBuffer -> SerialRequest);
}
TimeRequest -> tr_node . io_Command = TR_ADDREQUEST;
TimeRequest -> tr_time . tv_secs = 1;
TimeRequest -> tr_time . tv_micro = 0;
ClrSignal(SIG_TIMER);
SendIO(TimeRequest);
Signals = Wait(SIG_SERREAD | SIG_SERWRITE | SIG_CONREAD | SIG_WINDOW | SIG_TIMER);
if(!(Signals & SIG_TIMER))
{
if(!CheckIO(TimeRequest))
AbortIO(TimeRequest);
}
WaitIO(TimeRequest);
if(Signals & SIG_SERREAD)
{
WaitIO(ReadBuffer -> SerialRequest);
ReadBuffer -> IsBusy = FALSE;
ReadBuffer -> SerialFilled = ReadBuffer -> SerialRequest -> IOSer . io_Actual;
ReadBuffer -> SerialIndex = ReadBuffer -> SerialBuffer;
ReadBuffer -> SerialRequest -> IOSer . io_Command = SDCMD_QUERY;
DoIO(ReadBuffer -> SerialRequest);
if(ReadBuffer -> SerialRequest -> IOSer . io_Actual)
{
LONG Size = ReadBuffer -> SerialSize - ReadBuffer -> SerialFilled;
if(Size > 0)
{
if(Size > ReadBuffer -> SerialRequest -> IOSer . io_Actual)
Size = ReadBuffer -> SerialRequest -> IOSer . io_Actual;
ReadBuffer -> SerialRequest -> IOSer . io_Command = CMD_READ;
ReadBuffer -> SerialRequest -> IOSer . io_Data = ReadBuffer -> SerialBuffer + ReadBuffer -> SerialFilled;
ReadBuffer -> SerialRequest -> IOSer . io_Length = Size;
DoIO(ReadBuffer -> SerialRequest);
ReadBuffer -> SerialFilled += ReadBuffer -> SerialRequest -> IOSer . io_Actual;
}
}
}
if(Signals & SIG_SERWRITE)
{
struct SerialBuffer *Swap = ThisBuffer;
WaitIO(ThisBuffer -> SerialRequest);
ThisBuffer -> IsBusy = FALSE;
ThisBuffer -> SerialIndex = ThisBuffer -> SerialBuffer;
ThisBuffer = NextBuffer;
NextBuffer = Swap;
}
if(Signals & SIG_CONREAD)
{
WaitIO(ConsoleReadRequest);
ConsoleReady = TRUE;
}
if(Signals & SIG_WINDOW)
WindowReady = TRUE;
}
/* com_outfull(VOID):
*
* Return number of bytes still to be transferred.
*/
int
com_outfull(VOID)
{
return(ThisBuffer -> SerialIndex - ThisBuffer -> SerialBuffer + NextBuffer -> SerialIndex - NextBuffer -> SerialBuffer);
}
/* carrier(VOID):
*
* Return current carrier status.
*/
int
carrier(VOID)
{
if(nocarrier)
return(1);
else
{
if(!ThisBuffer -> IsBusy)
{
ThisBuffer -> SerialRequest -> IOSer . io_Command = SDCMD_QUERY;
DoIO(ThisBuffer -> SerialRequest);
if(ThisBuffer -> SerialRequest -> io_Status & CIAF_COMCD)
return(0);
else
return(1);
}
else
{
NextBuffer -> SerialRequest -> IOSer . io_Command = SDCMD_QUERY;
DoIO(NextBuffer -> SerialRequest);
if(NextBuffer -> SerialRequest -> io_Status & CIAF_COMCD)
return(0);
else
return(1);
}
}
}
/* com_flush(VOID):
*
* Make sure all pending data gets written.
*/
VOID
com_flush(VOID)
{
if(ThisBuffer -> IsBusy)
{
WaitIO(ThisBuffer -> SerialRequest);
ThisBuffer -> IsBusy = FALSE;
ThisBuffer -> SerialIndex = ThisBuffer -> SerialBuffer;
}
if(NextBuffer -> SerialIndex > NextBuffer -> SerialBuffer)
{
NextBuffer -> SerialRequest -> IOSer . io_Command = CMD_WRITE;
NextBuffer -> SerialRequest -> IOSer . io_Data = NextBuffer -> SerialBuffer;
NextBuffer -> SerialRequest -> IOSer . io_Length = NextBuffer -> SerialIndex - NextBuffer -> SerialBuffer;
DoIO(NextBuffer -> SerialRequest);
NextBuffer -> SerialIndex = NextBuffer -> SerialBuffer;
}
}
/* com_putbyte(byte c):
*
* Transmit a single byte, queueing it if necessary.
*/
VOID
com_putbyte(byte c)
{
if(ThisBuffer -> IsBusy)
{
if(NextBuffer -> SerialIndex + 1 >= NextBuffer -> SerialTop)
{
struct SerialBuffer *Swap = ThisBuffer;
WaitIO(ThisBuffer -> SerialRequest);
ThisBuffer -> IsBusy = FALSE;
ThisBuffer -> SerialIndex = ThisBuffer -> SerialBuffer;
ThisBuffer = NextBuffer;
NextBuffer = Swap;
ThisBuffer -> IsBusy = TRUE;
ThisBuffer -> SerialRequest -> IOSer . io_Command = CMD_WRITE;
ThisBuffer -> SerialRequest -> IOSer . io_Data = ThisBuffer -> SerialBuffer;
ThisBuffer -> SerialRequest -> IOSer . io_Length = ThisBuffer -> SerialIndex - ThisBuffer -> SerialBuffer;
ClrSignal(SIG_SERWRITE);
SendIO(ThisBuffer -> SerialRequest);
}
*NextBuffer -> SerialIndex++ = c;
}
else
{
if(ThisBuffer -> SerialIndex + 1 < ThisBuffer -> SerialTop)
{
*ThisBuffer -> SerialIndex++ = c;
ThisBuffer -> IsBusy = TRUE;
ThisBuffer -> SerialRequest -> IOSer . io_Command = CMD_WRITE;
ThisBuffer -> SerialRequest -> IOSer . io_Data = ThisBuffer -> SerialBuffer;
ThisBuffer -> SerialRequest -> IOSer . io_Length = 1;
ClrSignal(SIG_SERWRITE);
SendIO(ThisBuffer -> SerialRequest);
}
else
{
ThisBuffer -> IsBusy = TRUE;
ThisBuffer -> SerialRequest -> IOSer . io_Command = CMD_WRITE;
ThisBuffer -> SerialRequest -> IOSer . io_Data = ThisBuffer -> SerialBuffer;
ThisBuffer -> SerialRequest -> IOSer . io_Length = ThisBuffer -> SerialIndex - ThisBuffer -> SerialBuffer;
ClrSignal(SIG_SERWRITE);
SendIO(ThisBuffer -> SerialRequest);
*NextBuffer -> SerialIndex++ = c;
}
}
}
/* com_purge(VOID):
*
* Clear the read/write buffers.
*/
VOID
com_purge(VOID)
{
if(ThisBuffer -> IsBusy)
{
if(!CheckIO(ThisBuffer -> SerialRequest))
AbortIO(ThisBuffer -> SerialRequest);
WaitIO(ThisBuffer -> SerialRequest);
}
ThisBuffer -> IsBusy = FALSE;
ThisBuffer -> SerialIndex = ThisBuffer -> SerialBuffer;
NextBuffer -> IsBusy = FALSE;
NextBuffer -> SerialIndex = NextBuffer -> SerialBuffer;
if(ReadBuffer -> IsBusy)
{
if(!CheckIO(ReadBuffer -> SerialRequest))
AbortIO(ReadBuffer -> SerialRequest);
WaitIO(ReadBuffer -> SerialRequest);
}
ReadBuffer -> IsBusy = FALSE;
ReadBuffer -> SerialIndex = ReadBuffer -> SerialBuffer;
ReadBuffer -> SerialFilled = 0;
ThisBuffer -> SerialRequest -> IOSer . io_Command = CMD_CLEAR;
DoIO(ThisBuffer -> SerialRequest);
}
/* com_dump(VOID):
*
* Wait for asynchronous write request to terminate.
*/
VOID
com_dump(VOID)
{
com_flush();
}
/* com_getbyte(VOID):
*
* Read a single byte from the serial line. If not available,
* return EOF.
*/
int
com_getbyte(VOID)
{
int Result;
if(ReadBuffer -> SerialFilled <= 0)
{
if(ReadBuffer -> IsBusy)
{
if(!CheckIO(ReadBuffer -> SerialRequest))
return(EOF);
else
WaitIO(ReadBuffer -> SerialRequest);
ReadBuffer -> IsBusy = FALSE;
ReadBuffer -> SerialFilled = ReadBuffer -> SerialRequest -> IOSer . io_Actual;
ReadBuffer -> SerialIndex = ReadBuffer -> SerialBuffer;
ReadBuffer -> SerialRequest -> IOSer . io_Command = SDCMD_QUERY;
DoIO(ReadBuffer -> SerialRequest);
if(ReadBuffer -> SerialRequest -> IOSer . io_Actual)
{
LONG Size = ReadBuffer -> SerialSize - ReadBuffer -> SerialFilled;
if(Size > 0)
{
if(Size > ReadBuffer -> SerialRequest -> IOSer . io_Actual)
Size = ReadBuffer -> SerialRequest -> IOSer . io_Actual;
ReadBuffer -> SerialRequest -> IOSer . io_Command = CMD_READ;
ReadBuffer -> SerialRequest -> IOSer . io_Data = ReadBuffer -> SerialBuffer + ReadBuffer -> SerialFilled;
ReadBuffer -> SerialRequest -> IOSer . io_Length = Size;
DoIO(ReadBuffer -> SerialRequest);
ReadBuffer -> SerialFilled += ReadBuffer -> SerialRequest -> IOSer . io_Actual;
}
}
}
else
{
ReadBuffer -> SerialRequest -> IOSer . io_Command = SDCMD_QUERY;
DoIO(ReadBuffer -> SerialRequest);
if(!ReadBuffer -> SerialRequest -> IOSer . io_Actual)
return(EOF);
else
{
ReadBuffer -> SerialRequest -> IOSer . io_Command = CMD_READ;
ReadBuffer -> SerialRequest -> IOSer . io_Data = ReadBuffer -> SerialBuffer;
ReadBuffer -> SerialRequest -> IOSer . io_Length = MIN(ReadBuffer -> SerialRequest -> IOSer . io_Actual,ReadBuffer -> SerialSize);
DoIO(ReadBuffer -> SerialRequest);
if(!ReadBuffer -> SerialRequest -> IOSer . io_Actual)
return(EOF);
else
{
ReadBuffer -> SerialFilled = ReadBuffer -> SerialRequest -> IOSer . io_Actual;
ReadBuffer -> SerialIndex = ReadBuffer -> SerialBuffer;
}
}
}
}
Result = *ReadBuffer -> SerialIndex++;
ReadBuffer -> SerialFilled--;
if(ReadBuffer -> SerialFilled <= 0)
{
ReadBuffer -> IsBusy = TRUE;
ReadBuffer -> SerialIndex = ReadBuffer -> SerialBuffer;
ReadBuffer -> SerialRequest -> IOSer . io_Command = CMD_READ;
ReadBuffer -> SerialRequest -> IOSer . io_Data = ReadBuffer -> SerialBuffer;
ReadBuffer -> SerialRequest -> IOSer . io_Length = 1;
ClrSignal(SIG_SERREAD);
SendIO(ReadBuffer -> SerialRequest);
}
return(Result);
}
/* setstamp(STRPTR Name,LONG Time):
*
* Set time/date of a file.
*/
VOID
setstamp(char *Name,long Time)
{
struct DateStamp Date;
ULONG Seconds;
DB(kprintf("setstamp |%s| %ld\n",Name,Time));
/* Translate it into an Amiga date. */
if(Time > GMT_Offset)
Seconds = Time - GMT_Offset;
else
Seconds = 0;
Date . ds_Days = Seconds / (24 * 60 * 60);
Date . ds_Minute = (Seconds % (24 * 60 * 60)) / 60;
Date . ds_Tick = (Seconds % 60) * TICKS_PER_SECOND;
SetFileDate(Name,&Date);
}
/* freespace(STRPTR DrivePath):
*
* Get free disk space for specified drive.
*/
long
freespace(char *DrivePath)
{
struct DevProc *DevProc = GetDeviceProc(DrivePath,NULL);
struct DosList *DosList;
BOOL GoodDevice = FALSE;
LONG Size = (LONG)((ULONG)~0 >> 2);
if(!DrivePath)
DrivePath = "";
DB(kprintf("freespace |%s|\n",DrivePath));
if(DosList = LockDosList(LDF_DEVICES | LDF_READ))
{
while(DosList = NextDosEntry(DosList,LDF_DEVICES))
{
if(DosList -> dol_Task == DevProc -> dvp_Port)
{
struct FileSysStartupMsg *FSSM = (struct FileSysStartupMsg *)BADDR(DosList -> dol_misc . dol_handler . dol_Startup);
if(TypeOfMem(FSSM))
{
struct DosEnvec *DosEnvec = (struct DosEnvec *)BADDR(FSSM -> fssm_Environ);
STRPTR Name = (STRPTR)BADDR(FSSM -> fssm_Device);
if(TypeOfMem(DosEnvec) && TypeOfMem(Name))
{
if(Name[0] > 0 && !Name[(WORD)Name[0] + 1])
{
struct IOStdReq __aligned IORequest;
if(!OpenDevice(Name + 1,FSSM -> fssm_Unit,&IORequest,FSSM -> fssm_Unit))
{
CloseDevice(&IORequest);
if(DosEnvec -> de_TableSize > 0 && DosEnvec -> de_LowCyl <= DosEnvec -> de_HighCyl)
GoodDevice = TRUE;
}
}
}
}
}
}
UnLockDosList(LDF_DEVICES | LDF_READ);
}
FreeDeviceProc(DevProc);
if(GoodDevice)
{
struct InfoData *InfoData;
if(InfoData = (struct InfoData *)AllocVec(sizeof(struct InfoData),MEMF_ANY | MEMF_PUBLIC))
{
UBYTE NewName[256],*Index;
BPTR FileLock;
memcpy(NewName,DrivePath,255);
NewName[255] = 0;
Index = PathPart(NewName);
*Index = 0;
FileLock = Lock(NewName,ACCESS_READ);
if(FileLock)
{
if(Info(FileLock,InfoData))
Size = InfoData -> id_BytesPerBlock * (InfoData -> id_NumBlocks - InfoData -> id_NumBlocksUsed);
UnLock(FileLock);
}
FreeVec(InfoData);
}
}
return(Size);
}
/* ffirst(char *FileSpec):
*
* Return name of first file matching the given specs.
*/
char *
ffirst(char *filespec)
{
AnchorUsed = TRUE;
DB(kprintf("ffirst |%s|\n",filespec));
if(MatchFirst(filespec,Anchor))
return(NULL);
else
return((char *)Anchor -> ap_Buf);
}
/* fnext(VOID):
*
* Return name of next file matching the given specs.
*/
char *
fnext(VOID)
{
AnchorUsed = TRUE;
DB(kprintf("fnext\n"));
if(MatchNext(Anchor))
return(NULL);
else
return((char *)Anchor -> ap_Buf);
}
/* time(time_t *timeptr):
*
* Get the current time.
*/
time_t
time(time_t *timeptr)
{
struct timeval Now;
time_t CurrentTime;
DB(kprintf("time 0x%08lx\n",timeptr));
/* If the timer is already available,
* just read the time. Otherwise, open what
* we need to tell the time.
*/
if(TimerBase)
GetSysTime(&Now);
else
UpdateTime(&Now);
/* Determine the current time, taking the time
* zone into account.
*/
CurrentTime = (time_t)(Now . tv_secs + GMT_Offset);
if(timeptr)
*timeptr = CurrentTime;
return(CurrentTime);
}
/* localtime(const time_t *t):
*
* Convert UTC into local time.
*/
struct tm *
localtime(const time_t *t)
{
STATIC struct tm Time;
ULONG Seconds,
Delta;
struct ClockData ClockData;
BOOL CloseIt = FALSE;
DB(kprintf("localtime 0x%08lx\n",t));
/* We need utility.library for the date conversion. */
if(!UtilityBase)
{
if(UtilityBase = OpenLibrary("utility.library",37))
CloseIt = TRUE;
}
/* Any luck? */
if(!UtilityBase)
{
memset(&Time,0,sizeof(struct tm));
return(&Time);
}
/* Update the time data. */
if(!TimerBase)
UpdateTime(NULL);
/* Add the offset. */
if(*t < GMT_Offset)
Seconds = 0;
else
Seconds = (ULONG)*t - GMT_Offset;
/* Convert the seconds into time data. */
Amiga2Date(Seconds,&ClockData);
/* Convert the time data. */
Time . tm_sec = ClockData . sec;
Time . tm_min = ClockData . min;
Time . tm_hour = ClockData . hour;
Time . tm_mday = ClockData . mday;
Time . tm_mon = ClockData . month - 1;
Time . tm_year = ClockData . year - 1900;
Time . tm_wday = ClockData . wday;
/* No daylight savings time info is provided. */
Time . tm_isdst = 0;
/* We will need to fill in the yday entry. */
ClockData . mday = 1;
ClockData . month = 1;
Delta = Date2Amiga(&ClockData);
Time . tm_yday = (Seconds - Delta) / (24 * 60 * 60) + 1;
/* Clean up if necessary. */
if(CloseIt)
{
CloseLibrary(UtilityBase);
UtilityBase = NULL;
}
return(&Time);
}
/* stat(const char *file,struct stat *st):
*
* Get information on a file.
*/
int
stat(const char *file,struct stat *st)
{
BPTR FileLock;
DB(kprintf("stat |%s| 0%08lx\n",file,st));
/* Try to get a lock on the file. */
if(FileLock = Lock((STRPTR)file,ACCESS_READ))
{
STATIC char Volume[256],
Comment[80];
struct FileInfoBlock __aligned FileInfo;
struct InfoData __aligned InfoData;
/* Get information on file and filing system. */
if(Examine(FileLock,&FileInfo) && Info(FileLock,&InfoData))
{
unsigned short mode = 0;
/* Try to get the name of the volume. */
if(!NameFromLock(FileLock,Volume,256))
Volume[0] = 0;
else
{
WORD i;
/* Chop off everything after the colon. */
for(i = 0 ; i < 256 ; i++)
{
if(Volume[i] == ':')
{
Volume[i + 1] = 0;
break;
}
}
}
UnLock(FileLock);
/* Build the protection bits. */
if(!(FileInfo . fib_Protection & FIBF_EXECUTE))
mode |= S_IEXECUTE;
if(!(FileInfo . fib_Protection & FIBF_DELETE))
mode |= S_IDELETE;
if(!(FileInfo . fib_Protection & FIBF_READ))
mode |= S_IREAD;
if(!(FileInfo . fib_Protection & FIBF_WRITE))
mode |= S_IWRITE;
if(!(FileInfo . fib_Protection & FIBF_ARCHIVE))
mode |= S_IARCHIVE;
if(FileInfo . fib_Protection & FIBF_PURE)
mode |= S_IPURE;
if(FileInfo . fib_Protection & FIBF_SCRIPT)
mode |= S_ISCRIPT;
/* Keep the comment. */
strcpy(Comment,FileInfo . fib_Comment);
/* Fix the time if necessary. */
if(!TimerBase)
UpdateTime(NULL);
/* Fill in the data. */
st -> st_mode = mode;
st -> st_ino = FileInfo . fib_DiskKey;
st -> st_dev = InfoData . id_DiskType;
st -> st_rdev = Volume;
st -> st_nlink = FileInfo . fib_DirEntryType == ST_SOFTLINK || FileInfo . fib_DirEntryType == ST_LINKDIR || FileInfo . fib_DirEntryType == ST_LINKFILE;
st -> st_uid = FileInfo . fib_OwnerUID;
st -> st_gid = FileInfo . fib_OwnerGID;
st -> st_size = FileInfo . fib_Size;
st -> st_atime = GMT_Offset + (FileInfo . fib_Date . ds_Days * 24 * 60 + FileInfo . fib_Date . ds_Minute) * 60 + FileInfo . fib_Date . ds_Tick / TICKS_PER_SECOND;
st -> st_mtime = st -> st_atime;
st -> st_ctime = st -> st_atime;
st -> st_type = FileInfo . fib_DirEntryType;
st -> st_comment= Comment;
/* Success. */
return(0);
}
UnLock(FileLock);
}
/* What else should I choose? */
errno = _OSERR = EIO;
return(-1);
}