Operating System - OpenVMS

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