Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

yet another sys$qiow question

1,377 views
Skip to first unread message

k...@kayceesoftware.com

unread,
Jul 19, 2015, 8:34:43 PM7/19/15
to
I'm using VMS 8.4 on I64 rx2600, latest tcpip and patches.
I also tried the same on alpha vms 8.4 and alpha vms 7.3-2 with the same problem.

I don't understand sys$qiow very well, but years ago i followed an example to get data from a serial port and it has worked well for years. It was usually small messages...less than 50 bytes and I called qiow with a short timeout and 1 byte buffer size. I just recursively called qiow until i got the end byte that the device sent (ETX 0x03).

Now i want to read from a newer serial device, the message is XML with tons of wasted data. The message is 500-800 bytes and ends in EOT 0x04 or NAK. I thought from reading the VMS I/O manual that qiow would use any escape sequence as a terminator if I don't specify a terminator.

I thought it best to use a single qiow call with timeout and larger buffer. I've read some of the examples and gone over the VMS System REf manual and the I/O manual, but I must be missing something.

If I send the following with a 1 byte buffer size and copy each byte to another string...it gets the 500+ bytes of data...but randomly drops bytes. The TNA device/term is set ALTYPEAHD, in the past i think i got lucky as the message was always so small.
iostatus = SYS$QIOW (0, dbchan, iofunct, &iostat, 0, 0, &ubuf, 1, timeout, 0, 0, 0);

If I send the following with buffer size changing from 1 to 999, it seems to just timeout and get nothing.
iostatus = SYS$QIOW (0, dbchan, iofunct, &iostat, 0, 0, &ubuf, sizeof(ubuf), timeout, 0, 0, 0);

If i send the following it also seems to timeout and get nothing. I'm not sure how to mask the quadword for terminators to setup EOT and NAK as the only terminators.
iofunct = IO$_READVBLK | IO$M_NOFILTR | IO$M_NOECHO | IO$M_TIMED;
static const unsigned terminators[2] = { 0, 1 << 0x04 || 0x15 };
iostatus = SYS$QIOW (0, dbchan, iofunct, &iostat, 0, 0, &ubuf, sizeof(ubuf), timeout, terminators, 0, 0);

In all instances i have a serial sniffer between my port and the serial device and the expected data is going both ways. I don't understand why a buffer size of 1 seems to get the data, but the larger buffer size does not.

If you don't have the time to educate me, I understand.

I found one of the examples in sys$examples that refers to the terminator bits as follows:
/* The terminator mask has the <i>-th bit on if ASCII character <i> is to
** terminate a read when entered. This could also be done as a bitfield
** structure. */

struct term_mask {
unsigned long int first_4; /* first 4 bytes last 2 bytes */
unsigned short int last_2; /* Terminator mask includes */
} mask = { 1 << 0x0d, /* carriage return */
1 << 4 }; /* and "$"*/

abrsvc

unread,
Jul 19, 2015, 8:58:21 PM7/19/15
to
I had a similar problem with qios as well and would receive seemingly random buffers ass well. Use the "peek" option and loop until you receive the termination character. That should result in a complete buffer. I can send you the code later on. I am not connected to that machine at the moment.

Let me know.

Dan

Simon Clubley

unread,
Jul 19, 2015, 9:01:01 PM7/19/15
to
On 2015-07-20, k...@kayceesoftware.com <k...@kayceesoftware.com> wrote:
>
> Now i want to read from a newer serial device, the message is XML
> with tons of wasted data. The message is 500-800 bytes and ends in
> EOT 0x04 or NAK. I thought from reading the VMS I/O manual that qiow
> would use any escape sequence as a terminator if I don't specify a
> terminator.
>
> I thought it best to use a single qiow call with timeout and larger
> buffer. I've read some of the examples and gone over the VMS System
> REf manual and the I/O manual, but I must be missing something.
>
> If I send the following with a 1 byte buffer size and copy each byte
> to another string...it gets the 500+ bytes of data...but randomly
> drops bytes. The TNA device/term is set ALTYPEAHD, in the past i
> think i got lucky as the message was always so small.
> iostatus = SYS$QIOW (0, dbchan, iofunct, &iostat, 0, 0, &ubuf, 1, timeout, 0, 0, 0);
>

What flow control are you using and is it setup correctly at both ends ?

Is there any behaviour change when you use passthru mode ?

What is the size of your alternate typeahead buffer ?

Simon.

--
Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP
Microsoft: Bringing you 1980s technology to a 21st century world

k...@kayceesoftware.com

unread,
Jul 19, 2015, 9:33:30 PM7/19/15
to
No flow control, serial units have none available.
I'll try passthru next.
TTY_ALTYPAHD = 1024

But i'm not sure any of this matters with the current problem.
if bufsize = 1, i get the 1 byte at a time.

If bufsize > 1, then I get nothing. I thought that even if it times out I should get whatever comes back up to that point.

I vaguely recall something about needing to set a flag for enabling escape terminators in the iofunct param like IO$M_TIMED...but in searches all I read is that QIOW default terminators include most escape codes. I'm wondering if there is some IO$ESC_ENABLE or something like that that must be set. ??

BillPedersen

unread,
Jul 19, 2015, 11:42:07 PM7/19/15
to
Ok, the idea of the TTY_ALTYPAHD buffer is to provide more buffering in front of the specific typeahead capabilities that you have for the terminal device. The terminal driver(s) dump characters there until they are picked up.

So, the way you can attack this is to use a repeated call to the terminal device via QIOW or similar with the READ function but with the modifier IO$M_TYPEAHDCNT this will return information about what characters are in the typeahead buffer and then you can issue a specific QIOW with the specific count of the number of characters available.

You can find out more about this here:

http://h30266.www3.hp.com/odl/i64os/opsys/vmsos84/BA554_90018/ch05s03.html#term-read-func

Go to section "5.3.4.10.1 Type-ahead Count Function Modifier".

I have used this sort of function with physical lines, LAT lines, Telnet... It should help you with this issue.

Now, that said, this appears to be communicating with some sort of terminal server that then talks to your "serial device". Have you validated the configuration in the terminal server to make sure it is configured the way you expect?

Bill.

George Cornelius

unread,
Jul 20, 2015, 2:14:33 AM7/20/15
to
In article <2d6d1894-0938-4f91...@googlegroups.com>, k...@kayceesoftware.com writes:
> I'm using VMS 8.4 on I64 rx2600, latest tcpip and patches.
> I also tried the same on alpha vms 8.4 and alpha vms 7.3-2 with the same pr=
> oblem. =20
>
> I don't understand sys$qiow very well, but years ago i followed an example =
> to get data from a serial port and it has worked well for years. It was us=
> ually small messages...less than 50 bytes and I called qiow with a short ti=
> meout and 1 byte buffer size. I just recursively called qiow until i got t=
> he end byte that the device sent (ETX 0x03).
>
> Now i want to read from a newer serial device, the message is XML with tons=
> of wasted data. The message is 500-800 bytes and ends in EOT 0x04 or NAK=
> . I thought from reading the VMS I/O manual that qiow would use any escape=
> sequence as a terminator if I don't specify a terminator.
>
> I thought it best to use a single qiow call with timeout and larger buffer.=
> I've read some of the examples and gone over the VMS System REf manual an=
> d the I/O manual, but I must be missing something.
>
> If I send the following with a 1 byte buffer size and copy each byte to ano=
> ther string...it gets the 500+ bytes of data...but randomly drops bytes. =
> The TNA device/term is set ALTYPEAHD, in the past i think i got lucky as th=
> e message was always so small.
> iostatus =3D SYS$QIOW (0, dbchan, iofunct, &iostat, 0, 0, &ubuf, 1, time=
> out, 0, 0, 0);
>
> If I send the following with buffer size changing from 1 to 999, it seems t=
> o just timeout and get nothing.
> iostatus =3D SYS$QIOW (0, dbchan, iofunct, &iostat, 0, 0, &ubuf, sizeof(=
> ubuf), timeout, 0, 0, 0);
>
> If i send the following it also seems to timeout and get nothing. I'm not s=
> ure how to mask the quadword for terminators to setup EOT and NAK as the on=
> ly terminators.
> iofunct =3D IO$_READVBLK | IO$M_NOFILTR | IO$M_NOECHO | IO$M_TIMED;
> static const unsigned terminators[2] =3D { 0, 1 << 0x04 || 0x15 };
> iostatus =3D SYS$QIOW (0, dbchan, iofunct, &iostat, 0, 0, &ubuf, sizeof(=
> ubuf), timeout, terminators, 0, 0);
>
> In all instances i have a serial sniffer between my port and the serial dev=
> ice and the expected data is going both ways. I don't understand why a buf=
> fer size of 1 seems to get the data, but the larger buffer size does not.
>
> If you don't have the time to educate me, I understand.
>
> I found one of the examples in sys$examples that refers to the terminator b=
> its as follows:
> /* The terminator mask has the <i>-th bit on if ASCII character <i> i=
> s to
> ** terminate a read when entered. This could also be done as a bitfi=
> eld
> ** structure. */
>
> struct term_mask {
> unsigned long int first_4; /* first 4 bytes last 2 bytes =
> */
> unsigned short int last_2; /* Terminator mask includes */
> } mask =3D { 1 << 0x0d, /* carriage return */
> 1 << 4 }; /* and "$"*/


The terminal driver is capable of just about anything you
might think of asking of it with regard to communicating
with a serial device. And, yes, single character reads
can sometimes work rather well. Also, if you understand
how to do asynchronous I/O, and how to do it right, you
may find double buffering helpful.

Remember a few things, though:

o Know the difference between directive level failures
(status from the _issuance_ of the $qio) vs. iosb
level failures, remembering that the iosb is useless
if you have a failure issuing the command to begin
with.

o Know how to use event flags

o Know about the fact that realtime activities -
examining the buffer while the i/o is underway,
for example - run afoul of high level language
constructs and optimization in general unless
you take special precautions, including the
use of the 'volatile' keyword in C.

o Be aware that without flow control, you have
a tough row to hoe with regard to data integrity.
Data can and will be dropped without you being
aware of it. To work around it you can try a
large alt typeahead buffer, of course. And, if
your code is trustworthy and won't go into a
mode that effectively blocks everyone else, you
can run at high priority, including realtime
priorities. Be aware that locking pages in
memory may be necessary if you want to be
aboslutely certain you can read your data
into memory before typeahead buffer overruns
occur.

Often it's easier just to find a way to
do actual flow control. Or to at least use
a protocol with counts and checksums/CRC's
to assure integrity.

o Reading with escape sequence termination
is an option. The escape secquences should
follow the appropriate standard as specified
in the I/O users guide.

o Most important: if you have a protocol that
must pass binary and must use special terminators,
you may want to use PASTHRU, perhaps also turning
off software flow control, typically in both
directions. Special read functions are available
for passing through all characters except possibly
your terminator.

George

George Cornelius

unread,
Jul 20, 2015, 2:57:08 AM7/20/15
to
> I found one of the examples in sys$examples that refers to the terminator
> bits as follows:
> /* The terminator mask has the <i>-th bit on if ASCII character <i> is to
> ** terminate a read when entered. This could also be done as a bitfield
> ** structure. */
>
> struct term_mask {
> unsigned long int first_4; /* first 4 bytes last 2 bytes */
> unsigned short int last_2; /* Terminator mask includes */
> } mask = { 1 << 0x0d, /* carriage return */
> 1 << 4 }; /* and "$"*/

The example looks a bit ugly.

If tmask is a 64 bit integer and you want to set,
say, bit 21 (CTRL/U - same as a NAK?), you could
do

#define CTRL_U 21


tmask |= ( 1 << CTRL_U );



It's been awhile since I have really done any heavy duty
serial port programming, and on the system I am posting
from I don't have any good examples. If you don't mind
something in Macro, however, you might find the following
almost trivial example helpful. It reads 256 characters
and puts them to an RMS file. Don't remember why I
wrote it but it has perhaps some ideas that could be
helpful.

IO$M_PURGE is strange. Maybe it clears the tupeahead
buffer before reading.

Hope it renders OK in your news client!

George

----------------------- %< -----------------------------

;GET256.MAR GFC 20060225 Get binary data
.psect i__data,quad,noexe,wrt
iefn=1
bytes=256
rtmo=20 ; read timeout in seconds

IdeviceD: .ascid /tt/ ; Input device

.align quad
tmask: .long 0,0 ; Short form - no terminators
iiosb: .long 0,0

obuf: .blkb bytes
obuf_l=.-obuf


.align quad
ofab: $fab fnm=<sys$output> - ; <output.bin> -
,rfm=var - ; rfm=fix
,mrs=256 -
,fac=put
.align quad
orab: $rab fab=ofab -
,rsz=256 -
,rbf=obuf -
,rsz=obuf_l
.align quad

ichan: .word 0,0

.psect p__code,quad,nowrt,exe

.macro check_err invalue=r0,target,?dummy,?aa
blbs invalue,aa
movl invalue,r0
jmp target
aa:
.endm


.entry get256,^M<R2,R3,R4,R5,R6,R7>
.show expansions

$assign_s IdeviceD,ichan
check_err r0,finup

$create fab=ofab
check_err r0,finup

$connect rab=orab
check_err r0,finup
;
calls #0,clrbuf
clrl iiosb
clrl iiosb+2
;
$qiow_s chan=ichan -
,func= -
#IO$_READVBLK!IO$M_NOECHO!IO$M_NOFILTR!IO$M_PURGE!IO$M_TIMED -
,iosb=iiosb -
,efn=#iefn -
,p1=obuf -
,p2=#obuf_l -
,p3=#rtmo - ; time to wait
,p4=#tmask ; terminator mask
check_err r0,finup
cvtwl iiosb,r0
cmpl r0,#SS$_TIMEOUT
beql 11$
check_err r0,finup
11$:
movw iiosb+2,orab+rab$w_rsz
$put orab
finup:
pushl r0
$close fab=ofab
movl (sp)+,r0
ret
;
; Zero obuf
;
.entry clrbuf,^M<R2,R3,R4,R5,R6>
movc5 #0,obuf,#0,#obuf_l,obuf ;0 inbuf bytes, 0 fill
movl #1,r0
ret

