revert between 56095 -> 55830 in arch
[AROS.git] / rom / filesys / console_handler / con_handler.c
blob32ecd42437780f7c81711a54ec57f535949ebfaa
1 /*
2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <proto/exec.h>
7 #include <exec/libraries.h>
8 #include <exec/resident.h>
9 #include <exec/memory.h>
10 #include <exec/io.h>
11 #include <exec/errors.h>
12 #include <exec/alerts.h>
13 #include <utility/tagitem.h>
14 #include <dos/exall.h>
15 #include <dos/dosasl.h>
16 #include <intuition/intuition.h>
17 #include <proto/dos.h>
18 #include <proto/intuition.h>
19 #include <proto/workbench.h>
20 #include <workbench/startup.h>
21 #include <devices/conunit.h>
23 #include <stddef.h>
24 #include <string.h>
26 #include "con_handler_intern.h"
27 #include "support.h"
29 #undef SDEBUG
30 #undef DEBUG
31 #define SDEBUG 0
32 #define DEBUG 0
33 #include <aros/debug.h>
35 #if defined(__AROSPLATFORM_SMP__)
36 #include <aros/types/spinlock_s.h>
37 #include <proto/execlock.h>
38 #include <resources/execlock.h>
39 #endif
41 static char *BSTR2C(BSTR srcs)
43 UBYTE *src = BADDR(srcs);
44 char *dst;
46 dst = AllocVec(src[0] + 1, MEMF_ANY);
47 if (!dst)
48 return NULL;
49 memcpy(dst, src + 1, src[0]);
50 dst[src[0]] = 0;
51 return dst;
53 static WORD isdosdevicec(CONST_STRPTR s)
55 UBYTE b = 0;
56 while (s[b])
58 if (s[b] == ':')
59 return b;
60 b++;
62 return -1;
65 #define ioReq(x) ((struct IORequest *)x)
67 static const struct NewWindow default_nw =
69 0, /* LeftEdge */
70 0, /* TopEdge */
71 -1, /* Width */
72 -1, /* Height */
73 1, /* DetailPen */
74 0, /* BlockPen */
75 0, /* IDCMP */
76 WFLG_DEPTHGADGET |
77 WFLG_SIZEGADGET |
78 WFLG_DRAGBAR |
79 WFLG_SIZEBRIGHT |
80 WFLG_SMART_REFRESH |
81 WFLG_ACTIVATE,
82 0, /* FirstGadget */
83 0, /* CheckMark */
84 "CON:", /* Title */
85 0, /* Screen */
86 0, /* Bitmap */
87 100, /* MinWidth */
88 70, /* MinHeight */
89 32767, /* MaxWidth */
90 32767, /* MaxHeight */
91 WBENCHSCREEN /* type */
95 static LONG MakeConWindow(struct filehandle *fh)
97 LONG err = 0;
99 if (fh->otherwindow == NULL)
101 struct TagItem win_tags[] =
103 { WA_PubScreen, 0 },
104 { WA_AutoAdjust, TRUE },
105 { WA_PubScreenName, 0 },
106 { WA_PubScreenFallBack, TRUE },
107 { TAG_DONE }
110 win_tags[2].ti_Data = (IPTR) fh->screenname;
111 D(bug("[contask] Opening window on screen %s, IntuitionBase = 0x%p\n", fh->screenname, IntuitionBase));
113 /* Autoadjust doesn't enforce the window's width and height to be larger than
114 minwidth and minheight, so we set it here to avoid crashes in devs/console
115 if a user does e.g. dir >con:0/0/0/0
117 fh->nw.Width = fh->nw.Width > fh->nw.MinWidth ? fh->nw.Width : -1;
118 fh->nw.Height = (fh->flags & FHFLG_BOOTCON && fh->nw.Height == -1) ||
119 fh->nw.Height > fh->nw.MinHeight ? fh->nw.Height : fh->nw.MinHeight;
121 fh->window = OpenWindowTagList(&fh->nw, (struct TagItem *) win_tags);
123 else
125 D(bug("[contask] Using window %p\n", fh->otherwindow));
126 fh->window = fh->otherwindow;
129 if (fh->window)
131 D(bug("contask: window opened\n"));
132 fh->conreadio->io_Data = (APTR) fh->window;
133 fh->conreadio->io_Length = sizeof(struct Window);
135 if (0 == OpenDevice("console.device", CONU_SNIPMAP, ioReq(fh->conreadio), 0))
137 const UBYTE lf_on[] =
138 { 0x9B, 0x32, 0x30, 0x68 }; /* Set linefeed mode */
140 D(bug("contask: device opened\n"));
142 fh->flags |= FHFLG_CONSOLEDEVICEOPEN;
144 fh->conwriteio = *fh->conreadio;
145 fh->conwriteio.io_Message.mn_ReplyPort = fh->conwritemp;
147 /* Turn the console into LF+CR mode so that both
148 linefeed and carriage return is done on
150 fh->conwriteio.io_Command = CMD_WRITE;
151 fh->conwriteio.io_Data = (APTR) lf_on;
152 fh->conwriteio.io_Length = 4;
154 DoIO(ioReq(&fh->conwriteio));
156 if (fh->workbenchbase && (fh->appmsgport = CreateMsgPort()))
158 if ((fh->appwindow = AddAppWindow(0, 0, fh->window, fh->appmsgport, NULL)))
159 D(bug("[CON] Console promoted to be an AppWindow\n"));
162 } /* if (0 == OpenDevice("console.device", CONU_STANDARD, ioReq(fh->conreadio), 0)) */
163 else
165 err = ERROR_INVALID_RESIDENT_LIBRARY;
167 if (err)
168 CloseWindow(fh->window);
170 } /* if (fh->window) */
171 else
173 D(bug("[contask] Failed to open a window\n"));
174 err = ERROR_NO_FREE_STORE;
177 return err;
180 static BOOL MakeSureWinIsOpen(struct filehandle *fh)
182 if (fh->window)
183 return TRUE;
184 return MakeConWindow(fh) == 0;
187 static void close_con(struct filehandle *fh)
189 /* Clean up */
191 D(bug("[CON] Deleting timer request 0x%p\n", fh->timerreq));
192 if (fh->timerreq)
194 CloseDevice((struct IORequest *) fh->timerreq);
195 DeleteIORequest((struct IORequest *) fh->timerreq);
198 D(bug("[CON] Deleting timer port 0x%p\n", fh->timermp));
199 DeleteMsgPort(fh->timermp);
201 if (fh->flags & FHFLG_CONSOLEDEVICEOPEN)
203 D(bug("[CON] Closing console.device...\n"));
204 CloseDevice((struct IORequest *) fh->conreadio);
207 if (fh->appwindow)
209 D(bug("[CON] Unpromote console window from being an AppWindow\n"));
210 RemoveAppWindow(fh->appwindow);
212 if (fh->appmsgport)
214 struct AppMessage *appmsg;
215 while ((appmsg = (struct AppMessage *) GetMsg(fh->appmsgport)))
216 ReplyMsg ((struct Message *) appmsg);
217 D(bug("[CON] Delete MsgPort for AppWindow\n"));
218 DeleteMsgPort(fh->appmsgport);
221 D(bug("[CON] Closing window 0x%p\n", fh->window));
222 if (fh->window)
223 CloseWindow(fh->window);
225 D(bug("[CON] Delete console.device IORequest 0x%p\n", fh->conreadio));
226 DeleteIORequest(ioReq(fh->conreadio));
228 D(bug("[CON] Delete console.device MsgPort 0x%p\n", fh->conreadmp));
229 FreeVec(fh->conreadmp);
231 if (fh->screenname)
232 FreeVec(fh->screenname);
233 if (fh->wintitle)
234 FreeVec(fh->wintitle);
235 if (fh->pastebuffer)
236 FreeMem(fh->pastebuffer, PASTEBUFSIZE);
238 CloseLibrary((struct Library*) fh->intuibase);
239 CloseLibrary((struct Library*) fh->dosbase);
240 CloseLibrary((struct Library*) fh->workbenchbase);
242 /* These libraries are opened only if completion was used */
243 if (fh->gfxbase)
244 CloseLibrary((struct Library*) fh->gfxbase);
245 if (fh->gtbase)
246 CloseLibrary(fh->gtbase);
248 FreeVec(fh);
251 static struct filehandle *open_con(struct DosPacket *dp, LONG *perr)
253 #if defined(__AROSPLATFORM_SMP__)
254 void *ExecLockBase = OpenResource("execlock.resource");
255 #endif
256 char *filename, *fn;
257 struct filehandle *fh;
258 struct DeviceNode *dn;
259 LONG err, ok;
260 LONG i;
262 dn = BADDR(dp->dp_Arg3);
263 *perr = ERROR_NO_FREE_STORE;
264 fh = AllocVec(sizeof(struct filehandle), MEMF_PUBLIC | MEMF_CLEAR);
265 if (!fh)
266 return NULL;
268 fh->intuibase = (APTR) OpenLibrary("intuition.library", 0);
269 fh->dosbase = (APTR) OpenLibrary("dos.library", 0);
270 fh->utilbase = (APTR) OpenLibrary("utility.library", 0);
271 fh->workbenchbase = (APTR) OpenLibrary("workbench.library", 0);
273 #if defined(__AROSPLATFORM_SMP__)
274 if (ExecLockBase)
275 ObtainSystemLock(&SysBase->DeviceList, SPINLOCK_MODE_READ, LOCKF_FORBID);
276 else
277 Forbid();
278 #else
279 Forbid();
280 #endif
282 fh->inputbase = (struct Device *) FindName(&SysBase->DeviceList, "input.device");
284 #if defined(__AROSPLATFORM_SMP__)
285 if (ExecLockBase)
286 ReleaseSystemLock(&SysBase->DeviceList, LOCKF_FORBID);
287 else
288 Permit();
289 #else
290 Permit();
291 #endif
293 if (!fh->intuibase || !fh->dosbase || !fh->utilbase || !fh->inputbase)
295 CloseLibrary((APTR) fh->utilbase);
296 CloseLibrary((APTR) fh->dosbase);
297 CloseLibrary((APTR) fh->intuibase);
298 CloseLibrary((APTR) fh->workbenchbase);
299 FreeVec(fh);
300 return NULL;
303 fh->timermp = CreateMsgPort();
304 fh->timerreq = (struct timerequest*) CreateIORequest(fh->timermp, sizeof(struct timerequest));
305 OpenDevice(TIMERNAME, UNIT_MICROHZ, (struct IORequest *) fh->timerreq, 0);
307 err = 0;
308 filename = BSTR2C((BSTR) dp->dp_Arg1);
309 fn = filename;
310 i = isdosdevicec(fn);
311 if (i >= 0)
312 fn += i + 1;
314 fh->contask = FindTask(0);
316 NEWLIST(&fh->pendingReads);
318 /* Create msgport for console.device communication */
319 fh->conreadmp = AllocVec(sizeof(struct MsgPort) * 2, MEMF_PUBLIC | MEMF_CLEAR);
320 if (fh->conreadmp)
322 memset( fh->conreadmp, 0, sizeof( *fh->conreadmp ) );
323 fh->conreadmp->mp_Node.ln_Type = NT_MSGPORT;
324 fh->conreadmp->mp_Flags = PA_SIGNAL;
325 fh->conreadmp->mp_SigBit = AllocSignal(-1);
326 fh->conreadmp->mp_SigTask = fh->contask;
327 NEWLIST(&fh->conreadmp->mp_MsgList);
329 fh->conwritemp = fh->conreadmp + 1;
331 memset( fh->conwritemp, 0, sizeof( *fh->conwritemp ) );
332 fh->conwritemp->mp_Node.ln_Type = NT_MSGPORT;
333 fh->conwritemp->mp_Flags = PA_SIGNAL;
334 fh->conwritemp->mp_SigBit = AllocSignal(-1);
335 fh->conwritemp->mp_SigTask = fh->contask;
336 NEWLIST(&fh->conwritemp->mp_MsgList);
338 fh->conreadio = (struct IOStdReq *) CreateIORequest(fh->conreadmp, sizeof(struct IOStdReq));
339 if (fh->conreadio)
341 D(bug("contask: conreadio created, parms '%s'\n", fn));
343 fh->nw = default_nw;
345 if (parse_filename(fh, fn, &fh->nw))
347 if (!(fh->flags & FHFLG_AUTO))
349 err = MakeConWindow(fh);
350 if (!err)
351 ok = TRUE;
353 else
355 ok = TRUE;
358 else
359 err = ERROR_BAD_STREAM_NAME;
361 if (!ok)
363 DeleteIORequest(ioReq(fh->conreadio));
366 } /* if (fh->conreadio) */
367 else
369 err = ERROR_NO_FREE_STORE;
372 } /* if (fh->conreadmp) */
373 else
375 err = ERROR_NO_FREE_STORE;
378 if (dn->dn_Startup)
379 fh->flags |= FHFLG_RAW;
381 if (!ok)
382 close_con(fh);
384 *perr = err;
385 FreeVec(filename);
386 return fh;
389 static void startread(struct filehandle *fh)
391 if (fh->flags & FHFLG_ASYNCCONSOLEREAD)
392 return;
393 fh->conreadio->io_Command = CMD_READ;
394 fh->conreadio->io_Data = fh->consolebuffer;
395 fh->conreadio->io_Length = CONSOLEBUFFER_SIZE;
396 SendIO((struct IORequest*) fh->conreadio);
397 fh->flags |= FHFLG_ASYNCCONSOLEREAD;
400 static void stopwait(struct filehandle *fh, struct DosPacket *waitingdp, ULONG result)
402 if (waitingdp)
404 AbortIO((struct IORequest *) fh->timerreq);
405 WaitIO((struct IORequest *) fh->timerreq);
406 replypkt(waitingdp, result);
410 static void stopread(struct filehandle *fh, struct DosPacket *waitingdp)
412 struct Message *msg, *next_msg;
414 stopwait(fh, waitingdp, DOSFALSE);
416 ForeachNodeSafe(&fh->pendingReads, msg, next_msg)
418 struct DosPacket *dpr;
420 Remove((struct Node *) msg);
421 dpr = (struct DosPacket*) msg->mn_Node.ln_Name;
422 replypkt(dpr, DOSFALSE);
426 LONG CONMain(struct ExecBase *SysBase)
428 struct MsgPort *mp;
429 struct DosPacket *dp;
430 struct Message *mn;
431 struct FileHandle *dosfh;
432 LONG error;
433 struct filehandle *fh;
434 struct FileLock *fl;
435 struct DosPacket *waitingdp = NULL;
437 D(bug("[CON] started\n"));
438 mp = &((struct Process*) FindTask(NULL))->pr_MsgPort;
439 WaitPort(mp);
440 dp = (struct DosPacket*) GetMsg(mp)->mn_Node.ln_Name;
441 D(bug("[CON] startup message received. port=0x%p path='%b'\n", mp, dp->dp_Arg1));
443 fh = open_con(dp, &error);
444 if (!fh)
446 D(bug("[CON] init failed\n"));
447 goto end;
449 D(bug("[CON] 0x%p open\n", fh));
450 replypkt(dp, DOSTRUE);
452 for (;;)
454 ULONG conreadmask = 1L << fh->conreadmp->mp_SigBit;
455 ULONG timermask = 1L << fh->timermp->mp_SigBit;
456 ULONG packetmask = 1L << mp->mp_SigBit;
457 ULONG appwindowmask = fh->appmsgport ? 1L << fh->appmsgport->mp_SigBit : 0L;
458 ULONG i = 0, insertedlen = 0;
459 ULONG sigs;
460 UBYTE iconpath[INPUTBUFFER_SIZE];
461 WORD currentpos, currentrest;
463 sigs = Wait(packetmask | conreadmask | timermask | appwindowmask);
465 if (sigs & appwindowmask)
467 while ((fh->appmsg = (struct AppMessage *)GetMsg(fh->appmsgport)))
469 if (fh->appmsg->am_Type == AMTYPE_APPWINDOW)
471 if (fh->appmsg->am_NumArgs >= 1)
475 if (fh->appmsg->am_ArgList[i].wa_Lock)
477 NameFromLock(fh->appmsg->am_ArgList[i].wa_Lock,
478 iconpath, INPUTBUFFER_SIZE - 1);
479 AddPart(iconpath, fh->appmsg->am_ArgList[i].wa_Name,
480 INPUTBUFFER_SIZE - 1);
481 D(bug("[CON]: D&D iconpath: %s\n", iconpath));
483 if ((insertedlen = strlen(iconpath)))
486 * Get rid of trailing slashes of drawers?
487 if ((iconpath[insertedlen - 1] == '/'))
488 insertedlen--;
490 if ( strchr(iconpath, ' ')
491 && insertedlen <= (INPUTBUFFER_SIZE - 2))
493 memmove(iconpath + 1, iconpath, ++insertedlen);
494 iconpath[0] = iconpath[insertedlen++] = '"';
496 if (insertedlen <= (INPUTBUFFER_SIZE - 1))
497 iconpath[insertedlen++] = ' ';
499 currentpos = fh->inputpos;
500 currentrest = fh->inputsize - fh->inputpos;
501 memmove(&fh->inputbuffer[currentpos + insertedlen],
502 &fh->inputbuffer[currentpos],
503 currentrest);
504 CopyMem(iconpath, &fh->inputbuffer[currentpos],
505 insertedlen);
506 fh->inputsize += insertedlen;
507 fh->inputpos += insertedlen;
509 do_write(fh, &fh->inputbuffer[currentpos],
510 insertedlen + currentrest);
511 do_movecursor(fh, CUR_LEFT, currentrest);
514 } while (++i < fh->appmsg->am_NumArgs);
517 ReplyMsg((struct Message *)fh->appmsg);
519 ActivateWindow(fh->window);
522 if (sigs & timermask)
524 if (waitingdp)
526 replypkt(waitingdp, DOSFALSE);
527 waitingdp = NULL;
531 if (sigs & conreadmask)
533 GetMsg(fh->conreadmp);
534 fh->flags &= ~FHFLG_ASYNCCONSOLEREAD;
535 if (waitingdp)
537 stopwait(fh, waitingdp, DOSTRUE);
538 waitingdp = NULL;
540 D(bug("IO_READ %d\n", fh->conreadio->io_Actual));
541 fh->conbuffersize = fh->conreadio->io_Actual;
542 fh->conbufferpos = 0;
543 /* terminate with 0 char */
544 fh->consolebuffer[fh->conbuffersize] = '\0';
545 if (fh->flags & FHFLG_RAW)
547 LONG inp;
548 /* raw mode */
549 for (inp = 0; (inp < fh->conbuffersize) && (fh->inputpos < INPUTBUFFER_SIZE);)
551 fh->inputbuffer[fh->inputpos++] = fh->consolebuffer[inp++];
553 fh->inputsize = fh->inputstart = fh->inputpos;
554 HandlePendingReads(fh);
555 } /* if (fh->flags & FHFLG_RAW) */
556 else
558 /* Cooked mode */
559 if (process_input(fh))
562 * process_input() returns TRUE when EOF was received after the WAIT console
563 * has been closed by the owner.
565 dp = NULL;
566 goto end;
568 } /* if (fh->flags & FHFLG_RAW) else ... */
570 if (fh->flags & FHFLG_CONSOLEDEVICEOPEN) /* device could have been closed */
571 startread(fh);
574 while ((mn = GetMsg(mp)))
576 dp = (struct DosPacket*) mn->mn_Node.ln_Name;
577 dp->dp_Res2 = 0;
579 bug("[CON 0x%p] packet 0x%p:%d 0x%p,0x%p,0x%p\n", fh, dp, dp->dp_Type, dp->dp_Arg1, dp->dp_Arg2,
580 dp->dp_Arg3));
581 error = 0;
582 switch (dp->dp_Type)
584 case ACTION_FH_FROM_LOCK:
585 fl = BADDR(dp->dp_Arg2);
586 if (fl->fl_Task != mp || fl->fl_Key != (IPTR) fh)
588 replypkt2(dp, DOSFALSE, ERROR_OBJECT_NOT_FOUND);
589 break;
591 fh->usecount--;
592 FreeMem(fl, sizeof(*fl));
593 /* Fallthrough */
594 case ACTION_FINDINPUT:
595 case ACTION_FINDOUTPUT:
596 case ACTION_FINDUPDATE:
597 dosfh = BADDR(dp->dp_Arg1);
598 dosfh->fh_Interactive = DOSTRUE;
599 dosfh->fh_Arg1 = (SIPTR) fh;
600 fh->usecount++;
601 fh->breaktask = dp->dp_Port->mp_SigTask;
602 D(bug("[CON] Find fh=%x. Usecount=%d\n", dosfh, fh->usecount));
603 replypkt(dp, DOSTRUE);
604 break;
605 case ACTION_COPY_DIR_FH:
606 fl = AllocMem(sizeof(*fl), MEMF_CLEAR | MEMF_PUBLIC);
607 if (fl == BNULL)
609 replypkt2(dp, (SIPTR) BNULL, ERROR_NO_FREE_STORE);
611 else
613 fh->usecount++;
614 fl->fl_Task = mp;
615 fl->fl_Access = ACCESS_READ;
616 fl->fl_Key = (IPTR) fh;
617 replypkt(dp, (SIPTR) MKBADDR(fl));
619 break;
620 case ACTION_FREE_LOCK:
621 fl = BADDR(dp->dp_Arg1);
622 fh = (struct filehandle *)fl->fl_Key;
624 FreeMem(fl, sizeof(*fl));
625 fh->usecount--;
627 replypkt(dp, DOSTRUE);
628 break;
629 case ACTION_END:
630 fh->usecount--;
631 D(bug("[CON] usecount=%d\n", fh->usecount));
632 if (fh->usecount <= 0)
634 if (fh->flags & FHFLG_WAIT)
636 D(bug("[CON] Delayed close, waiting...\n"));
639 * Bounce all pending read and waits (the same as we do when exiting).
640 * However the process is still around, waiting for EOF input.
641 * Our user has just closed his struct FileHandle and dropped us.
643 stopread(fh, waitingdp);
644 waitingdp = NULL;
645 fh->flags = (fh->flags & ~FHFLG_READPENDING) | FHFLG_WAITFORCLOSE;
647 else
648 goto end;
650 replypkt(dp, DOSTRUE);
651 break;
652 case ACTION_READ:
653 if (!MakeSureWinIsOpen(fh))
655 replypkt2(dp, DOSFALSE, ERROR_NO_FREE_STORE);
656 break;
658 fh->breaktask = dp->dp_Port->mp_SigTask;
659 startread(fh);
660 con_read(fh, dp);
661 break;
662 case ACTION_WRITE:
663 if (!MakeSureWinIsOpen(fh))
665 replypkt2(dp, DOSFALSE, ERROR_NO_FREE_STORE);
666 break;
668 fh->breaktask = dp->dp_Port->mp_SigTask;
669 startread(fh);
670 answer_write_request(fh, dp);
671 break;
672 case ACTION_SCREEN_MODE:
674 D(bug("ACTION_SCREEN_MODE %s\n", dp->dp_Arg1 ? "RAW" : "CON"));
675 if (dp->dp_Arg1 && !(fh->flags & FHFLG_RAW))
677 /* Switching from CON: mode to RAW: mode */
678 fh->flags |= FHFLG_RAW;
679 fh->inputstart = fh->inputsize;
680 fh->inputpos = fh->inputsize;
681 HandlePendingReads(fh);
683 else
685 /* otherwise just copy the flags */
686 if (dp->dp_Arg1)
687 fh->flags |= FHFLG_RAW;
688 else
689 fh->flags &= ~FHFLG_RAW;
691 replypkt(dp, DOSTRUE);
693 break;
694 case ACTION_CHANGE_SIGNAL:
696 struct Task *old = fh->breaktask;
697 if (dp->dp_Arg2)
698 fh->breaktask = (struct Task*) dp->dp_Arg2;
699 replypkt2(dp, DOSTRUE, (SIPTR) old);
701 break;
702 case ACTION_WAIT_CHAR:
704 if (!MakeSureWinIsOpen(fh))
706 replypkt2(dp, DOSFALSE, ERROR_NO_FREE_STORE);
707 break;
709 if (fh->inputsize > 0)
711 replypkt(dp, DOSTRUE);
713 else if (dp->dp_Arg1 == 0)
715 replypkt(dp, DOSFALSE);
717 else
719 LONG timeout = dp->dp_Arg1;
720 LONG sec = timeout / 1000000;
721 LONG usec = timeout % 1000000;
723 fh->timerreq->tr_node.io_Command = TR_ADDREQUEST;
724 fh->timerreq->tr_time.tv_secs = sec;
725 fh->timerreq->tr_time.tv_micro = usec;
726 SendIO((struct IORequest *) fh->timerreq);
727 waitingdp = dp;
729 startread(fh);
731 break;
732 case ACTION_IS_FILESYSTEM:
733 replypkt(dp, DOSFALSE);
734 break;
735 case ACTION_DISK_INFO:
737 /* strange console handler features */
738 struct InfoData *id = BADDR(dp->dp_Arg1);
739 memset(id, 0, sizeof(struct InfoData));
740 id->id_DiskType =
741 (fh->flags & FHFLG_RAW) ? AROS_MAKE_ID('R', 'A', 'W', 0) : AROS_MAKE_ID('C', 'O', 'N', 0);
742 id->id_VolumeNode = (BPTR) fh->window;
743 id->id_InUse = (IPTR) fh->conreadio;
744 replypkt(dp, DOSTRUE);
746 break;
747 case ACTION_SEEK:
748 /* Yes, DOSTRUE. Check Guru Book for details. */
749 replypkt2(dp, DOSTRUE, ERROR_ACTION_NOT_KNOWN);
750 break;
751 default:
752 bug("[CON] unknown action %d\n", dp->dp_Type);
753 replypkt2(dp, DOSFALSE, ERROR_ACTION_NOT_KNOWN);
754 break;
758 end:
759 D(bug("[CON] 0x%p closing\n", fh));
760 if (fh)
762 D(bug("[CON] Cancelling read requests...\n"));
763 stopread(fh, waitingdp);
765 if (fh->flags & FHFLG_ASYNCCONSOLEREAD)
767 D(bug("[CON] Aborting console ioReq 0x%p\n", fh->conreadio));
769 AbortIO(ioReq(fh->conreadio));
770 WaitIO(ioReq(fh->conreadio));
773 D(bug("[CON] Closing handle...\n"));
774 close_con(fh);
777 if (dp)
779 D(bug("[CON] Replying packet 0x%p\n", dp));
780 replypkt(dp, DOSFALSE);
783 D(bug("[CON] 0x%p closed\n", fh));
784 return 0;