/* * REMCLI.C * * REMCLI * * 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. */ #include #include #include #include #include #include #include #include #include #include #include #include "fifo.h" 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; extern void *CreatePort(); extern void *AllocMem(); extern void *OpenFifo(); Ioc Iocr; Ioc Iocw; Message RMsg; Message WMsg; Window *Win; char *FifoName; /* fifo */ char *FifoSlav; /* fifo_s */ char *FifoMast; /* fifo_m */ MsgPort *IoSink; char ConBuf[32]; void *FifoR; void *FifoW; long FifoBase; long IntuitionBase; char IocrIP; /* console read pending*/ char IocrHold; char FifrIP; /* read msg pending */ char FifwIP; /* write msg pending */ 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 }; extern Window *OpenWindow(); void ConWriteStr(char *); void ConWrite(void *, long); void SendBreak(int); void myexit(); void WaitMsg(Message *); int brk(); main(ac, av) char **av; { long imask; long pmask; short notDone = 1; if (ac == 1) { fprintf(stderr, "Demonstration Remote Shell through FIFO:\n"); fprintf(stderr, "Instructions:\n"); fprintf(stderr, " 1> NewShell FIFO:name/rwkecs\n"); fprintf(stderr, " 1> RemCLI name\n"); exit(1); } atexit(myexit); onbreak(brk); FifoName = av[1]; FifoSlav = malloc(strlen(FifoName) + 16); FifoMast = malloc(strlen(FifoName) + 16); sprintf(FifoMast, "%s_m", FifoName); sprintf(FifoSlav, "%s_s", FifoName); IoSink = CreatePort(NULL, 0); /* * FIFOS */ FifoBase = OpenLibrary(FIFONAME, 0); if (!FifoBase) { fprintf(stderr, "unable to open %s\n", FIFONAME); exit(1); } FifoW = OpenFifo(FifoMast, 2048, FIFOF_WRITE | FIFOF_NORMAL | FIFOF_NBIO); if (FifoW == NULL) { fprintf(stderr, "unable to open fifo %s\n", FifoMast); exit(1); } FifoR = OpenFifo(FifoSlav, 2048, FIFOF_READ | FIFOF_NORMAL | FIFOF_NBIO); if (FifoR == NULL) { fprintf(stderr, "unable to open fifo %s\n", FifoSlav); exit(1); } RMsg.mn_ReplyPort = IoSink; WMsg.mn_ReplyPort = IoSink; /* * WINDOW */ IntuitionBase = OpenLibrary("intuition.library", 0); if (!IntuitionBase) { fprintf(stderr, "unable to open intuition.library\n"); exit(1); } Win = OpenWindow(&Nw); if (Win == NULL) { fprintf(stderr, "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, &Iocw, 0)) { fprintf(stderr, "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(&Iocr); IocrIP = 1; /* * start async FIFO requests */ RequestFifo(FifoR, &RMsg, FREQ_RPEND); FifrIP = 1; /* * start shell for slave side */ while (notDone) { long mask = Wait(imask | pmask); top: if (mask & imask) { IMess *im; while (im = (IMess *)GetMsg(Win->UserPort)) { switch(im->Class) { case CLOSEWINDOW: notDone = 0; mask = 0; break; case NEWSIZE: ConWriteStr("\017\233\164\233\165\233\166\233\167"); break; } ReplyMsg(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(&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"); notDone = 0; } 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() { if (IocrIP) { AbortIO(&Iocr); WaitIO(&Iocr); } if (Iocr.io_Device) CloseDevice(&Iocr); if (FifrIP) { RequestFifo(FifoR, &RMsg, FREQ_ABORT); WaitMsg(&RMsg); } if (FifwIP) { RequestFifo(FifoW, &WMsg, FREQ_ABORT); WaitMsg(&RMsg); } if (FifoR) CloseFifo(FifoR); if (FifoW) CloseFifo(FifoW); if (FifoBase) CloseLibrary(FifoBase); if (IntuitionBase) CloseLibrary(IntuitionBase); if (Win) CloseWindow(Win); if (IoSink) DeletePort(IoSink); } void ConWriteStr(buf) char *buf; { ConWrite(buf, strlen(buf)); } void ConWrite(buf, len) void *buf; { Iocw.io_Data = (APTR)buf; Iocw.io_Length = len; DoIO(&Iocw); } int brk() { return(0); } void WaitMsg(msg) 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(c) int c; { char buf[256]; long fh; sprintf(buf, "FIFO:%s/%c", FifoName, c); if (fh = Open(buf, 1005)) Close(fh); }