.end get256

----------------------- %< -----------------------------

Johnny Billquist

unread,
Jul 20, 2015, 6:33:13 AM7/20/15
to
On 2015-07-20 02:34, k...@kayceesoftware.com wrote:
> I'm using VMS 8.4 on I64 rx2600, latest tcpip and patches.
> I also tried the same on alpha vms 8.4 and alpha vms 7.3-2 with the same problem.
>
> I don't understand sys$qiow very well, but years ago i followed an example to get data from a serial port and it has worked well for years. It was usually small messages...less than 50 bytes and I called qiow with a short timeout and 1 byte buffer size. I just recursively called qiow until i got the end byte that the device sent (ETX 0x03).

[...]

SYS$QIOW is actually very easy to understand. It queue an I/O request,
and waits until it completes. So it's essentially two system calls
combined into one. The first is the queuing of the I/O request, and the
second is the wait for the completion. You can also do them separately.
That is what SYS$QIO is for.

That said, what you actually are having problems with is the I/O
functions provided by the terminal driver. The terminal driver is very
complex and provides tons of functionality.

From your description of what your protocol looks like on the serial
line, I would think the sensible way to do this would be to issue a read
in passall mode, so that the terminal driver do not interpret any
incoming characters as anything special. I would then add the
functionality of special terminators, and tell the driver exactly which
characters would finish the read. In your case, that would be EOT and
NAK. (Add a timeout if you really have a protocol where a timeout makes
sense, but do not use it to achieve some polling functionality.)

So you need to read up on how to use the terminal driver functions to do
this.

And apologies if my terminology is slightly off, as I might be mixing
terminology with RSX, which pretty much works the same way, but might
have slightly different names on things sometimes.

Johnny

--
Johnny Billquist || "I'm on a bus
|| on a psychedelic trip
email: b...@softjar.se || Reading murder books
pdp is alive! || tryin' to stay hip" - B. Idol

Neil Rieck

unread,
Jul 20, 2015, 6:35:10 AM7/20/15
to
Not sure if this example will help but it does show how to look for a specific terminator.

http://www3.sympatico.ca/n.rieck/demo_vms_html/bas_qio_demo.html

As others have already pointed out, sys$qio (and qiow) employ two return codes. The first represents the status of the queuing operation (did the OS accept it?) whilst the second (found in iosb) represents the status of the operation. You always need to test both.

A few other $qio demos can be found one level up and one of them involved TCPIP.

Neil Rieck
Kitchener / Waterloo / Cambridge,
Ontario, Canada.
http://www3.sympatico.ca/n.rieck/

Stephen Hoffman

unread,
Jul 20, 2015, 9:15:55 AM7/20/15
to
On 2015-07-20 00:34:41 +0000, k...@kayceesoftware.com said:

> I'm using VMS 8.4 on I64 rx2600, latest tcpip and patches.

So TCP/IP Services 5.7 with ECO 5.

> I don't understand sys$qiow very well...
> Now i want to read from a newer serial device, the message is XML with
> tons of wasted data....
> ...
> The message is 500-800 bytes and ends in EOT 0x04 or NAK. I thought
> from reading the VMS I/O manual that qiow would use any escape sequence
> as a terminator if I don't specify a terminator.
> ...T he TNA device/term is set ALTYPEAHD, in the past i think i got
> lucky as the message was always so small.

Could you provide a little more detail on the remote device and the TCP
port in use? XML usually isn't EOT- or NAK-delimited in general, nor
when accessed via telnet, which implies there might be something else
going on here, or that there might be an alternative approach toward
connecting to the remote device.

Now given that TCP is a stream — this streaming is a completely concept
for anybody that's been steeped in RMS and records — you could just
grab a kilobyte of data or whatever TCP has ready, then scan for the
EOT or NAK in the buffer, reading and appending new data onto the end
of the buffer as needed to find the end of the "record" being
transmitted.

TCP is not 1:1 for reads and writes, but there's likely no need to go
with a one-character read loop here, nor with any sort of special
termination handling from the terminal driver.


--
Pure Personal Opinion | HoffmanLabs LLC

k...@kayceesoftware.com

unread,
Jul 20, 2015, 10:38:05 AM7/20/15
to
Sorry about the typo in the 1 << 0x04 || 0x15....
It should have been bitwise OR, not logical OR.

Thanks for all the posts and hints, i'm still reading and trying to understand.
I do test the call status and the iosb status. The call status is normal and the iosb status changes to TIMEOUT when i increase the buffer size.

Itanium VMS 8.4, TCP 5.7 ECO 5, but also tried on other versions with same results.

The app reads student/faculty/staff ID cards. Is same device as credit card reader in other instances (Brands: Engenico, Verifon...).

In the FAR past was connected as LAT port and read as serial device. For 10+ years has been connected to varying linux thin clients with serial port set as raw pasthru mapped port, usually port 3001, then VMS side a TNA port defined.
Thin client running either puTTY or commercial VT emulator connecting via SSH.

The card readers used to return a simple fixed field text string, usually under 50 bytes. The newer models all return 500-800 bytes of XML with ETX CRC EOT as terminator.

I am used to RMS record programming, but this is good to learn. I send a wakeup message to the TNA port and it works as it has for years. I just want to switch from a 1 byte QIOW to 800 byte QIOW. I want to terminate with timeout or EOT or NAK. After reading the VMS I/O guide I thought it would be easy to make the change....but i'm missing something.

If I set NO terminators, what is the default? I thought it was NOT just CR, but any escape sequence? So I figured it would at least get something at the ETX. But I get TIMEOUT, and nothing in the buffer. If i switch it back to the 1 byte loop, i get the whole message...with a few random dropped bytes.

Again, thanks for all the help and pointers and advice.

Stephen Hoffman

unread,
Jul 20, 2015, 10:54:04 AM7/20/15
to
I'd probably open a socket connection to port 3001 on the specified
host, and grab the data directly from there. Then scan the buffer for
the delimiters, if those delimiters aren't some artifact of using
TNA0:. I'd expect that using sockets and a stream would be easier
than dealing with all this VMS $qio baggage.

If you haven't done C socket programming before, then start reading
Beej's guide here:

http://beej.us/guide/bgnet/

There's very little in that guide which does not apply to OpenVMS and
its C and socket API.

If you want to continue pounding on the brute-force old-school
it-drops-characters I'd-not-use-this-way approach, then look here:

http://www.digiater.nl/openvms/freeware/v80/hoffman_examples/qio_extended_read_3.c


That example shows ^Z (0x1a) as a terminator.

And again, TCP is a *stream* and *not* record-oriented. That single
TCP detail has burned more OpenVMS programmers than I care to count.

I'm mildly surprised you're reading that data via telnet and not via
SSL, too. I'd accordingly assume there's a VPN connection in use here.

Michael Moroney

unread,
Jul 20, 2015, 10:54:06 AM7/20/15
to
k...@kayceesoftware.com writes:

>If I set NO terminators, what is the default? I thought it was NOT just CR,
>but any escape sequence? So I figured it would at least get something at
>the ETX. But I get TIMEOUT, and nothing in the buffer. If i switch it
>back to the 1 byte loop, i get the whole message...with a few random
>dropped bytes.

Do you actually get any data transferred? If you issue a timed read for
800 bytes but you receive only 500 before the timer expires, you'll get
SS$_TIMEOUT status, but the IOSB will tell you that you did, in fact, get
500 bytes.

Bob Gezelter

unread,
Jul 20, 2015, 11:07:22 AM7/20/15
to
On Monday, July 20, 2015 at 2:14:33 AM UTC-4, George Cornelius wrote:
>
> o Know about the fact that realtime activities -
> examining the buffer while the i/o is underway,
> for example - run afoul of high level language
> constructs and optimization in general unless
> you take special precautions, including the
> use of the 'volatile' keyword in C.
>

George,

Actually, looking at the buffer while the IO pending (IOSB Status PENDING) is simply undefined.

Until the IOSB is set to the completion value, the contents of the buffer for ALL IO operations (not simply the terminal driver), are undefined. Thus, any code that looks at buffer contents prior to completion is simply incorrect.

- Bob Gezelter, http://www.rlgsc.com

k...@kayceesoftware.com

unread,
Jul 20, 2015, 11:24:26 AM7/20/15
to
On Monday, July 20, 2015 at 8:54:06 AM UTC-6, Michael Moroney wrote:
I get no data, and IOSB says zero bytes and TIMEOUT.

Johnny Billquist

unread,
Jul 20, 2015, 11:30:59 AM7/20/15
to
I'm not sure what the problem is. If you issue a read for 800 bytes,
with terminators, you will either get 800 bytes, or a timeout if one is
defined. Whichever happens first.

You also seem confused about what an escape sequence is. CR is not an
escape sequence, for example. Neither is NAK, nor ETX.

An escape sequence is a very specific sequence of characters that in
principal always starts with ESC. (There are some more possibilities if
you are using 8-bit control codes, but that is yet another story.)

In short, a normal read from the terminal driver will complete upon the
reception of a CR. The completion code will indicate that you got the
CR, and so on.
If you go into some mode, such as a read-pass-all, then CR is no longer
a terminator. Unless you define explicit terminators, and read with
special terminators, you do not have any terminators at all. The reads
will then only complete once you have read as much data as you specified.
If you have a timeout defined, and the timeout happens first, then your
I/O will instead finish with a timeout result.

Your description of XML do not match how XML looks like. There are no
ETX or similar stuff at the end of XML itself. So it would appear that
the device is sending some extra information outside of XML, which you
want to deal with as well. So XML is not really relevant here.

If you are getting timeouts when using a buffer size larger than 1, then
I wonder what timeout value you are using, as a buffer size of 2 (for
example) should not really be a problem, except it takes a while longer
to get 2 characters instead of 1.
Oh, and as this is all running over TCP, there are a whole bunch of
things that might cause interesting effects on the communication here.
Try to make sure you understand what you are doing at each step along
the way of the data...

k...@kayceesoftware.com

unread,
Jul 20, 2015, 11:42:06 AM7/20/15
to
Thanks Hoff.
I have been wondering the past few evenings if switching to direct socket would be better/faster/easier, but you are correct...i've never used socket programming either. I just thought that the switch from 1 byte QIO to multi byte would be simple.

The clients in question are on VPN and traffic restricted to intranet, so there is some limited security. Basically just validating a valid card...not validating that the holder of the card is the same. At some point, someone will sue someone (again) and we will have to have an armed guard taking DNA samples and validating card/pic/dna to actual presence.

I'll look at the socket examples, i need to learn that also for another project.

k...@kayceesoftware.com

unread,
Jul 20, 2015, 11:50:23 AM7/20/15
to
Thanks JB.
Your are correct the XML is irrelevent, it is just the message i must parse.
The messages is now ACK, STX, XML stuff, ETX, CRC, EOT.
I liked the SHORT, fixed length message, but that is history.
I don't have a problem parsing XML, i've been doing that for years.

I have tried a buffer size of 300 and still get nothing. The messages is always over 500 bytes and under 800, so I thought I should have gotten SOMETHING.

Stephen Hoffman

unread,
Jul 20, 2015, 11:59:34 AM7/20/15
to
On 2015-07-20 15:07:21 +0000, Bob Gezelter said:

> On Monday, July 20, 2015 at 2:14:33 AM UTC-4, George Cornelius wrote:
>>
>> o Know about the fact that realtime activities - examining the buffer
>> while the i/o is underway, for example - run afoul of high level
>> language constructs and optimization in general unless you take special
>> precautions, including the use of the 'volatile' keyword in C.
>
> ...any code that looks at buffer contents prior to completion is simply
> incorrect.

Interesting. Can't say I've ever thought about declaring with
volatile type for a $qio data buffer. The volatile type tells the
compiler not to optimize (cache) the loads. Adding the volatile
sort-of makes sense, but then AFAIK no present VMS C compiler caches a
data buffer, and no compiler should cache around a system service or C
library call.

Not that C99 (and prior) volatile handling and threading works at all
well together, and in C++11 volatile is explicitly not useful for
threading. But I digress.

In this case, VMS I/O post-processing guarantees that the operation
will be completed, the IOSB set non-zero and (if specified) the AST
fired without interruptions. You also get a memory barrier, which
deals with lower-level caching.

As Bob has correctly indicated, on either side of that VMS I/O
post-processing completion operation, there's garbage, and there's data.

So volatile is only necessary here if programmer suspects the compiler
is going to cache the buffer, and I'd hope that any compiler on VMS
that might try that — maybe for a really dinky I/O reading its data
into an int64_t, for instance? — would be smart enough not to allow
that caching to happen around a system service call that's in scope.
Based on a quick read of C11 Annex C Sequence Points, there are enough
sequence points involved with processing a system service call that
there should be no caching performed around a $qio or any other system
service, though IANALL (language lawyer). In short, it won't address
this case, and it won't alter anything here.

There's a _lot_ of VMS C code without the I/O buffers declared
volatile, too. AFAIK, it's not necessary.

Unlike C99, C11 does now default to a multithreaded machine environment
and does have better support for threading-related code, but that's not
available on VMS. But I digress again.

k...@kayceesoftware.com

unread,
Jul 20, 2015, 11:59:37 AM7/20/15
to
I'm using qiow modifiers of:
IO$_READVBLK | IO$M_NOFILTR | IO$M_NOECHO | IO$M_TIMED

Is there additional flags I should set to get all characters?

$show term tna1:
Terminal: _TNA1: Device_Type: Unknown Owner: No Owner
Remote Port Info: xxx.xxx.xxx.xxx:3001

Input: 9600 LFfill: 0 Width: 511 Parity: None
Output: 9600 CRfill: 0 Page: 24

