× The internal search function is temporarily non-functional. The current search engine is no longer viable and we are researching alternatives.
As a stop gap measure, we are using Google's custom search engine service.
If you know of an easy to use, open source, search engine ... please contact support@midrange.com.


  • Subject: Re: Calling a program without knowing the parms
  • From: Scott Klement <klemscot@xxxxxxxxxxxx>
  • Date: Tue, 3 Jul 2001 23:57:35 -0500 (CDT)



On Tue, 3 Jul 2001, John Ross wrote:
>
> >So, having said all of that, I've come up with this pseudo-code:
> >
> >1) A "listener" program is created on the AS/400 that listens for
> >     connection requests from the PC.  Whenever it receives a request,
> >     it submits a new job to process that request and uses the
> >     givedescriptor/takedescriptor APIs to hand the socket descriptor
> >     to that job.
> 
> This sockets program is written. Not sure about the 
> "givedescriptor/takedescriptor APIs". What do you mean by that.
> 

I mean just what I said :)   givedescriptor & takedescriptor are the
method that OS/400 uses to allow you to pass a socket descriptor from one
job to another.

The idea is that when two or more people on the LAN connect to your AS/400
at the same time, you'll need a separate job to handle each connection.
This prevents them from interfering with each other, etc.

So, you have one "listener" job that does nothing but wait for a
connection to your machine.  Once it gets that connection, it immediately
creates a new job and gives the newly connected socket to that new job
to do the processing....

That way, it can wait for the NEXT person to connect, and submit the NEXT
job, etc...


> >3) The "newly submitted" job will handle the rest of the processing
> >     for this request.  It will ask the PC program for a user-name
> >     and password, when it gets one, it will use the security APIs
> >     to set the current profile to the one passed from the PC.  It
> >     would be a huge security hole to try to write this application
> >     without doing this.
> 
> Done in number one above before the submit.
> 

Hmmm... doing this before the submit would work, but you'd have to be very
careful to use non-blocking sockets and never just "wait for a username"
or "wait for a password".   Because if you stop and wait for a username or
password, others on the network won't be able to connect until the userid
and password have been validated.

Does that make sense?  HAve you tested your apps with many users trying to
connect at once?

> >4) The As/400 program will request from the PC a program name to call
> >     and "parameter buffer".  The parameter buffer should probably
> >     contain the number of parms to use, an offset value into the
> >     buffer for each parm, and a length of the actual parm data, as
> >     well as the data itself.
> 
> I understand the concept, but not sure how the actual parameter buffer 
> would look. And if it really matters and long as the PC programs and the 
> AS/400 socket programs use the same format.

As long as they use the same format, it really shouldn't matter.  But keep
in mind that you'll need to do ASCII <--> EBCDIC translation of this data,
so sending raw packed/binary/float numbers might be a bad idea.

> >5) Once this parm data has been received by the AS/400, it will use
> >     the number of parms, and offsets for each parm to get a list of
> >     pointers to pass to the program that it's about to call.   It
> >     could base some 1A fields on these pointers, and pass these
> >     as parms to the program that it's about to call.   If there
> >     are less than 255 parms to pass, the remaining pointers should
> >     probably be set to NULL.  It can now do the actual call.
> 
> Ok really confused. I think Peter had an example in his email. But I did 
> not understand it.

Okay, here's an example, maybe that'll help you understand....

DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords+++++++++++++++++++++++++
D p_parm1         S               *
D p_parm2         S               *
D p_parm3         S               *

D parm1           S              1A   based(p_parm1)
D parm2           S              1A   based(p_parm2)
D parm3           S              1A   based(p_parm3)

D parmbuffer      S          32766A
D parmoffset      S              5S 0 DIM(3)

