doug@eris (Doug Merritt) (03/31/88)
In article <164000012@uiucdcsb> roch@uiucdcsb.cs.uiuc.edu writes: >Does anyone know if there is a way to receive a SIGINT interrupt during >a level 2 read operation (say scanf) without waiting for the >user to hit Return? I'm using Lattice 4.0. As far as I know, the answer is "no". Presumably the most straightforward way to get the same effect is to use level 1 I/O to gather characters and watch for ^C in raw mode, and then use string-oriented level 2 functions to parse the chars gathered up. My Lattice and Manx versions are pretty old by now, so maybe I'm wrong, but even if so the below code is still useful for switching to raw mode for level 1 i/o (perhaps by now these functions Raw() and Cooked() are available in Lattice and Manx libraries??? They should be! There also *should* be a way to directly do what Roch asked about: catching a SIGINT during a level two i/o function, just like you do on Unix) #include "setjmp.h" char buf[1024]; jmp_buf ctrlc_handler; if (setjmp(ctrlc_handler)) { /* ^C seen ? */ exit(1); /* for instance ... */ } Getline(buf); sscanf(buf, "%d,%d", &i, &j); . . . #define CTRL_C ('\03') Getline(s) char *s; { char c; Raw(); /* read chars as them come in */ while (1) { if (read(INPUT, s, 1) < 1) break; if (*s++ == CTRL_C) { longjmp(ctrlc_handler, 1); /* for instance...*/ break; } } Cooked(); /* switch back to "wait for CR" mode */ } The above code is illustrative and untested. The following code is tested. The functions Raw() and Cooked() I implemented based on several other pieces of public domain code: /********************** CUT HERE ******************************/ /* * * raw.c -- set window file handle to raw/cooked. Public Domain. Derived * from the two below PD packages. * * Raw(), * Cooked() -- modified 03-Jun-87 by Doug Merritt to work directly on * a file handle, capitalized names to look like AmigaDos * style (good idea considering parameter type change). * Minor mods to support both Manx and Lattice, changed * return code to match conventional true/false. * * -- written 18-Jun-87 By Chuck McManis. Public Domain. * If you use it I would appreciate credit for it somewhere. * * sendpacket() -- written by Phil Lindsay, Carolyn Scheppner, and * Andy Finkel of Commodore. Public Domain. * */ #include <exec/types.h> #include <libraries/dos.h> #include <libraries/dosextens.h> #include <stdio.h> /* New Packet in 1.2 */ #define ACTION_SCREEN_MODE 994L /* * Function raw() - Convert the specified file pointer to 'raw' mode. This * only works on TTY's and essentially keeps DOS from translating keys for * you, also (BIG WIN) it means getch() will return immediately rather than * wait for a return. You lose editing features though. */ int Raw(afh) struct FileHandle *afh; { struct MsgPort *mp; /* The File Handle message port */ long Arg[1]; int res; if (!IsInteractive(afh)) { return(0); } /* get its message port, send packet */ mp = ((struct FileHandle *)(BADDR(afh)))->fh_Type; Arg[0] = -1L; res = SendPacket(mp,ACTION_SCREEN_MODE,Arg,1L); /* Put it in RAW: mode */ return(res); } /* * Function - cooked() this function returns the designate file pointer to * it's normal, wait for a <CR> mode. This is exactly like raw() except that * it sends a 0 to the console to make it back into a CON: from a RAW: */ int Cooked(afh) struct FileHandle *afh; { struct MsgPort *mp; /* The File Handle message port */ long Arg[1],res; if ( ! IsInteractive(afh)) { return(0); } mp = ((struct FileHandle *)(BADDR(afh)))->fh_Type; Arg[0] = 0; res = SendPacket(mp,ACTION_SCREEN_MODE,Arg,1L); return(res); } /********************************************************************* * Sendpacket.c * * Function - SendPacket written by Phil Lindsay, Carolyn Scheppner, and * Andy Finkel. This function will send a packet of the given type to the * Message Port supplied. * * (This version, including the below note, supplied by Chuck McManis:) * * An invaluable addition to your Amiga.lib file. This code sends a packet * the given message port. This makes working around DOS lots easier. * * Note, I didn't write this, those wonderful folks at CBM did. I do suggest * however that you may wish to add it to Amiga.Lib, to do so, compile it * and say 'oml lib:amiga.lib -r sendpacket.o' */ #include <exec/types.h> #include <exec/ports.h> #include <exec/memory.h> #include <libraries/dos.h> #include <libraries/dosextens.h> int SendPacket(pid,action,args,nargs) struct MsgPort *pid; /* process indentifier ... (handlers message port ) */ long action, /* packet type ... (what you want handler to do ) */ args[], /* a pointer to a argument list */ nargs; /* number of arguments in list */ { struct MsgPort *CreatePort(), *replyport; struct StandardPacket *packet; UBYTE *AllocMem(); long count, *pargs, res1; replyport = (struct MsgPort *) CreatePort(NULL,0L); if(!replyport) return(0); /* Allocate space for a packet, make it public and clear it */ packet = (struct StandardPacket *) AllocMem((long)sizeof(struct StandardPacket),MEMF_PUBLIC|MEMF_CLEAR); if(!packet) { DeletePort(replyport); return(0); } packet->sp_Msg.mn_Node.ln_Name = (char *)&(packet->sp_Pkt); packet->sp_Pkt.dp_Link = &(packet->sp_Msg); packet->sp_Pkt.dp_Port = replyport; packet->sp_Pkt.dp_Type = action; /* copy the args into the packet */ pargs = &(packet->sp_Pkt.dp_Arg1); /* address of first argument */ for(count=0;count < nargs;count++) pargs[count]=args[count]; PutMsg(pid,packet); /* send packet */ WaitPort(replyport); GetMsg(replyport); res1 = packet->sp_Pkt.dp_Res1; FreeMem(packet,(long)sizeof(struct StandardPacket)); DeletePort(replyport); return((int) res1); } /* SendPacket() */ /************************* CUT HERE *************************************/ Doug Merritt doug@eris.berkeley.edu (ucbvax!eris!doug) or ucbvax!unisoft!certes!doug