Terminal Characteristics:
Interactive Echo Type_ahead Escape
Hostsync TTsync Lowercase Tab
Wrap Scope No Remote Eightbit
No Broadcast No Readsync No Form Fulldup
No Modem No Local_echo No Autobaud Hangup
No Brdcstmbx No DMA Altypeahd Set_speed
No Commsync Line Editing Overstrike editing No Fallback
No Dialup No Secure server No Disconnect Pasthru
No Syspassword No SIXEL Graphics No Soft Characters No Printer Port
Numeric Keypad No ANSI_CRT No Regis No Block_mode
No Advanced_video No Edit_mode No DEC_CRT No DEC_CRT2
No DEC_CRT3 No DEC_CRT4 No DEC_CRT5 No Ansi_Color
VMS Style Input <CTRL-H> Backspace

Simon Clubley

unread,
Jul 20, 2015, 12:18:02 PM7/20/15
to
> I'm using qiow modifiers of:
> IO$_READVBLK | IO$M_NOFILTR | IO$M_NOECHO | IO$M_TIMED
>
> Is there additional flags I should set to get all characters?
>
> $show term tna1:
> Terminal: _TNA1: Device_Type: Unknown Owner: No Owner
> Remote Port Info: xxx.xxx.xxx.xxx:3001
>
> Input: 9600 LFfill: 0 Width: 511 Parity: None
> Output: 9600 CRfill: 0 Page: 24
>
> Terminal Characteristics:
> Interactive Echo Type_ahead Escape
> Hostsync TTsync Lowercase Tab

If you are not using flow control, you need to turn off Hostsync and
TTsync.

I can't remember if they effectively get turned off when Pasthru is set,
but try turning them off anyway.

Jan-Erik Soderholm

unread,
Jul 20, 2015, 12:30:33 PM7/20/15
to
Now, a few other things...

We use something very similar. We create TNA devices against
different equipment on the factory floor. The TNA devices
are created with /Prot=none so there is no telnet protocol.

We also does a SET TERM/PERM/DEV=LA120 on the TNA devices.
I guess that is to get it into "hardcopy".

We also use EOT as terminator:

static short TermVec[4] = {0,0,0x0008,0x0000}; /* EOT */

The QIOW looks like:

sys_status = SYS$QIOW(0,chan_to_port,
IO$_READVBLK|IO$M_NOFILTR|IO$M_NOECHO|IO$M_TIMED,
&iosb_mail,
0,0,
&buffer,
maxmsg,
RecTime, /* Timeout time */
&TermVec,
0,0);

This works just fine, most data messages are in the
50-100 char range in lenght.

> I have tried a buffer size of 300 and still get nothing.

But was there any EOT in that block? Or did you use any
other terminator?

> The messages is always over 500 bytes and under 800...

How long messages does the terminal driver support?
I note that the SET TERM/WID has a max value of 511.

Doing a SET TERM/WIDTH=nnn also shows in a SH DEV/FU:

$ set term/wid=231 tna3001:/perm
$
$ sh dev tna3001:/fu
...
...
Reference count 0 Default buffer size 231
$

What is the buffer size of your TNA device set to?

I'm currently not sure if you can read a block over 511
(or thereabout) characters using the TNA device over the
terminal driver at all.

> ...so I thought I should have gotten SOMETHING.

If you get an timeout, and you have not seen any terminator,
I'm not sure you will see anything at all.


> If i switch it back to the 1 byte loop, i get the whole message...
> with a few random dropped bytes.

> varying linux thin clients with serial port set as raw pasthru
> mapped port,

And you are sure that it is not the port mapping in linux
that drops random bytes?

The scanners can not configured to send non-XML encoded data?

I would also look into either setting up something of your own
at the serial port of the linux box so that you can do some
simulation of your own without the card scanner, or do as below.

We have a setup where an 8 port Lantronix terminal server
has its ports looped in 4 pairs. That way we can run our
standard applications without modifications against one of
the ports (pretending that it is a PLC or whatever), then
using another VMS process (simulating the PLC), se send data
messages/packages to the other port in the pair. Works very
well...





Regards, Jan-Erik.

johnwa...@yahoo.co.uk

unread,
Jul 20, 2015, 12:33:11 PM7/20/15
to
Apologies if this is a daft question(s). It's in addition to (not
instead of other suggestions so far.

Are you at all familiar with VMS tcpdump, and is it available to you
here? Or alternatively its equivalent at the Linux end? Or even
wireshark somewhere in between?

If it is available, you have a relatively simple way of observing the
network traffic between the two boxes, which may be helpful.

For example, if the "card reader" isn't sending the data when you
request more than one character, you might want to look at why it
isn't. And in single character mode you could see whether the
characters that you expect to see ever actually appear on the
network, ie who is losing them.

I've seen cases where single-character reads are special-cased
somewhere along the way. It might or might not be relevant here.

Can you configure the "card reader" at all, e.g. to put a
newline/CR/etc at the end of the data, in case someone along
the way is mistakenly waiting for a newline?

Another semi-random suggestion:

$ SET HOST/DTE TNA1: (or whatever)
Ideally from a terminal (or emulator) with "Display Controls"
capability, so non-printing characters are visible. Don't
expect perfection, don't expect 100% match with what your
application will see. But it requires little effort and may
allow you to easily see the effect of changes to the config
in various places at the Linux end.

Also: You may want to set yourself up a real terminal (or
emulator) connected to a real serial port (if you have one)
and/or with a real Telnet port, and try typing by hand (or
scripting in the emulator) something resembling the data
you expect the "card reader" to send. And see what you get
on VMS, either in your application or (maybe) in SET HOST/DTE.

Lots of unknowns in this picture. You need to confirm which
pieces are working the way you expect them to, and look
closely at the rest. Best of luck.

johnwa...@yahoo.co.uk

unread,
Jul 20, 2015, 12:39:03 PM7/20/15
to
Hmmm. Interesting ideas. You've done this before haven't you :)

So have I, but probably not as recently as you.

Jan-Erik Soderholm

unread,
Jul 20, 2015, 12:39:30 PM7/20/15
to
Actualy, I have one Lantronix ETS8P setup in my office and
my hobbyists system connects to them.


$ sh dev tna

Device Device Error
Name Status Count
TNA0: Online 0
TNA3001: Online 0
TNA3002: Online 0
$

$ telnet
TELNET> show device tna3001:
TNA3001: BG16906: Outgoing Local: jescab2:50936
Remote: ETS8P:3001
TELNET> show device tna3002:
TNA3002: BG16907: Outgoing Local: jescab2:50937
Remote: ETS8P:3002

Port 1 and 2 are loopbacked with a short cable.

If it is possible to get an example of one of the XML
file (with dummy data of course), I could run a few
simple test using this loopbacked ports.


Jan-Erik.

>
>
>
>
> Regards, Jan-Erik.

Stephen Hoffman

unread,
Jul 20, 2015, 12:39:40 PM7/20/15
to
On 2015-07-20 15:59:36 +0000, k...@kayceesoftware.com said:

> Is there additional flags I should set to get all characters?

As was being discussed in a parallel thread just today, serial lines
and binary data is a bit of a mess, as you get to deal with in-band
flow control and other idiosyncracies of a fairly complex and old
stack. It's usually SET TERMINAL /PASTHRU (TT2$M_PASTHRU) that's
appropriate, and not the deprecated /PASSALL (TT$M_PASSALL) mechanism.

<http://www.itec.suny.edu/scsys/vms/ovmsdoc0731/731final/6136/6136pro_017.html>

If you're going to be working in this area, then the OpenVMS I/O
Abuser's Reference Manual (above link) is the OpenVMS $qio equivalent
of what Beej has provided for sockets. Plus the TCP/IP $qio
documentation will probably be in play here too, for some of what
you're up to.

Some more C socket examples:
http://www.linuxhowtos.org/data/6/server.c
http://www.linuxhowtos.org/data/6/client.c

Jan-Erik Soderholm

unread,
Jul 20, 2015, 12:45:17 PM7/20/15
to
Well, just simple "use what you have" type of solution... :-)

And yes, we use this regulary for the last tests before running
the final user acceptance tests in the factory.

If this was my problem I would probably start with checking if
the card readers aboslutely *has* to send XML formatted data.

Jan-Erik.

Stephen Hoffman

unread,
Jul 20, 2015, 12:50:32 PM7/20/15
to
On 2015-07-20 16:45:17 +0000, Jan-Erik Soderholm said:

> If this was my problem I would probably start with checking if the card
> readers aboslutely *has* to send XML formatted data.

If it does, then I have a port or two of libxml2 posted. Not the
newest and probably also not secure against rogue XML, but workable.

Jan-Erik Soderholm

unread,
Jul 20, 2015, 12:55:53 PM7/20/15
to
Den 2015-07-20 kl. 18:50, skrev Stephen Hoffman:
> On 2015-07-20 16:45:17 +0000, Jan-Erik Soderholm said:
>
>> If this was my problem I would probably start with checking if the card
>> readers aboslutely *has* to send XML formatted data.
>
> If it does, then I have a port or two of libxml2 posted. Not the newest
> and probably also not secure against rogue XML, but workable.
>
>

Doesn't solve the communication problem. The XML decoding
was never part of the problem as such. The XML is part
of the (possible) *size* issue with the message, and
libxml2 will not address that, does it?

Another solution would be to decode the XML on the linux
system and then send it in some simpler/plainer format to
the VMS box.

Jan-Erik Soderholm

unread,
Jul 20, 2015, 12:56:54 PM7/20/15
to
Sorry for my self-followup... :-)

I'd also like to get the actual brand and type number
of the card reader to look up its documentation.


George Cornelius

unread,
Jul 20, 2015, 1:04:33 PM7/20/15
to
In article <a1cd9359-51d6-46bc...@googlegroups.com>, Bob Gezelter <geze...@rlgsc.com> writes:
> On Monday, July 20, 2015 at 2:14:33 AM UTC-4, George Cornelius wrote:
>>
>> o Know about the fact that realtime activities -
>> examining the buffer while the i/o is underway,
>> for example - run afoul of high level language
>> constructs and optimization in general unless
>> you take special precautions, including the
>> use of the 'volatile' keyword in C.
>>
>
> George,
>
> Actually, looking at the buffer while the IO pending (IOSB Status PENDING) is simply undefined.

Yes, Bob. I took your course. And learned what all the bad
habits I was going to have to unlearn actually were.

When was that - 1989 or 1990?

But then you have taught a few.

> Until the IOSB is set to the completion value, the contents of the
> buffer for ALL IO operations (not simply the terminal driver), are
> undefined. Thus, any code that looks at buffer contents prior to
> completion is simply incorrect.

Doesn't mean that some of us haven't looked at the
way the device driver was implemented and, Dykstra's
recommendations be d*mned, written to the actual
infrastructure instead of doing it right and writing
to specifications.

Not with the terminal driver, of course, since it
is actually collecting its data in nompaged pool.
And not actually in VMS.

But if you have direct I/O and know that once the
I/O operation is underway that the hardware is
busy writing into your buffer, well...
you might be tempted.

My first system programming was in an IBM
minicomputer environment (1130/1800), way back
in the 60's, and son of a gun if IBM's command
parsing wasn't watching the characters arrive
from the 1442 card read punch so that the
command was already decoded by the time the
official I/O completion was posted.

But then that device was a bit odd to begin
with in that hell or high water it was going
to read a full 80 character buffer and not use
a channel I/O count like every other channel
based transfer would.

I was generally opposed to such things because
you had to be prepared to discard whatever was
done in advance if something went awry - but it
did work.

And you still need the volatile declaration
for your buffers if you do anything
asynchronous because when you ask for the
kth byte the HLL _might_ just remember the
value from the last time you asked for it
and return the same thing.

Remember that if you poll the IOSB and
it indicates completion you can go right
to the buffer without further ado.

George

k...@kayceesoftware.com

unread,
Jul 20, 2015, 1:09:31 PM7/20/15
to
The unit always sends XML 500-800 byte message, not configurable to change message.

As mentioned in first post, i have serial 'sniffer', that monitors messages going both ways. My messages get from VMS to client in full, and the return message comes in full immediately after i scan a card.

unsigned char ubuf[300] = "\0";
int timeout = 20; /* seconds */
static short TermVec[4] = {0,0,0x0008,0x0000}; /* EOT */
iofunct = IO$_READVBLK | IO$M_NOFILTR | IO$M_NOECHO | IO$M_TIMED;
iostatus = SYS$QIOW (0, dbchan, iofunct, &iostat, 0, 0, &ubuf, sizeof(ubuf),
timeout, &TermVec, 0, 0);

As Jan-Erik suggested I change my terminator to the above and I still get nothing in buffer and TIMEOUT.

If i ONLY change the ubuf size to 1, and send no terminator it works by getting one byte at a time. The message is over 500 bytes, so I would think that with a buffer size of 300 I would at least get the first 300 bytes. The QIO should terminate.

I MUST be missing something else that needs to be changed when getting a buffer bigger than 1 byte???

David Froble

unread,
Jul 20, 2015, 1:23:06 PM7/20/15
to
If you're interested in an example written in Basic, using the system
service interface for sockets, let me know. Some of us (maybe just 1 of
us) doesn't like C.

:-)

Stephen Hoffman

unread,
Jul 20, 2015, 1:29:20 PM7/20/15
to
On 2015-07-20 16:55:52 +0000, Jan-Erik Soderholm said:

> Doesn't solve the communication problem. The XML decoding was never
> part of the problem as such.

Should I have added a "FWIW"?

> The XML is part of the (possible) *size* issue with the message, and
> libxml2 will not address that, does it?

Nope. It was an aside, given the OP is working with XML code, and
given that the OP might not know that there are ports of XML-related
tools available for VMS.

> Another solution would be to decode the XML on the linux system and
> then send it in some simpler/plainer format to the VMS box.

Ayup. Though that then involves a library for JSON or creating some
potentially-arcane and potentially-private data format that's
sufficiently simplified for VMS, and it also pushes dependencies out to
outboard systems that may or may not be sufficiently flexible or
accessible. Systems such as the Linux box used here. There are
undoubtedly cases where this translation design does work, but it
inevitably involves translations and the construction of some other
format, and the maintenance of both the translator — itself possibly
based on libxml2, out on the Linux box — and the decoder, and whatever
test harnesses are necessary.

In short, dealing directly with the XML via libxml2 and then pushing
that to the local format might be more appropriate here.

