home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Geek Gadgets 1
/
ADE-1.bin
/
ade-dist
/
fifolib-38.3-src.tgz
/
tar.out
/
contrib
/
fifolib
/
remcli.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-09-28
|
8KB
|
388 lines
/*
* REMCLI.C
*
* REMCLI <fifo_name>
*
* PUBLIC DOMAIN CODE, sample code showing how to set up a remote CLI
* through the FIFO: device, using fifo.library to handle the master
* end.
*
* WARNING: ReadFifo() returns an EOF condition (-1) only once,
* calling it again will return 0 .. blocking until a
* writer writes something then closes again to generate
* another EOF.
* Huh? Clearing FIFOF_EOF is commented out in fifo.c so
* that EOF is reported every time. See TODO (Jörg Höhle)
*/
#include <exec/types.h>
#include <exec/io.h>
#include <exec/memory.h>
#include <devices/conunit.h>
#include <intuition/intuition.h>
#include <libraries/dos.h>
#include <libraries/fifo.h>
#if defined(_DCC) /* at least the very old DICE 2.06 */
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/intuition_protos.h>
#else
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#endif
#include <clib/alib_protos.h>
#include <proto/fifo.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h> /* write() */
#if defined(__GNUC__)
#include <unistd.h> /* write() */
#endif
#ifdef USE_SIGNAL
#include <signal.h>
#endif
typedef unsigned char ubyte;
typedef unsigned short uword;
typedef unsigned long ulong;
typedef struct MsgPort MsgPort;
typedef struct Task Task;
typedef struct Process Process;
typedef struct Window Window;
typedef struct IOStdReq Ioc;
typedef struct Message Message;
typedef struct IntuiMessage IMess;
typedef struct IORequest IORequest;
Ioc Iocr;
Ioc Iocw;
Message RMsg;
Message WMsg;
Window *Win;
char *FifoName; /* fifo */
char *FifoSlav; /* fifo_s */
char *FifoMast; /* fifo_m */
char *ErrBuf;
MsgPort *IoSink;
char ConBuf[32];
void *FifoR;
void *FifoW;
struct Library *FifoBase;
struct IntuitionBase *IntuitionBase;
char IocrIP; /* console read pending*/
char IocrHold;
char FifrIP; /* read msg pending */
char FifwIP; /* write msg pending */
short Done = 0;
struct NewWindow Nw = {
0, 0, 640, 200, -1, -1,
CLOSEWINDOW|MENUPICK|GADGETUP|GADGETDOWN|NEWSIZE,
WINDOWSIZING|WINDOWDRAG|WINDOWDEPTH|WINDOWCLOSE|SMART_REFRESH|
NOCAREREFRESH|ACTIVATE,
NULL, NULL, (ubyte *)"RemCLI", NULL, NULL, 32, 32, -1, -1, WBENCHSCREEN
};
const char verstring[] = "\0$VER: RemCLI 38.1 (20.12.95)\r\n";
#define errline(s,len) write(2, s, len)
#define errmsg(s) errline(s, sizeof(s)-1)
#define errmsg1(s,v) {int errlen = sprintf(ErrBuf, s, v); errline(ErrBuf, errlen);}
void ConWriteStr(char *);
void ConWrite(void *, long);
void SendBreak(int);
void myexit(void);
void WaitMsg(Message *);
#ifndef USE_SIGNAL
#ifdef _DCC
int brk(void);
#endif
#if defined(__GNUC__) /* actually libnix only */
void __chkabort(void);
#endif
#endif
int main(int ac, char **av)
{
long imask;
long pmask;
if (ac != 2) {
errmsg("Demonstration Remote Shell through FIFO:\n");
errmsg("Instructions:\n");
errmsg(" 1> NewShell FIFO:name/rwkecs\n");
errmsg(" 1> Run >NIL: RemCLI name\n");
exit(1);
}
atexit(myexit);
#ifndef USE_SIGNAL
#ifdef _DCC
onbreak(brk); /* onbreak() generates shorter code than signal() */
#endif
#else
signal(SIGINT, SIG_IGN);
#endif
FifoName = av[1];
{
int len = strlen(FifoName);
FifoSlav = malloc(len + (len<<1) + (3 + 3 + 35));
FifoMast = FifoSlav + len + 3;
ErrBuf = FifoMast + len + 3;
}
sprintf(FifoMast, "%s_m", FifoName);
sprintf(FifoSlav, "%s_s", FifoName);
IoSink = CreatePort(NULL, 0);
/*
* FIFOS
*/
FifoBase = OpenLibrary(FIFONAME, 0);
if (!FifoBase) {
errmsg1("unable to open %s\n", FIFONAME);
exit(1);
}
FifoW = OpenFifo(FifoMast, 2048, FIFOF_WRITE | FIFOF_NORMAL | FIFOF_NBIO);
if (FifoW == NULL) {
errmsg1("unable to open fifo %s\n", FifoMast);
exit(1);
}
FifoR = OpenFifo(FifoSlav, 2048, FIFOF_READ | FIFOF_NORMAL | FIFOF_NBIO);
if (FifoR == NULL) {
errmsg1("unable to open fifo %s\n", FifoSlav);
exit(1);
}
RMsg.mn_ReplyPort = IoSink;
WMsg.mn_ReplyPort = IoSink;
/*
* WINDOW
*/
IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 0);
if (!IntuitionBase) {
errmsg("unable to open intuition.library\n");
exit(1);
}
Win = OpenWindow(&Nw);
if (Win == NULL) {
errmsg("unable to open window!\n");
exit(1);
}
imask = 1 << Win->UserPort->mp_SigBit;
pmask = 1 << IoSink->mp_SigBit;
/*
* CONSOLE DEVICE
*/
Iocw.io_Message.mn_ReplyPort = IoSink;
Iocw.io_Data = (APTR)Win;
Iocw.io_Length = sizeof(*Win);
if (OpenDevice("console.device", 0, (IORequest *)&Iocw, 0)) {
errmsg("can't open console!\n");
exit(1);
}
Iocr = Iocw;
Iocw.io_Command = CMD_WRITE;
Iocr.io_Command = CMD_READ;
Iocr.io_Data = (APTR)ConBuf;
Iocr.io_Length = 1;
SendIO((IORequest *)&Iocr);
IocrIP = 1;
/*
* start async FIFO requests
*/
RequestFifo(FifoR, &RMsg, FREQ_RPEND);
FifrIP = 1;
/*
* start shell for slave side
*/
while (!Done) {
long mask = Wait(imask | pmask);
top:
if (mask & imask) {
IMess *im;
while ((im = (IMess *)GetMsg(Win->UserPort))) {
switch(im->Class) {
case CLOSEWINDOW:
Done = 2;
mask = 0;
break;
case NEWSIZE:
ConWriteStr("\017\233\164\233\165\233\166\233\167");
break;
}
ReplyMsg((Message *)im);
}
}
if (mask & pmask) {
Message *msg;
int n;
while ((msg = (Message *)GetMsg(IoSink))) {
if (msg == (Message *)&Iocr) {
IocrIP = 0;
if (Iocr.io_Actual > 0) {
switch(*(char *)Iocr.io_Data) {
case 3:
SendBreak('C');
break;
case 4:
SendBreak('D');
break;
case 5:
SendBreak('E');
break;
case 6:
SendBreak('F');
break;
default:
n = WriteFifo(FifoW, Iocr.io_Data, Iocr.io_Actual);
if (n != Iocr.io_Actual) {
IocrHold = 1;
if (FifwIP == 0) {
RequestFifo(FifoW, &WMsg, FREQ_WAVAIL);
FifwIP = 1;
}
}
break;
}
}
if (IocrHold == 0) {
Iocr.io_Data = (APTR)ConBuf;
Iocr.io_Length = 1;
SendIO((IORequest *)&Iocr);
IocrIP = 1;
}
} else
if (msg == (Message *)&RMsg) {
char *ptr;
long n;
FifrIP = 0;
if ((n = ReadFifo(FifoR, &ptr, 0)) > 0) {
if (n > 256) /* limit size */
n = 256;
ConWrite(ptr, n);
/* clear N bytes */
n = ReadFifo(FifoR, &ptr, n);
}
if (n < 0) { /* EOF */
ConWriteStr("REMOTE EOF!\n");
Done = 1;
} else {
RequestFifo(FifoR, &RMsg, FREQ_RPEND);
FifrIP = 1;
}
} else
if (msg == (Message *)&WMsg) {
FifwIP = 0;
if (IocrHold) { /* retry rd process */
ReplyMsg(&Iocr.io_Message);
IocrHold = 0;
}
}
goto top;
}
}
}
}
void myexit(void)
{
if (IocrIP) {
AbortIO((IORequest *)&Iocr);
WaitIO((IORequest *)&Iocr);
}
if (Iocr.io_Device)
CloseDevice((IORequest *)&Iocr);
if (FifrIP) {
RequestFifo(FifoR, &RMsg, FREQ_ABORT);
WaitMsg(&RMsg);
}
if (FifwIP) {
RequestFifo(FifoW, &WMsg, FREQ_ABORT);
WaitMsg(&WMsg);
}
if (FifoR)
CloseFifo(FifoR, FIFOF_EOF);
if (FifoW)
/* no FIFOF_EOF on CLOSEWINDOW to conform to documentation */
CloseFifo(FifoW, Done == 2 ? 0 : FIFOF_EOF);
if (FifoBase)
CloseLibrary(FifoBase);
if (IntuitionBase)
CloseLibrary((struct Library *)IntuitionBase);
if (Win)
CloseWindow(Win);
if (IoSink)
DeletePort(IoSink);
}
void ConWriteStr(char *buf)
{
ConWrite(buf, strlen(buf));
}
void ConWrite(void *buf, long len)
{
Iocw.io_Data = (APTR)buf;
Iocw.io_Length = len;
DoIO((IORequest *)&Iocw);
}
#ifndef USE_SIGNAL
#ifdef _DCC
int brk(void)
{
return(0); /* ignore ^C */
}
#endif
#if defined(__GNUC__) /* libnix internal function */
void __chkabort(void)
{
}
#endif
#endif
void WaitMsg(Message *msg)
{
while (msg->mn_Node.ln_Type == NT_MESSAGE)
Wait(1 << msg->mn_ReplyPort->mp_SigBit);
Forbid();
Remove(&msg->mn_Node);
Permit();
}
void SendBreak(int c)
{
char buf[256];
long fh;
sprintf(buf, "FIFO:%s/%c", FifoName, c);
if ((fh = Open(buf, 1005)))
Close(fh);
}