C** Lets assume here that the PC has (via sockets) sent us 15 bytes
C**  that we've already loaded into the parmoffset array.  It now
C**  should contain 3 zoned decimal numbers.   The PC has also 
C**  sent the number "100" which tells us how big the parameter
C**  buffer is, and then we read the next 100 bytes into the first
C**  100 positions of "parmbuffer".
C**
C**  Now:
C**     parmoffset(1) will be -1 if no parm1 is to be passed, or
C**       otherwise will be the offset to the data for parm1 in
C**       the parmbuffer data.   parmoffset(2) will be the offset
C**       for parm2, or -1 for none, etc.
C**
C**    Also, we've somehow loaded the name of the program to call
C**    into the "PgmNameVar" variable.
C**
C                   if        parmoffset(1) = -1
c                   eval      p_parm1 = *NULL
c                   else
c                   eval      p_parm1 = %addr(parmbuffer) + 
c                                parmoffset(1)
c                   endif
 
c                   if        parmoffset(2) = -1
c                   eval      p_parm2 = *NULL
c                   else
c                   eval      p_parm2 = %addr(parmbuffer) + 
c                                parmoffset(2)
c                   endif
 
c                   if        parmoffset(3) = -1
c                   eval      p_parm3 = *NULL
c                   else
c                   eval      p_parm3 = %addr(parmbuffer) + 
c                                parmoffset(3)
c                   endif


 ** When this call (below) is made, OS/400 will pass the address of
 **  parm1, parm2 and parm3 to the called program.   Since we've 
 **  forcibly set the addresses of these variables (in the code above)
 **  to an address within our parmbuffer, we'll effectively be sending
 **  whatever data is in that area of memory.
 **
 ** It doesn't matter that parm1, parm2 and parm3 are defined as "1A"
 ** because the program that we're calling doesn't get the data type
 ** or length of the variable, it only gets the memory address.
 **
 ** So, as long as the data in those positions of our parmbuffer is
 ** valid for whatever type & length the called program expects, 
 ** this SHOULD work.
 **
CL0N01Factor1+++++++Opcode&ExtFactor2+++++++Result++++++++Len++D+HiLoEq
c                   call(e)   PgmNameVar
c                   parm                    parm1
c                   parm                    parm2
c                   parm                    parm3

> 
> >6) When the program it calls completes, it needs to send the
> >     (possibly updated) parameter buffer back to the PC.  It's
> >     probably a good idea to also pass things like error messages
> >     and return codes, in case the program that was called had
> >     crashed.
> 
> Agree.
> 
> >7) Now you have the option of letting PC call another program
> >    (or the same program again) or simply closing the connection
> >    and ending the job.
> >
> >Probably the best way to organize the whole thing is to create your own
> >sort of an "API" on the PC end of the connection, so that this code
> >doesn't need to be rewritten for every application that uses it.
> 
> Agree. Another learning curve. It will have a connect, disconnect, format 
> call, parse data after call, and the call section. I think they are called 
> active x on the PC side.

ActiveX is Microsoft's system for creating "custom controls" and other
reusable system components.  However, as far as I can see, the only
methods that should really need to be exposed to outside programs should
be  "connect" (including sign-in)  "disconnect" and "call".   I'd try to
make the "call" part work in a way that would allow you to simply pass
parms to the method, and have your code automatically handle all the 
parsing and conversion "behind the scenes".

I used to do sockets in VB a few years ago (I used Catalyst's socketwrench
control, though) I don't really do them anymore, I guess I just don't like
Windows :)   Most of my PC to AS/400 code in recent years has been
designed to work from a FreeBSD machine, and then I make it cross-portable
to Linux systems...

> If this is in HTML format, please let me know. I have started to use Eudura 
> and not sure if I have it set right or not.

Your message was entirely "text/plain".  :)


+---
| This is the RPG/400 Mailing List!
| To submit a new message, send your mail to RPG400-L@midrange.com.
| To subscribe to this list send email to RPG400-L-SUB@midrange.com.
| To unsubscribe from this list send email to RPG400-L-UNSUB@midrange.com.
| Questions should be directed to the list owner/operator: david@midrange.com
+---

As an Amazon Associate we earn from qualifying purchases.

This thread ...

Replies:

Follow On AppleNews
Return to Archive home page | Return to MIDRANGE.COM home page

This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].

Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.