Other than XML, JSON or that ilk, the sorts of data exchange formats
start to get rather more creative, or rather less flexible, or both.
VMS just isn't good at most of these. Not without added help, such as
libxml2 or a JSON library or other add-ons, or available libraries for
Python or other languages.

You're quite right that VMS is incapable of interoperating with
standard data-interchange formats without add-on help, too. That's
unfortunate.

But more to the point, compressing the data or otherwise reducing the
transfer transfer sizes might not help things if the underlying
transport is dropping characters, either. It might just reduce the
exposure to whatever's happening here that's causing data loss.

As stated earlier, I'd look to replace the telnet driver, the terminal
driver, the $qio calls and the rest with some native C socket calls.
And I'd likely parse the arriving XML data via libxml2.

David Froble

unread,
Jul 20, 2015, 1:34:44 PM7/20/15
to
Jan-Erik Soderholm wrote:

> What is the buffer size of your TNA device set to?
>
> I'm currently not sure if you can read a block over 511
> (or thereabout) characters using the TNA device over the
> terminal driver at all.

Minor nit ..

He's stated he's using the AltTypeAhead buffer, which can be large.
I've seen 2048 and 4096. Wait, I "think" I've seen 4096, maybe not.

Checking ...

SYSGEN> SHOW TTY_ALT*
Parameter Name Current Default Min. Max. Unit
Dynamic
-------------- ------- ------- ------- ------- ----
-------
TTY_ALTYPAHD 512 200 0 32767 Bytes

John E. Malmberg

unread,
Jul 20, 2015, 1:39:29 PM7/20/15
to
On 7/20/2015 12:09 PM, k...@kayceesoftware.com wrote:
> The unit always sends XML 500-800 byte message, not configurable to change message.
>
> As mentioned in first post, i have serial 'sniffer', that monitors messages going both ways. My messages get from VMS to client in full, and the return message comes in full immediately after i scan a card.
>
> unsigned char ubuf[300] = "\0";
> int timeout = 20; /* seconds */
> static short TermVec[4] = {0,0,0x0008,0x0000}; /* EOT */

You are specifying the terminator wrong.

> iofunct = IO$_READVBLK | IO$M_NOFILTR | IO$M_NOECHO | IO$M_TIMED;
> iostatus = SYS$QIOW (0, dbchan, iofunct, &iostat, 0, 0, &ubuf, sizeof(ubuf),
> timeout, &TermVec, 0, 0);

> I MUST be missing something else that needs to be changed when
> getting a buffer bigger than 1 byte???

For EOT, your TermVec should be either:

unsigned long TermVec[2] = {0, 0x10}

or

unsigned short TermVec[4] = {0, 4, 0x10}

According to 5.3.1.2 of the IO Abuser guide.

EOT is bit 5 in the mask.

Making it static is not needed for SYS$QIOW, and would require very
careful use for SYS$QIO, as you could end up with multiple active I/Os
sharing the same data.

Regards,
-John
wb8...@qsl.netork.
--
Currently looking for employment.

k...@kayceesoftware.com

unread,
Jul 20, 2015, 1:41:01 PM7/20/15
to
The XML side is not an issue. i have used libxml2 for years, and i have my own routines for handling XML for all the apps that i must interface with over the years. XML and JSON are not an issue here.

I feel like an old man looking for my glasses when they are on top of my head.

I have tried the multi byte QIOW with the older card readers and have the same problem. So I don't think it is the size of the newer units message. It does not get the return message even it is only a 50 byte message from the older unit.

I think i am just not getting a termination except TIMEOUT. If buffer size changes from 1 to 999, what is so different?

David Froble

unread,
Jul 20, 2015, 1:42:14 PM7/20/15
to
Yeah, it does sound strange.

With the 1 byte buffer, when data comes in, it fills the buffer, and the
I/O completes. It appears that if you're not filling the buffer, the
I/O is not completing. I'm sure I've handled that in the past, but,
it's been a long time ....

One hint, if you want to decrease the overhead, setting a buffer size of
2 will reduce the overhead by half, and you'll not see anything after
that that will match it. Of course, you're back to the same problem if
the last buffer gets only 1 character.

:-)

That puts you back to the original problem, and if you solve that, then
one I/O would do the job.

Bob Gezelter

unread,
Jul 20, 2015, 1:42:23 PM7/20/15
to
George,

Yes, I did teach several seminars on this and related topics.

I have also been called in when this class of code fails, often sporadically.

Knowledge of the infrastructure is dangerous. It can change (e.g., System/360 CCW Read Reverse).

In the case of error recovery, all bets are off as to intermediate (before completion) buffer contents. Simply put, when one executes a QIO, one yields full control of the specified buffer(s) to the driver/ACP. Until the driver/ACP signals completion (IOSB not equal to PENDING), the contents of the buffer are undefined.

Knowledge of the infrastructure is fleeting. What a driver for one disk/tape/device does is not the same as what is done for an equivalent device (or later revision). Only the specification can be relied upon.

johnwa...@yahoo.co.uk

unread,
Jul 20, 2015, 1:47:15 PM7/20/15
to
Sorry, should have asked for clarification of where the serial sniffer is.

I am still not clear on what you mean by "the return message comes in
full immediately after I scan a card". Comes in full *where*?

If your serial sniffer is between the Linux box and the card reader it
cannot tell you what traffic is reaching the VMS box. And what reaches
the VMS box may or may not reach your application, depending on
terminal driver settings, QIO options, available buffer space, etc.

Experts: Is AltTypeAhead really relevant to Telnet sessions? It's
relevant to hardware serial (no inherent flow control) and maybe
to LAT (can't remember for sure) but Telnet runs over TCP which in
principle has built in flow control of a sort...

Keep 'em coming.

John E. Malmberg

unread,
Jul 20, 2015, 1:48:32 PM7/20/15
to
On 7/20/2015 12:38 PM, John E. Malmberg wrote:
> On 7/20/2015 12:09 PM, k...@kayceesoftware.com wrote:
>> The unit always sends XML 500-800 byte message, not configurable to
>> change message.
>>
>> As mentioned in first post, i have serial 'sniffer', that monitors
>> messages going both ways. My messages get from VMS to client in full,
>> and the return message comes in full immediately after i scan a card.
>>
>> unsigned char ubuf[300] = "\0";
>> int timeout = 20; /* seconds */
>> static short TermVec[4] = {0,0,0x0008,0x0000}; /* EOT */
>
> You are specifying the terminator wrong.
>
>> iofunct = IO$_READVBLK | IO$M_NOFILTR | IO$M_NOECHO | IO$M_TIMED;
>> iostatus = SYS$QIOW (0, dbchan, iofunct, &iostat, 0, 0, &ubuf,
>> sizeof(ubuf),
>> timeout, &TermVec, 0, 0);
>
>> I MUST be missing something else that needs to be changed when
>> getting a buffer bigger than 1 byte???
>
> For EOT, your TermVec should be either:
>
> unsigned long TermVec[2] = {0, 0x10}
>
> or
>
> unsigned short TermVec[4] = {0, 4, 0x10}
Correction:
unsigned short TermVec[4] = {4, 0, 0x10, 0}

The first format is much simpler if you only have control codes as
terminators.

k...@kayceesoftware.com

unread,
Jul 20, 2015, 2:05:35 PM7/20/15
to
OK, i tried
unsigned long TermVec[2] = {0, 0x10}
Still no termination except when TIMEOUT.

serial sniffer/logger is between card reader and linux terminal.
I know it only tells me what is going to/from card reader...after that it's all in telnet session.

i know reader gets my message and responds correctly.

i know that if QIOW buffer size is 1, my app gets message.
if buffer > 1, I get nothing.

k...@kayceesoftware.com

unread,
Jul 20, 2015, 2:11:03 PM7/20/15
to
FWIW,
I've skimmed the beginning of Beej's socket programming guide, and I like the writing STYLE. a bit tongue-in-cheek and understandable for a beginner.

now back to income producing manual labor. irrigating, mowing, weeds, fencing, feeding....but NICE weather in Colorado for manual labor.

Jan-Erik Soderholm

unread,
Jul 20, 2015, 2:12:21 PM7/20/15
to
Den 2015-07-20 kl. 19:47, skrev John E. Malmberg:
> On 7/20/2015 12:38 PM, John E. Malmberg wrote:
>> On 7/20/2015 12:09 PM, k...@kayceesoftware.com wrote:
>>> The unit always sends XML 500-800 byte message, not configurable to
>>> change message.
>>>
>>> As mentioned in first post, i have serial 'sniffer', that monitors
>>> messages going both ways. My messages get from VMS to client in full,
>>> and the return message comes in full immediately after i scan a card.
>>>
>>> unsigned char ubuf[300] = "\0";
>>> int timeout = 20; /* seconds */
>>> static short TermVec[4] = {0,0,0x0008,0x0000}; /* EOT */
>>
>> You are specifying the terminator wrong.

That might have been me... :-)

*Our* original code looks like:

> static short TermVec[4] = {0,0,0x0008,0x0000}; /* ETX */

I simply thought that ETX and EOT both ment "end of text" (hex 04)
I see now that ETX is "end of transmission", hex 03.

The correct format for EOT should probably be, as others has
suggested:

>>> static short TermVec[4] = {0,0,0x0010,0x0000}; /* EOT */

That is, setting the next bit in the bitmap...

Sorry for the confusion!

Regards, Jan-Erik.

Jan-Erik Soderholm

unread,
Jul 20, 2015, 2:21:19 PM7/20/15
to
Den 2015-07-20 kl. 19:29, skrev Stephen Hoffman:
> On 2015-07-20 16:55:52 +0000, Jan-Erik Soderholm said:
>
>> Doesn't solve the communication problem. The XML decoding was never
>> part of the problem as such.
>
> Should I have added a "FWIW"?

Maybe, maybe not. :-) It had been said clearly that the
XML handling was not any issue.

>
> You're quite right that VMS is incapable of interoperating with standard
> data-interchange formats without add-on help, too.

First, I do not know if I have said that here. Second, I do not
see how any other system handles XML without XML tools. In other
words, the only difference is what is pre-installed or not, not?

Or, does these "other" systems not use libxml2 (or similar)? I thought
it was a tool originaly developed for "other" systems and then ported
to VMS. It isn't unique for VMS, is it?




Jan-Erik Soderholm

unread,
Jul 20, 2015, 2:23:57 PM7/20/15
to
The max buffer size for a TNA device is 511 bytes. FWIW.
I do not know if ALT_TYPEahead come into play here. There
seems to be different opinions on that.

Jan-Erik Soderholm

unread,
Jul 20, 2015, 2:31:38 PM7/20/15
to
Den 2015-07-20 kl. 17:50, skrev k...@kayceesoftware.com:
> Thanks JB. Your are correct the XML is irrelevent, it is just the
> message i must parse. The messages is now ACK, STX, XML stuff, ETX, CRC,
> EOT.

If you set the TermVec to include STX, does the QIOW terminates
on the STX (second byte sent) even with a buffer of > 1 ?

Something like:

> static short TermVec[4] = {0,0,0x0014,0x0000}; /* EOT and STX */

That is, bit number 3 (hex 02) and 5 (hex 04) set in the bitmap.

Can you scan/read somethin else that will produce a shorter XML
package? That is, a bit shorter then 500 bytes.

With a setup with a loopback cable on a terminal server
you could easily simulate messages of different lenght.

Jan-Erik.

Jan-Erik Soderholm

unread,
Jul 20, 2015, 2:35:30 PM7/20/15
to
Den 2015-07-20 kl. 20:31, skrev Jan-Erik Soderholm:
> Den 2015-07-20 kl. 17:50, skrev k...@kayceesoftware.com:
>> Thanks JB. Your are correct the XML is irrelevent, it is just the
>> message i must parse. The messages is now ACK, STX, XML stuff, ETX, CRC,
>> EOT.
>
> If you set the TermVec to include STX, does the QIOW terminates
> on the STX (second byte sent) even with a buffer of > 1 ?

And if it does, that points to the fact that your QIOW read
never sees (reach) the EOT character...

You might have to ditch the TNA device and bypass the
terminal driver.

John E. Malmberg

unread,
Jul 20, 2015, 2:52:58 PM7/20/15
to
Interesting mystery.

For TN and LT devices the ALTYPEAHEAD parameter needs to be set by the
TTY_DEFCHAR2 sysgen parameter or it has no effect, because these devices
do not have a /PERM characteristics. And that would make it set for all
serial devices, since once it is set, it can not be unset.

The system default for ALTYPEAHD is 400 bytes and it requires a reboot
to change it.

With out that, the TTY_TYPAHDSZ sets how much data you can read in, and
that default is 156 bytes. It also requires a reboot to change.

Which means that you can issue QIOW() reads up to TTY_TYPAHDSZ.
Anything larger will never complete because you have exhausted the
typeahead buffer.

If a reboot with larger parameters is not possible, probably the
alternative is to set up a chain of ASTs to always keep a READ queued on
the serial port.

That is a more complicated program of course.

Regards,
-John
wb8...@qsl.network

Stephen Hoffman

unread,
Jul 20, 2015, 3:21:00 PM7/20/15
to
On 2015-07-20 18:21:17 +0000, Jan-Erik Soderholm said:

> Den 2015-07-20 kl. 19:29, skrev Stephen Hoffman:
>> On 2015-07-20 16:55:52 +0000, Jan-Erik Soderholm said:
>>
>>> Doesn't solve the communication problem. The XML decoding was never
>>> part of the problem as such.
>>
>> Should I have added a "FWIW"?
>
> Maybe, maybe not. :-) It had been said clearly that the XML handling
> was not any issue.

That was not even remotely a question here, and libxml2 would most
obviously not resolve the stated issues within this rather complex
communications design.

>> You're quite right that VMS is incapable of interoperating with
>> standard data-interchange formats without add-on help, too.
>
> First, I do not know if I have said that here.

You did write the following in an earlier reply:

> Another solution would be to decode the XML on the linux system and
> then send it in some simpler/plainer format to the VMS box.

