Operating System - OpenVMS
cancel
Showing results for 
Search instead for 
Did you mean: 

terminal $QIO test for read

SOLVED
Go to solution
Alex Chupahin
Super Advisor

terminal $QIO test for read

hello,
I'm need to check if terminal have something to read.
Mailbox driver has a good IO$M_READATTN parameter for sys$qio()

Is it possible to do something with terminal driver?
12 REPLIES
Hein van den Heuvel
Honored Contributor

Re: terminal $QIO test for read


IO$_SENSEMODE + IO$M_TYPEAHDCNT

Hein

Alex Chupahin
Super Advisor

Re: terminal $QIO test for read

It is seems do not work

"Yes have to read"
is just immediately after run. But still wait a second $qiow for real read from terminal


//---------------------------------------
#include
#include
#include
#include
#include
#include
#include

struct
{
unsigned short iosb_cond;
unsigned short iosb_count;
unsigned int iosb_dev;
} iosb;

static struct {
unsigned short number;
unsigned char first;
unsigned char filler[5];
} vkbuff;

int efn=32;
unsigned short ttchan;

main() {
unsigned int status;
$DESCRIPTOR(ttname,"TT:");
static long long time;

/* Assign a channel to a device */
status = SYS$ASSIGN( &ttname, /* devnam - device name */
&ttchan, /* chan - channel number */
0, /* acmode - access mode */
0, /* mbxnam - logical name for mailbox */
0 ); /* flags */
if (!$VMS_STATUS_SUCCESS(status))
LIB$SIGNAL(status);

status = sys$qiow(efn,ttchan,IO$_SENSEMODE|IO$M_TYPEAHDCNT,0, 0,0, 0,0,0,0,0,0);
printf("Yes have to read\n");
status = sys$qiow(efn,ttchan,IO$_TTYREADALL|IO$M_NOECHO|IO$M_TRMNOECHO,&iosb, 0,0, &vkbuff,sizeof(vkbuff),0,0,0,0);

return SS$_NORMAL;
}

Alex Chupahin
Super Advisor

Re: terminal $QIO test for read

I just read about M_TYPEAHDCNT
it returns a number of characters in the buffer and GET A FIRST CHARCTER from the buffer. This is the not thing I need. Do not any character should be read. I'll read the buffer from another place of the program.
Hein van den Heuvel
Honored Contributor

Re: terminal $QIO test for read


How do you manage to type something 'ahead' if you read right-away.

You have to pass that VKBUFF in you program to
fetch the count/char.

Then pass a real IO buffer to the read.

Corrected program below.
Works for me.

Hein

$ type READAHEAD.C
//---------------------------------------
#include
#include
#include
#include
#include
#include
#include
#include

struct
{
unsigned short iosb_cond;
unsigned short iosb_count;
unsigned int iosb_dev;
} iosb;

static struct {
unsigned short number;
unsigned char first;
unsigned char filler[5];
} vkbuff;

static char buf[1000];
int efn=32;
unsigned short ttchan;

main() {
unsigned int status;
$DESCRIPTOR(ttname,"TT:");
static long long time;

/* Assign a channel to a device */
status = SYS$ASSIGN( &ttname, /* devnam - device name */
&ttchan, /* chan - channel number */
0, /* acmode - access mode */
0, /* mbxnam - logical name for mailbox */
0 ); /* flags */
if (!$VMS_STATUS_SUCCESS(status))
LIB$SIGNAL(status);
printf ("sleeping for a second or two. Type something.\n");
sleep(2);
status = sys$qiow(efn,ttchan,IO$_SENSEMODE|IO$M_TYPEAHDCNT,&iosb, 0,0, &vkbuff,0,0,0,0,0);
printf ("read ahead count = %d, First char = %c\n", vkbuff.number, vkbuff.first);
printf("Yes have to read\n");
status = sys$qiow(efn,ttchan,IO$_TTYREADALL|IO$M_NOECHO|IO$M_TRMNOECHO,&iosb, 0,0, buf,sizeof(buf),0,0,0,0);
printf ("%s\n", buf); // sloppy.
return SS$_NORMAL;
}

$ run READAHEAD
sleeping for a second or two. Type something.
read ahead count = 20, First char = s
Yes have to read
sdgfsrtghsdtrghdtrgh
$ Exit



Hein van den Heuvel
Honored Contributor

Re: terminal $QIO test for read

>>> and GET A FIRST CHARCTER from the buffer.

NO.
It gives you an optional sneak preview.
It does not 'consume' the first character.
That's still there for the read elsewhere.

>>> This is the not thing I need.

Think again :-)

Cheers,
Hein

GuentherF
Trusted Contributor

Re: terminal $QIO test for read

Or do a sys$qio call without the "w" (no wait) and use an AST routine. This way you don't have to do the poor programmer's polling style.

Unless there is a good reason to do the polling for data on the serial line.

/Guenther
Robert Gezelter
Honored Contributor

