The first arg is the handle returned by CreateMailslot.
The second arg is the name of a variable that you have set to the maximum number of bytes you wish to allow for the next record. If you do not wish to set a specific limit, then you can omit this arg (and do not need to set any variable).
The third arg is the name of the variable where you want GetMailslotInfo to return the size (in bytes) of the next record.
The fourth arg is the name of the variable where you wish GetMailslotInfo to return the count of how many records are currently queued in the mailslot. If you do not need this count, then you can omit the arg.
The fifth arg is the name of a variable you have set to the number of milliseconds that you're prepared to wait for ReadFile to return the contents of the next record (which may not yet have arrived). You can omit this arg if you don't wish to set a limit.
We have FUNCDEF'ed GetMailslotInfo so that, if it fails to return information about the next record, then it will return an empty string and save the operating system error number so that we can fetch it with RXFUNCERRMSG().
Even if GetMailslotInfo does not return an error, it may still be that there is no record to read. After all, if you have told GetMailslotInfo not to wait forever for a record to arrive, it may return without obtaining any information about the next record's size. In this case, GetMailslotInfo will not return an empty string, but rather, will indicate that the next record's size is -1.
/* Get the size of the next record */ err = GetMailslotInfo(handle, , msgSize) /* Check for an error */ IF err == 0 THEN DO SAY "ERROR:" UNIXERROR(RXFUNCERRMSG()) END /* Check if there was a record. If so, the size is not -1 */ ELSE IF msgSize \= -1 THEN DO SAY "Next record is" msgSize "bytes." ENDAfter you get the size of the next record, you can then read it. You first need to obtain a memory buffer (of the required size) into which you can read the contents of the record. We'll use Reginald's CONVERTDATA with the "A" option to do that. Then you need to call the function ReadFile to read the actual record. Once the record has been read, it is removed from the mailslot. Finally, we'll use CONVERTDATA once more to convert the record from any binary datatype, to REXX variables. If your record is already text characters (such as what REXX clients scripts typically would write), then it doesn't need any conversion. It merely needs to be assigned to a variable, which CONVERTDATA's "=" option can do quickly and easily. (Otherwise, if the record contains binary, you'd want to FUNCDEF some datatype, such as a struct that describes the datatype, and then use CONVERTDATA's "T" option to stuff it into a REXX variable).
To allocate a simple memory buffer with CONVERTDATA, we pass a 0 for the first arg, the desired size for the second arg, omit the third arg, and pass an "A" for the last arg. If all goes well, CONVERTDATA will return a handle to the memory, which we will pass to ReadFile. If an error, CONVERTDATA will raise SYNTAX condition.
/* Allocate memory to read in the record */ buffer = CONVERTDATA(0, msgSize, , "A")
Now that we have a buffer to read in the record, we call ReadFile to do that.
The first arg is the handle to our mailslot.
The second arg is the handle to our memory buffer.
The third arg is the number of bytes we want to read.
The fourth arg is the name of a REXX variable where ReadFile will return how many bytes it actually read. We need to check this on return to make sure we read as many bytes as we expected.
The last arg you pass is the name of a REXX variable that is a SECURITY_ATTRIBUTES struct you fill in. We don't need this arg, so we can omit it.
If all goes well, ReadFile will read the contents of the record into our buffer, not return an empty string, and it will set our variable to the proper number of bytes that it read. Here we read the record:
/* Read the record */ err = ReadFile(handle, buffer, msgSize, numRead) /* See if an error */ IF err == "" THEN SAY "ERROR:" UNIXERROR(RXFUNCERRMSG()) /* Make sure all the chars were read */ ELSE IF msgSize \= numRead THEN SAY "ERROR: The correct number of characters weren't received!"Finally, the last step is to assign the contents of the record to a REXX variable so that we can directly manipulate it. We use CONVERTDATA to do so (and assign it to the same variable name, although you can use any name):
/* Assign the record chars to the REXX variable named "buffer" */ err = CONVERTDATA(buffer, "buffer", , "=") IF err == "" THEN SAY "Error assigning the record to a variable" /* Display the received record. Here you'd normally * do something useful with it */ SAY buffer