You're certainly correct there, too. It's quite true that VMS cannot
deal well with XML nor other standard formats as part of its standard
installation environment. JSON being another common choice for
encoding data these days, and that too is missing. In practice, VMS
does not have robust file format support. Though a good foundation is
available — not the least of which includes the remnants of CDA, as
ill-used and inconsistently-present as that tends to be — and this
foundation might be updated to allow operations with current-generation
tools and formats, there's more than a little work to integrate these
capabilities into the run-time environment, and into the tools. But
there is more than a little work here.

> Second, I do not see how any other system handles XML without XML
> tools. In other words, the only difference is what is pre-installed or
> not, not?

It's not just whether the system can deal with a particular common
format, but whether the system itself actually uses common formats.
Too often, folks end up reinventing formats and tools, whether that's
my oft-cited database, or support for UTF-8 for that matter — more than
a few folks have rolled their own databases here, with all the issues
that ensue — or having to scrounge up a current and secure version of
libxml2 or some other library, and where everybody tends to have those
pieces installed and ported and named and... entirely differently.

> Or, does these "other" systems not use libxml2 (or similar)? I thought
> it was a tool originaly developed for "other" systems and then ported
> to VMS. It isn't unique for VMS, is it?

You're using OpenVMS as an embedded system, and for an existing and
complex application. That's an entirely viable approach and a valid
model for your use case, and for folks with similar cases at other
existing sites.

But it's an approach that tends to shift more of the associated costs
onto the end-user of the system, as — for instance — you're now
responsible for keeping all those add-on parts current and updated.
Many of the competitive systems have libxml2 and many other tools
integrated and the vendor deals with the updates, and the available
OS-level integration is quite often well beyond what libxml2 provides.
UTF-8 support, for instance. Those capabilities and those add-on
parts are inherently not integrated into the base OS, too. For
instance, other systems have tools which allow easy access to
application-specific preferences using XML or JSON files, where VMS
applications will use a morass of home-grown configuration files and
logical names and what-not... this producing... well, producing what is
not exactly the paragon of consistency and clarity and simplicity that
VMS itself was classically known for.

For anybody that looks at new deployments of an operating system
platform, it's increasingly difficult to argue with deploying platforms
which have these and other tools available and integrated. That's less
"other" code I have to deal with, and means more time I can spend on
the code necessary for the application. Which is where OpenVMS started
out for many of us — the consistency and the completeness of VMS and
the layered products meant rather less "other" stuff I had to deal with.

Reinventing and reimplementing stuff — whether it's reinventing what
socket calls would provide, or rolling your own database using RMS sans
robust online backup, or porting and managing XML parsing, or whatever
— is increasingly unnecessary and expensive complexity. Competitive
operating systems provide these and other features, and the operating
system developers and the end-users can and do use these features to
provide a better experience for their customers.

Yes, existing VMS sites can and do have to deal with this stuff. Often
themselves. New sites and new applications for existing VMS sites?
They can choose the platform.

Johnny Billquist

unread,
Jul 20, 2015, 3:48:47 PM7/20/15
to
Agree that I would expect the read to complete at 300 chars if you put
that size in there, and you know that more than 300 chars are received.

Could you start by experimenting with just reading 2 bytes and see if
that completes. And then go to 4, and so on, ans see where it stops working?

Johnny

--
Johnny Billquist || "I'm on a bus
|| on a psychedelic trip
email: b...@softjar.se || Reading murder books
pdp is alive! || tryin' to stay hip" - B. Idol

Johnny Billquist

unread,
Jul 20, 2015, 3:57:18 PM7/20/15
to
I'm curious. When you have an active read in a program, do VMS actually
limit you to the typeahead buffer size parameter of the system for the read?

In RSX, the typeahead buffer is where data is stored before a read is
active. Once a read is started, data is copied from the typeahead buffer
into the program buffer, and you can read way larger amounts of data
than the typeahead buffer would allow.
(I/O size limit in RSX is about 8K, the size of a page.)
Which is also applicable to terminals that goes over telnet.

It seems weird if VMS could not complete a terminal read of more than
about 200 bytes.

George Cornelius

unread,
Jul 20, 2015, 4:58:06 PM7/20/15
to
In article <487ca8ab-2a75-47a7...@googlegroups.com>, Bob Gezelter <geze...@rlgsc.com> writes:
> Yes, I did teach several seminars on this and related topics.
>
> I have also been called in when this class of code fails, often sporadically.
>
> Knowledge of the infrastructure is dangerous. It can change (e.g., System/
> e60 CCW Read Reverse).
>
> In the case of error recovery, all bets are off as to intermediate (before =
> completion) buffer contents. Simply put, when one executes a QIO, one yield=
> s full control of the specified buffer(s) to the driver/ACP. Until the driv=
> er/ACP signals completion (IOSB not equal to PENDING), the contents of the =
> buffer are undefined.
>
> Knowledge of the infrastructure is fleeting. What a driver for one disk/tap=
> e/device does is not the same as what is done for an equivalent device (or =
> later revision). Only the specification can be relied upon.
>
> - Bob Gezelter, http://www.rlgsc.com

Actually, Bob, rather than confuse everyone, I should have
pointed out that it is the IOSB which is key. Declare it
volatile, and when it signals completion you are free to
treat the remaining data areas as well-behaved.

My real reason for declaring all sorts of things volatile
in asynchronous I/O has in its roots AST programming, and
in that case, there may be a lot of things changing when
you do not expect them to. The compiler may not know, for
example, that an AST completion routine may have started
many I/O's in addition to the one your main code used to
start the whole process going.

It is not really much more of a stretch to realize that
the O/S is asynchronous code as well. Any buffer or
data structure whose address is retained and modified
asynchronously is in that sense volatile.

The real reason we believe the IOSB is sufficient
to protect those asynchronously changing areas is that
we hope, and generally trust, that the O/S and the
compiler play well together.

I've just become more paranoid over time as compilers
became smarter and smarter and I became less knowledgeable
as to what they were doing under the covers.

Oh, and read reverse was a marvelous idea, although it
must have been rather expensive to have to put all of
that extra infrastructure into all the mainframe I/O
channel hardware just for that single class of device,
magnetic tapes. We actually had mainframe tape drives
but the read reverse functionality was not present in
our channel hardware.

George

David Froble

unread,
Jul 20, 2015, 5:22:21 PM7/20/15
to
Been down this road before, wondering if the scenery has changed ...

I looked at an XML parser. What I took away from that was that the XML
parser checked an XML file for correct format. What it did NOT do is
give me the information I wanted from the XML file.

Frankly, what do I care about the "correctness" of an XML file? If I
need a customer number, I still had to parse on <Customer number> and
</Customer number> to get the data. If the format was not correct, and
I could not find a customer number, then I'd just toss the entire
transmission. Not much different from tossing it for failing an XML
parser test, right?

Now, maybe things have changed since that time. Don't know.

I keep seeing these "tools" and such getting rave reviews. But if they
don't really do anything for me, then I got to ask, what good are they,
other than some check box for someone evaluating environments?

Stephen Hoffman

unread,
Jul 20, 2015, 5:27:04 PM7/20/15
to
On 2015-07-20 20:54:10 +0000, George Cornelius said:

> The real reason we believe the IOSB is sufficient to protect those
> asynchronously changing areas is that we hope, and generally trust,
> that the O/S and the compiler play well together.

Using $synch or otherwise waiting on an event flag is typical here, or
an AST, and that involves passing through synchronization points.

If the C code is explicitly (and inefficiently) spinning on the IOSB
entirely using local and in-line code, that might well be vulnerable to
compiler caching. But then a C compiler could choose to optimize the
associated block of C code, as there's no activity in scope that should
change the behavior of the code, too — volatile might well be the only
way to get that to work. If you're sharing code between the AST and
the mainline, then you definitely do need to deal with the asynchrony.

Some semi-related LLVM and Clang C reading:
<http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html>
<http://css.csail.mit.edu/stack/>
<http://llvm.org/docs/Atomics.html>

Stephen Hoffman

unread,
Jul 20, 2015, 6:04:54 PM7/20/15
to
On 2015-07-20 21:24:45 +0000, David Froble said:

> I looked at an XML parser. What I took away from that was that the XML
> parser checked an XML file for correct format. What it did NOT do is
> give me the information I wanted from the XML file.

libxml2 can extract data from an XML. I've used it for that purpose, too.

XML is more work initially than would be a simpler parser, but it
allows (many) changes the XML format without having to deal with the
parser again.

Like more than a few other pieces of code now around, it's a C API.
It's not going to be much fun to use from BASIC.

Some examples:
<http://xmlsoft.org/examples/>
<http://stackoverflow.com/questions/303845/how-to-use-libxml2-to-modify-an-existing-xml-file>

<http://charette.no-ip.com:81/programming/2010-01-03_LibXml2/>

Given the choice, I'd probably use JSON over XML. But both work. No,
I haven't tried porting libjson to VMS.

Rob Brown

unread,
Jul 20, 2015, 9:25:42 PM7/20/15
to
On 2015-07-20, k...@kayceesoftware.com <k...@kayceesoftware.com> wrote:
> If i ONLY change the ubuf size to 1, and send no terminator it works by
> getting one byte at a time.

What happens if set the buffer length to 1 and also specify the
terminator table?

k...@kayceesoftware.com

unread,
Jul 21, 2015, 2:25:57 AM7/21/15
to
Perhaps the manual labor cleared my head. Nothing like digging post holes and stretching barb wire to in the hot sun to give perspective!

I turned on rx2600, thin client, and card reader, defined fresh telnet connection to mapped port. Used same code as earlier except that i added NAK to terminator mask like:
unsigned long TermVec[2] = {0, 1 << 0x04 | 1 << 0x15}; /* EOT & NAK */

It all worked as expected and I have not dropped a single byte. Tests great and response seems much faster than 1 byte buffer with loop manually building string until i got to EOT.

Thanks for all the help and advice!!! I've had been playing around with
$set term/perm/.... params and I'm guessing that the fresh reboot of the thin client and new TNA session picked up the changes. I had tried logging out of VMS session and rebooting the card reader many times and that had not helped.
I hope it was not the reboot of the rx2600, although I will test that and other scenarios before this moves to production Itaniums and Alphas.

Hopefully I can implement this version soon and learn something about direct TCP sockets and change the code to socket communication.

Always something to learn and the office in loft, overlooking the creek is much appreciated after hard manual labor.

FWIW, the new multi byte QIOW call works fine with the older card readers also and with some digital scales that were polled with the older 1 byte reads.

Thanks again everyone.

George Cornelius

unread,
Jul 21, 2015, 3:13:25 AM7/21/15
to
In article <mojp0b$17u$1...@dont-email.me>, Stephen Hoffman <seao...@hoffmanlabs.invalid> writes:
> On 2015-07-20 20:54:10 +0000, George Cornelius said:

>> The real reason we believe the IOSB is sufficient to protect those
>> asynchronously changing areas is that we hope, and generally trust,
>> that the O/S and the compiler play well together.
>
> Using $synch or otherwise waiting on an event flag is typical here, or
> an AST, and that involves passing through synchronization points.

Yes, $synch may be important.

I know that in the past I have written code, perhaps not in VMS,
that checked whether an I/O had already completed before attempting
to go on to other activities. For example, a single character read
may have completed immediately because data was present in the
typeahead buffer, and I might want assume I can save an extra call
to $synch by just checking the IOSB immediately after issuing the
I/O.

But if I declare the buffer volatile, I may be able to assume
everything I process from the buffer after the IOSB check will
be freshly fetched, at the cost, of course, of bypassing any
optimizations the compiler might have used to overlap memory
fetches with other activities or to reuse data that has just
recently fetched. [Hmm. Are there extra Alpha memory barriers
present as well before each fetch from a buffer declared
volatile?]

> If the C code is explicitly (and inefficiently) spinning on the IOSB
> entirely using local and in-line code, that might well be vulnerable to
> compiler caching. But then a C compiler could choose to optimize the

I am never certain about these things. If I have

volatile unsigned long iosb[2];
char *buf[BUFLEN];

main(int argc,char **argv) {

[...]

and after a sys$qio() do

sys$synch(...);
if ( buf[0] == 'Y' )
process_successful_completion();

do I really know the compiler did not choose to prefetch
buf[0] sometime ahead of the time the sys$synch() was issued,
since, after all, the sys$synch() call does not reference the
buffer at all? I certainly cannot assume the compiler knows
what a sys$synch() is and will change its code generation
based upon its presence.

George

George Cornelius

unread,
Jul 21, 2015, 4:02:53 AM7/21/15
to
In article <d74e80f6-07f7-4dd7...@googlegroups.com>, k...@kayceesoftware.com writes:
> Perhaps the manual labor cleared my head. Nothing like digging
> post holes and stretching barb wire to in the hot sun to
> give perspective!
>
> I turned on rx2600, thin client, and card reader, defined fresh
> telnet connection to mapped port. Used same code as earlier
> except that i added NAK to terminator mask like:

> unsigned long TermVec[2] = {0, 1 << 0x04 | 1 << 0x15}; /* EOT & NAK */

That's good news.

Hope I did not mislead you when I made my comments about the
terminator mask. I was making wrong assumptions when I looked
at that sample code I provided, and did not recall at all
the extra complexity having to do with the first longword
specifying whether the second merely contained a 32 bit mask
or was a pointer to an array of bytes containing up to a
full 256 bit mask.

Once I got past that I was able to modify my sample program
to use the assembler equivalent of << (@) to initialize the
2nd element of my tmask array to use your terminators and
verify that that worked.

> It all worked as expected and I have not dropped a single byte.
> Tests great and response seems much faster than 1 byte buffer
> with loop manually building string until i got to EOT.

I perhaps gave you more reason to be alarmed than was
warranted when I made my comments about issues related
to the lack of flow control. Serial ports are generally
slow enough that it is not difficult to stay ahead of
them, especially if you use large enough buffers and
have some kind of handshake after each transfer. And
if the underlying infrastructure is tcp, it has its own
flow control as well.

But somewhere I have a manual that discusses realtime
programming in VMS, one that points out that VMS is
designed as a general purpose operating system and
not one designed to guarantee a certain response time,
and even if you use realtime priority levels various
features such as the use of virtual memory can make
deterministic or nearly deterministic timings
difficult to achieve.

> Thanks for all the help and advice!!!

You're welcome.

George

Jan-Erik Soderholm

unread,
Jul 21, 2015, 5:55:44 AM7/21/15
to
Den 2015-07-21 kl. 08:25, skrev k...@kayceesoftware.com:
> Perhaps the manual labor cleared my head. Nothing like digging post
> holes and stretching barb wire to in the hot sun to give perspective!
>
> I turned on rx2600, thin client, and card reader, defined fresh telnet
> connection to mapped port. Used same code as earlier except that i
> added NAK to terminator mask like: unsigned long TermVec[2] = {0, 1 <<
> 0x04 | 1 << 0x15}; /* EOT & NAK */
>

First, really nice that it works, of course. But I still have
a few questions... :-)