Re: terminal $QIO test for read

Alex,

My normal approach to this class of problem (on terminals, mailboxes, and other devices) is to use the AST facility.

Polling in any way is not the best of practices when an event-based alternative exists (e.g., ASTs).

For an introduction to ASTs, see the various manuals. My DECUS presentation "Introduction to OpenVMS AST Programming" can be found at http://www.rlgsc.com/cets/2000/435.html

- Bob Gezelter, http://www.rlgsc.com
Shriniketan Bhagwat
Trusted Contributor

Re: terminal $QIO test for read

Hi,

Below is the small program which reads and writes the user name and password from the terminal. May be helpful.

#include
#include
#include
#include
#include
#include
#include

main()
{
$DESCRIPTOR(term_dsc,"SYS$INPUT:");
char user_prmpt[50]="User Name :";
char passw_prmpt[50]="User Password :";
unsigned int status;
unsigned short chan,iosb[4];
char username[50];
char passw[50];

memset(passw,0,50);
memset(username,0,50);
status = sys$assign(&term_dsc,&chan,0,0,0);
status = sys$qiow(0,chan,IO$_READPROMPT,iosb,0,0,username,49,0,0,user_prmpt,strlen(user_prmpt));
username[iosb[1]] = '\0';
status = sys$qiow(0,chan,IO$_READPROMPT|IO$M_NOECHO,iosb,0,0,passw,49,0,0,passw_prmpt,strlen(passw_prmpt));
passw[iosb[1]] = '\0';
printf("\n\nYour User Name : %s \nPassword : %s\n",username,passw);

}

Regards,
Ketan
John Gillings
Honored Contributor
Solution

Re: terminal $QIO test for read

Alex,

This question implies a program design which suffers two flaws.

The first is polling - you sit in a loop checking at intervals if there's anything to do. The tradeoff is, a shorter period reduces the latency in processing, but increases the time wasted spinning in the loop when there's nothing to do.

The second is the model of checking to see if there's something to do before doing it, with inherent timing windows if you "just miss" the event you're waiting for.

In OpenVMS program design, polling is rarely necessary or desirable. You can use asynchronous code to detect and act on events only when necessary and immediately after they occur.

Change your design from:

loop
IF event has occured THEN ProcessEvent
wait polling interval
endloop

to

When event occurs ProcessEvent


In its simplest form, issue a $QIO (no W) when READVBLK specifying an AST routine to execute when the I/O completes.

In an AST design, typically the main program sets up the first AST for each thread of events then goes to sleep. As each AST fires it resets itself for the thread to continue.
A crucible of informative mistakes
Alex Chupahin
Super Advisor

Re: terminal $QIO test for read

Dear Hein,
thank you very much for code example.
If the
sys$qiow(efn,ttchan,IO$_SENSEMODE|IO$M_TYPEAHDCNT,&iosb, 0,0, &vkbuff,0,0,0,0,0);

be able to sleep while nothing to read vkbuff.number is equal to 0 this should be very great.
But it returns immediately.
Hein van den Heuvel
Honored Contributor

Re: terminal $QIO test for read



>> If the ...IO$_SENSEMODE|IO$M_TYPEAHDCNT ...
be able to sleep while nothing to read

Ah, now I understand your question better.
I was only answering the first question

>> I'm need to check if terminal have something to read.

That's exactly what the sensemode does but not what you want, nor as others pointed out what you want to use as it leads to polling algorithms.

>> Mailbox driver has a good IO$M_READATTN

Yes, that warn but takes no action.
This is not available in the terminal driver.
The closest thing is the OUTBAND setmode, but that initiated with selected control characters. Not generic.

And I suppose you could issue a 1 byte read with AST, but then that byte will be in the buffer. That becomes awkward quickly.

You'll probably want to create a wrappers to be able to give a 'read_terminal' routine which does not actually do a qio, but returns the data from a qio which already completed.

You can decide whether the program processes each read completely before issuing the next, or just keeps on reading fulling multiple buffers if need be.

As John indicated it is often handy to use SYS$DCLAST to get the show rolling. Probably passing control block parameter with IOSB and buffer and whatever else is handy to keep all context pointed to in one parameter.

The IOSB is needed if you do fancy terminator handling.... but for anything fancy yo may want to look at SMG or similar.

Cheers,
Hein
Hoff
Honored Contributor

Re: terminal $QIO test for read

If that's the actual C code being tested, consider adding return status and IOSB status checks into the C code.

Status checks are a defensive coding technique that often helps track the triggers of errors, and can provide an effective means of avoiding a application stackdump when something gets tangled and trips on an earlier and unhandled error within the application.

Also consider moving away from hard-coding a static EFN (and particularly not using an EF that the lib$get_ef call "owns" and can pass out) and moving to an allocated event flag or (for something akin to this case) to ENF$C_ENF "don't care" event flag, too.

ENF$C_ENF is defined in EFNDEF.H