Level: Introductory developerWorks staff (mmccrary@us.ibm.com), developerWorks eServer and Linux on POWER Content Editor, IBM
13 Aug 2001 We cover the basics of using the AS/400 command processor to help you port your application. Learn how to use command prompting and help, product installation methods and AS/400 messaging.
The code and programming advice herein, which is furnished by IBM, is a series of simple examples, intended to provide illustrations of concept. These examples have not been thoroughly tested under all conditions. IBM, therefore, cannot guarantee or imply reliability, serviceability, or function of this code.
All program code and programming advice contained herein is provided to you "AS IS". The implied warranties of merchantability and fitness for a particular purpose are expressly disclaimed. Ultimately, it is the responsibility of the individual programmer to understand his or her own application and use this advice as it best pertains to that application.
IBM offers the following as only as potential solutions, which must be evaluated on an individual-use basis. All brand, company, service, or product names mentioned are trademarks, service marks, or registered trademarks of their respective companies.
Overview
To complete the porting of your application to AS/400, you will want to use some of the basic AS/400 services such as command prompting and help, product installation methods, and AS/400 messaging. The first of these three topics will be covered in this document.
If you have an opportunity to spend some time using AS/400 command prompting, you will appreciate its helpfulness and probably wonder why UNIX or DOS never had something so clean and so completely integrated into the operating system. You can give your application this same kind of command interface following the simple instructions below.
First, here are the definitive references for all of the things I'll discuss:
Also, while there are plenty of complex and powerful actions that can be performed using the AS/400 command processor, it is not the intent of this document to cover all of these aspects -- just the necessary basics.
Here's a quick overview of the objects needed. The command object (*CMD) is what is entered on the command line. Parameters to creating a command include specifying a help panel group object (*PNLGRP) and a program object (*PGM) to process the data from the command. In the example to the right, the command processing program, FOOCPP builds a command string, which is used to call the foo program.
The program called 'FOO' has three command-line parameters:
- -o[filename] output to a file
- -s sort output
- -w display warnings
Foo understands all combinations of flags or lack thereof. So, valid uses of 'FOO' in a UNIX environment might be:
- % foo
- % foo -omyfile.out
- % foo -w
- % foo -w -s
- % foo -o/home/joe/out1 -s
- % foo -s
Similarly, typical matching AS/400 commands would look like:
- FOO
- FOO OUTPUT('myfile.out')
- FOO WARN(*YES)
- FOO OUTPUT('/home/joe/out1') SORT(*YES)
- OO SORT(*YES) WARN(*NO)
Plus, with the AS/400 version, a user would expect contextual help by pressing F1 anywhere on the command parameters, or for the command itself. Providing this capability is not very difficult and will represent the difference between an 'AS/400 application' and a 'UNIX application running on AS/400'.
AS/400 commands, like all other things on the system, are objects. These command objects have a type of *CMD. They are created by compiling 'command source'. This source must reside in a source physical file, typically called QCMDSRC. Part of creating a *CMD object is specifying a program to process the command. In our example, we will write a small C program to perform the processing of the data from the command. Another part of creating a *CMD object is specifying a 'panel group' for the interactive help. The creation of these parts can be easily done using the templates provided.
Briefly, the steps are:
- Change the current library (*CURLIB).
- Create the source physical files.
- Enter the source code for the command, the command processing program, and the help panel group.
- Create the help panel group (*PNLGRP) object.
- Create the command processing program (*PGM) object.
- Create the command (*CMD) object.
- Test the command.
Make the library in which you want to create the objects your 'current library'. This is done using the CHGCURLIB command. Or, you can change your user profile to set the 'current library' at signon time. Do this by prompting on the CHGPRF command. In this example, I have set the current library to MYLIB.
Next, create the source physical files. It is likely that you already have a source file named QCSRC, which contains the source for the program FOO which eventually does the work that we're building all of this stuff for, so in the example below, an error message is shown when creating QCSRC. To create the three source files, enter the following commands:
- CRTSRCPF QCMDSRC
File QCMDSRC created in library MYLIB.
- CRTSRCPF QPNLSRC
File QPNLSRC created in library MYLIB.
- CRTSRCPF QCSRC
File QCSRC already exists in library MYLIB.
File QCSRC not created in library MYLIB.
Then, enter the source. For this example, these are the members in the corresponding source physical files:
| MEMBER | TYPE | | FILE | | | | QCMDSRC | FOO | CMD | | QPNLSRC | FOO | PNLGRP | | QCSRC | FOOCPP | C | | QCSRC | FOO | C |
Remember, we're assuming that this member already exists.
Here are the three new source members, in the order listed above.
QCMDSRC/FOO
CMD PROMPT('Foo, as in FUBAR')
PARM KWD(OUTPUT) TYPE(*CHAR) LEN(32) DFT('') +
VARY(*YES) PROMPT('Output name')
PARM KWD(SORT) TYPE(*CHAR) LEN(4) RSTD(*YES) +
DFT(*NO) VALUES(*NO *YES) PROMPT('Sort +
output')
PARM KWD(WARN) TYPE(*CHAR) LEN(4) RSTD(*YES) +
DFT(*NO) VALUES(*NO *YES) PROMPT('Display +
Warnings')
|
QPNLSRC/FOO
:PNLGRP.
:HELP name=foo.
:P.
The text here describes what the command 'FOO' does.
You can use the formatting tags described in the book to make this look prettier.
Application Display Programming SC41-5715.
:EHELP.
:HELP name='foo/output'.
:P.
This help item is used for information about the first parameter.
:EHELP.
:HELP name='foo/sort'.
:P.
This help item is used for information about the second parameter.
:EHELP.
:HELP name='foo/warn'.
:P.
This help item is used for information about the third parameter.
:EHELP.
:HELP name=boo.
:P.
This help item is used for information about a phantom command, 'boo'.
:EHELP.
:EPNLGRP.
|
QCSRC/FOOCPP
#include <string.h>
#include <stdlib.h>
void main(int argc, char* argv[])
{
char cmdstr[512]="CALL PGM(FOO) PARM(";
if (argc != 4)
exit(1);
/* The first 2 bytes of the incoming text string represent, as a short,
the length of the text entered. There is no
null-terminator at the end of the string.
This is due to the VARY(*YES) option of the parameter in the command source.
*/
if (*(short*)argv[1] > 0)
{
strcat(cmdstr, " '-o");
strncat(cmdstr, argv[1]+2, *(short*)argv[1]);
strcat(cmdstr, "'");
}
if (strncmp(argv[2], "*YES", 4) == 0)
strcat(cmdstr, " '-s'");
if (strncmp(argv[3], "*YES", 4) == 0)
strcat(cmdstr, " '-w'");
strcat(cmdstr, ")");
system(cmdstr);
}
|
Next, we'll create the three objects from the source code above. Remember, since we have changed the current library to where we want to create these objects, they will be created there by default.
- CRTCMD CMD(FOO) PGM(FOOCPP) HLPPNLGRP(FOO) HLPID(FOO)
Command FOO created in library MYLIB.
- CRTPNLGRP PNLGRP(FOO)
Warning messages issued when panel group FOO created.
- CRTBNDC PGM(FOOCPP)
Program FOOCPP was created in library MYLIB on 11/05/97 at 17:17:50.
That's it! You can now prompt on the FOO command, since it's in the library list. Of course, if MYLIB wasn't in the library list, then you could prompt on MLIB/FOO. You can press F1 to get help about the parameters. You will probably want to place all of these objects in the same library as all of your application's programs to simplify things.
Notes
All of the help for multiple commands can be located in the same panel group, grouped within the same :PNLGRP and :EPNLGRP tags. The :HELP and :EHELP tags group help for individual commands. You'll notice that this language resembles HTML structurally, with tags to identify sections. If you look closely at the source code for the help panel group, you will notice that there is defined a help name of 'boo' for a phantom command, which does not exist.
All of the individual command source members, for many different commands and programs, should be placed in QCMDSRC.
The *CHAR parameters from the command prompting, passed to the command processing program, are not null-terminated, and this is why we use the VARY(*YES) option to the parameter. This makes the command prompt send a 2-byte (default) signed integer as the first 2 bytes of the string. That's why the C for dealing with that parameter gets ugly.
All parameters from a command are given to the command processing program. Therefore, even if you didn't enter anything for a given parameter, argc would still be set to the number of parameters defined in the command source.
The command analyzer (CA) can do a lot of syntax checking for you, so if the value for the OUTPUT parameter is really a path name, you can specify TYPE(*PNAME) and CA will verify that what the user specified is a valid name. You may also want to specify CASE(*MIXED) so that CA doesn't monocase any values not enclosed in single quotes.
The command analyzer (CA) can do a lot of parameter validation work for you and it won't let the user enter any parameters that are not defined in your command. For example, the way our command is defined, the user can't enter anything other than *YES or *NO for the SORT and WARN parameters. If FOO does a lot of parameter validation stuff (like checking for valid values), you may want to add another parameter to FOO to tell it that it is being called to process the FOO command; then it could skip any parameter validation work that had already been done by CA.
Resources
About the author
Rate this page
|