You wrote:

> The messages is now ACK, STX, XML stuff, ETX, CRC, EOT.

Where does the NAK come into play here? Are you sure that it
hadn't work after the restart even with only the EOT bit set?


> It all worked as expected and I have not dropped a single byte. Tests
> great and response seems much faster than 1 byte buffer with loop
> manually building string until i got to EOT.

So you get a full, up to 800 byte, message using one QIOW call now?

Stephen Hoffman

unread,
Jul 21, 2015, 8:15:12 AM7/21/15
to
On 2015-07-21 07:09:43 +0000, George Cornelius said:

> In article <mojp0b$17u$1...@dont-email.me>, Stephen Hoffman
> <seao...@hoffmanlabs.invalid> writes:
>>
>> Using $synch or otherwise waiting on an event flag is typical here, or
>> an AST, and that involves passing through synchronization points.
>
> Yes, $synch may be important.
> ...
> But if I declare the buffer volatile, I may be able to assume
> everything I process from the buffer after the IOSB check will be
> freshly fetched...

Please read about "synchronization points" and the handling of volatile
in the C11 specs. Annex C, IIRC.

John Reagan

unread,
Jul 21, 2015, 8:48:45 AM7/21/15
to
On Tuesday, July 21, 2015 at 3:13:25 AM UTC-4, George Cornelius wrote:

> sys$synch(...);
> if ( buf[0] == 'Y' )
> process_successful_completion();
>
> do I really know the compiler did not choose to prefetch
> buf[0] sometime ahead of the time the sys$synch() was issued,
> since, after all, the sys$synch() call does not reference the
> buffer at all? I certainly cannot assume the compiler knows
> what a sys$synch() is and will change its code generation
> based upon its presence.
>
> George

Since you took the address of 'buf' for the $QIO, the C frontend tells GEM that the address was taken (think 'weak volatile'). That should then cause the call to $SYNCH to be a fence.

k...@kayceesoftware.com

unread,
Jul 21, 2015, 11:09:48 AM7/21/15
to
When I send a message to the card reader I get back either:
a) ACK,STX,XML stuff, ETX,CRC,EOT or
b) NAK

The parse of the XML works fine and the CRC calc to verify no lost bytes is fine. When I validate XML and CRC, I send back a single ACK. That's it.
It did work with only the EOT set as terminator...i tried that first.

I do get all message sizes with one QIOW now. Testing so far I have been getting messages of 300-750 bytes, buffer size is set at 999 currently.

k...@kayceesoftware.com

unread,
Jul 21, 2015, 11:27:10 AM7/21/15
to
attaching code in case anyone else is newbie at QIOW. This should be good starting point.
The app user login has this:
$telnet/create xxx.xxx.xxx.xxx 3001 1 ! defines/creates TNA1
$def/nolog CARD_PORT TNA1: ! TNA number based on last param above
$set/term/perm/speed=9600/altyp/nobroad/nottsyncnohost/pasthru TNA1:
The app user logout has this:
$telnet/delete_session 1

C function as it currently works:

char *fxhot(int timeout)
{
static char response[1056];
static $DESCRIPTOR (name_desc, "CARD_PORT");
long int iofunct, iostatus;
unsigned short iostat[4];
unsigned long TermVec[2] = {0, 1 << 0x04 | 1 << 0x15}; /* EOT & NAK */
unsigned char ubuf[999]="\0";

memset(response, (char)NULL, sizeof(response)); /*clear response str */

if (dbchan == 0)
iostatus = SYS$ASSIGN (&name_desc, &dbchan, 0, 0);

/* IO$M_TIMED uses P3, by value, in seconds; check iostat for timeout*/
/* iostat[0] == SS$_TIMEOUT if timeout is reached, SS$_NORMAL if not */
iofunct = IO$_READVBLK | IO$M_NOFILTR | IO$M_NOECHO | IO$M_TIMED;
iostatus = SYS$QIOW (0, dbchan, iofunct, &iostat, 0, 0, &ubuf, sizeof(ubuf),
timeout, &TermVec, 0, 0);

/*printf("\033[5;1Hstatus=%d, %d characters read: '%s' with terminator %d\n",
iostatus, iostat[1], ubuf, iostat[2] );*/

if (iostat[0] == SS$_TIMEOUT)
{
ubuf[0] = 001; /* force SOH; test for this in call function */
printf("\033[4;1HTIMED OUT");
}
response[1055] = '\0';
strcpy(response, ubuf);
iostatus = SYS$DASSGN (dbchan);
dbchan = 0;
return (response);
}

Simon Clubley

unread,
Jul 21, 2015, 3:08:07 PM7/21/15
to
Will this still be the same with your LLVM port ?

Based on my direct experiences with bare metal programming using gcc for
some different variants of this, I would be uncomfortable relying on this
with unknown future compilers.

BTW, I don't know what current gcc versions do here. Variables modified
in ways not visible to the compiler _always_ get the volatile treatment
from me these days.

Simon.

--
Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP
Microsoft: Bringing you 1980s technology to a 21st century world

Stephen Hoffman

unread,
Jul 21, 2015, 3:20:40 PM7/21/15
to
On 2015-07-21 15:27:09 +0000, k...@kayceesoftware.com said:

Entirely FWIW... (Do I need to put further disclaimers here?)

