[comp.sys.amiga] SIGINT, Level2 I/O, Lattice4.0

roch@uiucdcsb.cs.uiuc.edu (03/29/88)

/* Crossposted from .tech after a week w/o response */

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.

			thanks in advance,
			david roch
			roch@b.cs.uiuc.edu

cmcmanis%pepper@Sun.COM (Chuck McManis) (03/31/88)

In article <164000012@uiucdcsb> roch@uiucdcsb.cs.uiuc.edu writes:
>/* Crossposted from .tech after a week w/o response */

So do you win a prize for stumping the Gurus? :-)

>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.

The answer is, by default, no. Hopefully John Toebes can answer
this one. An alternative is to do the scanf 'manually' with a
few calls to a non blocking getc() routine and call ChkAbort()
each time. Ugly but it will work.

--Chuck McManis
uucp: {anywhere}!sun!cmcmanis   BIX: cmcmanis  ARPAnet: cmcmanis@sun.com
These opinions are my own and no one elses, but you knew that didn't you.

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