/* * S_TERM.C * * DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved. * * Terminal window server. * -Echo what is received in the window. * -Transmit stuff typed on keyboard, echoing locally. * * Use FTERM on the other Amiga to connect. * * NOTE!!!! Spawned tasks are ... TASKS, not processes. No DOS calls * allowed. */ #include #include #include "servers.h" #include #include "/dnet/channel.h" int Enable_Abort; int NHandlers; long IntuitionBase; long GfxBase; extern PORT *DListen(); extern PORT *DAccept(); PORT *HdPort; PORT *LisPort; short HandShakeSig; _main() { struct Message *msg; long mask, pmask, hdmask; PROC *proc = FindTask(NULL); Enable_Abort = 0; if (proc->pr_CLI) { Version("STerm", VERSION, STERM_VERSION); _exit(0); } LisPort= DListen(PORT_IALPHATERM); WaitPort(&proc->pr_MsgPort); ReplyMsg(GetMsg(&proc->pr_MsgPort)); if (!LisPort) exit(1); HdPort = CreatePort(NULL, 0); HandShakeSig = AllocSignal(-1); pmask = 1 << LisPort->mp_SigBit; hdmask= 1 << HdPort->mp_SigBit; IntuitionBase = (long)OpenLibrary("intuition.library", 0); GfxBase = (long)OpenLibrary("graphics.library", 0); while (mask = Wait(SIGBREAKF_CTRL_C|pmask|hdmask)) { if (mask & SIGBREAKF_CTRL_C) break; if (mask & hdmask) { while (msg = GetMsg(HdPort)) { --NHandlers; FreeMem(msg, sizeof(*msg)); } } if (mask & pmask) { while (spawn_handler()) ; } } DUnListen(LisPort); while (NHandlers) { WaitPort(HdPort); msg = GetMsg(HdPort); FreeMem(msg, sizeof(*msg)); --NHandlers; } DeletePort(HdPort); CloseLibrary(IntuitionBase); CloseLibrary(GfxBase); } /* * Spawn a handler to accept the new connection, if any. Task sends * a message to HdPort when through. */ spawn_handler() { extern void term_task(); long oldhan = NHandlers; CreateTask("Term.channel", 0, term_task, 2048); Wait(1 << HandShakeSig); return (oldhan != NHandlers); } static NW Nw = { 64, 64, 400, 100, -1, -1, CLOSEWINDOW|NEWSIZE, WINDOWSIZING|WINDOWDRAG|WINDOWDEPTH|WINDOWCLOSE|ACTIVATE|NOCAREREFRESH, NULL, NULL, (unsigned char *)"DNET-Term", NULL, NULL, 32, 32, -1, -1, WBENCHSCREEN }; void term_task() { PORT *chan; /* actually only the front end is a msgport */ long imask, cmask, conmask; struct Window *win; char notdone = 1; short ignorens = 0; char conc[4]; IOCON iocw; IOCON iocr; geta4(); chan = (PORT *)DAccept(LisPort); if (chan) { DQueue(chan, 32); DIoctl(chan, CIO_MODE, 7, 0); ++NHandlers; Signal(HdPort->mp_SigTask, 1 << HandShakeSig); if (win = OpenWindow(&Nw)) { iocw.io_Command = CMD_WRITE; iocw.io_Data = (APTR)win; iocw.io_Message.mn_Node.ln_Type = NT_MESSAGE; iocw.io_Message.mn_ReplyPort = CreatePort(NULL,0); conmask = 1 << iocw.io_Message.mn_ReplyPort->mp_SigBit; OpenDevice("console.device", 0, &iocw, 0); iocr = iocw; iocr.io_Command = CMD_READ; imask = 1 << win->UserPort->mp_SigBit; cmask = 1 << chan->mp_SigBit; iocr.io_Data = (APTR)conc; iocr.io_Length = sizeof(conc); SendIO(&iocr); setsize(&iocw, NULL, win); while (notdone) { long mask; mask = Wait(imask|cmask|conmask); if (mask & imask) { register IMESS *im; while (im = (IMESS *)GetMsg(win->UserPort)) { switch(im->Class) { case CLOSEWINDOW: notdone = 0; break; case NEWSIZE: if (ignorens) { --ignorens; setsize(&iocw, NULL, win); } else { setsize(&iocw, chan, win); } break; } ReplyMsg(im); } } if ((mask & conmask) && CheckIO(&iocr)) { register short i; register char *ptr; WaitIO(&iocr); ptr = (char *)iocr.io_Data; if (iocr.io_Actual > 0) { for (i = 0; i < iocr.io_Actual; ++i) { if (ptr[i] == 13) ptr[i] = 10; } DWrite(chan, ptr, i); iocw.io_Data = (APTR)ptr; iocw.io_Length = i; DoIO(&iocw); } iocr.io_Data = (APTR)conc; iocr.io_Length = sizeof(conc); SendIO(&iocr); } if (mask & cmask) { register long n; char buf[32]; while (n = DNRead(chan, buf, sizeof(buf))) { if (n == -2) { short cmd, val; char aux; cmd = DGetIoctl(chan, &val, &aux); if (cmd >= 0) HandleIoctl(cmd, val, aux, win, &iocw, &ignorens); continue; } if (n < 0) { notdone = 0; break; } if (buf[0] == 3) /* remote ^C -- done */ notdone = 0; iocw.io_Data = (APTR)buf; iocw.io_Length = n; DoIO(&iocw); } } } AbortIO(&iocr); WaitIO(&iocr); CloseDevice(&iocw); DeletePort(iocw.io_Message.mn_ReplyPort); CloseWindow(win); } DClose(chan); { register struct Message *msg; msg = AllocMem(sizeof(*msg), MEMF_PUBLIC); Forbid(); PutMsg(HdPort, msg); } } else { Forbid(); Signal(HdPort->mp_SigTask, 1 << HandShakeSig); } RemTask(NULL); } HandleIoctl(cmd, val, aux, win, iocw, igns) short cmd, val; char aux; WIN *win; IOCON *iocw; short *igns; { static short saverows; short height, width; short dx, dy; switch(cmd) { case CIO_SETROWS: saverows = val; break; case CIO_SETCOLS: width = val * win->RPort->TxWidth + win->BorderLeft + win->BorderRight; height= saverows * win->RPort->TxHeight + win->BorderTop + win->BorderBottom; dx = win->WScreen->Width - (win->LeftEdge + width); if (dx > 0) dx = 0; if (-dx > win->LeftEdge) { dx = -win->LeftEdge; width = win->WScreen->Width; } dy = win->WScreen->Height - (win->TopEdge + height); if (dy > 0) dy = 0; if (-dy > win->TopEdge) { dy = -win->TopEdge; height = win->WScreen->Height; } if (dx || dy) { MoveWindow(win, dx, dy); } if (win->Width != width || win->Height != height) { SizeWindow(win, width - win->Width, height - win->Height); ++*igns; } break; } } setsize(iocw, chan, win) IOCON *iocw; { struct ConUnit *cu = (struct ConUnit *)iocw->io_Unit; static char Term[64]; iocw->io_Data = (APTR)"\033c\033[20h\033[t\033[u"; iocw->io_Length = 13; DoIO(iocw); if (chan) { DIoctl(chan, CIO_SETROWS, cu->cu_YMax+1, 0); DIoctl(chan, CIO_SETCOLS, cu->cu_XMax+1, 0); } sprintf(Term, "STERM %ld x %ld", cu->cu_YMax+1, cu->cu_XMax+1); SetWindowTitles(win, Term, -1); }