> attaching code in case anyone else is newbie at QIOW. This should be
> good starting point.
> ...
> C function as it currently works:
>
> char *fxhot(int timeout)
> {
> static char response[1056];

I'd consider using a #define for the buffer sizes, rather than
constants. There's probably also no need for a static buffer
declaration here, either — unless there's something happening with this
buffer beyond what's shown in this module, such as accessing this
buffer after this function has gone out of scope.

> static $DESCRIPTOR (name_desc, "CARD_PORT");
> long int iofunct, iostatus;
> unsigned short iostat[4];

I'd likely use the IOSB data structure declaration from iosbdef.h. The
IOSB contents such as the status and the other fields are then
accessable via iosb.iosb$w_status, or iosb.iosb$w_bcnt, or
iosb.iosb$l_dev_depend, or analogous.

If it's not enabled, I would probably also enable __NEW_STARLET for new
C code — that's better about catching argument mismatches on the system
services, and on local function calls. That's via the following:

#define __NEW_STARLET 1

This'll trigger various diagnostics and warnings in most C code, around
argument mismatches.

> unsigned long TermVec[2] = {0, 1 << 0x04 | 1 << 0x15}; /* EOT & NAK */
> unsigned char ubuf[999]="\0";

n.b. you can do variable declarations in-line now. Just declare the
variable before you use it. No need to have a wad of variables at the
top of a function any more.

> memset(response, (char)NULL, sizeof(response)); /*clear response str */
>
> if (dbchan == 0)
> iostatus = SYS$ASSIGN (&name_desc, &dbchan, 0, 0);

I'm assuming that dbchan is declared with a wider scope; somewhere else.

You should capture any $assign errors here. See below for comments on
returning a struct from this function, too. That check would normally
be something akin to the following, using a macro from the stsdef.h
include file:

if ( !$VMS_STATUS_SUCCESS( iostatus ) {
return iostatus;
}

>
> /* IO$M_TIMED uses P3, by value, in seconds; check iostat for timeout*/
> /* iostat[0] == SS$_TIMEOUT if timeout is reached, SS$_NORMAL if not */
> iofunct = IO$_READVBLK | IO$M_NOFILTR | IO$M_NOECHO | IO$M_TIMED;
> iostatus = SYS$QIOW (0, dbchan, iofunct, &iostat, 0, 0, &ubuf,
> sizeof(ubuf), timeout, &TermVec, 0, 0);

If you're not going to allocate your own event flag via lib$get_ef,
then use EFN$C_ENF from efndef.h and not EF 0.

I'd handle any $qiow errors here. These errors can and do happen, and
they'll generally happen before anything happens to the contents of the
IOSB.

if ( !$VMS_STATUS_SUCCESS( iostatus ) {
return iostatus;
}

>
> /*printf("\033[5;1Hstatus=%d, %d characters read: '%s' with terminator %d\n",
> iostatus, iostat[1], ubuf, iostat[2] );*/
>
> if (iostat[0] == SS$_TIMEOUT)
> {
> ubuf[0] = 001; /* force SOH; test for this in call function */
> printf("\033[4;1HTIMED OUT");
> }

I would probably handle other IOSB errors from $qiow here:

if ( !$VMS_STATUS_SUCCESS( iostat[0] )) {
return iostat[0];
}

> response[1055] = '\0';

I'd probably use a preprocessor #define constant here; for the buffer
size and for this near-the-end null. This null is not necessary, as
you've zeroed the buffer above. I *think* you might have meant to
place this after the following strcpy (strncpy) call? If you're
really unlucky, ubuf will return 999 characters and you'll be in deep
sneakers with the following strcpy, or you'll get something less than
that and ubuf will have non-null characters for the rest of the buffer
and you'll be in deep sneakers with the strcpy — ubuf was not zeroed
out.

> strcpy(response, ubuf);

I'd avoid using strcpy, strlen, and friends in all current and new C
code, and would use strncpy here. This to ensure that the call doesn't
overrun the target buffer.

> iostatus = SYS$DASSGN (dbchan);
> dbchan = 0;
> return (response);

Since you're returning a response here, you can't (also) return a
status — unless you return a struct containing both (which is very
easy, but many folks don't know C can do that
<http://stackoverflow.com/questions/9653072/return-a-struct-from-a-function-in-c>),
or can return the data or the status via a global variable (ugh), or
can write the data or status values via pointers in the argument list.

Craig A. Berry

unread,
Jul 23, 2015, 10:07:02 PM7/23/15
to
On 7/21/15 2:20 PM, Stephen Hoffman wrote:

> n.b. you can do variable declarations in-line now. Just declare the
> variable before you use it. No need to have a wad of variables at the
> top of a function any more.

The definition of "now" in this context is C99 or C11 (or C++). If
portability is a concern (which it isn't here because of the VMS system
service calls), you would want to avoid declarations after statements as
that is forbidden in C89 (aka ISO C90). Most large codebases that have
been around any length of time and/or have an interest in portability
still target C89, and that includes most major open source projects.

So in other words go ahead and put your declarations anywhere you want
if it's private, non-portable code with a known dependency on a compiler
that allows that. If you need to be able to compile on a variety of
compilers (including quite recent versions of Microsoft's MSVC) you'll
need to follow the C89 rule on this. (Though you've always been able to
put declarations at the beginning of a block rather than the beginning
of the function.)

David Froble

unread,
Jul 24, 2015, 11:50:39 AM7/24/15
to
Craig A. Berry wrote:
> On 7/21/15 2:20 PM, Stephen Hoffman wrote:
>
>> n.b. you can do variable declarations in-line now. Just declare the
>> variable before you use it. No need to have a wad of variables at the
>> top of a function any more.

If there is anything that would make code harder to read, at least for
me, it would be this ....

Old dog, tricks, beware ....

Stephen Hoffman

unread,
Jul 24, 2015, 2:40:27 PM7/24/15
to
Can't help with that. It does mean that there's no need to have to
keep a second window open on the variable declarations while working
with the code. The variables aren't declared far from the code. (Not
that a good IDE isn't a massive help here, as can be a compiler that
can tell you when a variable is no longer being used.)

As for Microsoft C support for C99 from another reply, they've been
supporting what's common with C++98 and C++11 for a while (and AFAIK,
that includes this feature), and the Microsoft folks are now further
along with C99 support than is OpenVMS:
<http://blogs.msdn.com/b/vcblog/archive/2013/07/19/c99-library-support-in-visual-studio-2013.aspx>.

Bob Koehler

unread,
Jul 24, 2015, 4:51:49 PM7/24/15
to
This old dog like it. Mean I don't have to jump to the top of the
file to remember what I declared a variable as, or to add a new one.
Everything tends to be near the code I'm writing.

Craig A. Berry

unread,
Jul 24, 2015, 6:37:56 PM7/24/15
to
On 7/24/15 1:40 PM, Stephen Hoffman wrote:

> As for Microsoft C support for C99 from another reply, they've been
> supporting what's common with C++98 and C++11 for a while (and AFAIK,
> that includes this feature),

Not this feature. The following is with Visual Studio 2012. Possibly
it's finally changed with 2013 or 2015, but I don't have ready access to
test those at the moment and of course it will be some years before
those can be relied on as minimum versions in the wild for folks writing
portable code.

C:\workdir> type testdecl.c
#include <stdio.h>

int
main()
{
int i = 123;
printf("i is %d\n", i);
int j = 456;
printf("j is %d\n", j);
}
C:\workdir> cl testdecl.c
Microsoft (R) C/C++ Optimizing Compiler Version 17.00.61030 for x64
Copyright (C) Microsoft Corporation. All rights reserved.

testdecl.c
testdecl.c(8) : error C2143: syntax error : missing ';' before 'type'
testdecl.c(9) : error C2065: 'j' : undeclared identifier

It's a horrible, inscrutable error message, but if you look it up on
StackOverflow or elsewhere it's what the C standard calls "declaration
after statement" as in my subject line.

clang and gcc cannot be made to care even with -std=c89. I believe there
are other compilers besides Microsoft's that do care, though (it might
be HP's compiler for HP-UX, but I could be misremembering).

BTW, I'm not saying it's a bad feature. It's just one that can't be
relied on in code that's expected to be portable.

> and the Microsoft folks are now further
> along with C99 support than is OpenVMS:
> <http://blogs.msdn.com/b/vcblog/archive/2013/07/19/c99-library-support-in-visual-studio-2013.aspx>.

About half of what Microsoft added in 2013 has been in the CRTL for many
years, though some of it is in the wrong place (fp.h rather than
math.h). But yes, everyone agrees the CRTL needs a great deal of work. I
hope we can also agree Microsoft is not the exemplar for getting up to
snuff with the C and C++ standards.

Stephen Hoffman

unread,
Jul 25, 2015, 9:26:21 AM7/25/15
to
On 2015-07-24 22:37:55 +0000, Craig A. Berry said:

> On 7/24/15 1:40 PM, Stephen Hoffman wrote:
>
>> As for Microsoft C support for C99 from another reply, they've been
>> supporting what's common with C++98 and C++11 for a while (and AFAIK,
>> that includes this feature),
>
> Not this feature. The following is with Visual Studio 2012. Possibly
> it's finally changed with 2013 or 2015, but I don't have ready access
> to test those at the moment and of course it will be some years before
> those can be relied on as minimum versions in the wild for folks
> writing portable code.
> ...
> BTW, I'm not saying it's a bad feature. It's just one that can't be
> relied on in code that's expected to be portable.

If Visual C 2013 or later can't deal with this directly — there's no
local Microsoft Windows 8.1 or beta 10 boxes to confirm that here —
then the LLVM Clang compiler works on Windows, and can be integrated
with Visual Studio 2013 and later. Which means that Windows users
have access to C11 and C++11 support.
<http://llvm.org/docs/GettingStartedVS.html>.

At least OpenVMS got as far as the compiler support for C99, even if
the RTL omissions require hauling over your own source bits from
OpenBSD and such, and occasionally hacking the OpenVMS header files.

I'm not seeing much C11 usage among what's getting ported, but that'll
undoubtedly start appearing in the wilds. The threading and atomics
support will be useful on OpenVMS. The not-OpenVMS compilers I'm
using already have C11 support.

The VSI folks here are faced with a most a wonderfully bad choice, as
they'll arguably be wrong either way they go: with C11 support via
Clang and whatever alterations — not really upgrades — they can
reasonably fit into Clang for compatibility with old OpenVMS code, or
by hauling the old C99 GEM-based front-ends forward and retrofitting
those for C11 and later where they can. Based on some of the comments
made, they're pondering the latter approach. Hopefully that GEM-based
approach dies out quickly after the x86-64 porting dust settles, and
folks using the OpenVMS front-end are encouraged to move onto C11 with
fewer OpenVMS-isms. (VSI will be faced with what to do with C++1z
(~2017?) support too, and likely also what to do with some new C draft
that will probably be underway. Best guess: VSI will ignore the drafts
or then-new standards for a few years. This stuff is a treadmill.
But I digress.)

>> and the Microsoft folks are now further along with C99 support than is
>> OpenVMS:
>> <http://blogs.msdn.com/b/vcblog/archive/2013/07/19/c99-library-support-in-visual-studio-2013.aspx>.
>>
>
> About half of what Microsoft added in 2013 has been in the CRTL for
> many years, though some of it is in the wrong place (fp.h rather than
> math.h). But yes, everyone agrees the CRTL needs a great deal of work.

VSI has a plethora of work ahead of them, with C11and C++14 support and
updates to the other languages and all the other tools and features and
authentication and encryption and such, and a whole pile of other OS
updates. They also don't have the staff to deal with all of this
stuff, and really can't have the staff — not without the license
revenues to fund all of the work. Which is why I'd hope that finishing
out C99 and adding a few BSD C bits and sorting out IP and socket
support in C makes the cut. Enough to get PostgreSQL ported over, to
remove the need for jacket-hackery to get standard behavior, and to
make (at least) C99 code more easily portable.

> I hope we can also agree Microsoft is not the exemplar for getting up
> to snuff with the C and C++ standards.

I'm citing Microsoft as an organization that has finally moved off
their assumptions, and has started moving forward. Redmond has awoken.
There are some parallels here with OpenVMS, too. Now whether there
are sufficient revenues?

RobertsonEricW

unread,
Jul 25, 2015, 2:28:20 PM7/25/15
to
On Saturday, July 25, 2015 at 9:26:21 AM UTC-4, Stephen Hoffman wrote:
> On 2015-07-24 22:37:55 +0000, Craig A. Berry said:
>
> > On 7/24/15 1:40 PM, Stephen Hoffman wrote:
> >
> >> As for Microsoft C support for C99 from another reply, they've been
> >> supporting what's common with C++98 and C++11 for a while (and AFAIK,
> >> that includes this feature),
> >
> > Not this feature. The following is with Visual Studio 2012. Possibly
> > it's finally changed with 2013 or 2015, but I don't have ready access
> > to test those at the moment and of course it will be some years before
> > those can be relied on as minimum versions in the wild for folks
> > writing portable code.
> > ...
> > BTW, I'm not saying it's a bad feature. It's just one that can't be
> > relied on in code that's expected to be portable.
>
> If Visual C 2013 or later can't deal with this directly -- there's no
> local Microsoft Windows 8.1 or beta 10 boxes to confirm that here --
> then the LLVM Clang compiler works on Windows, and can be integrated
> with Visual Studio 2013 and later. Which means that Windows users
> have access to C11 and C++11 support.
> <http://llvm.org/docs/GettingStartedVS.html>.
>
> At least OpenVMS got as far as the compiler support for C99, even if
> the RTL omissions require hauling over your own source bits from
> OpenBSD and such, and occasionally hacking the OpenVMS header files.
>
> I'm not seeing much C11 usage among what's getting ported, but that'll
> undoubtedly start appearing in the wilds. The threading and atomics
> support will be useful on OpenVMS. The not-OpenVMS compilers I'm
> using already have C11 support.
>
> The VSI folks here are faced with a most a wonderfully bad choice, as
> they'll arguably be wrong either way they go: with C11 support via
> Clang and whatever alterations -- not really upgrades -- they can
> reasonably fit into Clang for compatibility with old OpenVMS code, or
> by hauling the old C99 GEM-based front-ends forward and retrofitting
> those for C11 and later where they can. Based on some of the comments
> made, they're pondering the latter approach. Hopefully that GEM-based
> approach dies out quickly after the x86-64 porting dust settles, and
> folks using the OpenVMS front-end are encouraged to move onto C11 with
> fewer OpenVMS-isms. (VSI will be faced with what to do with C++1z
> (~2017?) support too, and likely also what to do with some new C draft
> that will probably be underway. Best guess: VSI will ignore the drafts
> or then-new standards for a few years. This stuff is a treadmill.
> But I digress.)
>
> >> and the Microsoft folks are now further along with C99 support than is
> >> OpenVMS:
> >> <http://blogs.msdn.com/b/vcblog/archive/2013/07/19/c99-library-support-in-visual-studio-2013.aspx>.
> >>
> >
> > About half of what Microsoft added in 2013 has been in the CRTL for
> > many years, though some of it is in the wrong place (fp.h rather than
> > math.h). But yes, everyone agrees the CRTL needs a great deal of work.
>
> VSI has a plethora of work ahead of them, with C11and C++14 support and
> updates to the other languages and all the other tools and features and
> authentication and encryption and such, and a whole pile of other OS
> updates. They also don't have the staff to deal with all of this
> stuff, and really can't have the staff -- not without the license
> revenues to fund all of the work. Which is why I'd hope that finishing
> out C99 and adding a few BSD C bits and sorting out IP and socket
> support in C makes the cut. Enough to get PostgreSQL ported over, to
> remove the need for jacket-hackery to get standard behavior, and to
> make (at least) C99 code more easily portable.
>
> > I hope we can also agree Microsoft is not the exemplar for getting up
> > to snuff with the C and C++ standards.
>
> I'm citing Microsoft as an organization that has finally moved off
> their assumptions, and has started moving forward. Redmond has awoken.
> There are some parallels here with OpenVMS, too. Now whether there
> are sufficient revenues?

Yes this is the real business "hat trick" that VSI must execute successfully. The hardest part for VSI right now is determining the "financially optimal" schedule for the development and release of the multitude of candidate tool and OS feature improvements that maximizes the return on the initial startup investment monies that are currently being consumed in order to "launch" VSI into metaphorical orbit. This is an extremely critical phase of business development for VSI; not so much the case for Microsoft. Anything that goes wrong during the metaphorical "launch and ascent" phases is potentially fatal to VSI. By comparison, Microsoft is in the metaphorically analagous phase of "orbital correction" which is much less fraught with danger because they have plenty of cash (metaphorical fuel) so even if Microsoft were to screw up the "orbital correction", recovery is still possible. In VSI's case, screw ups are most likely fatal. It will be interesting to see and/or hear what VSI's initial development and rollout plans look like.

Arne Vajhøj

unread,
Jul 25, 2015, 2:41:07 PM7/25/15
to
On 7/24/2015 6:37 PM, Craig A. Berry wrote:
> On 7/24/15 1:40 PM, Stephen Hoffman wrote:
>> As for Microsoft C support for C99 from another reply, they've been
>> supporting what's common with C++98 and C++11 for a while (and AFAIK,
>> that includes this feature),
>
> Not this feature. The following is with Visual Studio 2012. Possibly
> it's finally changed with 2013 or 2015,

It was added in 2013.

But before that most people would work around it by compiling the code
as C++.

> But yes, everyone agrees the CRTL needs a great deal of work. I
> hope we can also agree Microsoft is not the exemplar for getting up to
> snuff with the C and C++ standards.

They are not leading but they are catching up.

Arne


Stephen Hoffman

unread,
Jul 25, 2015, 6:05:14 PM7/25/15
to
On 2015-07-25 13:26:16 +0000, Stephen Hoffman said:

> At least OpenVMS got as far as the compiler support for C99, even if
> the RTL omissions require hauling over your own source bits from
> OpenBSD and such, and occasionally hacking the OpenVMS header files.

Right on cue, encountered a rather large accumulation of C code that's
using the #include_next pragma in its header files.

That's a GCC extension for hacking changes into existing header files,
and avoiding a recursive #include.

That pragma is missing from OpenVMS C. It's also one I've not had to
deal with yet, which means determining some new and pragmatic solution.

That's in addition to #include <stdint.h> that's being referenced in
that same accumulation of C code, and which is one of the missing bits
of C99 support.

John Reagan

unread,
Jul 25, 2015, 6:21:14 PM7/25/15
to
I had not heard of "include_next" until now. Interesting... And from the GCC docs: "The use of '#include_next' can lead to great confusion. We recommend it be used only when there is no other alternative."

That said, I'll put it on my list. "stdint.h" is already there. I hit it pretty quickly after I started compiling LLVM. My first_include has much of the missing header.

David Froble

unread,
Jul 25, 2015, 6:36:52 PM7/25/15
to
RobertsonEricW wrote:

> Yes this is the real business "hat trick" that VSI must execute
> successfully. The hardest part for VSI right now is determining the
> "financially optimal" schedule for the development and release of the
> multitude of candidate tool and OS feature improvements that
> maximizes the return on the initial startup investment monies that
> are currently being consumed in order to "launch" VSI into
> metaphorical orbit. This is an extremely critical phase of business
> development for VSI; not so much the case for Microsoft. Anything
> that goes wrong during the metaphorical "launch and ascent" phases is
> potentially fatal to VSI. By comparison, Microsoft is in the
> metaphorically analagous phase of "orbital correction" which is much
> less fraught with danger because they have plenty of cash
> (metaphorical fuel) so even if Microsoft were to screw up the
> "orbital correction", recovery is still possible. In VSI's case,
> screw ups are most likely fatal. It will be interesting to see and/or
> hear what VSI's initial development and rollout plans look like.


Hint ....

1) insure Basic is working on day 1

2) a well implemented and documented TCP/IP

3) capability to use cheap development systems

I'll be happy

:-)

Craig A. Berry

unread,
Jul 25, 2015, 6:44:48 PM7/25/15
to
This one is so common and is such low-hanging fruit I hope VSI gets to
it sooner rather than later. It's really just a few typedefs and macros
based on types that already exist and then including it from inttypes.h.
Filling out all the missing formatting-related macros in inttypes.h
might be a bit more work as that may entail changes to the printf and
scanf family of functions in the CRTL.

Stephen Hoffman

unread,
Jul 25, 2015, 7:40:21 PM7/25/15
to
On 2015-07-25 22:21:12 +0000, John Reagan said:

> I had not heard of "include_next" until now. Interesting...

First I've seen of the #include_next directive used in the wild, but
it's quite clearly useful for porting code across platforms. There are
~20 examples in this code to contend with.

It's somewhat analogous to the gnv$ include support
(GNV_CC_NO_MODULE_FIRST, gnv$first_include.h, etc) for what you can do,
but the #include_next is much more targeted.

Chris Scheers

unread,
Jul 27, 2015, 7:29:49 PM7/27/15
to
Try renaming your file to testdecl.cpp and try again.

I've noticed that some features are enable/disabled depending on the
file extension.

--
-----------------------------------------------------------------------
Chris Scheers, Applied Synergy, Inc.

Voice: 817-237-3360 Internet: ch...@applied-synergy.com
Fax: 817-237-3074

k...@kayceesoftware.com

unread,
Aug 11, 2015, 6:38:59 PM8/11/15
to
this is slightly related issue only as it pertains to the same serial comm to a card reader.
to refresh: vms 8.4 IA64, tcpip 5.7 ECO 5, C 7.3-018
sys$qiow working fine now and seems very stable, my problem was getting the terminator mask correct.

I've been reading on sockets and will be converting to that mode soon for another project and probably change this serial code at that point.

BUT, in researching a very random NAK of my comm, i've found that the CRC sometimes calcs a line feed (LF, ox0a), and the stored string shows ONLY the LF i put in it....but the message that ends up at the card reader has CRLF, which is then rejected as invalid.

The terminal port (TNA1) is set pasthru, the VMS IO Ref Manual says IO$M_NOFORMAT and TT2$M_PASTHRU are basically the same.

So, is it the TT driver, or tcp, or something else converting the LF to CRLF?
And....what flag(s) do I need to set to have full passthru?

Stephen Hoffman

unread,
Aug 11, 2015, 7:10:04 PM8/11/15
to
You're going to have to narrow down which application code path is
generating that string.

It's probably that there are different code-paths here, or there's a
path which doesn't initialize a shared structure, or one that doesn't
set NOFORMAT, etc.

FWIW, I've found sockets much easier, and much more maintainable.
While I'd usually recommend following Beej over what the OpenVMS
examples show — the OpenVMS examples tend to be pretty dusty — there
are some socket source examples provided with TCP/IP Services:

$ dir tcpip$examples:*.c

Directory SYS$COMMON:[SYSHLP.EXAMPLES.TCPIP]

TCPIP$ECHO_SERVER_PLUS.C;1 TCPIP$SCTP_CLIENT.C;1
TCPIP$SCTP_CLIENTX.C;1 TCPIP$SCTP_SELECT_SERVER.C;1
TCPIP$SCTP_SERVER.C;1 TCPIP$TCP_CLIENT_QIO.C;1
TCPIP$TCP_CLIENT_SOCK.C;1 TCPIP$TCP_SERVER_QIO.C;1
TCPIP$TCP_SERVER_QIO_AUXS.C;1 TCPIP$TCP_SERVER_SOCK.C;1
TCPIP$TCP_SERVER_SOCK_AUXS.C;1 TCPIP$UDP_CLIENT_QIO.C;1
TCPIP$UDP_CLIENT_SOCK.C;1 TCPIP$UDP_SERVER_QIO.C;1
TCPIP$UDP_SERVER_SOCK.C;1

Total of 15 files.

Johnny Billquist

unread,
Aug 11, 2015, 7:53:10 PM8/11/15
to
While I cannot answer, I should repeat what I pointed out before. The
"telnet" protocol is really just a TCP stream, with a couple of things
thrown in. 0xff is special, and you are expected to use the network
virtual terminal convention/protocol. One thing with that is about how
to deal with CR and LF. And depending on various parameters and
configurations, this could throw a wrench in your communication.

Running tcpdump and capture the traffic would be the easiest way to
confirm if the data transmitted contains a CR, or if the receiving end
adds it.

After that, you might want to continue hunting in greater depth wherever
the trail leads you...

Johnny

--
Johnny Billquist || "I'm on a bus
|| on a psychedelic trip
email: b...@softjar.se || Reading murder books
pdp is alive! || tryin' to stay hip" - B. Idol

Jan-Erik Soderholm

unread,
Aug 12, 2015, 4:12:00 AM8/12/15
to
Den 2015-08-12 kl. 01:53, skrev Johnny Billquist:
> On 2015-08-12 00:38, k...@kayceesoftware.com wrote:
>> this is slightly related issue only as it pertains to the same serial
>> comm to a card reader.
>> to refresh: vms 8.4 IA64, tcpip 5.7 ECO 5, C 7.3-018
>> sys$qiow working fine now and seems very stable, my problem was getting
>> the terminator mask correct.
>>
>> I've been reading on sockets and will be converting to that mode soon for
>> another project and probably change this serial code at that point.
>>
>> BUT, in researching a very random NAK of my comm, i've found that the CRC
>> sometimes calcs a line feed (LF, ox0a), and the stored string shows ONLY
>> the LF i put in it....but the message that ends up at the card reader has
>> CRLF, which is then rejected as invalid.
>>
>> The terminal port (TNA1) is set pasthru, the VMS IO Ref Manual says
>> IO$M_NOFORMAT and TT2$M_PASTHRU are basically the same.
>>
>> So, is it the TT driver, or tcp, or something else converting the LF to
>> CRLF?
>
> While I cannot answer, I should repeat what I pointed out before. The
> "telnet" protocol is really just a TCP stream, with a couple of things
> thrown in.

You can use TNA ports/devices without using the telnet protocol.
Just use /prot=none.

JF Mezei

unread,
Aug 12, 2015, 9:58:38 AM8/12/15
to
On 15-08-11 18:38, k...@kayceesoftware.com wrote:

> The terminal port (TNA1) is set pasthru, the VMS IO Ref Manual says IO$M_NOFORMAT and TT2$M_PASTHRU are basically the same.

I am not sure if you really use the full TT driver when using telenet
and if all functionality is supported. Someone else could confirm.

The problem here is that the Telnet protocol itself is not transparent
and a few constructs that allow session management (for instance, an
escape character to get to command mode). There are also exchanges early
on to define session characteristics.

Abnd I believe that line termination in Telnet is "standardized" on the
link. The client sees its local line termination and *may* send a
standard line termination instead (not sure of this).

> So, is it the TT driver, or tcp, or something else converting the LF to CRLF?
> And....what flag(s) do I need to set to have full passthru?


There is a way when you setup the TN device to make it behave as a dumb
TCP link.

If TT driver is involved it is only at the generic level and there would
be the underlying telenet driver below.

Johnny Billquist

unread,
Aug 12, 2015, 3:23:33 PM8/12/15
to
Do you have any specific information what that implies? The normal
behavior under Unix is that if you talk on a different port than 23, the
telnet negotiation is not performed. For many, this is the "telnet
protocol". The special interpretation of 0xff as well as the NVT
handling is still in effect. But that is under Unix. So I'm curious if
the *exact* behavior of that switch under VMS is documented.

Any way, tcpdump is still an excellent tool to start finding out what is
happening where.

(I guess my point being that the "telnet protocol" is a very unclear
thing to start with.)

Jan-Erik Soderholm

unread,
Aug 12, 2015, 3:40:12 PM8/12/15
to
I do not have anything more then online HELP and the TCPIP
user manual (same text at both sources) :

TELNET> help create /protocol

CREATE_SESSION

/PROTOCOL

/PROTOCOL=options

Optional. Default: NONE. Options include:

o NONE

Data is sent with no interpretation (raw).

o NVT

Network Virtual Terminal (NVT), TELNET's internal
representation of a standard network terminal. NVT format
is standard 7-bit ASCII code transmitted in 8-bit octets, the
canonical form of data representation used by both the client
and server.

o TELNET

Standard TELNET protocol.

o RLOGIN

Standard RLOGIN protocol.



Topic?


And I also know from 15 years of setting this up for equipment,
that *nothing* apart from what we write to the TNAxxx devices
in the QIO(W) is actualy sent on the line.

Jan-Erik.



Johnny Billquist

unread,
Aug 12, 2015, 4:21:34 PM8/12/15
to
Thanks for that info. While not definitive, it do sound as if perhaps
NONE really means none. That still leaves a lot of question marks,
though. So I'd still recommend tcpdump to find out what actually goes
over the net.

(And the "telnet protocol" is such a broken term... :-/ )

Jan-Erik Soderholm

unread,
Aug 12, 2015, 4:25:08 PM8/12/15
to
We haven't used any line trafic dump tool, but we have used
"raw" ports at the other side, and I know that PLCs and
other equipment never seens anything apart from the actual
content of the TCPIP package, the same data as we put in
into the QIO(W) call.

Never mind, I have lost track on who was having some
trouble with this. It wasn't us anyway... :-)

Jan-Erik.

k...@kayceesoftware.com

unread,
Aug 12, 2015, 5:18:46 PM8/12/15
to
as a quick test i changed my qiow and added
IO$M_NOFORMAT even though the VMS I/O manual says that NOFORMAT and NOPASTHRU are 'basically' the same.
I took out NOPASTHRU at the QIOW level, but the terminal TNA device is still set to nopasthru at login.
It has been working all day with hundreds of tests on a busy network.
I don't think I'm going to try to figure out the differences as I want to change it to socket communication asap.
It's working and bosses are happy, and hopefully they'll let me have time to switch to socket comm.

Jan-Erik Soderholm

unread,
Aug 12, 2015, 5:23:13 PM8/12/15
to
Den 2015-08-12 kl. 23:18, skrev k...@kayceesoftware.com:
> as a quick test i changed my qiow and added IO$M_NOFORMAT even though
> the VMS I/O manual says that NOFORMAT and NOPASTHRU are 'basically' the
> same. I took out NOPASTHRU at the QIOW level, but the terminal TNA
> device is still set to nopasthru at login. It has been working all day
> with hundreds of tests on a busy network. I don't think I'm going to try
> to figure out the differences as I want to change it to socket
> communication asap.

> It's working and bosses are happy,...

That are the two things that says "do not touch anything" to me. :-)

> and hopefully they'll let me have time to switch to socket comm.
>

I might have missed something at the beginning, but why mess with
it, if it is working and bosses are happy?


Stephen Hoffman

unread,
Aug 12, 2015, 5:47:39 PM8/12/15
to
On 2015-08-12 21:23:18 +0000, Jan-Erik Soderholm said:

> Den 2015-08-12 kl. 23:18, skrev k...@kayceesoftware.com:
>
>> It's working and bosses are happy,...
>
> That are the two things that says "do not touch anything" to me. :-)

Stopping at working code is a low-cost and low-effort strategy and
which often works for some years, but can also be how more than a few
projects and products end up too expensive or outclassed or even
unmaintainable.

Technical debt tends to accumulate, unfortunately.

>> and hopefully they'll let me have time to switch to socket comm.
>
> I might have missed something at the beginning, but why mess with it,
> if it is working and bosses are happy?

Refactoring is generally performed to clarify code, to lower
maintenance, to move to common code, and/or to simplify future
extensibility. Sometimes for performance or portability, too.

While it is certainly possible to spend too much time refactoring, it's
also possible — or even easier — to not spend enough time cleaning up
code, and particularly when you know and understand the code and the
requirements — rather than revisiting the code sometime later, when you
don't.

k...@kayceesoftware.com

unread,
Aug 12, 2015, 6:27:11 PM8/12/15
to
I agree Hoff,
and the bosses (today) agree.

The next project requires use of socket ports and changing this recent card reader app to use sockets makes sense for LOTS of reasons. some of the card reader manufacturers are going to ip ports only, the code will be more portable (major issue now for us), and it is a more direct comm with less middleware...just to name a few.

And I definitely cobbled the code together knowing I was going to redo it via sockets. As per my original post on this thread I am NOT very literate on qio/w, nor do I want to be. This is only the 2nd time i've used sys$qio in 29 years. The other code has been VERY stable for 29 years and it just reads all keyboard input 1 byte at a time

JF Mezei

unread,
Aug 12, 2015, 8:28:41 PM8/12/15
to
On 15-08-12 17:18, k...@kayceesoftware.com wrote:
> as a quick test i changed my qiow and added
> IO$M_NOFORMAT even though the VMS I/O manual says that NOFORMAT and NOPASTHRU are 'basically' the same.

Actually, you want PASTHRU.. NOPASTHRU means there is filterin/handling
of data.

Is PASSALL still supported ?

I believe NOFORNAT means that requests for specific input format are
ignored (never used them, not sure if it is just the mask or if there
are actual formats available (think COBOL ACCEPT statement that might
want certain formats for numbers).


JF Mezei

unread,
Aug 12, 2015, 8:30:46 PM8/12/15
to
On 15-08-12 17:47, Stephen Hoffman wrote:

> Stopping at working code is a low-cost and low-effort strategy and
> which often works for some years,

Many times, one gets something working, but the wrong way, and continued
research yields far mroe efficient techniques that work better and while
for that project may not yield advantages, will have great value for
next project.

So understanding why something works or doesn't work in one project
helps for subsequent ones.

JF Mezei

unread,
Aug 12, 2015, 8:35:18 PM8/12/15
to
On 15-08-12 18:27, k...@kayceesoftware.com wrote:

> The next project requires use of socket ports and changing this recent card reader app to use sockets makes sense


Yes,. But remember that the IP drivers lack many functions available on
the terminal driver, most notably the SS$M_TIMEOUT that cancels an IO
after X seconds of not receiving the data. You now have to roll your own
implementation with even flags for both the IO and the timer and makes
for far less clean code.

If you use the C routines for the IP stack (unix socket stuff) then of
course you have no access to timeout stuff. Makes it harder for a
program to be robust when soemthing goes wrong on the link or the remote
device and it fails to receive enough data to end the IO.

That is my biggest beef with the IP stack. the TIMMEOUT made for really
neat AST driven code for terminal driver and as I recall the DECNET
driver too (not sure I recall). moving to the IP stack made for ugly code.

Also, remember that with socketsm you have no garantee that code arrives
in a single packet, so you have to have code that assembles paclets into
a single buffer until you are satisfied the buffer is full.



Stephen Hoffman

unread,
Aug 12, 2015, 8:52:50 PM8/12/15
to
On 2015-08-12 22:27:10 +0000, k...@kayceesoftware.com said:

> ...The other code has been VERY stable for 29 years and it just reads
> all keyboard input 1 byte at a time

One keystroke at a time, I hope.

ps/JF: $ help crtl poll
<http://beej.us/guide/bgnet/output/html/multipage/pollman.html>
<http://h71000.www7.hp.com/doc/82final/6529/6529pro_018.html#r_poll>

k...@kayceesoftware.com

unread,
Aug 12, 2015, 9:07:05 PM8/12/15
to
On Wednesday, August 12, 2015 at 6:52:50 PM UTC-6, Stephen Hoffman wrote:
> On 2015-08-12 22:27:10 +0000, kc@ said:
>
> > ...The other code has been VERY stable for 29 years and it just reads
> > all keyboard input 1 byte at a time
>
> One keystroke at a time, I hope.

Look out, Hoff can read my mind! :)
I did mean 1 keystroke at a time. I was trying to eat ice cream and type and hold a conversation with a 4 year old that showed up with the ice cream. I guess i was only paying attention to the ice cream. I should have put the keyboard down and focused on the 4 year old.

David Froble

unread,
Aug 12, 2015, 10:21:58 PM8/12/15
to
So, you mean he should re-write everything in Basic?

:-)
It is loading more messages.
0 new messages